summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common
Unidiff
Diffstat (limited to 'gammu/emb/common') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/common.pro179
-rw-r--r--gammu/emb/common/config.h15
-rw-r--r--gammu/emb/common/device/bluetoth/affix.c44
-rw-r--r--gammu/emb/common/device/bluetoth/affix.h3
-rw-r--r--gammu/emb/common/device/bluetoth/blue_w32.c216
-rw-r--r--gammu/emb/common/device/bluetoth/blue_w32.h188
-rw-r--r--gammu/emb/common/device/bluetoth/bluetoth.c85
-rw-r--r--gammu/emb/common/device/bluetoth/bluetoth.h15
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.c207
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.h3
-rw-r--r--gammu/emb/common/device/devfunc.c266
-rw-r--r--gammu/emb/common/device/devfunc.h38
-rw-r--r--gammu/emb/common/device/irda/irda.c187
-rw-r--r--gammu/emb/common/device/irda/irda.h22
-rw-r--r--gammu/emb/common/device/irda/irda_unx.h61
-rw-r--r--gammu/emb/common/device/irda/irda_w32.h35
-rw-r--r--gammu/emb/common/device/serial/ser_djg.c74
-rw-r--r--gammu/emb/common/device/serial/ser_djg.h15
-rw-r--r--gammu/emb/common/device/serial/ser_unx.c291
-rw-r--r--gammu/emb/common/device/serial/ser_unx.h22
-rw-r--r--gammu/emb/common/device/serial/ser_w32.c340
-rw-r--r--gammu/emb/common/device/serial/ser_w32.h19
-rw-r--r--gammu/emb/common/gammu.h23
-rw-r--r--gammu/emb/common/gsmcomon.c260
-rw-r--r--gammu/emb/common/gsmcomon.h92
-rw-r--r--gammu/emb/common/gsmstate.c1246
-rw-r--r--gammu/emb/common/gsmstate.h1562
-rw-r--r--gammu/emb/common/misc/cfg.c332
-rw-r--r--gammu/emb/common/misc/cfg.h42
-rw-r--r--gammu/emb/common/misc/coding/coding.c1409
-rw-r--r--gammu/emb/common/misc/coding/coding.h133
-rw-r--r--gammu/emb/common/misc/coding/md5.c298
-rw-r--r--gammu/emb/common/misc/coding/md5.h6
-rw-r--r--gammu/emb/common/misc/misc.c591
-rw-r--r--gammu/emb/common/misc/misc.h137
-rw-r--r--gammu/emb/common/phone/alcatel/alcatel.c3991
-rw-r--r--gammu/emb/common/phone/alcatel/alcatel.h286
-rw-r--r--gammu/emb/common/phone/at/atgen.c3669
-rw-r--r--gammu/emb/common/phone/at/atgen.h110
-rw-r--r--gammu/emb/common/phone/at/siemens.c320
-rw-r--r--gammu/emb/common/phone/at/sonyeric.c411
-rw-r--r--gammu/emb/common/phone/nokia/dct3/dct3comm.h16
-rw-r--r--gammu/emb/common/phone/nokia/dct3/dct3func.c1535
-rw-r--r--gammu/emb/common/phone/nokia/dct3/dct3func.h78
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n6110.c2884
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n6110.h45
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n7110.c1724
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n7110.h45
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n9210.c396
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n9210.h17
-rw-r--r--gammu/emb/common/phone/nokia/dct4/dct4func.c115
-rw-r--r--gammu/emb/common/phone/nokia/dct4/dct4func.h30
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3320.c271
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3320.h30
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3650.c392
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n3650.h30
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n6510.c5782
-rw-r--r--gammu/emb/common/phone/nokia/dct4/n6510.h90
-rw-r--r--gammu/emb/common/phone/nokia/nauto.c144
-rw-r--r--gammu/emb/common/phone/nokia/ncommon.h66
-rw-r--r--gammu/emb/common/phone/nokia/nfunc.c2143
-rw-r--r--gammu/emb/common/phone/nokia/nfunc.h99
-rw-r--r--gammu/emb/common/phone/nokia/nfuncold.c226
-rw-r--r--gammu/emb/common/phone/nokia/nfuncold.h19
-rw-r--r--gammu/emb/common/phone/obex/obexgen.c851
-rw-r--r--gammu/emb/common/phone/obex/obexgen.h38
-rw-r--r--gammu/emb/common/phone/pfunc.c138
-rw-r--r--gammu/emb/common/phone/pfunc.h30
-rw-r--r--gammu/emb/common/phone/symbian/mroutgen.c220
-rw-r--r--gammu/emb/common/phone/symbian/mroutgen.h29
-rw-r--r--gammu/emb/common/protocol/alcatel/alcabus.c255
-rw-r--r--gammu/emb/common/protocol/alcatel/alcabus.h61
-rw-r--r--gammu/emb/common/protocol/at/at.c229
-rw-r--r--gammu/emb/common/protocol/at/at.h36
-rw-r--r--gammu/emb/common/protocol/nokia/fbus2.c444
-rw-r--r--gammu/emb/common/protocol/nokia/fbus2.h38
-rw-r--r--gammu/emb/common/protocol/nokia/mbus2.c252
-rw-r--r--gammu/emb/common/protocol/nokia/mbus2.h28
-rw-r--r--gammu/emb/common/protocol/nokia/phonet.c217
-rw-r--r--gammu/emb/common/protocol/nokia/phonet.h35
-rw-r--r--gammu/emb/common/protocol/obex/obex.c120
-rw-r--r--gammu/emb/common/protocol/obex/obex.h33
-rw-r--r--gammu/emb/common/protocol/protocol.h31
-rw-r--r--gammu/emb/common/protocol/symbian/mrouter.c110
-rw-r--r--gammu/emb/common/protocol/symbian/mrouter.h31
-rw-r--r--gammu/emb/common/service/backup/backgen.h69
-rw-r--r--gammu/emb/common/service/backup/backics.c42
-rw-r--r--gammu/emb/common/service/backup/backics.h17
-rw-r--r--gammu/emb/common/service/backup/backldif.c297
-rw-r--r--gammu/emb/common/service/backup/backldif.h17
-rw-r--r--gammu/emb/common/service/backup/backlmb.c413
-rw-r--r--gammu/emb/common/service/backup/backlmb.h17
-rw-r--r--gammu/emb/common/service/backup/backtext.c2908
-rw-r--r--gammu/emb/common/service/backup/backtext.h17
-rw-r--r--gammu/emb/common/service/backup/backvcf.c75
-rw-r--r--gammu/emb/common/service/backup/backvcf.h17
-rw-r--r--gammu/emb/common/service/backup/backvcs.c106
-rw-r--r--gammu/emb/common/service/backup/backvcs.h17
-rw-r--r--gammu/emb/common/service/backup/gsmback.c280
-rw-r--r--gammu/emb/common/service/backup/gsmback.h48
-rw-r--r--gammu/emb/common/service/gsmcal.c509
-rw-r--r--gammu/emb/common/service/gsmcal.h445
-rw-r--r--gammu/emb/common/service/gsmcall.h185
-rw-r--r--gammu/emb/common/service/gsmdata.c366
-rw-r--r--gammu/emb/common/service/gsmdata.h152
-rw-r--r--gammu/emb/common/service/gsmlogo.c1003
-rw-r--r--gammu/emb/common/service/gsmlogo.h180
-rw-r--r--gammu/emb/common/service/gsmmisc.c262
-rw-r--r--gammu/emb/common/service/gsmmisc.h316
-rw-r--r--gammu/emb/common/service/gsmnet.c444
-rw-r--r--gammu/emb/common/service/gsmnet.h98
-rw-r--r--gammu/emb/common/service/gsmpbk.c370
-rw-r--r--gammu/emb/common/service/gsmpbk.h270
-rw-r--r--gammu/emb/common/service/gsmprof.h104
-rw-r--r--gammu/emb/common/service/gsmring.c1600
-rw-r--r--gammu/emb/common/service/gsmring.h202
-rw-r--r--gammu/emb/common/service/sms/gsmems.c765
-rw-r--r--gammu/emb/common/service/sms/gsmems.h20
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.c1148
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.h271
-rw-r--r--gammu/emb/common/service/sms/gsmsms.c663
-rw-r--r--gammu/emb/common/service/sms/gsmsms.h492
122 files changed, 50851 insertions, 0 deletions
diff --git a/gammu/emb/common/common.pro b/gammu/emb/common/common.pro
new file mode 100644
index 0000000..49fecc6
--- a/dev/null
+++ b/gammu/emb/common/common.pro
@@ -0,0 +1,179 @@
1######################################################################
2# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004
3######################################################################
4
5TEMPLATE = lib
6DEPENDPATH += device \
7 misc \
8 phone \
9 protocol \
10 service \
11 device/bluetoth \
12 device/irda \
13 device/serial \
14 misc/coding \
15 phone/alcatel \
16 phone/at \
17 phone/nokia \
18 phone/obex \
19 phone/symbian \
20 protocol/alcatel \
21 protocol/at \
22 protocol/nokia \
23 protocol/obex \
24 protocol/symbian \
25 service/backup \
26 service/sms \
27 phone/nokia/dct3 \
28 phone/nokia/dct4
29INCLUDEPATH += . \
30 misc/coding \
31 misc \
32 device \
33 phone/nokia/dct4 \
34 phone/nokia/dct3 \
35 phone/at \
36 phone/alcatel \
37 phone/obex \
38 phone/symbian \
39 protocol \
40 protocol/nokia \
41 protocol/at \
42 protocol/alcatel \
43 protocol/obex \
44 protocol/symbian \
45 device/serial \
46 device/irda \
47 device/bluetoth \
48 service \
49 service/sms \
50 service/backup \
51 phone/nokia \
52 phone
53
54# Input
55HEADERS += config.h \
56 gammu.h \
57 gsmcomon.h \
58 gsmstate.h \
59 device/devfunc.h \
60 misc/cfg.h \
61 misc/misc.h \
62 phone/pfunc.h \
63 protocol/protocol.h \
64 service/gsmcal.h \
65 service/gsmcall.h \
66 service/gsmdata.h \
67 service/gsmlogo.h \
68 service/gsmmisc.h \
69 service/gsmnet.h \
70 service/gsmpbk.h \
71 service/gsmprof.h \
72 service/gsmring.h \
73 device/bluetoth/affix.h \
74 device/bluetoth/blue_w32.h \
75 device/bluetoth/bluetoth.h \
76 device/bluetoth/bluez.h \
77 device/irda/irda.h \
78 device/irda/irda_unx.h \
79 device/irda/irda_w32.h \
80 device/serial/ser_djg.h \
81 device/serial/ser_unx.h \
82 device/serial/ser_w32.h \
83 misc/coding/coding.h \
84 misc/coding/md5.h \
85 phone/alcatel/alcatel.h \
86 phone/at/atgen.h \
87 phone/nokia/ncommon.h \
88 phone/nokia/nfunc.h \
89 phone/nokia/nfuncold.h \
90 phone/obex/obexgen.h \
91 phone/symbian/mroutgen.h \
92 protocol/alcatel/alcabus.h \
93 protocol/at/at.h \
94 protocol/nokia/fbus2.h \
95 protocol/nokia/mbus2.h \
96 protocol/nokia/phonet.h \
97 protocol/obex/obex.h \
98 protocol/symbian/mrouter.h \
99 service/backup/backgen.h \
100 service/backup/backics.h \
101 service/backup/backldif.h \
102 service/backup/backlmb.h \
103 service/backup/backtext.h \
104 service/backup/backvcf.h \
105 service/backup/backvcs.h \
106 service/backup/gsmback.h \
107 service/sms/gsmems.h \
108 service/sms/gsmmulti.h \
109 service/sms/gsmsms.h \
110 phone/nokia/dct3/dct3comm.h \
111 phone/nokia/dct3/dct3func.h \
112 phone/nokia/dct3/n6110.h \
113 phone/nokia/dct3/n7110.h \
114 phone/nokia/dct3/n9210.h \
115 phone/nokia/dct4/dct4func.h \
116 phone/nokia/dct4/n3320.h \
117 phone/nokia/dct4/n3650.h \
118 phone/nokia/dct4/n6510.h
119SOURCES +=gsmcomon.c \
120gsmstate.c \
121misc/misc.c \
122misc/cfg.c \
123misc/coding/coding.c \
124misc/coding/md5.c \
125service/sms/gsmsms.c \
126service/sms/gsmems.c \
127service/sms/gsmmulti.c \
128service/gsmcal.c \
129service/gsmdata.c \
130service/gsmpbk.c \
131service/gsmring.c \
132service/gsmlogo.c \
133service/gsmmisc.c \
134service/gsmnet.c \
135service/backup/gsmback.c \
136service/backup/backldif.c \
137service/backup/backlmb.c \
138service/backup/backtext.c \
139service/backup/backvcs.c \
140service/backup/backvcf.c \
141service/backup/backics.c \
142device/bluetoth/affix.c \
143device/bluetoth/bluez.c \
144device/bluetoth/blue_w32.c \
145device/bluetoth/bluetoth.c \
146device/serial/ser_unx.c \
147device/serial/ser_djg.c \
148device/irda/irda.c \
149device/devfunc.c \
150protocol/at/at.c \
151protocol/alcatel/alcabus.c \
152protocol/nokia/mbus2.c \
153protocol/nokia/fbus2.c \
154protocol/nokia/phonet.c \
155protocol/obex/obex.c \
156protocol/symbian/mrouter.c \
157phone/pfunc.c \
158phone/at/atgen.c \
159phone/at/siemens.c \
160phone/at/sonyeric.c \
161phone/alcatel/alcatel.c \
162phone/nokia/dct3/n6110.c \
163phone/nokia/dct3/n7110.c \
164phone/nokia/dct3/n9210.c \
165phone/nokia/dct3/dct3func.c \
166phone/nokia/dct4/n3320.c \
167phone/nokia/dct4/n3650.c \
168phone/nokia/dct4/n6510.c \
169phone/nokia/dct4/dct4func.c \
170phone/nokia/nauto.c \
171phone/nokia/nfunc.c \
172phone/nokia/nfuncold.c \
173phone/obex/obexgen.c \
174phone/symbian/mroutgen.c
175
176TARGET = microgammu
177DESTDIR = $(QPEDIR)/lib
178OBJECTS_DIR = obj/$(PLATFORM)
179MOC_DIR = moc/$(PLATFORM)
diff --git a/gammu/emb/common/config.h b/gammu/emb/common/config.h
new file mode 100644
index 0000000..f48bb38
--- a/dev/null
+++ b/gammu/emb/common/config.h
@@ -0,0 +1,15 @@
1/* (c) 2003 by Michal Cihar */
2
3/*
4 * This is just wrapper for config.h to allow same path in headers for source
5 * tree and installation.
6 */
7
8#ifndef GAMMU_CONFIG_INCLUDED
9# include "../cfg/config.h"
10# define GAMMU_CONFIG_INCLUDED
11#endif
12
13/* How should editor hadle tabs in this file? Add editor commands here.
14 * vim: noexpandtab sw=8 ts=8 sts=8:
15 */
diff --git a/gammu/emb/common/device/bluetoth/affix.c b/gammu/emb/common/device/bluetoth/affix.c
new file mode 100644
index 0000000..30a917b
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/affix.c
@@ -0,0 +1,44 @@
1/* (c) 2004 by Marcin Wiacek */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_BLUETOOTHDEVICE
6#ifdef GSM_ENABLE_AFFIX
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <string.h>
13#include <sys/socket.h>
14#include <sys/time.h>
15#include <unistd.h>
16
17#include "../../gsmcomon.h"
18#include "../devfunc.h"
19#include "bluetoth.h"
20
21GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
22{
23 d->hPhone = fd;
24 return ERR_NONE;
25}
26
27#ifdef BLUETOOTH_RF_SEARCHING
28
29static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
30{
31}
32
33GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
34{
35 return error;
36}
37
38#endif
39#endif
40#endif
41
42/* How should editor hadle tabs in this file? Add editor commands here.
43 * vim: noexpandtab sw=8 ts=8 sts=8:
44 */
diff --git a/gammu/emb/common/device/bluetoth/affix.h b/gammu/emb/common/device/bluetoth/affix.h
new file mode 100644
index 0000000..896ecbe
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/affix.h
@@ -0,0 +1,3 @@
1
2GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
3GSM_Error bluetooth_findchannel(GSM_StateMachine *s);
diff --git a/gammu/emb/common/device/bluetoth/blue_w32.c b/gammu/emb/common/device/bluetoth/blue_w32.c
new file mode 100644
index 0000000..a631c9f
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/blue_w32.c
@@ -0,0 +1,216 @@
1/* (c) 2003-2004 by Marcin Wiacek and Intra */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_BLUETOOTHDEVICE
6#ifdef WIN32
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <string.h>
13#include <windows.h>
14#include <io.h>
15
16#include "../../misc/coding/coding.h"
17#include "../../gsmcomon.h"
18#include "../devfunc.h"
19#include "bluetoth.h"
20#include "blue_w32.h"
21
22GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
23{
24 GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
25 WSADATA wsaData;
26 SOCKADDR_BTH sab;
27 int i;
28
29 smprintf(s, "Connecting to RF channel %i\n",port);
30
31 WSAStartup(MAKEWORD(1,1), &wsaData);
32
33 d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
34 if (d->hPhone == INVALID_SOCKET) {
35 i = GetLastError();
36 GSM_OSErrorInfo(s, "Socket in bluetooth_open");
37 if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type
38 return ERR_UNKNOWN;
39 }
40
41 memset (&sab, 0, sizeof(sab));
42 sab.port = port;
43 sab.addressFamily = AF_BTH;
44 sab.btAddr = 0;
45 for (i=0;i<(int)strlen(device);i++) {
46 if (device[i] >='0' && device[i] <='9') {
47 sab.btAddr = sab.btAddr * 16;
48 sab.btAddr = sab.btAddr + (device[i]-'0');
49 }
50 if (device[i] >='a' && device[i] <='f') {
51 sab.btAddr = sab.btAddr * 16;
52 sab.btAddr = sab.btAddr + (device[i]-'a'+10);
53 }
54 if (device[i] >='A' && device[i] <='F') {
55 sab.btAddr = sab.btAddr * 16;
56 sab.btAddr = sab.btAddr + (device[i]-'A'+10);
57 }
58 }
59 dbgprintf("Remote Bluetooth device is %04x%08x\n",
60 GET_NAP(sab.btAddr), GET_SAP(sab.btAddr));
61
62 if (connect (d->hPhone, (struct sockaddr *)&sab, sizeof(sab)) != 0) {
63 i = GetLastError();
64 GSM_OSErrorInfo(s, "Connect in bluetooth_open");
65 if (i == 10060) return ERR_TIMEOUT; //remote device failed to respond
66 if (i == 10050) return ERR_DEVICENOTWORK; //socket operation connected with dead network
67 //noauth
68 close(d->hPhone);
69 return ERR_UNKNOWN;
70 }
71
72 return ERR_NONE;
73}
74
75#ifdef BLUETOOTH_RF_SEARCHING
76
77#pragma comment(lib, "irprops.lib")
78#pragma comment(lib, "ws2_32.lib")
79
80static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, char *address, WSAPROTOCOL_INFO *protocolInfo)
81{
82 GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
83 WSAQUERYSET querySet;
84 DWORD flags;
85 GUID protocol;
86 int i, result;
87 BYTE buffer[2000];
88 char addressAsString[1000];
89 DWORD bufferLength, addressSize;
90 WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
91 HANDLE handle;
92 GSM_Error error;
93
94 memset(&querySet, 0, sizeof(querySet));
95 querySet.dwSize = sizeof(querySet);
96 protocol = L2CAP_PROTOCOL_UUID;
97 querySet.lpServiceClassId = &protocol;
98 querySet.dwNameSpace = NS_BTH;
99 querySet.lpszContext = address;
100
101 flags = LUP_FLUSHCACHE | LUP_RETURN_NAME |
102 LUP_RETURN_TYPE | LUP_RETURN_ADDR |
103 LUP_RETURN_BLOB | LUP_RETURN_COMMENT;
104
105 result = WSALookupServiceBegin(&querySet, flags, &handle);
106 if (result != 0) return ERR_UNKNOWN;
107
108 bufferLength = sizeof(buffer);
109 while (1) {
110 result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
111 if (result != 0) break;
112 addressSize = sizeof(addressAsString);
113 addressAsString[0] = 0;
114 if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
115 pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, protocolInfo,
116 addressAsString,&addressSize)==0) {
117 smprintf(s, "%s - ", addressAsString);
118 }
119 smprintf(s, "\"%s\"\n", pResults->lpszServiceInstanceName);
120 if (addressAsString[0] != 0) {
121 for (i=strlen(addressAsString)-1;i>0;i--) {
122 if (addressAsString[i] == ':') break;
123 }
124 if (bluetooth_checkservicename(s, pResults->lpszServiceInstanceName) == ERR_NONE) {
125 error = bluetooth_connect(s,atoi(addressAsString+i+1),address+1);
126 result = WSALookupServiceEnd(handle);
127 return error;
128 }
129 }
130 }
131 result = WSALookupServiceEnd(handle);
132 return ERR_NOTSUPPORTED;
133}
134
135GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
136{
137 GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
138 WSADATA wsaData;
139 int i, protocolInfoSize, result;
140 WSAPROTOCOL_INFO protocolInfo;
141 HANDLE handle;
142 DWORD flags;
143 WSAQUERYSET querySet;
144 BYTE buffer[2000];
145 char addressAsString[1000];
146 DWORD bufferLength, addressSize;
147 WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer;
148 GSM_Error error;
149
150 if (WSAStartup(MAKEWORD(2,2), &wsaData)!=0x00) return ERR_DEVICENODRIVER;
151
152 d->hPhone = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
153 if (d->hPhone == INVALID_SOCKET) {
154 i = GetLastError();
155 GSM_OSErrorInfo(s, "Socket in bluetooth_open");
156 if (i == 10041) return ERR_DEVICENODRIVER;//unknown socket type
157 return ERR_UNKNOWN;
158 }
159
160 protocolInfoSize = sizeof(protocolInfo);
161 if (getsockopt(d->hPhone, SOL_SOCKET, SO_PROTOCOL_INFO,
162 (char*)&protocolInfo, &protocolInfoSize) != 0)
163 {
164 close(d->hPhone);
165 return ERR_UNKNOWN;
166 }
167 close(d->hPhone);
168
169 if (!strcmp(s->CurrentConfig->Device,"com2:")) {
170 bufferLength = sizeof(buffer);
171
172 flags = LUP_RETURN_NAME | LUP_CONTAINERS |
173 LUP_RETURN_ADDR | LUP_FLUSHCACHE |
174 LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE;
175
176 memset(&querySet, 0, sizeof(querySet));
177 querySet.dwSize = sizeof(querySet);
178 querySet.dwNameSpace = NS_BTH;
179
180 result = WSALookupServiceBegin(&querySet, flags, &handle);
181 if (result != 0) return ERR_UNKNOWN;
182
183 while (1) {
184 result = WSALookupServiceNext(handle, flags, &bufferLength, pResults);
185 if (result != 0) break;
186
187 smprintf(s, "\"%s\"", pResults->lpszServiceInstanceName);
188
189 addressSize = sizeof(addressAsString);
190 addressAsString[0] = 0;
191 if (WSAAddressToString(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr,
192 pResults->lpcsaBuffer->RemoteAddr.iSockaddrLength, &protocolInfo,
193 addressAsString,&addressSize)==0) {
194 smprintf(s, " - %s\n", addressAsString);
195 error = bluetooth_checkdevice(s, addressAsString,&protocolInfo);
196 if (error == ERR_NONE) {
197 result = WSALookupServiceEnd(handle);
198 return error;
199 }
200 } else smprintf(s, "\n");
201 }
202
203 result = WSALookupServiceEnd(handle);
204 return ERR_NOTSUPPORTED;
205 } else {
206 return bluetooth_checkdevice(s, s->CurrentConfig->Device,&protocolInfo);
207 }
208}
209
210#endif
211#endif
212#endif
213
214/* How should editor hadle tabs in this file? Add editor commands here.
215 * vim: noexpandtab sw=8 ts=8 sts=8:
216 */
diff --git a/gammu/emb/common/device/bluetoth/blue_w32.h b/gammu/emb/common/device/bluetoth/blue_w32.h
new file mode 100644
index 0000000..e457c92
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/blue_w32.h
@@ -0,0 +1,188 @@
1
2GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
3GSM_Error bluetooth_findchannel(GSM_StateMachine *s);
4
5/* MS Platform SDK */
6
7#ifndef __blue_w32_h
8#define __blue_w32_h
9
10 #include <pshpack1.h> // Without it compiled code hangs up BT stack
11
12 typedef ULONGLONG BTH_ADDR, *PBTH_ADDR;
13
14#define NAP_MASK ((ULONGLONG) 0xFFFF00000000)
15#define SAP_MASK ((ULONGLONG) 0x0000FFFFFFFF)
16
17#define NAP_BIT_OFFSET (8 * 4)
18#define SAP_BIT_OFFSET (0)
19
20 #define GET_NAP(_bth_addr) ((USHORT) (((_bth_addr) & NAP_MASK) >> NAP_BIT_OFFSET))
21 #define GET_SAP(_bth_addr) ((ULONG) (((_bth_addr) & SAP_MASK) >> SAP_BIT_OFFSET))
22
23#ifndef AF_BTH
24 #define AF_BTH 32
25#endif
26
27typedef struct _SOCKADDR_BTH {
28 USHORT addressFamily; // Always AF_BTH
29 BTH_ADDR btAddr; // Bluetooth device address
30 GUID serviceClassId; // [OPTIONAL] system will query SDP for port
31 ULONG port; // RFCOMM channel or L2CAP PSM
32} SOCKADDR_BTH, *PSOCKADDR_BTH;
33
34 #define BTHPROTO_RFCOMM 0x0003
35
36#ifdef BLUETOOTH_RF_SEARCHING
37
38typedef struct _SOCKET_ADDRESS {
39 LPSOCKADDR lpSockaddr ;
40 INT iSockaddrLength ;
41} SOCKET_ADDRESS, *PSOCKET_ADDRESS, FAR * LPSOCKET_ADDRESS ;
42
43typedef struct _CSADDR_INFO {
44 SOCKET_ADDRESS LocalAddr ;
45 SOCKET_ADDRESS RemoteAddr ;
46 INT iSocketType ;
47 INT iProtocol ;
48} CSADDR_INFO, *PCSADDR_INFO, FAR * LPCSADDR_INFO ;
49
50typedef struct _AFPROTOCOLS {
51 INT iAddressFamily;
52 INT iProtocol;
53} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS;
54
55typedef enum _WSAEcomparator
56{
57 COMP_EQUAL = 0,
58 COMP_NOTLESS
59} WSAECOMPARATOR, *PWSAECOMPARATOR, *LPWSAECOMPARATOR;
60
61typedef struct _WSAVersion
62{
63 DWORD dwVersion;
64 WSAECOMPARATOR ecHow;
65}WSAVERSION, *PWSAVERSION, *LPWSAVERSION;
66
67typedef struct _WSAQuerySetA
68{
69 DWORD dwSize;
70 LPSTR lpszServiceInstanceName;
71 LPGUID lpServiceClassId;
72 LPWSAVERSION lpVersion;
73 LPSTR lpszComment;
74 DWORD dwNameSpace;
75 LPGUID lpNSProviderId;
76 LPSTR lpszContext;
77 DWORD dwNumberOfProtocols;
78 LPAFPROTOCOLS lpafpProtocols;
79 LPSTR lpszQueryString;
80 DWORD dwNumberOfCsAddrs;
81 LPCSADDR_INFO lpcsaBuffer;
82 DWORD dwOutputFlags;
83 LPBLOB lpBlob;
84} WSAQUERYSET, WSAQUERYSETA, *PWSAQUERYSETA, *LPWSAQUERYSETA;
85
86DEFINE_GUID(L2CAP_PROTOCOL_UUID, 0x00000100, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB);
87
88#ifndef NS_BTH
89# define NS_BTH 16
90#endif
91
92#define LUP_CONTAINERS 0x0002
93#define LUP_RETURN_NAME 0x0010
94#define LUP_RETURN_TYPE 0x0020
95#define LUP_RETURN_COMMENT 0x0080
96#define LUP_RETURN_ADDR 0x0100
97#define LUP_RETURN_BLOB 0x0200
98 #define LUP_FLUSHCACHE 0x1000
99#define LUP_RES_SERVICE 0x8000
100
101#define WSAAPI FAR PASCAL
102
103#ifndef WINSOCK_API_LINKAGE
104#ifdef DECLSPEC_IMPORT
105#define WINSOCK_API_LINKAGE DECLSPEC_IMPORT
106#else
107#define WINSOCK_API_LINKAGE
108#endif
109#endif
110
111WINSOCK_API_LINKAGE INT WSAAPI
112WSALookupServiceBeginA(
113 IN LPWSAQUERYSETA lpqsRestrictions,
114 IN DWORD dwControlFlags,
115 OUT LPHANDLE lphLookup
116 );
117
118#define WSALookupServiceBegin WSALookupServiceBeginA
119
120WINSOCK_API_LINKAGE INT WSAAPI
121WSALookupServiceNextA(
122 IN HANDLE hLookup,
123 IN DWORD dwControlFlags,
124 IN OUT LPDWORD lpdwBufferLength,
125 OUT LPWSAQUERYSETA lpqsResults
126 );
127
128#define WSALookupServiceNext WSALookupServiceNextA
129
130WINSOCK_API_LINKAGE INT WSAAPI WSALookupServiceEnd(IN HANDLE hLookup);
131
132#define MAX_PROTOCOL_CHAIN 7
133
134typedef struct _WSAPROTOCOLCHAIN {
135 int ChainLen; /* the length of the chain, */
136 /* length = 0 means layered protocol, */
137 /* length = 1 means base protocol, */
138 /* length > 1 means protocol chain */
139 DWORD ChainEntries[MAX_PROTOCOL_CHAIN]; /* a list of dwCatalogEntryIds */
140} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;
141
142#define WSAPROTOCOL_LEN 255
143
144typedef struct _WSAPROTOCOL_INFOA {
145 DWORD dwServiceFlags1;
146 DWORD dwServiceFlags2;
147 DWORD dwServiceFlags3;
148 DWORD dwServiceFlags4;
149 DWORD dwProviderFlags;
150 GUID ProviderId;
151 DWORD dwCatalogEntryId;
152 WSAPROTOCOLCHAIN ProtocolChain;
153 int iVersion;
154 int iAddressFamily;
155 int iMaxSockAddr;
156 int iMinSockAddr;
157 int iSocketType;
158 int iProtocol;
159 int iProtocolMaxOffset;
160 int iNetworkByteOrder;
161 int iSecurityScheme;
162 DWORD dwMessageSize;
163 DWORD dwProviderReserved;
164 CHAR szProtocol[WSAPROTOCOL_LEN+1];
165} WSAPROTOCOL_INFOA, FAR * LPWSAPROTOCOL_INFOA;
166
167typedef WSAPROTOCOL_INFOA WSAPROTOCOL_INFO;
168
169#define SO_PROTOCOL_INFOA 0x2004 /* WSAPROTOCOL_INFOA structure */
170#define SO_PROTOCOL_INFO SO_PROTOCOL_INFOA
171
172WINSOCK_API_LINKAGE INT WSAAPI
173WSAAddressToStringA(
174 IN LPSOCKADDR lpsaAddress,
175 IN DWORD dwAddressLength,
176 IN LPWSAPROTOCOL_INFOA lpProtocolInfo,
177 IN OUT LPSTR lpszAddressString,
178 IN OUT LPDWORD lpdwAddressStringLength
179 );
180
181#define WSAAddressToString WSAAddressToStringA
182
183#endif
184#endif
185
186/* How should editor hadle tabs in this file? Add editor commands here.
187 * vim: noexpandtab sw=8 ts=8 sts=8:
188 */
diff --git a/gammu/emb/common/device/bluetoth/bluetoth.c b/gammu/emb/common/device/bluetoth/bluetoth.c
new file mode 100644
index 0000000..c20e04b
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluetoth.c
@@ -0,0 +1,85 @@
1/* (c) 2003-2004 by Marcin Wiacek and Marcel Holtmann and others */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_BLUETOOTHDEVICE
6#ifndef DJGPP
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <string.h>
13
14#include "../../misc/coding/coding.h"
15#include "../../gsmcomon.h"
16#include "../devfunc.h"
17#include "bluetoth.h"
18
19#ifdef GSM_ENABLE_BLUEZ
20# include "bluez.h"
21#endif
22#ifdef GSM_ENABLE_AFFIX
23# include "affix.h"
24#endif
25#ifdef WIN32
26# include "blue_w32.h"
27#endif
28
29GSM_Error bluetooth_findrfchannel(GSM_StateMachine *s)
30{
31 GSM_Error error;
32
33#ifdef BLUETOOTH_RF_SEARCHING
34 if (!mystrncasecmp(s->CurrentConfig->Connection, "bluerf", 6)) return bluetooth_findchannel(s);
35#endif
36
37 switch (s->ConnectionType) {
38 case GCT_BLUEAT:
39 return bluetooth_connect(s,1,s->CurrentConfig->Device);
40 case GCT_BLUEOBEX:
41 return bluetooth_connect(s,9,s->CurrentConfig->Device);
42 case GCT_BLUEPHONET:
43 error = bluetooth_connect(s,14,s->CurrentConfig->Device); //older Series 40 - 8910, 6310
44 if (error == ERR_NONE) return error;
45 return bluetooth_connect(s,15,s->CurrentConfig->Device); //new Series 40 - 6310i, 6230
46 default:
47 return ERR_UNKNOWN;
48 }
49}
50
51static int bluetooth_read(GSM_StateMachine *s, void *buf, size_t nbytes)
52{
53 return socket_read(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone);
54}
55
56#ifdef WIN32
57static int bluetooth_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes)
58#else
59static int bluetooth_write(GSM_StateMachine *s, void *buf, size_t nbytes)
60#endif
61{
62 return socket_write(s, buf, nbytes, s->Device.Data.BlueTooth.hPhone);
63}
64
65static GSM_Error bluetooth_close(GSM_StateMachine *s)
66{
67 return socket_close(s, s->Device.Data.BlueTooth.hPhone);
68}
69
70GSM_Device_Functions BlueToothDevice = {
71 bluetooth_findrfchannel,
72 bluetooth_close,
73 NONEFUNCTION,
74 NONEFUNCTION,
75 NONEFUNCTION,
76 bluetooth_read,
77 bluetooth_write
78};
79
80#endif
81#endif
82
83/* How should editor hadle tabs in this file? Add editor commands here.
84 * vim: noexpandtab sw=8 ts=8 sts=8:
85 */
diff --git a/gammu/emb/common/device/bluetoth/bluetoth.h b/gammu/emb/common/device/bluetoth/bluetoth.h
new file mode 100644
index 0000000..8a7fdf4
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluetoth.h
@@ -0,0 +1,15 @@
1
2#ifndef DJGPP
3#ifndef unixbluetooth_h
4#define unixbluetooth_h
5
6typedef struct {
7 int hPhone;
8} GSM_Device_BlueToothData;
9
10#endif
11#endif
12
13/* How should editor hadle tabs in this file? Add editor commands here.
14 * vim: noexpandtab sw=8 ts=8 sts=8:
15 */
diff --git a/gammu/emb/common/device/bluetoth/bluez.c b/gammu/emb/common/device/bluetoth/bluez.c
new file mode 100644
index 0000000..8a4807e
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluez.c
@@ -0,0 +1,207 @@
1/* Based on work by Marcel Holtmann and other authors of Bluez */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_BLUETOOTHDEVICE
6#ifdef GSM_ENABLE_BLUEZ
7
8#include <stdlib.h>
9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <string.h>
13#include <sys/socket.h>
14#include <sys/time.h>
15#include <unistd.h>
16#include <bluetooth/bluetooth.h>
17#include <bluetooth/rfcomm.h>
18#include <bluetooth/sdp.h>
19#include <bluetooth/sdp_lib.h>
20
21#include "../../gsmcomon.h"
22#include "../devfunc.h"
23#include "bluetoth.h"
24
25GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
26{
27 GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
28 struct sockaddr_rc laddr, raddr;
29 bdaddr_t bdaddr;
30 int fd;
31
32 smprintf(s, "Connecting to RF channel %i\n",port);
33
34 fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
35 if (fd < 0) {
36 dbgprintf("Can't create socket\n");
37 return ERR_DEVICENODRIVER;
38 }
39
40 bacpy(&laddr.rc_bdaddr, BDADDR_ANY);
41 laddr.rc_family = AF_BLUETOOTH;
42 laddr.rc_channel = 0;
43
44 if (bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
45 dbgprintf("Can't bind socket\n");
46 close(fd);
47 return ERR_DEVICEOPENERROR;
48 }
49
50 str2ba(device, &bdaddr);
51 bacpy(&raddr.rc_bdaddr, &bdaddr);
52 raddr.rc_family = AF_BLUETOOTH;
53 raddr.rc_channel = port;
54
55 if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) {
56 dbgprintf("Can't connect\n");
57 close(fd);
58 return ERR_DEVICEOPENERROR;
59 }
60
61 d->hPhone = fd;
62 return ERR_NONE;
63}
64
65#ifdef BLUETOOTH_RF_SEARCHING
66
67struct search_context {
68 char *svc;
69 uuid_t group;
70 int tree;
71 uint32_t handle;
72};
73
74static void print_service_desc(void *value, void *user)
75{
76 sdp_data_t *p = (sdp_data_t *)value;
77 int i = 0, proto = 0, *channel = (int *)user;
78
79 for (; p; p = p->next, i++) {
80 switch (p->dtd) {
81 case SDP_UUID16:
82 case SDP_UUID32:
83 case SDP_UUID128:
84 proto = 1;//sdp_uuid_to_proto(&p->val.uuid);
85 break;
86 case SDP_UINT8:
87 if (proto == RFCOMM_UUID) {
88 (*channel) = p->val.uint8;
89 return;
90 }
91 break;
92 }
93 }
94}
95
96void print_access_protos(value, user)
97{
98 sdp_list_t *protDescSeq = (sdp_list_t *)value;
99 int *channel = (int *)user;
100
101 sdp_list_foreach(protDescSeq,print_service_desc,channel);
102}
103
104static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
105{
106 sdp_session_t *sess;
107 sdp_list_t *attrid, *search, *seq, *next, *proto = 0;
108 uint32_t range = 0x0000ffff;
109 char str[20];
110 sdp_record_t *rec;
111 sdp_data_t *d;
112 bdaddr_t interface;
113 struct search_context subcontext;
114 int channel,channel2;
115
116 bacpy(&interface,BDADDR_ANY);
117
118 ba2str(bdaddr, str);
119 smprintf(s,"%s\n", str);
120
121 sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
122 if (!sess) {
123 dbgprintf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
124 return ERR_UNKNOWN;
125 }
126
127 attrid = sdp_list_append(0, &range);
128 search = sdp_list_append(0, &context->group);
129 if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
130 dbgprintf("Service Search failed: %s\n", strerror(errno));
131 sdp_close(sess);
132 return ERR_UNKNOWN;
133 }
134 sdp_list_free(attrid, 0);
135 sdp_list_free(search, 0);
136
137 channel2 = -1;
138 for (; seq; seq = next) {
139 rec = (sdp_record_t *) seq->data;
140
141 if (channel2 == -1) {
142 if (!context->tree) {
143 d = sdp_data_get(rec,SDP_ATTR_SVCNAME_PRIMARY);
144
145 if (false) {
146 channel = -1;
147 sdp_list_foreach(proto,print_access_protos,&channel);
148 //sdp_list_free(proto,(sdp_free_func_t)sdp_data_free);
149 }
150 smprintf(s,"Channel %i",channel);
151 if (d) smprintf(s," - \"%s\"",d->val.str);
152 smprintf(s,"\n");
153 if (channel2 == -1 && bluetooth_checkservicename(s, d->val.str) == ERR_NONE) {
154 channel2 = channel;
155 }
156 }
157 if (sdp_get_group_id(rec,&subcontext.group) != -1) {
158 memcpy(&subcontext, context, sizeof(struct search_context));
159 if (subcontext.group.value.uuid16 != context->group.value.uuid16) bluetooth_checkdevice(s,bdaddr,&subcontext);
160 }
161 }
162
163 next = seq->next;
164 free(seq);
165 //sdp_record_free(rec);
166 }
167 sdp_close(sess);
168
169 if (channel2 != -1) return bluetooth_connect(s, channel2, str);
170
171 return ERR_UNKNOWN;
172}
173
174GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
175{
176 inquiry_info ii[20];
177 uint8_t count = 0;
178 int i;
179 struct search_context context;
180 GSM_Error error = ERR_NOTSUPPORTED;
181
182 memset(&context, '\0', sizeof(struct search_context));
183 //sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP);
184
185 if (!strcmp(s->CurrentConfig->Device,"/dev/ttyS1")) {
186 dbgprintf("Searching for devices\n");
187 if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
188 return ERR_UNKNOWN;
189 }
190 } else {
191 count = 1;
192 str2ba(s->CurrentConfig->Device,&ii[0].bdaddr);
193 }
194 for (i=0;i<count;i++) {
195 error = bluetooth_checkdevice(s,&ii[i].bdaddr,&context);
196 if (error == ERR_NONE) return error;
197 }
198 return error;
199}
200
201#endif
202#endif
203#endif
204
205/* How should editor hadle tabs in this file? Add editor commands here.
206 * vim: noexpandtab sw=8 ts=8 sts=8:
207 */
diff --git a/gammu/emb/common/device/bluetoth/bluez.h b/gammu/emb/common/device/bluetoth/bluez.h
new file mode 100644
index 0000000..896ecbe
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluez.h
@@ -0,0 +1,3 @@
1
2GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device);
3GSM_Error bluetooth_findchannel(GSM_StateMachine *s);
diff --git a/gammu/emb/common/device/devfunc.c b/gammu/emb/common/device/devfunc.c
new file mode 100644
index 0000000..d31ebbf
--- a/dev/null
+++ b/gammu/emb/common/device/devfunc.c
@@ -0,0 +1,266 @@
1
2#include <string.h>
3#ifdef WIN32
4# include <io.h>
5#else
6# include <errno.h>
7# include <signal.h>
8#endif
9
10#include "../gsmstate.h"
11
12#ifdef GSM_ENABLE_BLUETOOTHDEVICE
13#ifdef BLUETOOTH_RF_SEARCHING
14
15GSM_Error bluetooth_checkservicename(GSM_StateMachine *s, char *name)
16{
17 if (s->ConnectionType == GCT_BLUEPHONET && strstr(name,"Nokia PC Suite")!=NULL) return ERR_NONE;
18 if (s->ConnectionType == GCT_BLUEOBEX && strstr(name,"OBEX") !=NULL) return ERR_NONE;
19 if (s->ConnectionType == GCT_BLUEAT && strstr(name,"COM 1") !=NULL) return ERR_NONE;
20 return ERR_UNKNOWN;
21}
22
23#endif
24#endif
25
26#if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE)
27
28int socket_read(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone)
29{
30 fd_set readfds;
31#ifdef WIN32
32 struct timeval timer;
33#endif
34
35 FD_ZERO(&readfds);
36 FD_SET(hPhone, &readfds);
37#ifndef WIN32
38 if (select(hPhone+1, &readfds, NULL, NULL, 0)) {
39 return(read(hPhone, buf, nbytes));
40 }
41#else
42 memset(&timer,0,sizeof(timer));
43 if (select(0, &readfds, NULL, NULL, &timer) != 0) {
44 return(recv(hPhone, buf, nbytes, 0));
45 }
46#endif
47 return 0;
48}
49
50#ifdef WIN32
51int socket_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes, int hPhone)
52#else
53int socket_write(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone)
54#endif
55{
56 int ret;
57 size_t actual = 0;
58
59 do {
60 ret = send(hPhone, buf, nbytes - actual, 0);
61 if (ret < 0) {
62 if (actual != nbytes) GSM_OSErrorInfo(s,"socket_write");
63 return actual;
64 }
65 actual += ret;
66 buf += ret;
67 } while (actual < nbytes);
68
69 return actual;
70}
71
72GSM_Error socket_close(GSM_StateMachine *s, int hPhone)
73{
74 shutdown(hPhone, 0);
75#ifdef WIN32
76 closesocket(hPhone); /*FIXME: error checking */
77#else
78 close(hPhone); /*FIXME: error checking */
79#endif
80 return ERR_NONE;
81}
82
83#endif
84
85#ifdef ENABLE_LGPL
86
87GSM_Error lock_device(const char* port, char **lock_device)
88{
89 *lock_device = 0;
90 return ERR_NONE;
91}
92
93bool unlock_device(char **lock_file)
94{
95 return true;
96}
97
98#else
99
100 #define max_buf_len 128
101 #define lock_path "/var/lock/LCK.."
102
103/* Lock the device. Allocated string with a lock name is returned
104 * in lock_device
105 */
106GSM_Error lock_device(const char* port, char **lock_device)
107{
108#ifndef WIN32
109 char *lock_file = NULL;
110 char buffer[max_buf_len];
111 const char *aux;
112 int fd, len;
113 GSM_Errorerror = ERR_NONE;
114
115 dbgprintf("Locking device\n");
116
117 aux = strrchr(port, '/');
118 /* Remove leading '/' */
119 if (aux) {
120 aux++;
121 } else {
122 /* No / in port */
123 aux = port;
124 }
125 len = strlen(aux) + strlen(lock_path);
126
127 memset(buffer, 0, sizeof(buffer));
128 lock_file = calloc(len + 1, 1);
129 if (!lock_file) {
130 dbgprintf("Out of memory error while locking device\n");
131 return ERR_MOREMEMORY;
132 }
133 /* I think we don't need to use strncpy, as we should have enough
134 * buffer due to strlen results
135 */
136 strcpy(lock_file, lock_path);
137 strcat(lock_file, aux);
138
139 /* Check for the stale lockfile.
140 * The code taken from minicom by Miquel van Smoorenburg */
141 if ((fd = open(lock_file, O_RDONLY)) >= 0) {
142 char buf[max_buf_len];
143 int pid, n = 0;
144
145 n = read(fd, buf, sizeof(buf) - 1);
146 close(fd);
147 if (n > 0) {
148 pid = -1;
149 if (n == 4)
150 /* Kermit-style lockfile. */
151 pid = *(int *)buf;
152 else {
153 /* Ascii lockfile. */
154 buf[n] = 0;
155 sscanf(buf, "%d", &pid);
156 }
157 if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
158 dbgprintf("Lockfile %s is stale. Overriding it..\n", lock_file);
159 sleep(1);
160 if (unlink(lock_file) == -1) {
161 dbgprintf("Overriding failed, please check the permissions\n");
162 dbgprintf("Cannot lock device\n");
163 error = ERR_PERMISSION;
164 goto failed;
165 }
166 } else {
167 dbgprintf("Device already locked by PID %d.\n", pid);
168 error = ERR_DEVICELOCKED;
169 goto failed;
170 }
171 }
172 /* this must not happen. because we could open the file */
173 /* no wrong permissions are set. only reason could be */
174 /* flock/lockf or a empty lockfile due to a broken binary */
175 /* which is more likely */
176 if (n == 0) {
177 dbgprintf("Unable to read lockfile %s.\n", lock_file);
178 dbgprintf("Please check for reason and remove the lockfile by hand.\n");
179 dbgprintf("Cannot lock device\n");
180 error = ERR_UNKNOWN;
181 goto failed;
182 }
183 }
184
185 /* Try to create a new file, with 0644 mode */
186 fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
187 if (fd == -1) {
188 if (errno == EEXIST) {
189 dbgprintf("Device seems to be locked by unknown process\n");
190 error = ERR_DEVICEOPENERROR;
191 } else if (errno == EACCES) {
192 dbgprintf("Please check permission on lock directory\n");
193 error = ERR_PERMISSION;
194 } else if (errno == ENOENT) {
195 dbgprintf("Cannot create lockfile %s. Please check for existence of path\n", lock_file);
196 error = ERR_UNKNOWN;
197 } else {
198 dbgprintf("Unknown error with creating lockfile %s\n", lock_file);
199 error = ERR_UNKNOWN;
200 }
201 goto failed;
202 }
203 sprintf(buffer, "%10ld gammu\n", (long)getpid());
204 write(fd, buffer, strlen(buffer));
205 close(fd);
206 *lock_device = lock_file;
207 return ERR_NONE;
208failed:
209 free(lock_file);
210 *lock_device = 0;
211 return error;
212#else
213 *lock_device = 0;
214 return ERR_NONE;
215#endif
216}
217
218/* Removes lock and frees memory */
219bool unlock_device(char **lock_file)
220{
221#ifndef WIN32
222 int err;
223
224 if (!lock_file) {
225 dbgprintf("Cannot unlock device\n");
226 return false;
227 }
228 err = unlink(*lock_file);
229 free(*lock_file);
230 *lock_file = NULL;
231 return (err + 1);
232#else
233 return true;
234#endif
235}
236
237#endif
238
239int FindSerialSpeed(char *buffer)
240{
241 switch (atoi(buffer)) {
242 case 50 : return 50;
243 case 75 : return 75;
244 case 110: return 110;
245 case 134: return 134;
246 case 150: return 150;
247 case 200: return 200;
248 case 300: return 300;
249 case 600: return 600;
250 case 1200: return 1200;
251 case 1800: return 1800;
252 case 2400: return 2400;
253 case 4800: return 4800;
254 case 9600: return 9600;
255 case 19200: return 19200;
256 case 38400: return 38400;
257 case 57600: return 57600;
258 case 115200: return 115200;
259 case 230400: return 230400;
260 default : return 0;
261 }
262}
263
264/* How should editor hadle tabs in this file? Add editor commands here.
265 * vim: noexpandtab sw=8 ts=8 sts=8:
266 */
diff --git a/gammu/emb/common/device/devfunc.h b/gammu/emb/common/device/devfunc.h
new file mode 100644
index 0000000..6e8fb62
--- a/dev/null
+++ b/gammu/emb/common/device/devfunc.h
@@ -0,0 +1,38 @@
1
2#ifndef device_functions_h
3#define device_functions_h
4
5#include "../gsmstate.h"
6
7#ifdef GSM_ENABLE_BLUETOOTHDEVICE
8#ifdef BLUETOOTH_RF_SEARCHING
9
10GSM_Error bluetooth_checkservicename(GSM_StateMachine *s, char *name);
11
12#endif
13#endif
14
15#if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE)
16
17int socket_read(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone);
18
19#ifdef WIN32
20int socket_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes, int hPhone);
21#else
22int socket_write(GSM_StateMachine *s, void *buf, size_t nbytes, int hPhone);
23#endif
24
25GSM_Error socket_close(GSM_StateMachine *s, int hPhone);
26
27#endif
28
29 GSM_Error lock_device(const char* port, char **lock_device);
30 bool unlock_device(char **lock_file);
31
32int FindSerialSpeed(char *buffer);
33
34#endif
35
36/* How should editor hadle tabs in this file? Add editor commands here.
37 * vim: noexpandtab sw=8 ts=8 sts=8:
38 */
diff --git a/gammu/emb/common/device/irda/irda.c b/gammu/emb/common/device/irda/irda.c
new file mode 100644
index 0000000..fef50ac
--- a/dev/null
+++ b/gammu/emb/common/device/irda/irda.c
@@ -0,0 +1,187 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Ralf Thelen and MyGnokii */
3/* based on some work from Gnokii and MSDN */
4
5/* You have to include wsock32.lib library to MS VC project to compile it */
6
7#include "../../gsmstate.h"
8
9#ifdef GSM_ENABLE_IRDADEVICE
10#ifndef DJGPP
11
12#ifndef WIN32
13# include <stdlib.h>
14# include <unistd.h>
15# include <stdio.h>
16# include <fcntl.h>
17# include <errno.h>
18# include <string.h>
19# include <sys/time.h>
20# include <sys/poll.h>
21# include <sys/socket.h>
22# include <sys/ioctl.h>
23#else
24# include <windows.h>
25# include <io.h>
26#endif
27
28#include "../../gsmcomon.h"
29#include "../devfunc.h"
30#include "irda.h"
31
32static bool irda_discover_device(GSM_StateMachine *state)
33{
34 GSM_Device_IrdaData *d = &state->Device.Data.Irda;
35 struct irda_device_list*list;
36 unsigned char *buf;
37 unsigned int sec;
38 int s, z, len, fd, i;
39 GSM_DateTime Date;
40 bool founddevice = false;
41#ifdef WIN32
42 int index;
43#endif
44
45 fd = socket(AF_IRDA, SOCK_STREAM, 0);
46
47 /* can handle maximally 10 devices during discovering */
48 len = sizeof(struct irda_device_list) + sizeof(struct irda_device_info) * 10;
49 buf = malloc(len);
50 list = (struct irda_device_list *)buf;
51
52 /* Trying to find device during 2 seconds */
53 for (z=0;z<2;z++) {
54 GSM_GetCurrentDateTime (&Date);
55 sec = Date.Second;
56 while (sec==Date.Second) {
57 s = len;
58 memset(buf, 0, s);
59
60 if (getsockopt(fd, SOL_IRLMP, IRLMP_ENUMDEVICES, buf, &s) == 0) {
61 for (i = 0; i < (int)list->numDevice; i++) {
62 dbgprintf("Irda: found device \"%s\" (address %x) - ",list->Device[i].irdaDeviceName,list->Device[i].irdaDeviceID);
63 if (strcmp(GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number,"") != 0) {
64 founddevice = true;
65 /* Model AUTO */
66 if (state->CurrentConfig->Model[0]==0) strcpy(state->Phone.Data.Model,GetModelData(NULL,NULL,list->Device[i].irdaDeviceName)->number);
67 state->Phone.Data.ModelInfo = GetModelData(NULL,state->Phone.Data.Model,NULL);
68 }
69 if (founddevice) {
70 dbgprintf("correct\n");
71#ifdef WIN32
72 for(index=0; index <= 3; index++)
73 d->peer.irdaDeviceID[index] = list->Device[i].irdaDeviceID[index];
74#else
75 d->peer.irdaDeviceID = list->Device[i].irdaDeviceID;
76#endif
77 break;
78 }
79 dbgprintf("\n");
80 }
81 }
82 if (founddevice) break;
83 my_sleep(10);
84 GSM_GetCurrentDateTime(&Date);
85 }
86 if (founddevice) break;
87 }
88 free(buf);
89 close(fd);
90
91 return founddevice;
92}
93
94static GSM_Error irda_open (GSM_StateMachine *s)
95{
96 GSM_Device_IrdaData *d = &s->Device.Data.Irda;
97 int fd = -1;
98#ifdef WIN32
99 int Enable9WireMode = 1;
100 WSADATA wsaData;
101
102 WSAStartup(MAKEWORD(1,1), &wsaData);
103#else
104 if (s->ConnectionType == GCT_IRDAAT) return ERR_SOURCENOTAVAILABLE;
105#endif
106
107 /* discovering devices */
108 if (irda_discover_device(s)==false) return ERR_TIMEOUT;
109
110 /* Creating socket */
111 fd = socket(AF_IRDA, SOCK_STREAM, 0);
112
113 d->peer.irdaAddressFamily = AF_IRDA;
114#ifndef WIN32
115 d->peer.sir_lsap_sel = LSAP_ANY;
116#endif
117 switch (s->ConnectionType) {
118 case GCT_IRDAAT:
119 strcpy(d->peer.irdaServiceName, "IrDA:IrCOMM");
120
121#ifdef WIN32
122 if (setsockopt(fd, SOL_IRLMP, IRLMP_9WIRE_MODE, (const char *) &Enable9WireMode,
123 sizeof(int))==SOCKET_ERROR) return ERR_UNKNOWN;
124#endif
125 break;
126 case GCT_IRDAPHONET:
127 strcpy(d->peer.irdaServiceName, "Nokia:PhoNet");
128 break;
129 case GCT_IRDAOBEX:
130 /* IrDA:OBEX not supported by N3650 */
131 // strcpy(d->peer.irdaServiceName, "IrDA:OBEX");
132
133 strcpy(d->peer.irdaServiceName, "OBEX");
134
135 /* Alternative server is "OBEX:IrXfer" */
136 break;
137 default:
138 return ERR_UNKNOWN;
139 }
140
141 /* Connecting to service */
142 if (connect(fd, (struct sockaddr *)&d->peer, sizeof(d->peer))) {
143 dbgprintf("Can't connect to service %s\n",d->peer.irdaServiceName);
144 close(fd);
145 return ERR_NOTSUPPORTED;
146 }
147
148 d->hPhone=fd;
149
150 return ERR_NONE;
151}
152
153static int irda_read(GSM_StateMachine *s, void *buf, size_t nbytes)
154{
155 return socket_read(s, buf, nbytes, s->Device.Data.Irda.hPhone);
156}
157
158#ifdef WIN32
159static int irda_write(GSM_StateMachine *s, unsigned char *buf, size_t nbytes)
160#else
161static int irda_write(GSM_StateMachine *s, void *buf, size_t nbytes)
162#endif
163{
164 return socket_write(s, buf, nbytes, s->Device.Data.Irda.hPhone);
165}
166
167static GSM_Error irda_close(GSM_StateMachine *s)
168{
169 return socket_close(s, s->Device.Data.Irda.hPhone);
170}
171
172GSM_Device_Functions IrdaDevice = {
173 irda_open,
174 irda_close,
175 NONEFUNCTION,
176 NONEFUNCTION,
177 NONEFUNCTION,
178 irda_read,
179 irda_write
180};
181
182#endif
183#endif
184
185/* How should editor hadle tabs in this file? Add editor commands here.
186 * vim: noexpandtab sw=8 ts=8 sts=8:
187 */
diff --git a/gammu/emb/common/device/irda/irda.h b/gammu/emb/common/device/irda/irda.h
new file mode 100644
index 0000000..455e6af
--- a/dev/null
+++ b/gammu/emb/common/device/irda/irda.h
@@ -0,0 +1,22 @@
1
2#ifndef DJGPP
3#ifndef unixirda_h
4#define unixirda_h
5
6#ifndef WIN32
7# include "irda_unx.h"
8#else
9# include "irda_w32.h"
10#endif
11
12typedef struct {
13 int hPhone;
14 struct sockaddr_irdapeer;
15} GSM_Device_IrdaData;
16
17#endif
18#endif
19
20/* How should editor hadle tabs in this file? Add editor commands here.
21 * vim: noexpandtab sw=8 ts=8 sts=8:
22 */
diff --git a/gammu/emb/common/device/irda/irda_unx.h b/gammu/emb/common/device/irda/irda_unx.h
new file mode 100644
index 0000000..8dbcb97
--- a/dev/null
+++ b/gammu/emb/common/device/irda/irda_unx.h
@@ -0,0 +1,61 @@
1/* part of irda.h available in Linux kernel source */
2
3/*********************************************************************
4 *
5 * Filename: irda.h
6 * Version:
7 * Description:
8 * Status: Experimental.
9 * Author: Dag Brattli <dagb@cs.uit.no>
10 * Created at: Mon Mar 8 14:06:12 1999
11 * Modified at: Sat Dec 25 16:06:42 1999
12 * Modified by: Dag Brattli <dagb@cs.uit.no>
13 *
14 * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of
19 * the License, or (at your option) any later version.
20 *
21 * Neither Dag Brattli nor University of Tromsø admit liability nor
22 * provide warranty for any of this software. This material is
23 * provided "AS-IS" and at no charge.
24 *
25 ********************************************************************/
26
27#ifndef __irda_unx_h
28#define __irda_unx_h
29
30#include <sys/types.h>
31#include <sys/socket.h>
32
33 #define SOL_IRLMP 266 /* Same as SOL_IRDA for now */
34 #define IRLMP_ENUMDEVICES 1 /* Return discovery log */
35#define LSAP_ANY 0xff
36
37struct sockaddr_irda {
38 sa_family_t irdaAddressFamily;/* AF_IRDA */
39 u_int8_t sir_lsap_sel; /* LSAP selector */
40 u_int32_t irdaDeviceID; /* Device address */
41 char irdaServiceName[25]; /* Usually <service>:IrDA:TinyTP */
42};
43
44struct irda_device_info {
45 u_int32_t saddr; /* Address of local interface */
46 u_int32_t irdaDeviceID; /* Address of remote device */
47 char irdaDeviceName[22]; /* Description */
48 u_int8_t charset; /* Charset used for description */
49 u_int8_t hints[2]; /* Hint bits */
50};
51
52struct irda_device_list {
53 u_int32_t numDevice;
54 struct irda_device_info Device[1];
55};
56
57#endif
58
59/* How should editor hadle tabs in this file? Add editor commands here.
60 * vim: noexpandtab sw=8 ts=8 sts=8:
61 */
diff --git a/gammu/emb/common/device/irda/irda_w32.h b/gammu/emb/common/device/irda/irda_w32.h
new file mode 100644
index 0000000..daffa37
--- a/dev/null
+++ b/gammu/emb/common/device/irda/irda_w32.h
@@ -0,0 +1,35 @@
1
2/* MS Platform SDK */
3
4#ifndef __irda_w32_h
5#define __irda_w32_h
6
7 #define AF_IRDA 26
8 #define SOL_IRLMP 0x00FF
9 #define IRLMP_ENUMDEVICES 0x00000010
10 #define IRLMP_9WIRE_MODE 0x00000016
11
12struct sockaddr_irda {
13 unsigned short irdaAddressFamily;
14 unsigned char irdaDeviceID[4];
15 char irdaServiceName[25];
16};
17
18struct irda_device_info {
19 unsigned char irdaDeviceID[4];
20 char irdaDeviceName[22];
21 unsigned char irdaDeviceHints1;
22 unsigned char irdaDeviceHints2;
23 unsigned char irdaCharSet;
24};
25
26struct irda_device_list {
27 ULONG numDevice;
28 struct irda_device_info Device[1];
29};
30
31#endif
32
33/* How should editor hadle tabs in this file? Add editor commands here.
34 * vim: noexpandtab sw=8 ts=8 sts=8:
35 */
diff --git a/gammu/emb/common/device/serial/ser_djg.c b/gammu/emb/common/device/serial/ser_djg.c
new file mode 100644
index 0000000..ac9d7c8
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_djg.c
@@ -0,0 +1,74 @@
1
2#include "../../gsmstate.h"
3
4#ifdef GSM_ENABLE_SERIALDEVICE
5#ifdef DJGPP
6
7#include "../../gsmcomon.h"
8#include "ser_djg.h"
9
10static GSM_Error serial_close(GSM_StateMachine *s)
11{
12 GSM_Device_SerialData *d = &s->Device.Data.Serial;
13
14 return ERR_NONE;
15}
16
17static GSM_Error serial_open (GSM_StateMachine *s)
18{
19 GSM_Device_SerialData *d = &s->Device.Data.Serial;
20
21 return ERR_NONE;
22}
23
24static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
25{
26 GSM_Device_SerialData *d = &s->Device.Data.Serial;
27
28 return ERR_NONE;
29}
30
31static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
32{
33 GSM_Device_SerialData *d = &s->Device.Data.Serial;
34
35 return ERR_NONE;
36}
37
38static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
39{
40 GSM_Device_SerialData *d = &s->Device.Data.Serial;
41
42 return ERR_NONE;
43}
44
45static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
46{
47 GSM_Device_SerialData *d = &s->Device.Data.Serial;
48
49 return 0;
50}
51
52static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
53{
54 GSM_Device_SerialData *d = &s->Device.Data.Serial;
55
56 return 0;
57}
58
59GSM_Device_Functions SerialDevice = {
60 serial_open,
61 serial_close,
62 serial_setparity,
63 serial_setdtrrts,
64 serial_setspeed,
65 serial_read,
66 serial_write
67};
68
69#endif
70#endif
71
72/* How should editor hadle tabs in this file? Add editor commands here.
73 * vim: noexpandtab sw=8 ts=8 sts=8:
74 */
diff --git a/gammu/emb/common/device/serial/ser_djg.h b/gammu/emb/common/device/serial/ser_djg.h
new file mode 100644
index 0000000..b35b282
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_djg.h
@@ -0,0 +1,15 @@
1
2#ifdef DJGPP
3#ifndef djgppserial_h
4#define djgppserial_h
5
6typedef struct {
7 int hPhone;
8} GSM_Device_SerialData;
9
10#endif
11#endif
12
13/* How should editor hadle tabs in this file? Add editor commands here.
14 * vim: noexpandtab sw=8 ts=8 sts=8:
15 */
diff --git a/gammu/emb/common/device/serial/ser_unx.c b/gammu/emb/common/device/serial/ser_unx.c
new file mode 100644
index 0000000..2a87b11
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_unx.c
@@ -0,0 +1,291 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* locking device and settings all speeds by Michal Cihar */
3
4#include "../../gsmstate.h"
5
6#ifdef GSM_ENABLE_SERIALDEVICE
7#ifndef WIN32
8#ifndef DJGPP
9
10#include <sys/file.h>
11#include <sys/time.h>
12#include <string.h>
13#include <termios.h>
14#include <errno.h>
15
16#include "../../gsmcomon.h"
17#include "ser_unx.h"
18
19static GSM_Error serial_close(GSM_StateMachine *s)
20{
21 GSM_Device_SerialData *d = &s->Device.Data.Serial;
22
23 /* Restores old settings */
24 tcsetattr(d->hPhone, TCSANOW, &d->old_settings);
25
26 /* Closes device */
27 close(d->hPhone);
28
29 return ERR_NONE;
30}
31
32#ifndef O_NONBLOCK
33# define O_NONBLOCK 0
34#endif
35
36static GSM_Error serial_open (GSM_StateMachine *s)
37{
38 GSM_Device_SerialData *d = &s->Device.Data.Serial;
39 struct termios t;
40 int i;
41
42 /* O_NONBLOCK MUST is required to avoid waiting for DCD */
43 d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK);
44 if (d->hPhone < 0) {
45 i = errno;
46 GSM_OSErrorInfo(s,"open in serial_open");
47 if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory
48 if (i == 13) return ERR_DEVICENOPERMISSION;//permission denied
49 return ERR_DEVICEOPENERROR;
50 }
51
52#ifdef TIOCEXCL
53 /* open() calls from other applications shall fail now */
54 ioctl(d->hPhone, TIOCEXCL, (char *) 0);
55#endif
56
57 if (tcgetattr(d->hPhone, &d->old_settings) == -1) {
58 close(d->hPhone);
59 GSM_OSErrorInfo(s,"tcgetattr in serial_open");
60 return ERR_DEVICEREADERROR;
61 }
62
63 if (tcflush(d->hPhone, TCIOFLUSH) == -1) {
64 serial_close(s);
65 GSM_OSErrorInfo(s,"tcflush in serial_open");
66 return ERR_DEVICEOPENERROR;
67 }
68
69 memcpy(&t, &d->old_settings, sizeof(struct termios));
70
71 /* Opening without parity */
72 t.c_iflag = IGNPAR;
73 t.c_oflag = 0;
74 /* disconnect line, 8 bits, enable receiver,
75 * ignore modem lines,lower modem line after disconnect
76 */
77 t.c_cflag = B0 | CS8 | CREAD | CLOCAL | HUPCL;
78 /* enable hardware (RTS/CTS) flow control (NON POSIX) */
79 /* t.c_cflag |= CRTSCTS; */
80 t.c_lflag = 0;
81 t.c_cc[VMIN] = 1;
82 t.c_cc[VTIME] = 0;
83
84 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
85 serial_close(s);
86 GSM_OSErrorInfo(s,"tcsetattr in serial_open");
87 return ERR_DEVICEOPENERROR;
88 }
89
90 /* Making file descriptor asynchronous. */
91 if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) {
92 serial_close(s);
93 GSM_OSErrorInfo(s,"fcntl in serial_open");
94 return ERR_DEVICEOPENERROR;
95 }
96
97 return ERR_NONE;
98}
99
100static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
101{
102 GSM_Device_SerialData *d = &s->Device.Data.Serial;
103 struct termios t;
104
105 if (tcgetattr(d->hPhone, &t)) {
106 GSM_OSErrorInfo(s,"tcgetattr in serial_setparity");
107 return ERR_DEVICEREADERROR;
108 }
109
110 if (parity) {
111 t.c_cflag |= (PARENB | PARODD);
112 t.c_iflag = 0;
113 } else {
114 t.c_iflag = IGNPAR;
115 }
116
117 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){
118 serial_close(s);
119 GSM_OSErrorInfo(s,"tcsetattr in serial_setparity");
120 return ERR_DEVICEPARITYERROR;
121 }
122
123 return ERR_NONE;
124}
125
126static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
127{
128 GSM_Device_SerialData *d = &s->Device.Data.Serial;
129 struct termios t;
130 unsigned int flags;
131
132 if (tcgetattr(d->hPhone, &t)) {
133 GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts");
134 return ERR_DEVICEREADERROR;
135 }
136
137#ifdef CRTSCTS
138 /* Disabling hardware flow control */
139 t.c_cflag &= ~CRTSCTS;
140#endif
141
142 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
143 serial_close(s);
144 GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts");
145 return ERR_DEVICEDTRRTSERROR;
146 }
147
148 flags = TIOCM_DTR;
149 if (dtr) {
150 ioctl(d->hPhone, TIOCMBIS, &flags);
151 } else {
152 ioctl(d->hPhone, TIOCMBIC, &flags);
153 }
154
155 flags = TIOCM_RTS;
156 if (rts) {
157 ioctl(d->hPhone, TIOCMBIS, &flags);
158 } else {
159 ioctl(d->hPhone, TIOCMBIC, &flags);
160 }
161
162 flags = 0;
163 ioctl(d->hPhone, TIOCMGET, &flags);
164
165 dbgprintf("Serial device:");
166 dbgprintf(" DTR is %s", flags&TIOCM_DTR?"up":"down");
167 dbgprintf(", RTS is %s", flags&TIOCM_RTS?"up":"down");
168 dbgprintf(", CAR is %s", flags&TIOCM_CAR?"up":"down");
169 dbgprintf(", CTS is %s\n", flags&TIOCM_CTS?"up":"down");
170 if (((flags&TIOCM_DTR)==TIOCM_DTR) != dtr) return ERR_DEVICEDTRRTSERROR;
171 if (((flags&TIOCM_RTS)==TIOCM_RTS) != rts) return ERR_DEVICEDTRRTSERROR;
172
173 return ERR_NONE;
174}
175
176static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
177{
178 GSM_Device_SerialData *d = &s->Device.Data.Serial;
179 struct termios t;
180 int speed2 = B19200;
181
182 if (tcgetattr(d->hPhone, &t)) {
183 GSM_OSErrorInfo(s,"tcgetattr in serial_setspeed");
184 return ERR_DEVICEREADERROR;
185 }
186
187 smprintf(s, "Setting speed to %d\n", speed);
188
189 switch (speed) {
190 case 50: speed2 = B50; break;
191 case 75: speed2 = B75; break;
192 case 110: speed2 = B110; break;
193 case 134: speed2 = B134; break;
194 case 150: speed2 = B150; break;
195 case 200: speed2 = B200; break;
196 case 300: speed2 = B300; break;
197 case 600: speed2 = B600; break;
198 case 1200: speed2 = B1200; break;
199 case 1800: speed2 = B1800; break;
200 case 2400: speed2 = B2400; break;
201 case 4800: speed2 = B4800; break;
202 case 9600: speed2 = B9600; break;
203 case 19200: speed2 = B19200;break;
204 case 38400: speed2 = B38400;break;
205 case 57600: speed2 = B57600;break;
206 case 115200: speed2 = B115200;break;
207 case 230400: speed2 = B230400;break;
208 case 460800: speed2 = B460800;break;
209 case 500000: speed2 = B500000;break;
210 case 576000: speed2 = B576000;break;
211 case 921600: speed2 = B921600;break;
212 case 1000000: speed2 = B1000000;break;
213 case 1152000: speed2 = B1152000;break;
214 case 1500000: speed2 = B1500000;break;
215 case 2000000: speed2 = B2000000;break;
216 case 2500000: speed2 = B2500000;break;
217 case 3000000: speed2 = B3000000;break;
218 case 3500000: speed2 = B3500000;break;
219 case 4000000: speed2 = B4000000; break;
220 }
221
222 /* This should work on all systems because it is done according to POSIX */
223 cfsetispeed(&t, speed2);
224 cfsetospeed(&t, speed2);
225
226 if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) {
227 serial_close(s);
228 GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed");
229 return ERR_DEVICECHANGESPEEDERROR;
230 }
231
232 return ERR_NONE;
233}
234
235static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
236{
237 GSM_Device_SerialData *d = &s->Device.Data.Serial;
238 struct timeval timeout2;
239 fd_set readfds;
240 int actual = 0;
241
242 FD_ZERO(&readfds);
243 FD_SET(d->hPhone, &readfds);
244
245 timeout2.tv_sec = 0;
246 timeout2.tv_usec = 1;
247
248 if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) {
249 actual = read(d->hPhone, buf, nbytes);
250 if (actual == -1) GSM_OSErrorInfo(s,"serial_read");
251 }
252 return actual;
253}
254
255static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
256{
257 GSM_Device_SerialData *d = &s->Device.Data.Serial;
258 int ret;
259 size_t actual = 0;
260
261 do {
262 ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual);
263 if (ret < 0 && errno == EAGAIN) continue;
264 if (ret < 0) {
265 if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write");
266 return actual;
267 }
268 actual += ret;
269 buf += ret;
270 if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1);
271 } while (actual < nbytes);
272 return actual;
273}
274
275GSM_Device_Functions SerialDevice = {
276 serial_open,
277 serial_close,
278 serial_setparity,
279 serial_setdtrrts,
280 serial_setspeed,
281 serial_read,
282 serial_write
283};
284
285#endif
286#endif
287#endif
288
289/* How should editor hadle tabs in this file? Add editor commands here.
290 * vim: noexpandtab sw=8 ts=8 sts=8:
291 */
diff --git a/gammu/emb/common/device/serial/ser_unx.h b/gammu/emb/common/device/serial/ser_unx.h
new file mode 100644
index 0000000..ca8fe5a
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_unx.h
@@ -0,0 +1,22 @@
1
2#ifndef WIN32
3#ifndef DJGPP
4#ifndef unixserial_h
5#define unixserial_h
6
7#include <fcntl.h>
8#include <sys/ioctl.h>
9#include <termios.h>
10
11typedef struct {
12 int hPhone;
13 struct termios old_settings;
14} GSM_Device_SerialData;
15
16#endif
17#endif
18#endif
19
20/* How should editor hadle tabs in this file? Add editor commands here.
21 * vim: noexpandtab sw=8 ts=8 sts=8:
22 */
diff --git a/gammu/emb/common/device/serial/ser_w32.c b/gammu/emb/common/device/serial/ser_w32.c
new file mode 100644
index 0000000..9fa0135
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_w32.c
@@ -0,0 +1,340 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* based on some work from Gnokii, MSDN and others */
3
4#include "../../gsmstate.h"
5
6#ifdef GSM_ENABLE_SERIALDEVICE
7#ifdef WIN32
8
9#include <windows.h>
10#include <string.h>
11#include <stdio.h>
12#include <io.h>
13#include <memory.h>
14
15#include "../../gsmcomon.h"
16#include "ser_w32.h"
17
18static GSM_Error serial_close(GSM_StateMachine *s)
19{
20 GSM_Device_SerialData *d = &s->Device.Data.Serial;
21
22 /* Disables all monitored events for device */
23 SetCommMask(d->hPhone, 0);
24
25 /* Discards all characters from input/output buffer and terminates
26 * pending read/write operations
27 */
28 PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
29 PURGE_TXCLEAR | PURGE_RXCLEAR);
30
31 /* Clears the DTR (data-terminal-ready) signal */
32 EscapeCommFunction(d->hPhone, CLRDTR);
33
34 /* Restores old settings */
35 if (SetCommState(d->hPhone, &d->old_settings)==0) {
36 GSM_OSErrorInfo(s, "SetCommState in serial_close");
37 }
38
39 /* Closes device */
40 if (CloseHandle(d->hPhone)==0) {
41 GSM_OSErrorInfo(s, "CloseHandle in serial_close");
42 }
43
44 return ERR_NONE;
45}
46
47static GSM_Error serial_open (GSM_StateMachine *s)
48{
49 GSM_Device_SerialData *d = &s->Device.Data.Serial;
50 DCB dcb;
51 unsigned char DeviceName[80],DeviceName2[80];
52 int i;
53#ifdef GSM_ENABLE_FBUS2DKU5
54 HKEY hKey;
55 DWORD DeviceNameLen, KeyNameLen;
56 unsigned char KeyName[100];
57#endif
58
59 strcpy(DeviceName2,s->CurrentConfig->Device);
60
61#ifdef GSM_ENABLE_FBUS2DKU5
62 if (s->ConnectionType == GCT_FBUS2DKU5) {
63 smprintf(s,"Reading DKU5 device\n");
64 DeviceName2[0] = 0;
65 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
66 smprintf(s,"Error opening key\n");
67 return ERR_DEVICENOTWORK;
68 }
69 i = 0;
70 while(1) {
71 DeviceNameLen = 80;
72 KeyNameLen = 100;
73 if (RegEnumValue(hKey,i,KeyName,&KeyNameLen,NULL,NULL,DeviceName2,&DeviceNameLen) != ERROR_SUCCESS) {
74 smprintf(s,"Error reading key value\n");
75 return ERR_DEVICENOTWORK;
76 }
77 // smprintf(s,"Key name is %s, value is %s\n",KeyName,DeviceName2);
78 if (!strncmp(KeyName,"\\Device\\AtmelVirtualPort",24)) break;
79 i++;
80 }
81 RegCloseKey(hKey);
82 if (strlen(DeviceName2) == 0) return ERR_DEVICENOTWORK;
83 smprintf(s,"DKU5 device is \"%s\"\n",DeviceName2);
84 //nodriver
85 }
86#endif
87
88 if ((s->ConnectionType == GCT_FBUS2DKU5) ||
89 (!strncmp(DeviceName2,"com",3) && strlen(DeviceName2)>3)) {
90 sprintf(DeviceName,"\\\\.\\COM%i",atoi(DeviceName2+3));
91 } else {
92 strcpy(DeviceName,DeviceName2);
93 }
94
95 smprintf(s,"Device is %s\n",DeviceName);
96
97 /* Allows for reading/writing, no device sharing */
98 d->hPhone = CreateFile(DeviceName,
99 GENERIC_READ | GENERIC_WRITE,
100 0,
101 0,
102 OPEN_EXISTING,
103 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
104 NULL);
105
106 if (d->hPhone == INVALID_HANDLE_VALUE) {
107 i = GetLastError();
108 GSM_OSErrorInfo(s, "CreateFile in serial_open");
109 if (i == 2) return ERR_DEVICENOTWORK; //can't find specified file
110 if (i == 5) return ERR_DEVICEBUSY; //access denied
111 if (i == 31) return ERR_DEVICENOTWORK; //attached device not working
112 if (i == 123) return ERR_DEVICENOTEXIST;
113 return ERR_DEVICEOPENERROR;
114 }
115
116 d->old_settings.DCBlength = sizeof(DCB);
117 if (GetCommState(d->hPhone, &d->old_settings)==0) {
118 GSM_OSErrorInfo(s, "ReadDevice in serial_open");
119 return ERR_DEVICEREADERROR;
120 }
121
122 /* When char will be received, we will receive notifications */
123 SetCommMask(d->hPhone, EV_RXCHAR);
124
125 /* Sets size for input/output buffer */
126 SetupComm(d->hPhone, 4096, 4096);
127
128 /* Discards all characters from input/output buffer and terminates
129 * pending read/write operations
130 */
131 PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
132 PURGE_TXCLEAR | PURGE_RXCLEAR);
133
134 memcpy(&dcb, &d->old_settings, sizeof(DCB));
135
136 dcb.ByteSize = 8;
137 dcb.Parity = NOPARITY;
138 dcb.StopBits = ONESTOPBIT;
139
140 /* No Xon/Xof flow control */
141 // dcb.fOutX = false;
142 // dcb.fInX = false;
143
144 /* Hardware flow control */
145 //dcb.fOutxDsrFlow = true;
146 //dcb.fOutxCtsFlow = true;
147 //dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
148 //dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
149
150 /* Initialise the port settings */
151 if (SetCommState(d->hPhone, &dcb)==0) {
152 GSM_OSErrorInfo(s, "WriteDevice in serial_open");
153 return ERR_DEVICEOPENERROR;
154 }
155
156 return ERR_NONE;
157}
158
159static GSM_Error serial_setparity (GSM_StateMachine *s, bool parity)
160{
161 DCB dcb;
162 GSM_Device_SerialData *d = &s->Device.Data.Serial;
163
164 dcb.DCBlength = sizeof(DCB);
165 if (GetCommState(d->hPhone, &dcb)==0) {
166 GSM_OSErrorInfo(s, "ReadDevice in serial_setparity");
167 return ERR_DEVICEREADERROR;
168 }
169
170 if (parity) {
171 dcb.Parity = ODDPARITY;
172 } else {
173 dcb.Parity = NOPARITY;
174 }
175
176 if (SetCommState(d->hPhone, &dcb)==0) {
177 GSM_OSErrorInfo(s, "WriteDevice in serial_setparity");
178 return ERR_DEVICEPARITYERROR;
179 }
180
181 return ERR_NONE;
182}
183
184static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
185{
186 DCB dcb;
187 GSM_Device_SerialData *d = &s->Device.Data.Serial;
188
189 dcb.DCBlength = sizeof(DCB);
190 if (GetCommState(d->hPhone, &dcb)==0) {
191 GSM_OSErrorInfo(s, "ReadDevice in serial_setdtrrts");
192 return ERR_DEVICEREADERROR;
193 }
194
195 dcb.fOutxDsrFlow = 0;
196 dcb.fDtrControl = DTR_CONTROL_DISABLE;
197 if (dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE;
198
199 dcb.fOutxCtsFlow = 0;
200 dcb.fRtsControl = RTS_CONTROL_DISABLE;
201 if (rts) dcb.fRtsControl = RTS_CONTROL_ENABLE;
202
203 /* no software (Xon/Xof) flow control */
204 dcb.fInX = dcb.fOutX = 0;
205
206 if (SetCommState(d->hPhone, &dcb)==0) {
207 GSM_OSErrorInfo(s, "WriteDevice in serial_setdtrrts");
208 return ERR_DEVICEDTRRTSERROR;
209 }
210
211 /* the rest of function checks, if setting was really done */
212
213 dcb.DCBlength = sizeof(DCB);
214 GetCommState(d->hPhone, &dcb);
215
216 dbgprintf("Serial device:");
217 dbgprintf(" DTR is ");
218 switch (dcb.fDtrControl) {
219 case DTR_CONTROL_ENABLE : dbgprintf("up"); break;
220 case DTR_CONTROL_DISABLE : dbgprintf("down"); break;
221 case DTR_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
222 }
223 dbgprintf(", RTS is ");
224 switch (dcb.fRtsControl) {
225 case RTS_CONTROL_ENABLE : dbgprintf("up"); break;
226 case RTS_CONTROL_DISABLE : dbgprintf("down"); break;
227 case RTS_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
228 case RTS_CONTROL_TOGGLE : dbgprintf("toggle"); break;
229 }
230 dbgprintf("\n");
231 if ( dtr && dcb.fDtrControl != DTR_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
232 if (!dtr && dcb.fDtrControl != DTR_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
233 if ( rts && dcb.fRtsControl != RTS_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
234 if (!rts && dcb.fRtsControl != RTS_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
235
236 return ERR_NONE;
237}
238
239static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
240{
241 DCB dcb;
242 GSM_Device_SerialData *d = &s->Device.Data.Serial;
243
244 dcb.DCBlength = sizeof(DCB);
245 if (GetCommState(d->hPhone, &dcb)==0) {
246 GSM_OSErrorInfo(s, "ReadDevice in serial_setspeed");
247 return ERR_DEVICEREADERROR;
248 }
249
250 dcb.BaudRate = speed;
251
252 if (SetCommState(d->hPhone, &dcb)==0) {
253 GSM_OSErrorInfo(s, "WriteDevice in serial_setspeed");
254 return ERR_DEVICECHANGESPEEDERROR;
255 }
256
257 return ERR_NONE;
258}
259
260static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
261{
262 COMSTAT ComStat;
263 DWORD ErrorFlags, Length;
264 GSM_Device_SerialData *d = &s->Device.Data.Serial;
265
266 /* Gets information about a communications error and
267 * current status of device
268 */
269 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
270 Length = ComStat.cbInQue;
271
272 /* Nothing to read */
273 if (Length <= 0) return Length;
274
275 /* Read without problems */
276 if (ReadFile(d->hPhone, buf, Length, &Length, &d->osRead)) return Length;
277
278 if (GetLastError() != ERROR_IO_PENDING) {
279 GSM_OSErrorInfo(s, "serial_read1");
280 Length = 0;
281 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
282 return Length;
283 }
284
285 while(1) {
286 if (GetOverlappedResult(d->hPhone,&d->osRead, &Length, TRUE)) break;
287 if (GetLastError() != ERROR_IO_INCOMPLETE) {
288 GSM_OSErrorInfo(s, "serial_read2");
289 /* an error occurred, try to recover */
290 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
291 break;
292 }
293 }
294 return Length;
295}
296
297static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
298{
299 DWORD BytesWritten,ErrorFlags,BytesSent=0;
300 COMSTAT ComStat;
301 GSM_Device_SerialData *d = &s->Device.Data.Serial;
302
303 if (WriteFile(d->hPhone, buf, nbytes, &BytesSent, &d->osWrite)) return BytesSent;
304
305 if (GetLastError() != ERROR_IO_PENDING) {
306 GSM_OSErrorInfo(s, "serial_write1");
307 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
308 return BytesSent;
309 }
310
311 while (1) {
312 if (GetOverlappedResult(d->hPhone, &d->osWrite, &BytesWritten, TRUE)) break;
313 if (GetLastError() != ERROR_IO_INCOMPLETE) {
314 GSM_OSErrorInfo(s, "serial_write2");
315 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
316 break;
317 }
318 BytesSent += BytesWritten;
319 }
320 BytesSent += BytesWritten;
321
322 return BytesSent;
323}
324
325GSM_Device_Functions SerialDevice = {
326 serial_open,
327 serial_close,
328 serial_setparity,
329 serial_setdtrrts,
330 serial_setspeed,
331 serial_read,
332 serial_write
333};
334
335#endif
336#endif
337
338/* How should editor hadle tabs in this file? Add editor commands here.
339 * vim: noexpandtab sw=8 ts=8 sts=8:
340 */
diff --git a/gammu/emb/common/device/serial/ser_w32.h b/gammu/emb/common/device/serial/ser_w32.h
new file mode 100644
index 0000000..d226f32
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_w32.h
@@ -0,0 +1,19 @@
1
2#ifdef WIN32
3#ifndef winserial_h
4#define winserial_h
5
6#include <windows.h>
7
8typedef struct {
9 HANDLE hPhone;
10 DCB old_settings;
11 OVERLAPPED osWrite,osRead;
12} GSM_Device_SerialData;
13
14#endif
15#endif
16
17/* How should editor hadle tabs in this file? Add editor commands here.
18 * vim: noexpandtab sw=8 ts=8 sts=8:
19 */
diff --git a/gammu/emb/common/gammu.h b/gammu/emb/common/gammu.h
new file mode 100644
index 0000000..88d94c5
--- a/dev/null
+++ b/gammu/emb/common/gammu.h
@@ -0,0 +1,23 @@
1/* (c) 2003 by Michal Cihar */
2
3/*
4 * This file includes some core Gammu headers, that you will probably need.
5 */
6
7#include "config.h"
8#include "gsmcomon.h"
9#include "gsmstate.h"
10#include "misc/cfg.h"
11#include "misc/misc.h"
12#include "misc/coding/coding.h"
13#include "service/gsmpbk.h"
14#include "service/gsmring.h"
15#include "service/gsmlogo.h"
16#include "service/gsmnet.h"
17#include "service/backup/gsmback.h"
18#include "phone/pfunc.h"
19#include "phone/nokia/nfunc.h"
20
21/* How should editor hadle tabs in this file? Add editor commands here.
22 * vim: noexpandtab sw=8 ts=8 sts=8:
23 */
diff --git a/gammu/emb/common/gsmcomon.c b/gammu/emb/common/gsmcomon.c
new file mode 100644
index 0000000..d094ef3
--- a/dev/null
+++ b/gammu/emb/common/gsmcomon.c
@@ -0,0 +1,260 @@
1/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6#include <stdio.h>
7#ifndef __OpenBSD__
8# include <wchar.h>
9#endif
10#ifdef WIN32
11# include <windows.h>
12#else
13# include <stdlib.h>
14# include <errno.h>
15# include <fcntl.h>
16# include <signal.h>
17#endif
18
19#include "gsmcomon.h"
20#include "misc/coding/coding.h"
21
22GSM_Error NoneFunction(void)
23{
24 return ERR_NONE;
25}
26
27GSM_Error NotImplementedFunction(void)
28{
29 return ERR_NOTIMPLEMENTED;
30}
31
32GSM_Error NotSupportedFunction(void)
33{
34 return ERR_NOTSUPPORTED;
35}
36
37unsigned char *GetMsg (INI_Section *cfg, unsigned char *default_string)
38{
39 unsigned char *retval, buffer[40], buff2[40], buff[2000];
40 static unsigned chardef_str[2000];
41 INI_Entry *e;
42 INI_Section *h;
43 int num;
44 int len;
45
46 if (cfg==NULL) return default_string;
47
48 EncodeUnicode (buff2, "common", 6);
49
50 /* Set all 0x0a to \n */
51 memset(def_str,0,sizeof(def_str));
52 for (num=0;num<((int)strlen(default_string));num++) {
53 if (default_string[num] == 0x0a) {
54 def_str[strlen(def_str)] = '\\';
55 def_str[strlen(def_str)] = 'n';
56 } else def_str[strlen(def_str)] = default_string[num];
57 }
58
59 e = NULL;
60 /* First find our section */
61 for (h = cfg; h != NULL; h = h->Next) {
62 if (mywstrncasecmp(buff2, h->SectionName, 0)) {
63 e = h->SubEntries;
64 break;
65 }
66 }
67 while (e != NULL) {
68 num = -1;
69 DecodeUnicode(e->EntryName,buffer);
70 if (strlen(buffer) == 5 && (buffer[0] == 'F' || buffer[0] == 'f')) {
71 num = atoi(buffer+2);
72 }
73 if (num!=-1) {
74 DecodeUnicode(e->EntryValue,buff);
75 /* Remove quotes */
76 if (buff[0] == '"') {
77 len = strlen(buff);
78 memmove(buff, buff + 1, len - 1);
79 if (buff[len - 2] == '"') buff[len - 2] = 0;
80 }
81 if (strcmp(buff, def_str) == 0) {
82 sprintf(buff,"T%04i",num);
83 EncodeUnicode (buffer, buff, 5);
84 retval = INI_GetValue(cfg, buff2, buffer, true);
85 if (retval) {
86 sprintf(buff,"%s",DecodeUnicodeConsole(retval+2));
87 buff[strlen(buff)-1] = 0;
88 /* Set all \n to 0x0a */
89 memset(def_str,0,sizeof(def_str));
90 num = 0;
91 while (num != (int)strlen(buff)) {
92 if (num < (int)strlen(buff) - 1) {
93 if (buff[num] == '\\' && buff[num+1] == 'n') {
94 def_str[strlen(def_str)] = 0x0a;
95 num+=2;
96 } else {
97 def_str[strlen(def_str)] = buff[num++];
98 }
99 } else {
100 def_str[strlen(def_str)] = buff[num++];
101 }
102 }
103 retval = def_str;
104 } else {
105 retval = default_string;
106 }
107 return retval;
108 }
109 }
110 e = e->Next;
111 }
112 return default_string;
113}
114
115typedef struct {
116 GSM_Error ErrorNum;
117 unsigned char *ErrorText;
118} PrintErrorEntry;
119
120static PrintErrorEntry PrintErrorEntries[] = {
121 {ERR_NONE, "No error."},
122 {ERR_DEVICEOPENERROR, "Error opening device. Unknown/busy or no permissions."},
123 {ERR_DEVICELOCKED, "Error opening device. Device locked."},
124 {ERR_DEVICENOTEXIST, "Error opening device. Not exist."},
125 {ERR_DEVICEBUSY, "Error opening device. Already opened by other application."},
126 {ERR_DEVICENOPERMISSION,"Error opening device. No permissions."},
127 {ERR_DEVICENODRIVER, "Error opening device. No required driver in operating system."},
128 {ERR_DEVICENOTWORK, "Error opening device. Some hardware not connected/wrong configured."},
129 {ERR_DEVICEDTRRTSERROR, "Error setting device DTR or RTS."},
130 {ERR_DEVICECHANGESPEEDERROR,"Error setting device speed. Maybe speed not supported."},
131 {ERR_DEVICEWRITEERROR, "Error writing device."},
132 {ERR_DEVICEREADERROR, "Error during reading device"},
133 {ERR_DEVICEPARITYERROR, "Can't set parity on device"},
134 {ERR_TIMEOUT, "No response in specified timeout. Probably phone not connected."},
135 /* Some missed */
136 {ERR_UNKNOWNRESPONSE, "Unknown response from phone. See readme.txt, how to report it."},
137 /* Some missed */
138 {ERR_UNKNOWNCONNECTIONTYPESTRING,"Unknown connection type string. Check config file."},
139 {ERR_UNKNOWNMODELSTRING,"Unknown model type string. Check config file."},
140 {ERR_SOURCENOTAVAILABLE,"Some required functions not compiled for your OS. Please contact."},
141 {ERR_NOTSUPPORTED, "Function not supported by phone."},
142 {ERR_EMPTY, "Entry is empty"},
143 {ERR_SECURITYERROR, "Security error. Maybe no PIN ?"},
144 {ERR_INVALIDLOCATION, "Invalid location. Maybe too high ?"},
145 {ERR_NOTIMPLEMENTED, "Function not implemented. Help required."},
146 {ERR_FULL, "Memory full."},
147 {ERR_UNKNOWN, "Unknown error."},
148 /* Some missed */
149 {ERR_CANTOPENFILE, "Can't open specified file. Read only ?"},
150 {ERR_MOREMEMORY, "More memory required..."},
151 {ERR_PERMISSION, "Permission to file/device required..."},
152 {ERR_EMPTYSMSC, "Empty SMSC number. Set in phone or use -smscnumber"},
153 {ERR_INSIDEPHONEMENU, "You're inside phone menu (during editing ?). Leave it and try again."},
154 {ERR_WORKINPROGRESS, "Function is during writing. If want help, please contact with authors."},
155 {ERR_PHONEOFF, "Phone is disabled and connected to charger"},
156 {ERR_FILENOTSUPPORTED, "File format not supported by Gammu"},
157 {ERR_BUG, "Nobody is perfect, some bug appeared in protocol implementation. Please contact authors."},
158 {ERR_CANCELED, "Transfer was canceled by phone (you pressed cancel on phone?)."},
159 /* Some missed */
160 {ERR_OTHERCONNECTIONREQUIRED,"Current connection type doesn't support called function."},
161 /* Some missed */
162 {ERR_INVALIDDATETIME, "Invalid date or time specified."},
163 {ERR_MEMORY, "Phone memory error, maybe it is read only"},
164 {ERR_INVALIDDATA, "Invalid data"},
165
166 {0, ""}
167};
168
169unsigned char *print_error(GSM_Error e, FILE *df, INI_Section *cfg)
170{
171 unsigned char *def = NULL;
172 int i= 0;
173
174 while (PrintErrorEntries[i].ErrorNum != 0) {
175 if (PrintErrorEntries[i].ErrorNum == e) {
176 def = PrintErrorEntries[i].ErrorText;
177 break;
178 }
179 i++;
180 }
181 if (def == NULL) def = "Unknown error.";
182 if (df!=NULL && di.dl!=0) fprintf(df,"[ERROR %i: %s]\n",e,def);
183
184 return GetMsg(cfg,def);
185}
186
187const char *GetGammuLocalePath(void)
188{
189#ifdef LOCALE_PATH
190 static const char Buffer[] = LOCALE_PATH;
191 return Buffer;
192#else
193 return NULL;
194#endif
195}
196
197const char *GetGammuVersion(void)
198{
199 static const char Buffer[] = VERSION;
200 return Buffer;
201}
202
203GSM_Error GSM_SetDebugFile(char *info, Debug_Info *privdi)
204{
205 FILE *testfile;
206
207 /* If we should use global file descriptor, use it */
208 if (privdi->use_global) {
209 /* Aren't we the changing the global di? */
210 if (privdi != &di) {
211 if (privdi->df != di.df &&
212 privdi->dl!=0 &&
213 fileno(privdi->df) != 1 &&
214 fileno(privdi->df) != 2)
215 fclose(privdi->df);
216 privdi->df = di.df;
217 return ERR_NONE;
218 }
219 } else {
220 /* If we should not use global file descriptor, don't even try use it */
221 if (privdi->df == di.df) privdi->df = stdout;
222 }
223
224 if (info[0]!=0 && privdi->dl != 0) {
225 switch (privdi->dl) {
226 case DL_BINARY:
227 testfile = fopen(info,"wcb");
228 break;
229 case DL_TEXTERROR:
230 case DL_TEXTERRORDATE:
231 testfile = fopen(info,"ac");
232 if (!testfile) {
233 dbgprintf("Can't open debug file\n");
234 return ERR_CANTOPENFILE;
235 }
236 fseek(testfile, 0, SEEK_END);
237 if (ftell(testfile) > 5000000) {
238 fclose(testfile);
239 testfile = fopen(info,"wc");
240 }
241 break;
242 default:
243 testfile = fopen(info,"wc");
244 }
245 if (!testfile) {
246 dbgprintf("Can't open debug file\n");
247 return ERR_CANTOPENFILE;
248 } else {
249 if (privdi->df && privdi->df != stdout) {
250 fclose(privdi->df);
251 }
252 privdi->df = testfile;
253 }
254 }
255 return ERR_NONE;
256}
257
258/* How should editor hadle tabs in this file? Add editor commands here.
259 * vim: noexpandtab sw=8 ts=8 sts=8:
260 */
diff --git a/gammu/emb/common/gsmcomon.h b/gammu/emb/common/gsmcomon.h
new file mode 100644
index 0000000..cd36708
--- a/dev/null
+++ b/gammu/emb/common/gsmcomon.h
@@ -0,0 +1,92 @@
1/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
2
3#ifndef __gsm_comon_h
4#define __gsm_comon_h
5
6#include <stdio.h>
7#ifndef WIN32
8# include <unistd.h>
9#endif
10
11#include "config.h"
12#include "misc/misc.h"
13#include "misc/cfg.h"
14
15 #define MAX_MANUFACTURER_LENGTH 50
16 #define MAX_MODEL_LENGTH 50
17 #define MAX_VERSION_LENGTH 50
18 #define MAX_VERSION_DATE_LENGTH 50
19 #define MAX_IMEI_LENGTH 20
20 #define PHONE_MAXSMSINFOLDER 200
21 #define GSM_MAX_NUMBER_LENGTH 50
22 #define GSM_MAXCALENDARTODONOTES300
23
24/* GSM_Error is used to notify about errors */
25typedef enum {
26 /* 1*/ERR_NONE=1,
27 ERR_DEVICEOPENERROR, /* Error during opening device */
28 ERR_DEVICELOCKED, /* Device locked */
29 ERR_DEVICENOTEXIST,
30 ERR_DEVICEBUSY,
31 ERR_DEVICENOPERMISSION,
32 ERR_DEVICENODRIVER,
33 ERR_DEVICENOTWORK,
34 ERR_DEVICEDTRRTSERROR, /* Error during setting DTR/RTS in device */
35 /*10*/ ERR_DEVICECHANGESPEEDERROR,/* Error during changing speed in device */
36 ERR_DEVICEWRITEERROR, /* Error during writing device */
37 ERR_DEVICEREADERROR, /* Error during reading device */
38 ERR_DEVICEPARITYERROR, /* Can't set parity on device */
39 ERR_TIMEOUT, /* Command timed out */
40 ERR_FRAMENOTREQUESTED, /* Frame handled, but not requested in this moment */
41 ERR_UNKNOWNRESPONSE, /* Response not handled by gammu */
42 ERR_UNKNOWNFRAME, /* Frame not handled by gammu */
43 ERR_UNKNOWNCONNECTIONTYPESTRING,/* Unknown connection type given by user */
44 ERR_UNKNOWNMODELSTRING, /* Unknown model given by user */
45 /*20*/ ERR_SOURCENOTAVAILABLE, /* Some functions not compiled in your OS */
46 ERR_NOTSUPPORTED, /* Not supported by phone */
47 ERR_EMPTY, /* Empty phonebook entry, ... */
48 ERR_SECURITYERROR, /* Not allowed */
49 ERR_INVALIDLOCATION, /* Too high or too low location... */
50 ERR_NOTIMPLEMENTED, /* Function not implemented */
51 ERR_FULL, /* Memory is full */
52 ERR_UNKNOWN,
53 ERR_CANTOPENFILE, /* Error during opening file */
54 ERR_MOREMEMORY, /* More memory required */
55 /*30*/ ERR_PERMISSION, /* No permission */
56 ERR_EMPTYSMSC, /* SMSC number is empty */
57 ERR_INSIDEPHONEMENU, /* Inside phone menu - can't make something */
58 ERR_NOTCONNECTED, /* Phone NOT connected - can't make something */
59 ERR_WORKINPROGRESS, /* Work in progress */
60 ERR_PHONEOFF, /* Phone is disabled and connected to charger */
61 ERR_FILENOTSUPPORTED, /* File format not supported by Gammu */
62 ERR_BUG, /* Found bug in implementation or phone */
63 ERR_CANCELED, /* Action was canceled by user */
64 ERR_NEEDANOTHERANSWER, /* Inside Gammu: phone module need to send another answer frame */
65 /*40*/ERR_OTHERCONNECTIONREQUIRED,
66 ERR_WRONGCRC,
67 ERR_INVALIDDATETIME, /* Invalid date/time */
68 ERR_MEMORY, /* Phone memory error, maybe it is read only */
69 ERR_INVALIDDATA /* Invalid data */
70} GSM_Error;
71
72 extern GSM_Error NoneFunction (void);
73 extern GSM_Error NotImplementedFunction(void);
74 extern GSM_Error NotSupportedFunction(void);
75
76 #define NONEFUNCTION (void *) NoneFunction
77 #define NOTIMPLEMENTED (void *) NotImplementedFunction
78 #define NOTSUPPORTED (void *) NotSupportedFunction
79
80 unsigned char *GetMsg (INI_Section *cfg, unsigned char *default_string);
81 unsigned char *print_error(GSM_Error e, FILE *df, INI_Section *cfg);
82
83GSM_Error GSM_SetDebugFile(char *info, Debug_Info *privdi);
84
85const char *GetGammuLocalePath(void);
86const char *GetGammuVersion(void);
87
88#endif
89
90/* How should editor hadle tabs in this file? Add editor commands here.
91 * vim: noexpandtab sw=8 ts=8 sts=8:
92 */
diff --git a/gammu/emb/common/gsmstate.c b/gammu/emb/common/gsmstate.c
new file mode 100644
index 0000000..b8f5f89
--- a/dev/null
+++ b/gammu/emb/common/gsmstate.c
@@ -0,0 +1,1246 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* Phones ID (c) partially by Walek */
3
4#include <stdarg.h>
5#include <string.h>
6#include <errno.h>
7
8#include "gsmcomon.h"
9#include "gsmstate.h"
10#include "misc/cfg.h"
11#include "misc/coding/coding.h"
12#include "device/devfunc.h"
13
14static void GSM_RegisterConnection(GSM_StateMachine *s, unsigned int connection,
15 GSM_Device_Functions *device, GSM_Protocol_Functions *protocol)
16{
17 if ((unsigned int)s->ConnectionType == connection) {
18 s->Device.Functions = device;
19 s->Protocol.Functions= protocol;
20 }
21}
22
23static GSM_Error GSM_RegisterAllConnections(GSM_StateMachine *s, char *connection)
24{
25 /* We check here is used connection string type is correct for ANY
26 * OS. If not, we return with error, that string is incorrect at all
27 */
28 s->ConnectionType = 0;
29 if (mystrncasecmp("mbus",connection,0)) s->ConnectionType = GCT_MBUS2;
30 if (mystrncasecmp("fbus",connection,0)) s->ConnectionType = GCT_FBUS2;
31 if (mystrncasecmp("fbusdlr3",connection,0)) s->ConnectionType = GCT_FBUS2DLR3;
32 if (mystrncasecmp("fbusdku5",connection,0)) s->ConnectionType = GCT_FBUS2DKU5;
33 if (mystrncasecmp("fbuspl2303",connection,0)) s->ConnectionType = GCT_FBUS2PL2303;
34 if (mystrncasecmp("fbusblue",connection,0)) s->ConnectionType = GCT_FBUS2BLUE;
35 if (mystrncasecmp("fbusirda",connection,0)) s->ConnectionType = GCT_FBUS2IRDA;
36 if (mystrncasecmp("phonetblue",connection,0)) s->ConnectionType = GCT_PHONETBLUE;
37 if (mystrncasecmp("mrouterblue",connection,0)) s->ConnectionType = GCT_MROUTERBLUE;
38 if (mystrncasecmp("irdaphonet",connection,0)) s->ConnectionType = GCT_IRDAPHONET;
39 if (mystrncasecmp("irdaat",connection,0)) s->ConnectionType = GCT_IRDAAT;
40 if (mystrncasecmp("irdaobex",connection,0)) s->ConnectionType = GCT_IRDAOBEX;
41 if (mystrncasecmp("blueobex",connection,0)) s->ConnectionType = GCT_BLUEOBEX;
42 if (mystrncasecmp("bluefbus",connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
43 if (mystrncasecmp("bluephonet",connection,0)) s->ConnectionType = GCT_BLUEPHONET;
44 if (mystrncasecmp("blueat",connection,0)) s->ConnectionType = GCT_BLUEAT;
45 if (mystrncasecmp("bluerfobex",connection,0)) s->ConnectionType = GCT_BLUEOBEX;
46 if (mystrncasecmp("bluerffbus",connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
47 if (mystrncasecmp("bluerfphonet",connection,0)) s->ConnectionType = GCT_BLUEPHONET;
48 if (mystrncasecmp("bluerfat",connection,0)) s->ConnectionType = GCT_BLUEAT;
49
50 /* These are for compatibility only */
51 if (mystrncasecmp("atblue",connection,0)) s->ConnectionType = GCT_BLUEAT;
52 if (mystrncasecmp("dlr3blue",connection,0)) s->ConnectionType = GCT_BLUEFBUS2;
53 if (mystrncasecmp("irda",connection,0)) s->ConnectionType = GCT_IRDAPHONET;
54 if (mystrncasecmp("dlr3",connection,0)) s->ConnectionType = GCT_FBUS2DLR3;
55 if (mystrncasecmp("infrared",connection,0)) s->ConnectionType = GCT_FBUS2IRDA;
56
57 if (mystrncasecmp("at" ,connection,2)) {
58 /* Use some resonable default, when no speed defined */
59 if (strlen(connection) == 2) {
60 s->Speed = 19200;
61 } else {
62 s->Speed = FindSerialSpeed(connection+2);
63 }
64 if (s->Speed != 0) s->ConnectionType = GCT_AT;
65 }
66 if (s->ConnectionType==0) return ERR_UNKNOWNCONNECTIONTYPESTRING;
67
68 /* We check now if user gave connection type compiled & available
69 * for used OS (if not, we return, that source not available)
70 */
71 s->Device.Functions = NULL;
72 s->Protocol.Functions= NULL;
73#ifdef GSM_ENABLE_MBUS2
74 GSM_RegisterConnection(s, GCT_MBUS2, &SerialDevice, &MBUS2Protocol);
75#endif
76#ifdef GSM_ENABLE_FBUS2
77 GSM_RegisterConnection(s, GCT_FBUS2, &SerialDevice, &FBUS2Protocol);
78#endif
79#ifdef GSM_ENABLE_FBUS2DLR3
80 GSM_RegisterConnection(s, GCT_FBUS2DLR3, &SerialDevice, &FBUS2Protocol);
81#endif
82#ifdef GSM_ENABLE_FBUS2DKU5
83 GSM_RegisterConnection(s, GCT_FBUS2DKU5, &SerialDevice, &FBUS2Protocol);
84#endif
85#ifdef GSM_ENABLE_FBUS2PL2303
86 GSM_RegisterConnection(s, GCT_FBUS2PL2303,&SerialDevice, &FBUS2Protocol);
87#endif
88#ifdef GSM_ENABLE_FBUS2BLUE
89 GSM_RegisterConnection(s, GCT_FBUS2BLUE, &SerialDevice, &FBUS2Protocol);
90#endif
91#ifdef GSM_ENABLE_FBUS2IRDA
92 GSM_RegisterConnection(s, GCT_FBUS2IRDA, &SerialDevice, &FBUS2Protocol);
93#endif
94#ifdef GSM_ENABLE_PHONETBLUE
95 GSM_RegisterConnection(s, GCT_PHONETBLUE,&SerialDevice, &PHONETProtocol);
96#endif
97#ifdef GSM_ENABLE_MROUTERBLUE
98 GSM_RegisterConnection(s, GCT_MROUTERBLUE,&SerialDevice, &MROUTERProtocol);
99#endif
100#ifdef GSM_ENABLE_IRDAPHONET
101 GSM_RegisterConnection(s, GCT_IRDAPHONET,&IrdaDevice, &PHONETProtocol);
102#endif
103#ifdef GSM_ENABLE_BLUEFBUS2
104 GSM_RegisterConnection(s, GCT_BLUEFBUS2, &BlueToothDevice,&FBUS2Protocol);
105#endif
106#ifdef GSM_ENABLE_BLUEPHONET
107 GSM_RegisterConnection(s, GCT_BLUEPHONET,&BlueToothDevice,&PHONETProtocol);
108#endif
109#ifdef GSM_ENABLE_BLUEAT
110 GSM_RegisterConnection(s, GCT_BLUEAT, &BlueToothDevice,&ATProtocol);
111#endif
112#ifdef GSM_ENABLE_AT
113 GSM_RegisterConnection(s, GCT_AT, &SerialDevice, &ATProtocol);
114#endif
115#ifdef GSM_ENABLE_IRDAAT
116 GSM_RegisterConnection(s, GCT_IRDAAT, &IrdaDevice, &ATProtocol);
117#endif
118#ifdef GSM_ENABLE_IRDAOBEX
119 GSM_RegisterConnection(s, GCT_IRDAOBEX, &IrdaDevice, &OBEXProtocol);
120#endif
121#ifdef GSM_ENABLE_BLUEOBEX
122 GSM_RegisterConnection(s, GCT_BLUEOBEX, &BlueToothDevice,&OBEXProtocol);
123#endif
124 if (s->Device.Functions==NULL || s->Protocol.Functions==NULL)
125 return ERR_SOURCENOTAVAILABLE;
126 return ERR_NONE;
127}
128
129static void GSM_RegisterModule(GSM_StateMachine *s,GSM_Phone_Functions *phone)
130{
131 /* Auto model */
132 if (s->CurrentConfig->Model[0] == 0) {
133 if (strstr(phone->models,GetModelData(NULL,s->Phone.Data.Model,NULL)->model) != NULL) {
134 smprintf(s,"[Module - \"%s\"]\n",phone->models);
135 s->Phone.Functions = phone;
136 }
137 } else {
138 if (strstr(phone->models,s->CurrentConfig->Model) != NULL) {
139 smprintf(s,"[Module - \"%s\"]\n",phone->models);
140 s->Phone.Functions = phone;
141 }
142 }
143}
144
145GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s)
146{
147 OnePhoneModel *model;
148
149 /* Auto model */
150 if (s->CurrentConfig->Model[0] == 0) {
151 model = GetModelData(NULL,s->Phone.Data.Model,NULL);
152#ifdef GSM_ENABLE_ALCATEL
153 if (model->model[0] != 0 && IsPhoneFeatureAvailable(model, F_ALCATEL)) {
154 smprintf(s,"[Module - \"%s\"]\n",ALCATELPhone.models);
155 s->Phone.Functions = &ALCATELPhone;
156 return ERR_NONE;
157 }
158#endif
159#ifdef GSM_ENABLE_ATGEN
160 /* With ATgen and auto model we can work with unknown models too */
161 if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT) {
162 smprintf(s,"[Module - \"%s\"]\n",ATGENPhone.models);
163 s->Phone.Functions = &ATGENPhone;
164 return ERR_NONE;
165 }
166#endif
167 if (model->model[0] == 0) return ERR_UNKNOWNMODELSTRING;
168 }
169 s->Phone.Functions=NULL;
170#ifdef GSM_ENABLE_ATGEN
171 /* AT module can have the same models ID to "normal" Nokia modules */
172 if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT) {
173 GSM_RegisterModule(s,&ATGENPhone);
174 if (s->Phone.Functions!=NULL) return ERR_NONE;
175 }
176#endif
177#ifdef GSM_ENABLE_OBEXGEN
178 GSM_RegisterModule(s,&OBEXGENPhone);
179#endif
180#ifdef GSM_ENABLE_MROUTERGEN
181 GSM_RegisterModule(s,&MROUTERGENPhone);
182#endif
183#ifdef GSM_ENABLE_NOKIA3320
184 GSM_RegisterModule(s,&N3320Phone);
185#endif
186#ifdef GSM_ENABLE_NOKIA3650
187 GSM_RegisterModule(s,&N3650Phone);
188#endif
189#ifdef GSM_ENABLE_NOKIA6110
190 GSM_RegisterModule(s,&N6110Phone);
191#endif
192#ifdef GSM_ENABLE_NOKIA6510
193 GSM_RegisterModule(s,&N6510Phone);
194#endif
195#ifdef GSM_ENABLE_NOKIA7110
196 GSM_RegisterModule(s,&N7110Phone);
197#endif
198#ifdef GSM_ENABLE_NOKIA9210
199 GSM_RegisterModule(s,&N9210Phone);
200#endif
201#ifdef GSM_ENABLE_ALCATEL
202 GSM_RegisterModule(s,&ALCATELPhone);
203#endif
204 if (s->Phone.Functions==NULL) return ERR_UNKNOWNMODELSTRING;
205 return ERR_NONE;
206}
207
208GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum)
209{
210 GSM_Errorerror;
211 GSM_DateTimetime;
212 int i;
213 char Buffer[80];
214
215 for (i=0;i<s->ConfigNum;i++) {
216 s->CurrentConfig = &s->Config[i];
217
218 s->Speed = 0;
219 s->ReplyNum = ReplyNum;
220 s->Phone.Data.ModelInfo = GetModelData("unknown",NULL,NULL);
221 s->Phone.Data.Manufacturer[0] = 0;
222 s->Phone.Data.Model[0] = 0;
223 s->Phone.Data.Version[0] = 0;
224 s->Phone.Data.VerDate[0] = 0;
225 s->Phone.Data.VerNum = 0;
226 s->Phone.Data.StartInfoCounter = 0;
227 s->Phone.Data.SentMsg = NULL;
228
229 s->Phone.Data.HardwareCache[0] = 0;
230 s->Phone.Data.ProductCodeCache[0] = 0;
231 s->Phone.Data.EnableIncomingCall = false;
232 s->Phone.Data.EnableIncomingSMS = false;
233 s->Phone.Data.EnableIncomingCB = false;
234 s->Phone.Data.EnableIncomingUSSD = false;
235 s->User.UserReplyFunctions = NULL;
236 s->User.IncomingCall = NULL;
237 s->User.IncomingSMS = NULL;
238 s->User.IncomingCB = NULL;
239 s->User.IncomingUSSD = NULL;
240 s->User.SendSMSStatus = NULL;
241 s->LockFile = NULL;
242 s->opened = false;
243 s->Phone.Functions = NULL;
244
245 s->di = di;
246 s->di.use_global = s->CurrentConfig->UseGlobalDebugFile;
247 GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di);
248 error=GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di);
249 if (error != ERR_NONE) return error;
250
251 if (s->di.dl == DL_TEXTALL || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTERROR ||
252 s->di.dl == DL_TEXTALLDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTERRORDATE) {
253 smprintf(s,"[Gammu - version %s built %s %s]\n",VERSION,__TIME__,__DATE__);
254 smprintf(s,"[Connection - \"%s\"]\n",s->CurrentConfig->Connection);
255 smprintf(s,"[Model type - \"%s\"]\n",s->CurrentConfig->Model);
256 smprintf(s,"[Device - \"%s\"]\n",s->CurrentConfig->Device);
257
258 Buffer[0] = 0;
259 if (strlen(GetOS()) != 0) sprintf(Buffer,"%s",GetOS());
260 if (strlen(GetCompiler()) != 0) {
261 if (Buffer[0] != 0) strcat(Buffer+strlen(Buffer),", ");
262 strcat(Buffer+strlen(Buffer),GetCompiler());
263 }
264 if (Buffer[0] != 0) smprintf(s,"[OS/compiler - %s]\n",Buffer);
265 }
266 if (s->di.dl==DL_BINARY) {
267 smprintf(s,"%c",((unsigned char)strlen(VERSION)));
268 smprintf(s,"%s",VERSION);
269 }
270
271 error=GSM_RegisterAllConnections(s, s->CurrentConfig->Connection);
272 if (error!=ERR_NONE) return error;
273
274 /* Model auto */
275 if (s->CurrentConfig->Model[0]==0) {
276 if (mystrncasecmp(s->CurrentConfig->LockDevice,"yes",0)) {
277 error = lock_device(s->CurrentConfig->Device, &(s->LockFile));
278 if (error != ERR_NONE) return error;
279 }
280
281 /* Irda devices can set now model to some specific and
282 * we don't have to make auto detection later */
283 error=s->Device.Functions->OpenDevice(s);
284 if (i != s->ConfigNum - 1) {
285 if (error == ERR_DEVICEOPENERROR) continue;
286 if (error == ERR_DEVICELOCKED) continue;
287 if (error == ERR_DEVICENOTEXIST) continue;
288 if (error == ERR_DEVICEBUSY) continue;
289 if (error == ERR_DEVICENOPERMISSION) continue;
290 if (error == ERR_DEVICENODRIVER) continue;
291 if (error == ERR_DEVICENOTWORK) continue;
292 }
293 if (error!=ERR_NONE) {
294 if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
295 return error;
296 }
297
298 s->opened = true;
299
300 error=s->Protocol.Functions->Initialise(s);
301 if (error!=ERR_NONE) return error;
302
303 /* If still auto model, try to get model by asking phone for it */
304 if (s->Phone.Data.Model[0]==0) {
305 smprintf(s,"[Module - \"auto\"]\n");
306 switch (s->ConnectionType) {
307#ifdef GSM_ENABLE_ATGEN
308 case GCT_AT:
309 case GCT_BLUEAT:
310 case GCT_IRDAAT:
311 s->Phone.Functions = &ATGENPhone;
312 break;
313#endif
314#ifdef GSM_ENABLE_OBEXGEN
315 case GCT_IRDAOBEX:
316 case GCT_BLUEOBEX:
317 s->Phone.Functions = &OBEXGENPhone;
318 break;
319#endif
320#ifdef GSM_ENABLE_MROUTERGEN
321 case GCT_MROUTERBLUE:
322 s->Phone.Functions = &MROUTERGENPhone;
323 break;
324#endif
325#if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
326 case GCT_MBUS2:
327 case GCT_FBUS2:
328 case GCT_FBUS2DLR3:
329 case GCT_FBUS2DKU5:
330 case GCT_FBUS2PL2303:
331 case GCT_FBUS2BLUE:
332 case GCT_FBUS2IRDA:
333 case GCT_PHONETBLUE:
334 case GCT_IRDAPHONET:
335 case GCT_BLUEFBUS2:
336 case GCT_BLUEPHONET:
337 s->Phone.Functions = &NAUTOPhone;
338 break;
339#endif
340 default:
341 s->Phone.Functions = NULL;
342 }
343 if (s->Phone.Functions == NULL) return ERR_UNKNOWN;
344
345 /* Please note, that AT module need to send first
346 * command for enabling echo
347 */
348 error=s->Phone.Functions->Initialise(s);
349 if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
350 if (error != ERR_NONE) return error;
351
352 error=s->Phone.Functions->GetModel(s);
353 if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
354 if (error != ERR_NONE) return error;
355 }
356 }
357
358 /* Switching to "correct" module */
359 error=GSM_RegisterAllPhoneModules(s);
360 if (error!=ERR_NONE) return error;
361
362 /* We didn't open device earlier ? Make it now */
363 if (!s->opened) {
364 if (mystrncasecmp(s->CurrentConfig->LockDevice,"yes",0)) {
365 error = lock_device(s->CurrentConfig->Device, &(s->LockFile));
366 if (error != ERR_NONE) return error;
367 }
368
369 error=s->Device.Functions->OpenDevice(s);
370 if (i != s->ConfigNum - 1) {
371 if (error == ERR_DEVICEOPENERROR) continue;
372 if (error == ERR_DEVICELOCKED) continue;
373 if (error == ERR_DEVICENOTEXIST) continue;
374 if (error == ERR_DEVICEBUSY) continue;
375 if (error == ERR_DEVICENOPERMISSION) continue;
376 if (error == ERR_DEVICENODRIVER) continue;
377 if (error == ERR_DEVICENOTWORK) continue;
378 }
379 if (error!=ERR_NONE) {
380 if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
381 return error;
382 }
383
384 s->opened = true;
385
386 error=s->Protocol.Functions->Initialise(s);
387 if (error!=ERR_NONE) return error;
388 }
389
390 error=s->Phone.Functions->Initialise(s);
391 if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
392 if (error != ERR_NONE) return error;
393
394 if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
395 s->Phone.Functions->ShowStartInfo(s,true);
396 s->Phone.Data.StartInfoCounter = 30;
397 }
398
399 if (mystrncasecmp(s->CurrentConfig->SyncTime,"yes",0)) {
400 GSM_GetCurrentDateTime (&time);
401 s->Phone.Functions->SetDateTime(s,&time);
402 }
403
404 /* For debug it's good to have firmware and real model version and manufacturer */
405 error=s->Phone.Functions->GetManufacturer(s);
406 if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) continue;
407 if (error != ERR_NONE) return error;
408 error=s->Phone.Functions->GetModel(s);
409 if (error != ERR_NONE) return error;
410 error=s->Phone.Functions->GetFirmware(s);
411 if (error != ERR_NONE) return error;
412 return ERR_NONE;
413 }
414 return ERR_UNKNOWN;
415}
416
417int GSM_ReadDevice (GSM_StateMachine *s, bool wait)
418{
419 unsigned charbuff[255];
420 int res = 0, count;
421
422 unsigned inti;
423 GSM_DateTimeDate;
424
425 GSM_GetCurrentDateTime (&Date);
426 i=Date.Second;
427 while (i==Date.Second) {
428 res = s->Device.Functions->ReadDevice(s, buff, 255);
429 if (!wait) break;
430 if (res > 0) break;
431 my_sleep(5);
432 GSM_GetCurrentDateTime(&Date);
433 }
434
435 for (count = 0; count < res; count++)
436 s->Protocol.Functions->StateMachine(s,buff[count]);
437
438 return res;
439}
440
441GSM_Error GSM_TerminateConnection(GSM_StateMachine *s)
442{
443 GSM_Error error;
444
445 if (!s->opened) return ERR_UNKNOWN;
446
447 smprintf(s,"[Closing]\n");
448
449 if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
450 if (s->Phone.Data.StartInfoCounter > 0) s->Phone.Functions->ShowStartInfo(s,false);
451 }
452
453 if (s->Phone.Functions != NULL) {
454 error=s->Phone.Functions->Terminate(s);
455 if (error!=ERR_NONE) return error;
456 }
457
458 error=s->Protocol.Functions->Terminate(s);
459 if (error!=ERR_NONE) return error;
460
461 error = s->Device.Functions->CloseDevice(s);
462 if (error!=ERR_NONE) return error;
463
464 s->Phone.Data.ModelInfo = NULL;
465 s->Phone.Data.Manufacturer[0] = 0;
466 s->Phone.Data.Model[0] = 0;
467 s->Phone.Data.Version[0] = 0;
468 s->Phone.Data.VerDate[0] = 0;
469 s->Phone.Data.VerNum = 0;
470
471 if (s->LockFile!=NULL) unlock_device(&(s->LockFile));
472
473 if (!s->di.use_global && s->di.dl!=0 && fileno(s->di.df) != 1 && fileno(s->di.df) != 2) fclose(s->di.df);
474
475 s->opened = false;
476
477 return ERR_NONE;
478}
479
480GSM_Error GSM_WaitForOnce(GSM_StateMachine *s, unsigned char *buffer,
481 int length, unsigned char type, int time)
482{
483 GSM_Phone_Data *Phone = &s->Phone.Data;
484 GSM_Protocol_Message sentmsg;
485 int i;
486
487 i=0;
488 do {
489 if (length != 0) {
490 sentmsg.Length = length;
491 sentmsg.Type= type;
492 sentmsg.Buffer = (unsigned char *)malloc(length);
493 memcpy(sentmsg.Buffer,buffer,length);
494 Phone->SentMsg = &sentmsg;
495 }
496
497 /* Some data received. Reset timer */
498 if (GSM_ReadDevice(s,true)!=0) i=0;
499
500 if (length != 0) {
501 free (sentmsg.Buffer);
502 Phone->SentMsg = NULL;
503 }
504
505 /* Request completed */
506 if (Phone->RequestID==ID_None) return Phone->DispatchError;
507
508 i++;
509 } while (i<time);
510
511 return ERR_TIMEOUT;
512}
513
514GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned char *buffer,
515 int length, unsigned char type, int time,
516 GSM_Phone_RequestID request)
517{
518 GSM_Phone_Data *Phone = &s->Phone.Data;
519 GSM_Error error;
520 int reply;
521
522 if (mystrncasecmp(s->CurrentConfig->StartInfo,"yes",0)) {
523 if (Phone->StartInfoCounter > 0) {
524 Phone->StartInfoCounter--;
525 if (Phone->StartInfoCounter == 0) s->Phone.Functions->ShowStartInfo(s,false);
526 }
527 }
528
529 Phone->RequestID= request;
530 Phone->DispatchError= ERR_TIMEOUT;
531
532 for (reply=0;reply<s->ReplyNum;reply++) {
533 if (reply!=0) {
534 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl == DL_TEXTERROR ||
535 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl == DL_TEXTERRORDATE)
536 {
537 smprintf(s, "[Retrying %i type 0x%02X]\n", reply, type);
538 }
539 }
540 error = s->Protocol.Functions->WriteMessage(s, buffer, length, type);
541 if (error!=ERR_NONE) return error;
542
543 error = GSM_WaitForOnce(s, buffer, length, type, time);
544 if (error != ERR_TIMEOUT) return error;
545 }
546
547 return Phone->DispatchError;
548}
549
550static GSM_Error CheckReplyFunctions(GSM_StateMachine *s, GSM_Reply_Function *Reply, int *reply)
551{
552 GSM_Phone_Data *Data = &s->Phone.Data;
553 GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg;
554 bool execute;
555 bool available = false;
556 int i = 0;
557
558 while (Reply[i].requestID!=ID_None) {
559 execute=false;
560 /* Binary frames like in Nokia */
561 if (strlen(Reply[i].msgtype) < 2) {
562 if (Reply[i].msgtype[0]==msg->Type) {
563 if (Reply[i].subtypechar!=0) {
564 if (Reply[i].subtypechar<=msg->Length) {
565 if (msg->Buffer[Reply[i].subtypechar]==Reply[i].subtype)
566 execute=true;
567 }
568 } else execute=true;
569 }
570 } else {
571 if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) {
572 execute=true;
573 }
574 }
575
576 if (execute) {
577 *reply=i;
578 if (Reply[i].requestID == ID_IncomingFrame ||
579 Reply[i].requestID == Data->RequestID ||
580 Data->RequestID== ID_EachFrame) {
581 return ERR_NONE;
582 }
583 available=true;
584 }
585 i++;
586 }
587
588 if (available) {
589 return ERR_FRAMENOTREQUESTED;
590 } else {
591 return ERR_UNKNOWNFRAME;
592 }
593}
594
595GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
596{
597 GSM_Error error= ERR_UNKNOWNFRAME;
598 GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg;
599 GSM_Phone_Data *Phone= &s->Phone.Data;
600 bool disp = false;
601 GSM_Reply_Function*Reply;
602 int reply, i;
603
604 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
605 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
606 smprintf(s, "RECEIVED frame ");
607 smprintf(s, "type 0x%02X/length 0x%02X/%i", msg->Type, msg->Length, msg->Length);
608 DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, msg->Buffer, msg->Length);
609 if (msg->Length == 0) smprintf(s, "\n");
610 fflush(s->di.df);
611 }
612 if (s->di.dl==DL_BINARY) {
613 smprintf(s,"%c",0x02);/* Receiving */
614 smprintf(s,"%c",msg->Type);
615 smprintf(s,"%c",msg->Length/256);
616 smprintf(s,"%c",msg->Length%256);
617 for (i=0;i<msg->Length;i++) {
618 smprintf(s,"%c",msg->Buffer[i]);
619 }
620 }
621
622 Reply=s->User.UserReplyFunctions;
623 if (Reply!=NULL) error=CheckReplyFunctions(s,Reply,&reply);
624
625 if (error==ERR_UNKNOWNFRAME) {
626 Reply=s->Phone.Functions->ReplyFunctions;
627 error=CheckReplyFunctions(s,Reply,&reply);
628 }
629
630 if (error==ERR_NONE) {
631 error=Reply[reply].Function(*msg, s);
632 if (Reply[reply].requestID==Phone->RequestID) {
633 if (error == ERR_NEEDANOTHERANSWER) {
634 error = ERR_NONE;
635 } else {
636 Phone->RequestID=ID_None;
637 }
638 }
639 }
640
641 if (strcmp(s->Phone.Functions->models,"NAUTO")) {
642 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
643 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
644 disp = true;
645 switch (error) {
646 case ERR_UNKNOWNRESPONSE:
647 smprintf(s, "\nUNKNOWN response");
648 break;
649 case ERR_UNKNOWNFRAME:
650 smprintf(s, "\nUNKNOWN frame");
651 break;
652 case ERR_FRAMENOTREQUESTED:
653 smprintf(s, "\nFrame not request now");
654 break;
655 default:
656 disp = false;
657 }
658 }
659
660 if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) {
661 error = ERR_TIMEOUT;
662 }
663 }
664
665 if (disp) {
666 smprintf(s,". If you can, PLEASE report it (see readme.txt). THANK YOU\n");
667 if (Phone->SentMsg != NULL) {
668 smprintf(s,"LAST SENT frame ");
669 smprintf(s, "type 0x%02X/length %i", Phone->SentMsg->Type, Phone->SentMsg->Length);
670 DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, Phone->SentMsg->Buffer, Phone->SentMsg->Length);
671 }
672 smprintf(s, "RECEIVED frame ");
673 smprintf(s, "type 0x%02X/length 0x%02X/%i", msg->Type, msg->Length, msg->Length);
674 DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, msg->Buffer, msg->Length);
675 smprintf(s, "\n");
676 }
677
678 return error;
679}
680
681INI_Section *GSM_FindGammuRC(void)
682{
683 INI_Section*ini_file;
684 char *HomeDrive,*HomePath,*FileName=malloc(1);
685 int FileNameUsed=1;
686
687 FileName[0] = 0;
688#if defined(WIN32) || defined(DJGPP)
689 HomeDrive = getenv("HOMEDRIVE");
690 if (HomeDrive) {
691 FileName = realloc(FileName,FileNameUsed+strlen(HomeDrive)+1);
692 FileName = strcat(FileName, HomeDrive);
693 FileNameUsed+= strlen(HomeDrive)+1;
694 }
695 HomePath = getenv("HOMEPATH");
696 if (HomePath) {
697 FileName = realloc(FileName,FileNameUsed+strlen(HomePath)+1);
698 FileName = strcat(FileName, HomePath);
699 FileNameUsed+= strlen(HomePath)+1;
700 }
701 FileName = realloc(FileName,FileNameUsed+8+1);
702 strcat(FileName, "\\gammurc");
703#else
704 HomeDrive = NULL;
705 HomePath = getenv("HOME");
706 if (HomePath) {
707 FileName = realloc(FileName,FileNameUsed+strlen(HomePath)+1);
708 FileName = strcat(FileName, HomePath);
709 FileNameUsed+= strlen(HomePath)+1;
710 }
711 FileName = realloc(FileName,FileNameUsed+9+1);
712 strcat(FileName, "/.gammurc");
713#endif
714 //dbgprintf("\"%s\"\n",FileName);
715
716 ini_file = INI_ReadFile(FileName, false);
717 free(FileName);
718 if (ini_file == NULL) {
719#if defined(WIN32) || defined(DJGPP)
720 ini_file = INI_ReadFile("gammurc", false);
721 if (ini_file == NULL) return NULL;
722#else
723 ini_file = INI_ReadFile("/etc/gammurc", false);
724 if (ini_file == NULL) return NULL;
725#endif
726 }
727
728 return ini_file;
729}
730
731bool GSM_ReadConfig(INI_Section *cfg_info, GSM_Config *cfg, int num)
732{
733 INI_Section *h;
734 unsigned char section[50];
735 bool found = false;
736
737#if defined(WIN32) || defined(DJGPP)
738 char *DefaultPort = "com2:";
739#else
740 char *DefaultPort = "/dev/ttyS1";
741#endif
742 char *DefaultModel = "";
743 char *DefaultConnection = "fbus";
744 char *DefaultSynchronizeTime= "no";
745 char *DefaultDebugFile = "";
746 char *DefaultDebugLevel = "";
747 char *DefaultLockDevice = "no";
748 char *DefaultStartInfo = "no";
749 char *Temp;
750
751 /* By default all debug output will go to one filedescriptor */
752 bool DefaultUseGlobalDebugFile = true;
753
754 cfg->Device = DefaultPort;
755 cfg->Connection = DefaultConnection;
756 cfg->SyncTime = DefaultSynchronizeTime;
757 cfg->DebugFile = DefaultDebugFile;
758 strcpy(cfg->Model,DefaultModel);
759 strcpy(cfg->DebugLevel,DefaultDebugLevel);
760 cfg->LockDevice = DefaultLockDevice;
761 cfg->StartInfo = DefaultStartInfo;
762 cfg->DefaultDevice = true;
763 cfg->DefaultModel = true;
764 cfg->DefaultConnection = true;
765 cfg->DefaultSyncTime = true;
766 cfg->DefaultDebugFile = true;
767 cfg->DefaultDebugLevel = true;
768 cfg->DefaultLockDevice = true;
769 cfg->DefaultStartInfo = true;
770
771 cfg->UseGlobalDebugFile = DefaultUseGlobalDebugFile;
772
773 if (cfg_info==NULL) return false;
774
775 if (num == 0) {
776 sprintf(section,"gammu");
777 } else {
778 sprintf(section,"gammu%i",num);
779 }
780 for (h = cfg_info; h != NULL; h = h->Next) {
781 if (mystrncasecmp(section, h->SectionName, strlen(section))) {
782 found = true;
783 break;
784 }
785 }
786 if (!found) return false;
787
788 cfg->Device = INI_GetValue(cfg_info, section, "port", false);
789 if (!cfg->Device) {
790 free(cfg->Device);
791 cfg->Device = strdup(DefaultPort);
792 } else {
793 cfg->DefaultDevice = false;
794 }
795 cfg->Connection = INI_GetValue(cfg_info, section, "connection", false);
796 if (!cfg->Connection) {
797 free(cfg->Connection);
798 cfg->Connection = strdup(DefaultConnection);
799 } else {
800 cfg->DefaultConnection = false;
801 }
802 cfg->SyncTime = INI_GetValue(cfg_info, section, "synchronizetime",false);
803 if (!cfg->SyncTime) {
804 free(cfg->SyncTime);
805 cfg->SyncTime = strdup(DefaultSynchronizeTime);
806 } else {
807 cfg->DefaultSyncTime = false;
808 }
809 cfg->DebugFile = INI_GetValue(cfg_info, section, "logfile", false);
810 if (!cfg->DebugFile) {
811 free(cfg->DebugFile);
812 cfg->DebugFile = strdup(DefaultDebugFile);
813 } else {
814 cfg->DefaultDebugFile = false;
815 }
816 cfg->LockDevice = INI_GetValue(cfg_info, section, "use_locking", false);
817 if (!cfg->LockDevice) {
818 free(cfg->LockDevice);
819 cfg->LockDevice = strdup(DefaultLockDevice);
820 } else {
821 cfg->DefaultLockDevice = false;
822 }
823 Temp = INI_GetValue(cfg_info, section, "model", false);
824 if (!Temp) {
825 strcpy(cfg->Model,DefaultModel);
826 } else {
827 cfg->DefaultModel = false;
828 strcpy(cfg->Model,Temp);
829 }
830 Temp = INI_GetValue(cfg_info, section, "logformat", false);
831 if (!Temp) {
832 strcpy(cfg->DebugLevel,DefaultDebugLevel);
833 } else {
834 cfg->DefaultDebugLevel = false;
835 strcpy(cfg->DebugLevel,Temp);
836 }
837 cfg->StartInfo = INI_GetValue(cfg_info, section, "startinfo", false);
838 if (!cfg->StartInfo) {
839 free(cfg->StartInfo);
840 cfg->StartInfo = strdup(DefaultStartInfo);
841 } else {
842 cfg->DefaultStartInfo = false;
843 }
844 return true;
845}
846
847static OnePhoneModel allmodels[] = {
848#ifdef GSM_ENABLE_NOKIA6510
849 {"1100", "RH-18" ,"", {0}},
850 {"1100a","RH-38" ,"", {0}},
851 {"1100b","RH-36" ,"", {0}},
852#endif
853#ifdef GSM_ENABLE_NOKIA6110
854 {"2100" ,"NAM-2" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},//quess
855#endif
856#ifdef GSM_ENABLE_NOKIA6510
857 {"3100" ,"RH-19" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},
858 {"3100b","RH-50" ,"", {F_PBKTONEGAL,F_PBKSMSLIST,0}},
859 {"3108", "RH-6", "Nokia 3108",{0}}, //does it have irda ?
860 {"3200", "RH-30" ,"Nokia 3200",{F_PBKTONEGAL,0}},
861 {"3200a","RH-31" ,"Nokia 3200",{F_PBKTONEGAL,0}},
862#endif
863#ifdef GSM_ENABLE_NOKIA6110
864 {"3210" ,"NSE-8" ,"", {F_NOWAP,F_NOCALLER,F_NOCALENDAR,F_NOPBKUNICODE,F_POWER_BATT,F_PROFILES51,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
865 {"3210" ,"NSE-9" ,"", {F_NOWAP,F_NOCALLER,F_NOCALENDAR,F_NOPBKUNICODE,F_POWER_BATT,F_PROFILES51,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
866#endif
867#ifdef GSM_ENABLE_NOKIA6510
868 {"3300" ,"NEM-1" ,"Nokia 3300", {F_PBKTONEGAL,0}},
869 {"3300" ,"NEM-2" ,"Nokia 3300", {F_PBKTONEGAL,0}},
870#endif
871#ifdef GSM_ENABLE_NOKIA6110
872 {"3310" ,"NHM-5" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},
873#endif
874#ifdef GSM_ENABLE_NOKIA3320
875 {"3320" ,"NPC-1" ,"Nokia 3320", {F_CAL62,F_DAYMONTH,0}},//fixme
876#endif
877#ifdef GSM_ENABLE_NOKIA6110
878 {"3330" ,"NHM-6" ,"", {F_NOCALLER,F_RING_SM,F_CAL33,F_PROFILES33,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
879 {"3390" ,"NPB-1" ,"", {F_NOWAP,F_NOCALLER,F_RING_SM,F_CAL33,F_PROFILES33,F_NOPICTUREUNI,F_NOCALLINFO,F_NODTMF,0}},
880 {"3410" ,"NHM-2" ,"", {F_RING_SM,F_CAL33,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},
881#endif
882#ifdef GSM_ENABLE_NOKIA6510
883 {"3510" ,"NHM-8" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
884 {"3510i","RH-9" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
885 {"3530" ,"RH-9" ,"", {F_CAL35,F_PBK35,F_NOGPRSPOINT,F_VOICETAGS,0}},
886 {"3589i","RH-44" ,"", {F_VOICETAGS,0}},
887 {"3590" ,"NPM-8" ,"", {0}},//irda?
888 {"3595" ,"NPM-10" ,"", {0}},//irda?
889#endif
890#ifdef GSM_ENABLE_NOKIA6110
891 {"3610" ,"NAM-1" ,"", {F_NOCALLER,F_RING_SM,F_CAL33,F_POWER_BATT,F_PROFILES33,F_NOCALLINFO,F_NODTMF,0}},//quess
892#endif
893#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA3650)
894 {"3650" ,"NHL-8" ,"Nokia 3650", {0}},
895 {"NGAGE","NEM-4" ,"", {F_RADIO,0}},
896#endif
897#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
898 {"5100" ,"NPM-6" ,"Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
899 {"5100" ,"NPM-6U","Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
900 {"5100" ,"NPM-6X","Nokia 5100", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
901#endif
902#ifdef GSM_ENABLE_NOKIA6110
903 {"5110" ,"NSE-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
904 {"5110i","NSE-2" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
905 {"5130" ,"NSK-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
906 {"5190" ,"NSB-1" ,"", {F_NOWAP,F_NOCALLER,F_NORING,F_NOPICTURE,F_NOSTARTUP,F_NOCALENDAR,F_NOPBKUNICODE,F_PROFILES51,F_MAGICBYTES,F_DISPSTATUS,0}},
907#endif
908#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
909 {"5210" ,"NSM-5" ,"Nokia 5210", {F_CAL52,F_NOSTARTANI,F_NOPICTUREUNI,F_NODTMF,0}},
910#endif
911#ifdef GSM_ENABLE_NOKIA6110
912 {"5510" ,"NPM-5" ,"", {F_NOCALLER,F_PROFILES33,F_NOPICTUREUNI,0}},
913#endif
914#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
915 {"6100" ,"NPL-2" ,"Nokia 6100", {F_PBKTONEGAL,F_TODO66,0}},
916#endif
917#ifdef GSM_ENABLE_NOKIA6110
918 {"6110" ,"NSE-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
919 {"6130" ,"NSK-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
920 {"6150" ,"NSM-1" ,"", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,F_NOPICTUREUNI,0}},
921 {"6190" ,"NSB-3" ,"", {F_NOWAP,F_NOPICTURE,F_NOSTARTANI,F_NOPBKUNICODE,F_MAGICBYTES,F_DISPSTATUS,0}},
922#endif
923#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
924 {"6200" ,"NPL-3" ,"Nokia 6200", {F_PBKTONEGAL,0}},
925 {"6220" ,"RH-20" ,"Nokia 6220", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,F_WAPMMSPROXY,0}},
926#endif
927#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA7110)
928 {"6210" ,"NPE-3" ,"Nokia 6210", {F_VOICETAGS,F_CAL62,0}},
929 {"6250" ,"NHM-3" ,"Nokia 6250", {F_VOICETAGS,F_CAL62,0}},
930#endif
931#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
932 {"6230" ,"RH-12" ,"Nokia 6230", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,F_PBKUSER,0}},
933 {"6310" ,"NPE-4" ,"Nokia 6310", {F_TODO63,F_CAL65,F_NOMIDI,F_NOMMS,F_VOICETAGS,0}},
934 {"6310i","NPL-1" ,"Nokia 6310i",{F_TODO63,F_CAL65,F_NOMIDI,F_BLUETOOTH,F_NOMMS,F_VOICETAGS,0}},
935 {"6385" ,"NHP-2AX","Nokia 6385",{F_TODO63,F_CAL65,F_NOMIDI,F_NOMMS,F_VOICETAGS,0}},
936 {"6510" ,"NPM-9" ,"Nokia 6510", {F_TODO63,F_CAL65,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
937 {"6610" ,"NHL-4U","Nokia 6610", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
938 {"6800" ,"NSB-9" ,"Nokia 6800", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},
939 {"6800" ,"NHL-6" ,"Nokia 6800", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKSMSLIST,0}},
940#endif
941#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA7110)
942 {"7110" ,"NSE-5" ,"Nokia 7110", {F_CAL62,0}},
943 {"7190" ,"NSB-5" ,"Nokia 7190", {F_CAL62,0}},
944#endif
945#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
946 {"7210" ,"NHL-4" ,"Nokia 7210", {F_PBKTONEGAL,F_TODO66,F_RADIO,0}},
947 {"7250" ,"NHL-4J","Nokia 7250", {F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKIMG,0}},
948 {"7250i","NHL-4JX","Nokia 7250i",{F_PBKTONEGAL,F_TODO66,F_RADIO,F_PBKIMG,0}},
949 {"7600", "NMM-3", "Nokia 7600", {F_TODO66,0}},
950#endif
951#if defined(GSM_ENABLE_ATGEN)
952 {"7650" ,"NHL-2" ,"Nokia 7650", {0}},
953#endif
954#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
955 {"8210" ,"NSM-3" ,"Nokia 8210", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_NOPICTUREUNI,0}},
956 {"8250" ,"NSM-3D","Nokia 8250", {F_NOWAP,F_NOSTARTANI,F_CAL82,F_NOPICTUREUNI,0}},
957 {"8290" ,"NSB-7" ,"Nokia 8290", {F_NOWAP,F_NOSTARTANI,F_NOPBKUNICODE,F_NOPICTUREUNI,0}},
958#endif
959#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
960 {"8310" ,"NHM-7" ,"Nokia 8310", {F_CAL62,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
961 {"8390" ,"NSB-8" ,"Nokia 8390", {F_CAL62,F_NOMIDI,F_RADIO,F_NOFILESYSTEM,F_NOMMS,F_VOICETAGS,0}},
962#endif
963#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6110)
964 {"8850" ,"NSM-2" ,"Nokia 8850", {0}},
965 {"8855" ,"NSM-4" ,"Nokia 8855", {0}},
966 {"8890" ,"NSB-6" ,"Nokia 8890", {0}},
967#endif
968#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_NOKIA6510)
969 {"8910" ,"NHM-4" ,"Nokia 8910", {F_CAL62,F_NOMIDI,F_NOFILESYSTEM,F_NOMMS,0}},
970 {"8910i","NHM-4" ,"Nokia 8910i",{F_CAL62,F_NOMIDI,F_NOFILESYSTEM,F_NOMMS,0}},
971#endif
972#ifdef GSM_ENABLE_NOKIA9210
973 {"9210" ,"RAE-3" ,"", {0}},
974 {"9210i","RAE-5" ,"", {0}},
975#endif
976#ifdef GSM_ENABLE_ATGEN
977 {"at" , "at", "", {0}},
978 {"M20" , "M20", "", {F_M20SMS,F_SLOWWRITE,0}},
979 {"MC35" , "MC35", "", {0}},
980 {"S25", "S25", "SIEMENS S25", {0}},
981 {"C35i" , "C35i", "", {0}},
982 {"S35i" , "S35i", "", {0}},
983 {"M35i" , "M35i", "", {0}},
984 {"S40" , "Siemens S40", "", {0}},
985 {"C45" , "C45", "", {0}},
986 {"S45" , "S45", "", {0}},
987 {"ME45" , "ME45", "", {0}},
988 {"SL45" , "SL45", "", {0}},
989 {"SL45i" , "SL45i", "", {0}},
990 {"M50" , "M50", "", {0}},
991 {"S45" , "6618" , "", {0}},
992 {"ME45" , "3618" , "", {0}},
993 {"S55" , "S55" , "", {0}},
994 {"T28s", "1101101-BVT28s","", {0}},
995 {"R320s" , "1101201-BV R320s","", {0}},
996 {"R380s", "7100101-BVR380s" ,"", {0}},
997 {"R520m", "1130101-BVR520m" ,"", {0}},
998 {"T39m", "1130102-BVT39m" ,"", {0}},
999 {"T65", "1101901-BVT65" , "", {0}},
1000 {"T68", "1130201-BVT68" , "", {0}},
1001 {"T68i", "1130202-BVT68" , "", {0}},
1002 {"R600", "102001-BVR600" , "", {0}},
1003 {"T200", "1130501-BVT200" ,"", {0}},
1004 {"T300", "1130601-BVT300" ,"T300", {0}},
1005 {"T310", "1130602-BVT310" ,"", {0}},
1006 {"P800", "7130501-BVP800" ,"", {0}},
1007 {"iPAQ" , "iPAQ" , "" , {0}},
1008 {"A2D" , "A2D" , "" , {0}},
1009 {"9210" , "RAE-3", "Nokia Communicator GSM900/1800",{0}},
1010 {"myV-65", "myV-65 GPRS", "", {F_SMSME900,0}},
1011#endif
1012#if defined(GSM_ENABLE_ATGEN) || defined(GSM_ENABLE_ALCATEL)
1013 {"BE5", "ONE TOUCH 500","", {F_ALCATEL,F_SMSONLYSENT,F_BROKENCPBS,0}},
1014 {"BH4", "ONE TOUCH 535","ALCATEL OT535", {F_ALCATEL,F_SMSONLYSENT,0}},
1015 {"BF5", "ONE TOUCH 715","ALCATEL OT715", {F_ALCATEL,F_SMSONLYSENT,F_BROKENCPBS,0}},
1016#endif
1017 {"unknown", "" ,"", {0}}
1018};
1019
1020OnePhoneModel *GetModelData(char *model, char *number, char *irdamodel)
1021{
1022 int i = 0;
1023
1024 while (strcmp(allmodels[i].number,"") != 0) {
1025 if (model !=NULL) {
1026 if (strcmp (model, allmodels[i].model) == 0) {
1027 return (&allmodels[i]);
1028 }
1029 }
1030 if (number !=NULL) {
1031 if (strcmp (number, allmodels[i].number) == 0) {
1032 return (&allmodels[i]);
1033 }
1034 }
1035 if (irdamodel !=NULL) {
1036 if (strcmp (irdamodel, allmodels[i].irdamodel) == 0) {
1037 return (&allmodels[i]);
1038 }
1039 }
1040 i++;
1041 }
1042 return (&allmodels[i]);
1043}
1044
1045bool IsPhoneFeatureAvailable(OnePhoneModel *model, Feature feature)
1046{
1047 int i= 0;
1048 boolretval = false;
1049
1050 while (model->features[i] != 0) {
1051 if (model->features[i] == feature) {
1052 retval = true;
1053 break;
1054 }
1055 i++;
1056 }
1057 return retval;
1058}
1059
1060void GSM_DumpMessageLevel2(GSM_StateMachine *s, unsigned char *message, int messagesize, int type)
1061{
1062 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
1063 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
1064 smprintf(s,"SENDING frame ");
1065 smprintf(s,"type 0x%02X/length 0x%02X/%i", type, messagesize, messagesize);
1066 DumpMessage(s->di.use_global ? di.df : s->di.df, s->di.dl, message, messagesize);
1067 if (messagesize == 0) smprintf(s,"\n");
1068 if (s->di.df) fflush(s->di.df);
1069 }
1070}
1071
1072void GSM_DumpMessageLevel3(GSM_StateMachine *s, unsigned char *message, int messagesize, int type)
1073{
1074 int i;
1075
1076 if (s->di.dl==DL_BINARY) {
1077 smprintf(s,"%c",0x01);/* Sending */
1078 smprintf(s,"%c",type);
1079 smprintf(s,"%c",messagesize/256);
1080 smprintf(s,"%c",messagesize%256);
1081 for (i=0;i<messagesize;i++) smprintf(s,"%c",message[i]);
1082 }
1083}
1084
1085#ifdef __GNUC__
1086__attribute__((format(printf, 2, 3)))
1087#endif
1088int smprintf(GSM_StateMachine *s, const char *format, ...)
1089{
1090 va_list argp;
1091 int result=0;
1092 unsigned charbuffer[2000];
1093 Debug_Leveldl;
1094 FILE *df;
1095
1096 va_start(argp, format);
1097 if (s == NULL) {
1098 dl = di.dl;
1099 df = di.df;
1100 } else {
1101 dl = s->di.dl;
1102 if (s->di.use_global) {
1103 df = di.df;
1104 } else {
1105 df = s->di.df;
1106 }
1107 }
1108
1109 if (dl != 0) {
1110 result = vsprintf(buffer, format, argp);
1111 result = smfprintf(df, dl, "%s", buffer);
1112 }
1113
1114 va_end(argp);
1115 return result;
1116}
1117
1118void GSM_OSErrorInfo(GSM_StateMachine *s, char *description)
1119{
1120#ifdef WIN32
1121 int i;
1122 unsigned char *lpMsgBuf;
1123
1124 /* We don't use errno in win32 - GetLastError gives better info */
1125 if (GetLastError()!=-1) {
1126 if (s->di.dl == DL_TEXTERROR || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTALL ||
1127 s->di.dl == DL_TEXTERRORDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTALLDATE) {
1128 FormatMessage(
1129 FORMAT_MESSAGE_ALLOCATE_BUFFER |
1130 FORMAT_MESSAGE_FROM_SYSTEM |
1131 FORMAT_MESSAGE_IGNORE_INSERTS,
1132 NULL,
1133 GetLastError(),
1134 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
1135 (LPTSTR) &lpMsgBuf,
1136 0,
1137 NULL
1138 );
1139 for (i=0;i<(int)strlen(lpMsgBuf);i++) {
1140 if (lpMsgBuf[i] == 13 || lpMsgBuf[i] == 10) {
1141 lpMsgBuf[i] = ' ';
1142 }
1143 }
1144 smprintf(s,"[System error - %s, %i, \"%s\"]\n",description,GetLastError(),(LPCTSTR)lpMsgBuf);
1145 LocalFree(lpMsgBuf);
1146 }
1147 }
1148 return;
1149#endif
1150
1151 if (errno!=-1) {
1152 if (s->di.dl == DL_TEXTERROR || s->di.dl == DL_TEXT || s->di.dl == DL_TEXTALL ||
1153 s->di.dl == DL_TEXTERRORDATE || s->di.dl == DL_TEXTDATE || s->di.dl == DL_TEXTALLDATE) {
1154 smprintf(s,"[System error - %s, %i, \"%s\"]\n",description,errno,strerror(errno));
1155 }
1156 }
1157}
1158
1159#ifdef GSM_ENABLE_BACKUP
1160
1161void GSM_GetPhoneFeaturesForBackup(GSM_StateMachine *s, GSM_Backup_Info *info)
1162{
1163 GSM_Error error;
1164 GSM_MemoryStatusMemStatus;
1165 GSM_ToDoStatus ToDoStatus;
1166 GSM_CalendarEntry Note;
1167 GSM_WAPBookmark Bookmark;
1168 GSM_MultiWAPSettingsWAPSettings;
1169 GSM_FMStation FMStation;
1170 GSM_GPRSAccessPointGPRSPoint;
1171 // GSM_Profile Profile;
1172
1173 if (info->PhonePhonebook) {
1174 MemStatus.MemoryType = MEM_ME;
1175 error=s->Phone.Functions->GetMemoryStatus(s, &MemStatus);
1176 if (error==ERR_NONE && MemStatus.MemoryUsed != 0) {
1177 } else {
1178 info->PhonePhonebook = false;
1179 }
1180 }
1181 if (info->SIMPhonebook) {
1182 MemStatus.MemoryType = MEM_SM;
1183 error=s->Phone.Functions->GetMemoryStatus(s, &MemStatus);
1184 if (error==ERR_NONE && MemStatus.MemoryUsed != 0) {
1185 } else {
1186 info->SIMPhonebook = false;
1187 }
1188 }
1189 if (info->Calendar) {
1190 error=s->Phone.Functions->GetNextCalendar(s,&Note,true);
1191 if (error!=ERR_NONE) info->Calendar = false;
1192 }
1193 if (info->ToDo) {
1194 error=s->Phone.Functions->GetToDoStatus(s,&ToDoStatus);
1195 if (error == ERR_NONE && ToDoStatus.Used != 0) {
1196 } else {
1197 info->ToDo = false;
1198 }
1199 }
1200 if (info->WAPBookmark) {
1201 Bookmark.Location = 1;
1202 error=s->Phone.Functions->GetWAPBookmark(s,&Bookmark);
1203 if (error == ERR_NONE) {
1204 } else {
1205 info->WAPBookmark = false;
1206 }
1207 }
1208 if (info->WAPSettings) {
1209 WAPSettings.Location = 1;
1210 error=s->Phone.Functions->GetWAPSettings(s,&WAPSettings);
1211 if (error == ERR_NONE) {
1212 } else {
1213 info->WAPSettings = false;
1214 }
1215 }
1216 if (info->MMSSettings) {
1217 WAPSettings.Location = 1;
1218 error=s->Phone.Functions->GetMMSSettings(s,&WAPSettings);
1219 if (error == ERR_NONE) {
1220 } else {
1221 info->WAPSettings = false;
1222 }
1223 }
1224 if (info->FMStation) {
1225 FMStation.Location = 1;
1226 error = s->Phone.Functions->GetFMStation(s,&FMStation);
1227 if (error == ERR_NONE || error == ERR_EMPTY) {
1228 } else {
1229 info->FMStation = false;
1230 }
1231 }
1232 if (info->GPRSPoint) {
1233 GPRSPoint.Location = 1;
1234 error = s->Phone.Functions->GetGPRSAccessPoint(s,&GPRSPoint);
1235 if (error == ERR_NONE || error == ERR_EMPTY) {
1236 } else {
1237 info->GPRSPoint = false;
1238 }
1239 }
1240}
1241
1242#endif
1243
1244/* How should editor hadle tabs in this file? Add editor commands here.
1245 * vim: noexpandtab sw=8 ts=8 sts=8:
1246 */
diff --git a/gammu/emb/common/gsmstate.h b/gammu/emb/common/gsmstate.h
new file mode 100644
index 0000000..cb17623
--- a/dev/null
+++ b/gammu/emb/common/gsmstate.h
@@ -0,0 +1,1562 @@
1/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
2
3#ifndef __gsm_state_h
4#define __gsm_state_h
5
6#include <time.h>
7
8#include "config.h"
9#include "misc/cfg.h"
10
11#ifdef GSM_ENABLE_NOKIA3320
12# include "phone/nokia/dct4/n3320.h"
13#endif
14#ifdef GSM_ENABLE_NOKIA3650
15# include "phone/nokia/dct4/n3650.h"
16#endif
17#ifdef GSM_ENABLE_NOKIA6110
18# include "phone/nokia/dct3/n6110.h"
19#endif
20#ifdef GSM_ENABLE_NOKIA6510
21# include "phone/nokia/dct4/n6510.h"
22#endif
23#ifdef GSM_ENABLE_NOKIA7110
24# include "phone/nokia/dct3/n7110.h"
25#endif
26#ifdef GSM_ENABLE_NOKIA9210
27# include "phone/nokia/dct3/n9210.h"
28#endif
29#ifdef GSM_ENABLE_ATGEN
30# include "phone/at/atgen.h"
31#endif
32#ifdef GSM_ENABLE_ALCATEL
33# include "phone/alcatel/alcatel.h"
34#endif
35#ifdef GSM_ENABLE_OBEXGEN
36# include "phone/obex/obexgen.h"
37#endif
38#ifdef GSM_ENABLE_MROUTERGEN
39# include "phone/symbian/mroutgen.h"
40#endif
41
42#ifndef GSM_USED_MBUS2
43# undef GSM_ENABLE_MBUS2
44#endif
45#ifndef GSM_USED_FBUS2
46# undef GSM_ENABLE_FBUS2
47#endif
48#ifndef GSM_USED_FBUS2DLR3
49# undef GSM_ENABLE_FBUS2DLR3
50#endif
51#ifndef GSM_USED_FBUS2DKU5
52# undef GSM_ENABLE_FBUS2DKU5
53#endif
54#ifndef GSM_USED_FBUS2PL2303
55# undef GSM_ENABLE_FBUS2PL2303
56#endif
57#ifndef GSM_USED_FBUS2BLUE
58# undef GSM_ENABLE_FBUS2BLUE
59#endif
60#ifndef GSM_USED_FBUS2IRDA
61# undef GSM_ENABLE_FBUS2IRDA
62#endif
63#ifndef GSM_USED_PHONETBLUE
64# undef GSM_ENABLE_PHONETBLUE
65#endif
66#ifndef GSM_USED_AT
67# undef GSM_ENABLE_AT
68#endif
69#ifndef GSM_USED_IRDAOBEX
70# undef GSM_ENABLE_IRDAOBEX
71#endif
72#ifndef GSM_USED_BLUEOBEX
73# undef GSM_ENABLE_BLUEOBEX
74#endif
75#ifndef GSM_USED_ALCABUS
76# undef GSM_ENABLE_ALCABUS
77#endif
78#ifndef GSM_USED_IRDAPHONET
79# undef GSM_ENABLE_IRDAPHONET
80#endif
81#ifndef GSM_USED_BLUEFBUS2
82# undef GSM_ENABLE_BLUEFBUS2
83#endif
84#ifndef GSM_USED_BLUEPHONET
85# undef GSM_ENABLE_BLUEPHONET
86#endif
87#ifndef GSM_USED_BLUEAT
88# undef GSM_ENABLE_BLUEAT
89#endif
90#ifndef GSM_USED_IRDAAT
91# undef GSM_ENABLE_IRDAAT
92#endif
93#ifndef GSM_USED_MROUTERBLUE
94# undef GSM_ENABLE_MROUTERBLUE
95#endif
96
97#if defined(GSM_ENABLE_NOKIA3320) || defined(GSM_ENABLE_NOKIA6110) || defined(GSM_ENABLE_NOKIA7110) || defined(GSM_ENABLE_NOKIA9210)
98# define GSM_ENABLE_NOKIA_DCT3
99#endif
100#if defined(GSM_ENABLE_NOKIA3650) || defined(GSM_ENABLE_NOKIA6510)
101# define GSM_ENABLE_NOKIA_DCT4
102#endif
103
104#include "protocol/protocol.h"
105#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)
106# include "protocol/nokia/fbus2.h"
107#endif
108#ifdef GSM_ENABLE_MBUS2
109# include "protocol/nokia/mbus2.h"
110#endif
111#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
112# include "protocol/nokia/phonet.h"
113#endif
114#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
115# include "protocol/at/at.h"
116#endif
117#ifdef GSM_ENABLE_ALCABUS
118# include "protocol/alcatel/alcabus.h"
119#endif
120#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
121# include "protocol/obex/obex.h"
122#endif
123#if defined(GSM_ENABLE_MROUTERBLUE)
124# include "protocol/symbian/mrouter.h"
125#endif
126
127#define GSM_ENABLE_SERIALDEVICE
128#ifndef GSM_USED_SERIALDEVICE
129# undef GSM_ENABLE_SERIALDEVICE
130#endif
131#define GSM_ENABLE_IRDADEVICE
132#ifndef GSM_USED_IRDADEVICE
133# undef GSM_ENABLE_IRDADEVICE
134#endif
135#define GSM_ENABLE_BLUETOOTHDEVICE
136#ifndef GSM_USED_BLUETOOTHDEVICE
137# undef GSM_ENABLE_BLUETOOTHDEVICE
138#endif
139
140#ifdef DJGPP
141# undef GSM_ENABLE_IRDADEVICE
142# undef GSM_ENABLE_IRDAPHONET
143# undef GSM_ENABLE_IRDAOBEX
144# undef GSM_ENABLE_IRDAAT
145# undef GSM_ENABLE_FBUS2IRDA
146
147# undef GSM_ENABLE_BLUETOOTHDEVICE
148# undef GSM_ENABLE_BLUEPHONET
149# undef GSM_ENABLE_BLUEOBEX
150# undef GSM_ENABLE_BLUEAT
151# undef GSM_ENABLE_BLUEFBUS2
152# undef GSM_ENABLE_PHONETBLUE
153# undef GSM_ENABLE_FBUS2BLUE
154# undef GSM_ENABLE_MROUTERBLUE
155#endif
156
157#ifndef WIN32
158# ifdef ENABLE_LGPL
159# undef GSM_ENABLE_IRDADEVICE
160# undef GSM_ENABLE_IRDAPHONET
161# undef GSM_ENABLE_IRDAOBEX
162# undef GSM_ENABLE_IRDAAT
163# undef GSM_ENABLE_FBUS2IRDA
164
165# undef GSM_ENABLE_BLUETOOTHDEVICE
166# undef GSM_ENABLE_BLUEPHONET
167# undef GSM_ENABLE_BLUEOBEX
168# undef GSM_ENABLE_BLUEAT
169# undef GSM_ENABLE_BLUEFBUS2
170# undef GSM_ENABLE_PHONETBLUE
171# undef GSM_ENABLE_FBUS2BLUE
172# undef GSM_ENABLE_MROUTERBLUE
173# endif
174#endif
175
176#ifdef GSM_ENABLE_SERIALDEVICE
177# include "device/serial/ser_w32.h"
178# include "device/serial/ser_unx.h"
179# include "device/serial/ser_djg.h"
180#endif
181#ifdef GSM_ENABLE_IRDADEVICE
182# include "device/irda/irda.h"
183#endif
184#ifdef GSM_ENABLE_BLUETOOTHDEVICE
185# include "device/bluetoth/bluetoth.h"
186#endif
187
188#include "service/gsmpbk.h"
189#include "service/gsmnet.h"
190#include "service/gsmring.h"
191#include "service/gsmcal.h"
192#include "service/gsmdata.h"
193#include "service/gsmlogo.h"
194#include "service/gsmmisc.h"
195#include "service/gsmprof.h"
196#include "service/gsmcall.h"
197#include "service/sms/gsmsms.h"
198#include "service/sms/gsmems.h"
199#include "service/sms/gsmmulti.h"
200#include "service/backup/gsmback.h"
201
202typedef struct _GSM_StateMachine GSM_StateMachine;
203 typedef struct _GSM_User GSM_User;
204 typedef struct _OnePhoneModel OnePhoneModel;
205
206/* ------------------------- Device layer ---------------------------------- */
207
208/**
209 * Device functions, each device has to provide these.
210 */
211typedef struct {
212 /**
213 * Opens device.
214 */
215 GSM_Error (*OpenDevice) (GSM_StateMachine *s);
216 /**
217 * Closes device.
218 */
219 GSM_Error (*CloseDevice) (GSM_StateMachine *s);
220 /**
221 * Sets parity for device.
222 */
223 GSM_Error (*DeviceSetParity) (GSM_StateMachine *s, bool parity);
224 /**
225 * Sets dtr (data to read) and rts (ready to send) flags.
226 */
227 GSM_Error (*DeviceSetDtrRts) (GSM_StateMachine *s, bool dtr, bool rts);
228 /**
229 * Sets device speed.
230 */
231 GSM_Error (*DeviceSetSpeed) (GSM_StateMachine *s, int speed);
232 /**
233 * Attempts to read nbytes from device.
234 */
235 int (*ReadDevice) (GSM_StateMachine *s, void *buf, size_t nbytes);
236 /**
237 * Attempts to read nbytes from device.
238 */
239 int (*WriteDevice) (GSM_StateMachine *s, void *buf, size_t nbytes);
240} GSM_Device_Functions;
241
242#ifdef GSM_ENABLE_SERIALDEVICE
243 extern GSM_Device_Functions SerialDevice;
244#endif
245#ifdef GSM_ENABLE_IRDADEVICE
246 extern GSM_Device_Functions IrdaDevice;
247#endif
248#ifdef GSM_ENABLE_BLUETOOTHDEVICE
249 extern GSM_Device_Functions BlueToothDevice;
250#endif
251
252/**
253 * Structure containing device specific data and pointer to device functions -
254 * @ref GSM_Device_Functions. The data are in a union, so you can use only
255 * one device at one time.
256 */
257typedef struct {
258 union {
259 char fake;
260#ifdef GSM_ENABLE_SERIALDEVICE
261 GSM_Device_SerialData Serial;
262#endif
263#ifdef GSM_ENABLE_IRDADEVICE
264 GSM_Device_IrdaData Irda;
265#endif
266#ifdef GSM_ENABLE_BLUETOOTHDEVICE
267 GSM_Device_BlueToothDataBlueTooth;
268#endif
269 } Data;
270 GSM_Device_Functions *Functions;
271} GSM_Device;
272
273/* ---------------------- Protocol layer ----------------------------------- */
274
275/**
276 * Protocol functions, each protocol has to implement these.
277 */
278typedef struct {
279 /**
280 * Writes message to device.
281 */
282 GSM_Error (*WriteMessage) (GSM_StateMachine *s, unsigned char *buffer,
283 int length, unsigned char type);
284 /**
285 * This one is called when character is received from device.
286 */
287 GSM_Error (*StateMachine) (GSM_StateMachine *s, unsigned char rx_char);
288 /**
289 * Protocol initialisation.
290 */
291 GSM_Error (*Initialise) (GSM_StateMachine *s);
292 /**
293 * Protocol termination.
294 */
295 GSM_Error (*Terminate) (GSM_StateMachine *s);
296} GSM_Protocol_Functions;
297
298#ifdef GSM_ENABLE_MBUS2
299 extern GSM_Protocol_Functions MBUS2Protocol;
300#endif
301#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)
302 extern GSM_Protocol_Functions FBUS2Protocol;
303#endif
304#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
305 extern GSM_Protocol_Functions PHONETProtocol;
306#endif
307#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
308 extern GSM_Protocol_Functions ATProtocol;
309#endif
310#ifdef GSM_ENABLE_ALCABUS
311 extern GSM_Protocol_Functions ALCABUSProtocol;
312#endif
313#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
314 extern GSM_Protocol_Functions OBEXProtocol;
315#endif
316#if defined(GSM_ENABLE_MROUTERBLUE)
317 extern GSM_Protocol_Functions MROUTERProtocol;
318#endif
319
320/**
321 * Structure containing protocol specific data and pointer to protocol
322 * functions - @ref GSM_Protocol_Functions. The data are in a structure, so
323 * you may use more protocols at once and switch between them.
324 */
325typedef struct {
326 struct {
327 char fake;
328#ifdef GSM_ENABLE_MBUS2
329 GSM_Protocol_MBUS2Data MBUS2;
330#endif
331#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)
332 GSM_Protocol_FBUS2Data FBUS2;
333#endif
334#if defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_IRDAPHONET) || defined(GSM_ENABLE_BLUEPHONET)
335 GSM_Protocol_PHONETData PHONET;
336#endif
337#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
338 GSM_Protocol_ATData AT;
339#endif
340#ifdef GSM_ENABLE_ALCABUS
341 GSM_Protocol_ALCABUSDataALCABUS;
342#endif
343#if defined(GSM_ENABLE_IRDAOBEX) || defined(GSM_ENABLE_BLUEOBEX)
344 GSM_Protocol_OBEXData OBEX;
345#endif
346#if defined(GSM_ENABLE_MROUTERBLUE)
347 GSM_Protocol_MROUTERDataMROUTER;
348#endif
349 } Data;
350 GSM_Protocol_Functions *Functions;
351} GSM_Protocol;
352
353/* -------------------------- Phone layer ---------------------------------- */
354
355/**
356 * Phone requests identificators, these are used for internally identifying
357 * which operation is being performed.
358 */
359typedef enum {
360 ID_None=1,
361 ID_GetModel,
362 ID_GetFirmware,
363 ID_EnableSecurity,
364 ID_GetIMEI,
365 ID_GetDateTime,
366 ID_GetAlarm,
367 ID_GetMemory,
368 ID_GetMemoryStatus,
369 ID_GetSMSC,
370 ID_GetSMSMessage,
371 ID_EnableEcho,
372 ID_EnableErrorInfo,
373 ID_SetOBEX,
374 ID_GetSignalQuality,
375 ID_GetBatteryCharge,
376 ID_GetSMSFolders,
377 ID_GetSMSFolderStatus,
378 ID_GetSMSStatus,
379 ID_AddSMSFolder,
380 ID_GetNetworkInfo,
381 ID_GetRingtone,
382 ID_DialVoice,
383 ID_GetCalendarNotesInfo,
384 ID_GetCalendarNote,
385 ID_GetSecurityCode,
386 ID_GetWAPBookmark,
387 ID_GetBitmap,
388 ID_SaveSMSMessage,
389 ID_CancelCall,
390 ID_SetDateTime,
391 ID_SetAlarm,
392 ID_DisableConnectFunc,
393 ID_EnableConnectFunc,
394 ID_AnswerCall,
395 ID_SetBitmap,
396 ID_SetRingtone,
397 ID_DeleteSMSMessage,
398 ID_DeleteCalendarNote,
399 ID_SetPath,
400 ID_SetSMSC,
401 ID_SetProfile,
402 ID_SetMemory,
403 ID_DeleteMemory,
404 ID_SetCalendarNote,
405 ID_SetIncomingSMS,
406 ID_SetIncomingCB,
407 ID_GetCalendarNotePos,
408 ID_Initialise,
409 ID_GetConnectSet,
410 ID_SetWAPBookmark,
411 ID_GetLocale,
412 ID_SetLocale,
413 ID_GetCalendarSettings,
414 ID_SetCalendarSettings,
415 ID_GetGPRSPoint,
416 ID_SetGPRSPoint,
417 ID_EnableGPRSPoint,
418 ID_DeleteWAPBookmark,
419 ID_Netmonitor,
420 ID_HoldCall,
421 ID_UnholdCall,
422 ID_ConferenceCall,
423 ID_SplitCall,
424 ID_TransferCall,
425 ID_SwitchCall,
426 ID_GetManufactureMonth,
427 ID_GetProductCode,
428 ID_GetOriginalIMEI,
429 ID_GetHardware,
430 ID_GetPPM,
431 ID_GetSMSMode,
432 ID_GetSMSMemories,
433 ID_GetManufacturer,
434 ID_SetMemoryType,
435 ID_SetMemoryCharset,
436 ID_GetMMSSettings,
437 ID_SetSMSParameters,
438 ID_GetFMStation,
439 ID_SetFMStation,
440 ID_GetLanguage,
441 ID_Reset,
442 ID_GetToDo,
443 ID_PressKey,
444 ID_DeleteAllToDo,
445 ID_SetLight,
446 ID_Divert,
447 ID_SetToDo,
448 ID_PlayTone,
449 ID_GetChatSettings,
450 ID_GetSyncMLSettings,
451 ID_GetSyncMLName,
452 ID_GetSecurityStatus,
453 ID_EnterSecurityCode,
454 ID_GetProfile,
455 ID_GetRingtonesInfo,
456 ID_MakeAuthentication,
457 ID_GetSpeedDial,
458 ID_ResetPhoneSettings,
459 ID_SendDTMF,
460 ID_GetDisplayStatus,
461 ID_SetAutoNetworkLogin,
462 ID_SetConnectSet,
463 ID_SetMMSSettings,
464 ID_GetSIMIMSI,
465 ID_GetFileInfo,
466 ID_FileSystemStatus,
467 ID_GetFile,
468 ID_AddFile,
469 ID_AddFolder,
470 ID_DeleteFile,
471#ifdef GSM_ENABLE_ALCATEL
472 /* AT mode */
473 ID_SetFlowControl,
474 ID_AlcatelConnect,
475 ID_AlcatelProtocol,
476
477 /* Binary mode */
478 ID_AlcatelAttach,
479 ID_AlcatelDetach,
480 ID_AlcatelCommit,
481 ID_AlcatelCommit2,
482 ID_AlcatelEnd,
483 ID_AlcatelClose,
484 ID_AlcatelStart,
485 ID_AlcatelSelect1,
486 ID_AlcatelSelect2,
487 ID_AlcatelSelect3,
488 ID_AlcatelBegin1,
489 ID_AlcatelBegin2,
490 ID_AlcatelGetIds1,
491 ID_AlcatelGetIds2,
492 ID_AlcatelGetCategories1,
493 ID_AlcatelGetCategories2,
494 ID_AlcatelGetCategoryText1,
495 ID_AlcatelGetCategoryText2,
496 ID_AlcatelAddCategoryText1,
497 ID_AlcatelAddCategoryText2,
498 ID_AlcatelGetFields1,
499 ID_AlcatelGetFields2,
500 ID_AlcatelGetFieldValue1,
501 ID_AlcatelGetFieldValue2,
502 ID_AlcatelDeleteItem1,
503 ID_AlcatelDeleteItem2,
504 ID_AlcatelDeleteField,
505 ID_AlcatelCreateField,
506 ID_AlcatelUpdateField,
507#endif
508 ID_IncomingFrame,
509
510 ID_User1,
511 ID_User2,
512 ID_User3,
513 ID_User4,
514 ID_User5,
515 ID_User6,
516 ID_User7,
517 ID_User8,
518 ID_User9,
519 ID_User10,
520
521 ID_EachFrame
522} GSM_Phone_RequestID;
523
524/**
525 * Phone related data are stored here.
526 */
527typedef struct {
528 /**
529 * Phone IMEI (or serial number).
530 */
531 char IMEI[MAX_IMEI_LENGTH];
532 /**
533 * Phone manufacturer as reported by phone.
534 */
535 char Manufacturer[MAX_MANUFACTURER_LENGTH];
536 /**
537 * Phone model as reported by phone.
538 */
539 char Model[MAX_MODEL_LENGTH];
540 /**
541 * Model information, pointer to static @ref allmodels array.
542 */
543 OnePhoneModel *ModelInfo;
544 /**
545 * Phone version as reported by phone. It doesn't have to be numerical
546 * at all.
547 */
548 char Version[MAX_VERSION_LENGTH];
549 /**
550 * Phone version date, might be empty for some models.
551 */
552 char VerDate[MAX_VERSION_DATE_LENGTH];
553 /**
554 * Phone version as number, if applicable.
555 */
556 double VerNum;
557 /**
558 * Cache for hardware version used by some modules.
559 */
560 char HardwareCache[50];
561 /**
562 * Cache for product code version used by some modules.
563 */
564 char ProductCodeCache[50];
565
566 /**
567 * Counter used for disabling startup info on phone, see
568 * @ref GSM_Phone_Functions::ShowStartInfo . After this is 0, the startup info is hidden.
569 */
570 int StartInfoCounter;
571
572 /**
573 * Pointer to structure used internally by phone drivers.
574 */
575 GSM_GPRSAccessPoint*GPRSPoint;
576 /**
577 * Pointer to structure used internally by phone drivers.
578 */
579 GSM_SpeedDial *SpeedDial;
580 /**
581 * Pointer to structure used internally by phone drivers.
582 */
583 GSM_DateTime *DateTime;
584 /**
585 * Pointer to structure used internally by phone drivers.
586 */
587 GSM_Alarm *Alarm;
588 /**
589 * Pointer to structure used internally by phone drivers.
590 */
591 GSM_MemoryEntry *Memory;
592 /**
593 * Pointer to structure used internally by phone drivers.
594 */
595 GSM_MemoryStatus*MemoryStatus;
596 /**
597 * Pointer to structure used internally by phone drivers.
598 */
599 GSM_SMSC *SMSC;
600 /**
601 * Pointer to structure used internally by phone drivers.
602 */
603 GSM_MultiSMSMessage*GetSMSMessage;
604 /**
605 * Pointer to structure used internally by phone drivers.
606 */
607 GSM_SMSMessage *SaveSMSMessage;
608 /**
609 * Pointer to structure used internally by phone drivers.
610 */
611 GSM_SMSMemoryStatus*SMSStatus;
612 /**
613 * Pointer to structure used internally by phone drivers.
614 */
615 GSM_SMSFolders *SMSFolders;
616 /**
617 * Used internally by phone drivers.
618 */
619 int *VoiceRecord;
620 /**
621 * Used internally by phone drivers.
622 */
623 int CallID;
624 /**
625 * Pointer to structure used internally by phone drivers.
626 */
627 GSM_SignalQuality*SignalQuality;
628 /**
629 * Pointer to structure used internally by phone drivers.
630 */
631 GSM_BatteryCharge*BatteryCharge;
632 /**
633 * Pointer to structure used internally by phone drivers.
634 */
635 GSM_NetworkInfo *NetworkInfo;
636 /**
637 * Pointer to structure used internally by phone drivers.
638 */
639 GSM_Ringtone *Ringtone;
640 /**
641 * Pointer to structure used internally by phone drivers.
642 */
643 GSM_CalendarEntry*Cal;
644 /**
645 * Used internally by phone drivers.
646 */
647 unsigned char *SecurityCode;
648 /**
649 * Pointer to structure used internally by phone drivers.
650 */
651 GSM_WAPBookmark *WAPBookmark;
652 /**
653 * Pointer to structure used internally by phone drivers.
654 */
655 GSM_MultiWAPSettings*WAPSettings;
656 /**
657 * Pointer to structure used internally by phone drivers.
658 */
659 GSM_Bitmap *Bitmap;
660 /**
661 * Used internally by phone drivers.
662 */
663 unsigned char *Netmonitor;
664 /**
665 * Pointer to structure used internally by phone drivers.
666 */
667 GSM_MultiCallDivert*Divert;
668 /**
669 * Pointer to structure used internally by phone drivers.
670 */
671 GSM_ToDoEntry *ToDo;
672 /**
673 * Used internally by phone drivers.
674 */
675 bool PressKey;
676 /**
677 * Pointer to structure used internally by phone drivers.
678 */
679 GSM_SecurityCodeType*SecurityStatus;
680 /**
681 * Pointer to structure used internally by phone drivers.
682 */
683 GSM_Profile *Profile;
684 /**
685 * Pointer to structure used internally by phone drivers.
686 */
687 GSM_AllRingtonesInfo*RingtonesInfo;
688 /**
689 * Pointer to structure used internally by phone drivers.
690 */
691 GSM_DisplayFeatures*DisplayFeatures;
692 /**
693 * Pointer to structure used internally by phone drivers.
694 */
695 GSM_FMStation *FMStation;
696 /**
697 * Pointer to structure used internally by phone drivers.
698 */
699 GSM_Locale *Locale;
700 /**
701 * Pointer to structure used internally by phone drivers.
702 */
703 GSM_CalendarSettings*CalendarSettings;
704 /**
705 * Used internally by phone drivers.
706 */
707 unsigned char *PhoneString;
708 /**
709 * Used internally by phone drivers.
710 */
711 int StartPhoneString;
712 /**
713 * Pointer to structure used internally by phone drivers.
714 */
715 GSM_File *FileInfo;
716 /**
717 * Pointer to structure used internally by phone drivers.
718 */
719 GSM_File *File;
720 /**
721 * Pointer to structure used internally by phone drivers.
722 */
723 GSM_FileSystemStatus*FileSystemStatus;
724 GSM_ChatSettings*ChatSettings;
725 GSM_SyncMLSettings*SyncMLSettings;
726
727 /**
728 * Should phone notify about incoming calls?
729 */
730 bool EnableIncomingCall;
731 /**
732 * Should phone notify about incoming SMSes?
733 */
734 bool EnableIncomingSMS;
735 /**
736 * Should phone notify about incoming CBs?
737 */
738 bool EnableIncomingCB;
739 /**
740 * Should phone notify about incoming USSDs?
741 */
742 bool EnableIncomingUSSD;
743
744 /**
745 * Last message received from phone.
746 */
747 GSM_Protocol_Message*RequestMsg;
748 /**
749 * Last message sent by Gammu.
750 */
751 GSM_Protocol_Message*SentMsg;
752 /**
753 * What operation is being performed now, see @ref GSM_Phone_RequestID
754 * for possible values.
755 */
756 GSM_Phone_RequestIDRequestID;
757 /**
758 * Error returned by function in phone module.
759 */
760 GSM_Error DispatchError;
761
762 /**
763 * Structure with private phone modules data.
764 */
765 struct {
766 int fake;
767#ifdef GSM_ENABLE_NOKIA3320
768 GSM_Phone_N3320Data N3320;
769#endif
770#ifdef GSM_ENABLE_NOKIA3650
771 GSM_Phone_N3650Data N3650;
772#endif
773#ifdef GSM_ENABLE_NOKIA6110
774 GSM_Phone_N6110Data N6110;
775#endif
776#ifdef GSM_ENABLE_NOKIA6510
777 GSM_Phone_N6510Data N6510;
778#endif
779#ifdef GSM_ENABLE_NOKIA7110
780 GSM_Phone_N7110Data N7110;
781#endif
782#ifdef GSM_ENABLE_ATGEN
783 GSM_Phone_ATGENData ATGEN;
784#endif
785#ifdef GSM_ENABLE_ALCATEL
786 GSM_Phone_ALCATELData ALCATEL;
787#endif
788#ifdef GSM_ENABLE_OBEXGEN
789 GSM_Phone_OBEXGENData OBEXGEN;
790#endif
791#ifdef GSM_ENABLE_MROUTERGEN
792 GSM_Phone_MROUTERGENData MROUTERGEN;
793#endif
794 } Priv;
795} GSM_Phone_Data;
796
797/**
798 * Structure for defining reply functions.
799 *
800 * Function is called when requestID matches current operation or is
801 * ID_IncomingFrame and msgtype matches start message and (if msgtype is just
802 * one character) subtypechar is zero or subtypechar-th character of message
803 * matches subtype.
804 *
805 * Should be used in array with last element containing ID_None as requestID.
806 */
807typedef struct {
808 /**
809 * Pointer to function that should be executed.
810 */
811 GSM_Error (*Function)(GSM_Protocol_Message msg, GSM_StateMachine *s);
812 /**
813 * Message type, if it is longer than 1 character, it disables subtype
814 * checking.
815 */
816 unsigned char *msgtype;
817 /**
818 * Which character of message should be checked as subtype. Zero to
819 * disable subtype checking.
820 */
821 int subtypechar;
822 /**
823 * Subtype to be checked.
824 */
825 unsigned char subtype;
826 /**
827 * Phone request when this can be called, use ID_IncomingFrame when
828 * you want to use this in any state.
829 */
830 GSM_Phone_RequestIDrequestID;
831} GSM_Reply_Function;
832
833/**
834 * Structure defining phone functions.
835 */
836typedef struct {
837 /**
838 * Names of supported models separated by |. Must contain at least one
839 * name.
840 */
841 char *models;
842 /**
843 * Array of reply functions for the phone, see
844 * @ref GSM_Reply_Function for details about it.
845 */
846 GSM_Reply_Function *ReplyFunctions;
847 /**
848 * Initializes phone.
849 */
850 GSM_Error (*Initialise) (GSM_StateMachine *s);
851 /**
852 * Terminates phone communication.
853 */
854 GSM_Error (*Terminate) (GSM_StateMachine *s);
855 /**
856 * Dispatches messages from phone, at the end it should call
857 * @ref GSM_DispatchMessage.
858 */
859 GSM_Error (*DispatchMessage) (GSM_StateMachine *s);
860 /**
861 * Enables showing information on phone display.
862 */
863 GSM_Error (*ShowStartInfo) (GSM_StateMachine *s, bool enable);
864 /**
865 * Reads manufacturer from phone.
866 */
867 GSM_Error (*GetManufacturer) (GSM_StateMachine *s);
868 /**
869 * Reads model from phone.
870 */
871 GSM_Error (*GetModel) (GSM_StateMachine *s);
872 /**
873 * Reads firmware information from phone.
874 */
875 GSM_Error (*GetFirmware)(GSM_StateMachine *s);
876 /**
877 * Reads IMEI/serial number from phone.
878 */
879 GSM_Error (*GetIMEI) (GSM_StateMachine *s);
880 /**
881 * Gets date and time from phone.
882 */
883 GSM_Error (*GetOriginalIMEI) (GSM_StateMachine *s, char *value);
884 /**
885 * Gets month when device was manufactured.
886 */
887 GSM_Error (*GetManufactureMonth)(GSM_StateMachine *s, char *value);
888 /**
889 * Gets product code of device.
890 */
891 GSM_Error (*GetProductCode) (GSM_StateMachine *s, char *value);
892 /**
893 * Gets hardware information about device.
894 */
895 GSM_Error (*GetHardware)(GSM_StateMachine *s, char *value);
896 /**
897 * Gets PPM (Post Programmable Memory) info from phone
898 * (in other words for Nokia get, which language pack is in phone)
899 */
900 GSM_Error (*GetPPM) (GSM_StateMachine *s, char *value);
901 /**
902 * Gets SIM IMSI from phone.
903 */
904 GSM_Error (*GetSIMIMSI) (GSM_StateMachine *s, char *IMSI);
905 /**
906 * Reads date and time from phone.
907 */
908 GSM_Error (*GetDateTime)(GSM_StateMachine *s, GSM_DateTime *date_time);
909 /**
910 * Sets date and time in phone.
911 */
912 GSM_Error (*SetDateTime)(GSM_StateMachine *s, GSM_DateTime *date_time);
913 /**
914 * Reads alarm set in phone.
915 */
916 GSM_Error (*GetAlarm) (GSM_StateMachine *s, GSM_Alarm*alarm);
917 /**
918 * Sets alarm in phone.
919 */
920 GSM_Error (*SetAlarm) (GSM_StateMachine *s, GSM_Alarm *alarm);
921 /**
922 * Gets locale from phone.
923 */
924 GSM_Error (*GetLocale) (GSM_StateMachine *s, GSM_Locale *locale);
925 /**
926 * Sets locale of phone.
927 */
928 GSM_Error (*SetLocale) (GSM_StateMachine *s, GSM_Locale *locale);
929 /**
930 * Emulates key press or key release.
931 */
932 GSM_Error (*PressKey) (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
933 /**
934 * Performs phone reset.
935 */
936 GSM_Error (*Reset) (GSM_StateMachine *s, bool hard);
937 /**
938 * Resets phone settings.
939 */
940 GSM_Error (*ResetPhoneSettings) (GSM_StateMachine *s, GSM_ResetSettingsType Type);
941 /**
942 * Enters security code (PIN, PUK,...) .
943 */
944 GSM_Error (*EnterSecurityCode) (GSM_StateMachine *s, GSM_SecurityCode Code);
945 /**
946 * Queries whether some security code needs to be entered./
947 */
948 GSM_Error (*GetSecurityStatus) (GSM_StateMachine *s, GSM_SecurityCodeType *Status);
949 /**
950 * Acquired display status.
951 */
952 GSM_Error (*GetDisplayStatus) (GSM_StateMachine *s, GSM_DisplayFeatures *features);
953 /**
954 * Enables network auto login.
955 */
956 GSM_Error (*SetAutoNetworkLogin)(GSM_StateMachine *s);
957 /**
958 * Gets information about batery charge and phone charging state.
959 */
960 GSM_Error (*GetBatteryCharge) (GSM_StateMachine *s, GSM_BatteryCharge *bat);
961 /**
962 * Reads signal quality (strength and error rate).
963 */
964 GSM_Error (*GetSignalQuality) (GSM_StateMachine *s, GSM_SignalQuality *sig);
965 /**
966 * Gets network information.
967 */
968 GSM_Error (*GetNetworkInfo) (GSM_StateMachine *s, GSM_NetworkInfo *netinfo);
969 /**
970 * Reads category from phone.
971 */
972 GSM_Error (*GetCategory)(GSM_StateMachine *s, GSM_Category *Category);
973 /**
974 * Adds category to phone.
975 */
976 GSM_Error (*AddCategory)(GSM_StateMachine *s, GSM_Category *Category);
977 /**
978 * Reads category status (number of used entries) from phone.
979 */
980 GSM_Error (*GetCategoryStatus) (GSM_StateMachine *s, GSM_CategoryStatus *Status);
981 /**
982 * Gets memory (phonebooks or calls) status (eg. number of used and
983 * free entries).
984 */
985 GSM_Error (*GetMemoryStatus) (GSM_StateMachine *s, GSM_MemoryStatus *status);
986 /**
987 * Reads entry from memory (phonebooks or calls). Which entry should
988 * be read is defined in entry.
989 */
990 GSM_Error (*GetMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
991 /**
992 * Reads entry from memory (phonebooks or calls). Which entry should
993 * be read is defined in entry. This can be easily used for reading all entries.
994 */
995 GSM_Error (*GetNextMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start);
996 /**
997 * Sets memory (phonebooks or calls) entry.
998 */
999 GSM_Error (*SetMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
1000 /**
1001 * Deletes memory (phonebooks or calls) entry.
1002 */
1003 GSM_Error (*AddMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
1004 /**
1005 * Deletes memory (phonebooks or calls) entry.
1006 */
1007 GSM_Error (*DeleteMemory) (GSM_StateMachine *s, GSM_MemoryEntry *entry);
1008 /**
1009 * Deletes all memory (phonebooks or calls) entries of specified type.
1010 */
1011 GSM_Error (*DeleteAllMemory) (GSM_StateMachine *s, GSM_MemoryType MemoryType);
1012 /**
1013 * Gets speed dial.
1014 */
1015 GSM_Error (*GetSpeedDial) (GSM_StateMachine *s, GSM_SpeedDial *Speed);
1016 /**
1017 * Sets speed dial.
1018 */
1019 GSM_Error (*SetSpeedDial) (GSM_StateMachine *s, GSM_SpeedDial *Speed);
1020 /**
1021 * Gets SMS Service Center number and SMS settings.
1022 */
1023 GSM_Error (*GetSMSC) (GSM_StateMachine *s, GSM_SMSC *smsc);
1024 /**
1025 * Sets SMS Service Center number and SMS settings.
1026 */
1027 GSM_Error (*SetSMSC) (GSM_StateMachine *s, GSM_SMSC *smsc);
1028 /**
1029 * Gets information about SMS memory (read/unread/size of memory for
1030 * both SIM and phone).
1031 */
1032 GSM_Error (*GetSMSStatus) (GSM_StateMachine *s, GSM_SMSMemoryStatus *status);
1033 /**
1034 * Reads SMS message.
1035 */
1036 GSM_Error (*GetSMS) (GSM_StateMachine *s, GSM_MultiSMSMessage *sms);
1037 /**
1038 * Reads next (or first if start set) SMS message. This might be
1039 * faster for some phones than using @ref GetSMS for each message.
1040 */
1041 GSM_Error (*GetNextSMS) (GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start);
1042 /**
1043 * Sets SMS.
1044 */
1045 GSM_Error (*SetSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
1046 /**
1047 * Adds SMS to specified folder.
1048 */
1049 GSM_Error (*AddSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
1050 /**
1051 * Deletes SMS.
1052 */
1053 GSM_Error (*DeleteSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
1054 /**
1055 * Sends SMS.
1056 */
1057 GSM_Error (*SendSMS) (GSM_StateMachine *s, GSM_SMSMessage *sms);
1058 /**
1059 * Sends SMS already saved in phone.
1060 */
1061 GSM_Error (*SendSavedSMS)(GSM_StateMachine *s, int Folder, int Location);
1062 /**
1063 * Enable/disable notification on incoming SMS.
1064 */
1065 GSM_Error (*SetIncomingSMS) (GSM_StateMachine *s, bool enable);
1066 /**
1067 * Gets network information from phone.
1068 */
1069 GSM_Error (*SetIncomingCB) (GSM_StateMachine *s, bool enable);
1070 /**
1071 * Returns SMS folders information.
1072 */
1073 GSM_Error (*GetSMSFolders) (GSM_StateMachine *s, GSM_SMSFolders *folders);
1074 /**
1075 * Creates SMS folder.
1076 */
1077 GSM_Error (*AddSMSFolder) (GSM_StateMachine *s, unsigned char *name);
1078 /**
1079 * Deletes SMS folder.
1080 */
1081 GSM_Error (*DeleteSMSFolder) (GSM_StateMachine *s, int ID);
1082 /**
1083 * Dials number and starts voice call.
1084 */
1085 GSM_Error (*DialVoice) (GSM_StateMachine *s, char *Number, GSM_CallShowNumber ShowNumber);
1086 /**
1087 * Accept current incoming call.
1088 */
1089 GSM_Error (*AnswerCall) (GSM_StateMachine *s, int ID, bool all);
1090 /**
1091 * Deny current incoming call.
1092 */
1093 GSM_Error (*CancelCall) (GSM_StateMachine *s, int ID, bool all);
1094 /**
1095 * Holds call.
1096 */
1097 GSM_Error (*HoldCall) (GSM_StateMachine *s, int ID);
1098 /**
1099 * Unholds call.
1100 */
1101 GSM_Error (*UnholdCall) (GSM_StateMachine *s, int ID);
1102 /**
1103 * Initiates conference call.
1104 */
1105 GSM_Error (*ConferenceCall) (GSM_StateMachine *s, int ID);
1106 /**
1107 * Splits call.
1108 */
1109 GSM_Error (*SplitCall) (GSM_StateMachine *s, int ID);
1110 /**
1111 * Transfers call.
1112 */
1113 GSM_Error (*TransferCall) (GSM_StateMachine *s, int ID, bool next);
1114 /**
1115 * Switches call.
1116 */
1117 GSM_Error (*SwitchCall) (GSM_StateMachine *s, int ID, bool next);
1118 /**
1119 * Gets call diverts.
1120 */
1121 GSM_Error (*GetCallDivert) (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
1122 /**
1123 * Sets call diverts.
1124 */
1125 GSM_Error (*SetCallDivert) (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
1126 /**
1127 * Cancels all diverts.
1128 */
1129 GSM_Error (*CancelAllDiverts) (GSM_StateMachine *s);
1130 /**
1131 * Activates/deactivates noticing about incoming calls.
1132 */
1133 GSM_Error (*SetIncomingCall) (GSM_StateMachine *s, bool enable);
1134 /**
1135 * Activates/deactivates noticing about incoming USSDs (UnStructured Supplementary Services).
1136 */
1137 GSM_Error (*SetIncomingUSSD) (GSM_StateMachine *s, bool enable);
1138 /**
1139 * Sends DTMF (Dual Tone Multi Frequency) tone.
1140 */
1141 GSM_Error (*SendDTMF) (GSM_StateMachine *s, char *sequence);
1142 /**
1143 * Gets ringtone from phone.
1144 */
1145 GSM_Error (*GetRingtone)(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone);
1146 /**
1147 * Sets ringtone in phone.
1148 */
1149 GSM_Error (*SetRingtone)(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength);
1150 /**
1151 * Acquires ringtone informaiton.
1152 */
1153 GSM_Error (*GetRingtonesInfo) (GSM_StateMachine *s, GSM_AllRingtonesInfo *Info);
1154 /**
1155 * Deletes user defined ringtones from phone.
1156 */
1157 GSM_Error (*DeleteUserRingtones)(GSM_StateMachine *s);
1158 /**
1159 * Plays tone.
1160 */
1161 GSM_Error (*PlayTone) (GSM_StateMachine *s, int Herz, unsigned char Volume, bool start);
1162 /**
1163 * Reads WAP bookmark.
1164 */
1165 GSM_Error (*GetWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
1166 /**
1167 * Sets WAP bookmark.
1168 */
1169 GSM_Error (*SetWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
1170 /**
1171 * Deletes WAP bookmark.
1172 */
1173 GSM_Error (*DeleteWAPBookmark) (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
1174 /**
1175 * Acquires WAP settings.
1176 */
1177 GSM_Error (*GetWAPSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
1178 /**
1179 * Changes WAP settings.
1180 */
1181 GSM_Error (*SetWAPSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
1182 /**
1183 * Acquires MMS settings.
1184 */
1185 GSM_Error (*GetMMSSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
1186 /**
1187 * Changes MMS settings.
1188 */
1189 GSM_Error (*SetMMSSettings) (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
1190 /**
1191 * Acquires SyncML settings.
1192 */
1193 GSM_Error (*GetSyncMLSettings) (GSM_StateMachine *s, GSM_SyncMLSettings *settings);
1194 /**
1195 * Changes SyncML settings.
1196 */
1197 GSM_Error (*SetSyncMLSettings) (GSM_StateMachine *s, GSM_SyncMLSettings *settings);
1198 /**
1199 * Acquires chat/presence settings.
1200 */
1201 GSM_Error (*GetChatSettings) (GSM_StateMachine *s, GSM_ChatSettings *settings);
1202 /**
1203 * Changes chat/presence settings.
1204 */
1205 GSM_Error (*SetChatSettings) (GSM_StateMachine *s, GSM_ChatSettings *settings);
1206 /**
1207 * Gets bitmap.
1208 */
1209 GSM_Error (*GetBitmap) (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
1210 /**
1211 * Sets bitmap.
1212 */
1213 GSM_Error (*SetBitmap) (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
1214 /**
1215 * Gets status of ToDos (count of used entries).
1216 */
1217 GSM_Error (*GetToDoStatus) (GSM_StateMachine *s, GSM_ToDoStatus *status);
1218 /**
1219 * Reads ToDo from phone.
1220 */
1221 GSM_Error (*GetToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
1222 /**
1223 * Reads ToDo from phone.
1224 */
1225 GSM_Error (*GetNextToDo)(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start);
1226 /**
1227 * Sets ToDo in phone.
1228 */
1229 GSM_Error (*SetToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
1230 /**
1231 * Adds ToDo in phone.
1232 */
1233 GSM_Error (*AddToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
1234 /**
1235 * Deletes ToDo entry in phone.
1236 */
1237 GSM_Error (*DeleteToDo) (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
1238 /**
1239 * Deletes all todo entries in phone.
1240 */
1241 GSM_Error (*DeleteAllToDo) (GSM_StateMachine *s);
1242 /**
1243 * Retrieves calendar status (number of used entries).
1244 */
1245 GSM_Error (*GetCalendarStatus) (GSM_StateMachine *s, GSM_CalendarStatus *Status);
1246 /**
1247 * Retrieves calendar entry.
1248 */
1249 GSM_Error (*GetCalendar)(GSM_StateMachine *s, GSM_CalendarEntry *Note);
1250 /**
1251 * Retrieves calendar entry. This is useful for continuous reading of all
1252 * calendar entries.
1253 */
1254 GSM_Error (*GetNextCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
1255 /**
1256 * Sets calendar entry
1257 */
1258 GSM_Error (*SetCalendar)(GSM_StateMachine *s, GSM_CalendarEntry *Note);
1259 /**
1260 * Adds calendar entry.
1261 */
1262 GSM_Error (*AddCalendar)(GSM_StateMachine *s, GSM_CalendarEntry *Note);
1263 /**
1264 * Deletes calendar entry.
1265 */
1266 GSM_Error (*DeleteCalendar) (GSM_StateMachine *s, GSM_CalendarEntry *Note);
1267 /**
1268 * Deletes all calendar entries.
1269 */
1270 GSM_Error (*DeleteAllCalendar) (GSM_StateMachine *s);
1271 /**
1272 * Reads calendar settings.
1273 */
1274 GSM_Error (*GetCalendarSettings)(GSM_StateMachine *s, GSM_CalendarSettings *settings);
1275 /**
1276 * Sets calendar settings.
1277 */
1278 GSM_Error (*SetCalendarSettings)(GSM_StateMachine *s, GSM_CalendarSettings *settings);
1279 /**
1280 * Gets note.
1281 */
1282 GSM_Error (*GetNote) (GSM_StateMachine *s, GSM_NoteEntry *Note, bool refresh);
1283 /**
1284 * Reads profile.
1285 */
1286 GSM_Error (*GetProfile) (GSM_StateMachine *s, GSM_Profile *Profile);
1287 /**
1288 * Updates profile.
1289 */
1290 GSM_Error (*SetProfile) (GSM_StateMachine *s, GSM_Profile *Profile);
1291 /**
1292 * Reads FM station.
1293 */
1294 GSM_Error (*GetFMStation) (GSM_StateMachine *s, GSM_FMStation *FMStation);
1295 /**
1296 * Sets FM station.
1297 */
1298 GSM_Error (*SetFMStation) (GSM_StateMachine *s, GSM_FMStation *FMStation);
1299 /**
1300 * Clears defined FM stations.
1301 */
1302 GSM_Error (*ClearFMStations) (GSM_StateMachine *s);
1303 /**
1304 * Gets next filename from filesystem.
1305 */
1306 GSM_Error (*GetNextFileFolder) (GSM_StateMachine *s, GSM_File *File, bool start);
1307 /**
1308 * Gets file part from filesystem.
1309 */
1310 GSM_Error (*GetFilePart)(GSM_StateMachine *s, GSM_File *File);
1311 /**
1312 * Adds file part to filesystem.
1313 */
1314 GSM_Error (*AddFilePart)(GSM_StateMachine *s, GSM_File *File, int *Pos);
1315 /**
1316 * Acquires filesystem status.
1317 */
1318 GSM_Error (*GetFileSystemStatus)(GSM_StateMachine *s, GSM_FileSystemStatus *Status);
1319 /**
1320 * Deletes file from filessytem.
1321 */
1322 GSM_Error (*DeleteFile) (GSM_StateMachine *s, unsigned char *ID);
1323 /**
1324 * Adds folder to filesystem.
1325 */
1326 GSM_Error (*AddFolder) (GSM_StateMachine *s, GSM_File *File);
1327 /**
1328 * Gets GPRS access point.
1329 */
1330 GSM_Error (*GetGPRSAccessPoint) (GSM_StateMachine *s, GSM_GPRSAccessPoint *point);
1331 /**
1332 * Sets GPRS access point.
1333 */
1334 GSM_Error (*SetGPRSAccessPoint) (GSM_StateMachine *s, GSM_GPRSAccessPoint *point);
1335} GSM_Phone_Functions;
1336
1337 extern GSM_Phone_Functions NAUTOPhone;
1338#ifdef GSM_ENABLE_NOKIA3320
1339 extern GSM_Phone_Functions N3320Phone;
1340#endif
1341#ifdef GSM_ENABLE_NOKIA3650
1342 extern GSM_Phone_Functions N3650Phone;
1343#endif
1344#ifdef GSM_ENABLE_NOKIA6110
1345 extern GSM_Phone_Functions N6110Phone;
1346#endif
1347#ifdef GSM_ENABLE_NOKIA6510
1348 extern GSM_Phone_Functions N6510Phone;
1349#endif
1350#ifdef GSM_ENABLE_NOKIA7110
1351 extern GSM_Phone_Functions N7110Phone;
1352#endif
1353#ifdef GSM_ENABLE_NOKIA9210
1354 extern GSM_Phone_Functions N9210Phone;
1355#endif
1356#ifdef GSM_ENABLE_ATGEN
1357 extern GSM_Phone_Functions ATGENPhone;
1358#endif
1359#ifdef GSM_ENABLE_ALCATEL
1360 extern GSM_Phone_Functions ALCATELPhone;
1361#endif
1362#ifdef GSM_ENABLE_OBEXGEN
1363 extern GSM_Phone_Functions OBEXGENPhone;
1364#endif
1365#ifdef GSM_ENABLE_MROUTERGEN
1366 extern GSM_Phone_Functions MROUTERGENPhone;
1367#endif
1368
1369typedef struct {
1370 GSM_Phone_Data Data;
1371 GSM_Phone_Functions*Functions;
1372} GSM_Phone;
1373
1374/* --------------------------- User layer ---------------------------------- */
1375
1376struct _GSM_User {
1377 GSM_Reply_Function *UserReplyFunctions;
1378
1379 void (*IncomingCall) (char *Device, GSM_Call call);
1380 void (*IncomingSMS)(char *Device, GSM_SMSMessage sms);
1381 void (*IncomingCB) (char *Device, GSM_CBMessage cb);
1382 void (*IncomingUSSD) (char *Device, char *Text);
1383 void (*SendSMSStatus) (char *Device, int status, int MessageReference);
1384};
1385
1386/* --------------------------- Statemachine layer -------------------------- */
1387
1388typedef enum {
1389 GCT_MBUS2=1,
1390 GCT_FBUS2,
1391 GCT_FBUS2DLR3,
1392 GCT_FBUS2DKU5,
1393 GCT_FBUS2PL2303,
1394 GCT_FBUS2BLUE,
1395 GCT_FBUS2IRDA,
1396 GCT_PHONETBLUE,
1397 GCT_AT,
1398 GCT_MROUTERBLUE,
1399
1400 GCT_IRDAOBEX,
1401 GCT_IRDAAT,
1402 GCT_IRDAPHONET,
1403 GCT_BLUEFBUS2,
1404 GCT_BLUEAT,
1405 GCT_BLUEPHONET,
1406 GCT_BLUEOBEX
1407} GSM_ConnectionType;
1408
1409typedef struct {
1410 /* Config file (or Registry or...) variables */
1411 char Model[50]; /* Model from config file */
1412 char DebugLevel[50]; /* Debug level */
1413 char *Device; /* Device name from config file */
1414 char *Connection; /* Connection type as string */
1415 char *SyncTime; /* Synchronize time on startup? */
1416 char *LockDevice; /* Lock device ? (Unix) */
1417 char *DebugFile; /* Name of debug file */
1418 char *Localize; /* Name of localisation file */
1419 char *StartInfo; /* Display something during start ? */
1420 bool UseGlobalDebugFile;/* Should we use global debug file?*/
1421 bool DefaultModel;
1422 bool DefaultDebugLevel;
1423 bool DefaultDevice;
1424 bool DefaultConnection;
1425 bool DefaultSyncTime;
1426 bool DefaultLockDevice;
1427 bool DefaultDebugFile;
1428 bool DefaultLocalize;
1429 bool DefaultStartInfo;
1430} GSM_Config;
1431
1432 #define MAX_CONFIG_NUM 5
1433
1434struct _GSM_StateMachine {
1435 GSM_ConnectionType ConnectionType; /* Type of connection as int */
1436 char *LockFile; /* Lock file name for Unix */
1437 Debug_Info di; /* Debug information */
1438 bool opened; /* Is connection opened ? */
1439 GSM_Config Config[MAX_CONFIG_NUM + 1];
1440 GSM_Config *CurrentConfig; /* Config file (or Registry or...) variables */
1441 int ConfigNum;
1442 INI_Section *msg; /* Localisation strings structure */
1443 int ReplyNum; /* How many times make sth. */
1444 int Speed; /* For some protocols used speed */
1445
1446 GSM_Device Device;
1447 GSM_Protocol Protocol;
1448 GSM_Phone Phone;
1449 GSM_User User;
1450};
1451
1452/* ------------------------ Other general definitions ---------------------- */
1453
1454 GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s);
1455
1456 GSM_Error GSM_InitConnection (GSM_StateMachine *s, int ReplyNum);
1457 GSM_Error GSM_TerminateConnection(GSM_StateMachine *s);
1458
1459 int GSM_ReadDevice (GSM_StateMachine *s, bool wait);
1460
1461 GSM_Error GSM_WaitForOnce (GSM_StateMachine *s, unsigned char *buffer,
1462 int length, unsigned char type, int time);
1463
1464 GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned char *buffer,
1465 int length, unsigned char type, int time,
1466 GSM_Phone_RequestID request);
1467
1468 GSM_Error GSM_DispatchMessage (GSM_StateMachine *s);
1469
1470 INI_Section *GSM_FindGammuRC(void);
1471
1472 bool GSM_ReadConfig (INI_Section *cfg_info, GSM_Config *cfg, int num);
1473
1474 void GSM_DumpMessageLevel2 (GSM_StateMachine *s, unsigned char *message, int messagesize, int type);
1475 void GSM_DumpMessageLevel3 (GSM_StateMachine *s, unsigned char *message, int messagesize, int type);
1476
1477/* ---------------------- Phone features ----------------------------------- */
1478
1479typedef enum {
1480 /* n6110.c */
1481 F_CAL33 = 1, /* Calendar,3310 style - 10 reminders, Unicode, 3 coding types*/
1482 F_CAL52, /* Calendar,5210 style - full Unicode, etc. */
1483 F_CAL82, /* Calendar,8250 style - "normal", but with Unicode */
1484 F_RING_SM, /* Ringtones returned in SM format - 33xx */
1485 F_NORING, /* No ringtones */
1486 F_NOPBKUNICODE, /* No phonebook in Unicode */
1487 F_NOWAP, /* No WAP */
1488 F_NOCALLER, /* No caller groups */
1489 F_NOPICTURE, /* No Picture Images */
1490 F_NOPICTUREUNI, /* No Picture Images text in Unicode */
1491 F_NOSTARTUP, /* No startup logo */
1492 F_NOCALENDAR, /* No calendar */
1493 F_NOSTARTANI, /* Startup logo is not animated */
1494 F_POWER_BATT, /* Network and battery level get from netmonitor */
1495 F_PROFILES33, /* Phone profiles in 3310 style */
1496 F_PROFILES51, /* Phone profiles in 5110 style */
1497 F_MAGICBYTES, /* Phone can make authentication with magic bytes */
1498 F_NODTMF, /* Phone can't send DTMF */
1499 F_DISPSTATUS, /* Phone return display status */
1500 F_NOCALLINFO,
1501
1502 /* n3320.c */
1503 F_DAYMONTH, /* Day and month reversed in pbk, when compare to GSM models*/
1504
1505 /* n6510.c */
1506 F_PBK35, /* Phonebook in 3510 style with ringtones ID */
1507 F_PBKIMG, /* Phonebook in 7250 style with picture ID */
1508 F_PBKTONEGAL,/* Phonebook with selecting ringtones from gallery */
1509 F_PBKSMSLIST, /* Phonebook with SMS list */
1510 F_PBKUSER, /* Phonebook with user ID */
1511 F_RADIO, /* Phone with FM radio */
1512 F_TODO63, /* ToDo in 6310 style - 0x55 msg type */
1513 F_TODO66, /* ToDo in 6610 style - like calendar, with date and other*/
1514 F_NOMIDI, /* No ringtones in MIDI */
1515 F_BLUETOOTH, /* Bluetooth support */
1516 F_NOFILESYSTEM, /* No images, ringtones, java saved in special filesystem*/
1517 F_NOMMS, /* No MMS sets in phone */
1518 F_NOGPRSPOINT, /* GPRS point are not useable */
1519 F_CAL35, /* Calendar,3510 style - Reminder,Call,Birthday */
1520 F_CAL65, /* Calendar,6510 style - CBMM, method 3 */
1521 F_WAPMMSPROXY, /* WAP & MMS settings contains first & second proxy */
1522
1523 /* n6510.c && n7110.c */
1524 F_VOICETAGS, /* Voice tags available */
1525 F_CAL62, /* Calendar,6210 style - Call,Birthday,Memo,Meeting */
1526
1527 /* AT modules */
1528 F_SMSONLYSENT, /* Phone supports only sent/unsent messages */
1529 F_BROKENCPBS, /* CPBS on some memories can hang phone */
1530 F_M20SMS, /* Siemens M20 like SMS handling */
1531 F_SLOWWRITE, /* Use slower writing which some phone need */
1532 F_SMSME900, /* SMS in ME start from location 900 - case of Sagem */
1533 F_ALCATEL /* Phone supports Alcatel protocol */
1534} Feature;
1535
1536/* For models table */
1537struct _OnePhoneModel {
1538 char *model;
1539 char *number;
1540 char *irdamodel;
1541 Feature features[12];
1542};
1543
1544 bool IsPhoneFeatureAvailable(OnePhoneModel *model, Feature feature);
1545 OnePhoneModel *GetModelData (char *model, char *number, char *irdamodel);
1546
1547#ifdef __GNUC__
1548__attribute__((format(printf, 2, 3)))
1549#endif
1550int smprintf(GSM_StateMachine *s, const char *format, ...);
1551
1552void GSM_OSErrorInfo(GSM_StateMachine *s, char *description);
1553
1554#ifdef GSM_ENABLE_BACKUP
1555void GSM_GetPhoneFeaturesForBackup(GSM_StateMachine *s, GSM_Backup_Info *info);
1556#endif
1557
1558#endif
1559
1560/* How should editor hadle tabs in this file? Add editor commands here.
1561 * vim: noexpandtab sw=8 ts=8 sts=8:
1562 */
diff --git a/gammu/emb/common/misc/cfg.c b/gammu/emb/common/misc/cfg.c
new file mode 100644
index 0000000..1c74874
--- a/dev/null
+++ b/gammu/emb/common/misc/cfg.c
@@ -0,0 +1,332 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <ctype.h>
7#include <errno.h>
8#ifndef __OpenBSD__
9# include <wchar.h>
10# include <wctype.h>
11#endif
12
13#include "../config.h"
14#include "coding/coding.h"
15#include "cfg.h"
16#include "misc.h"
17
18/*
19 * Read information from file in Windows INI format style
20 */
21INI_Section *INI_ReadFile(char *FileName, bool Unicode)
22{
23 FILE *f;
24 bool FFEEUnicode=false;
25 int level = -1, buffer1used, buffer2used;
26 int bufferused, i, buffused=1000,buffread=1000, num;
27 unsigned charch[3], *buffer = NULL;
28 unsigned char*buffer2 = NULL, *buffer1 = NULL, buff[1000];
29 INI_Section *INI_info = NULL, *INI_head = NULL, *heading;
30 INI_Entry *entry;
31
32 f = fopen(FileName,"rb");
33 if (f == NULL) return NULL;
34
35 num = 0;
36 while(1) {
37 /* We read one line from file */
38 bufferused = 0;
39 while (1) {
40 if (buffused == buffread) {
41 buffused = fread(buff,1,1000,f);
42 buffread = 0;
43 if (buffused == 0) {
44 free(buffer); free(buffer1); free(buffer2);
45 fclose(f);
46 return INI_head;
47 }
48 }
49 if (Unicode) {
50 if (num == 0) {
51 if (buffused == buffread) continue;
52 ch[0] = buff[buffread++];
53 num = 1;
54 }
55 if (num == 1) {
56 if (buffused == buffread) continue;
57 ch[1] = buff[buffread++];
58 num = 0;
59 }
60 if (level == -1) {
61 if (ch[0] == 0xFF && ch[1] == 0xFE) FFEEUnicode = true;
62 level = 0;
63 continue;
64 }
65 if (FFEEUnicode) {
66 ch[2] = ch[0]; ch[0] = ch[1]; ch[1] = ch[2];
67 }
68 } else {
69 if (buffused == buffread) continue;
70 ch[0] = 0;
71 ch[1] = buff[buffread++];
72 if (level == -1) level = 0;
73 }
74 if ((ch[0] == 0 && ch[1] == 13) ||
75 (ch[0] == 0 && ch[1] == 10)) {
76 break;
77 }
78 buffer = realloc(buffer,bufferused+2);
79 buffer[bufferused] = ch[0];
80 buffer[bufferused+1] = ch[1];
81 bufferused = bufferused + 2;
82 }
83 // printf("line \"%s\"\n",DecodeUnicodeConsole(buffer));
84
85 buffer1used = 0;
86 buffer2used = 0;
87 if (level == 1) level = 0;
88 if (level == 3 || level == 4 || level == 5) level = 2;
89
90 /* We parse read line */
91 for (i=0;i<bufferused/2;i++) {
92 ch[0] = buffer[i*2];
93 ch[1] = buffer[i*2+1];
94 if (level == 0) { //search for name of section
95 if (ch[0] == 0 && ch[1] == '[') level = 1;
96 if (ch[0] == 0 && ch[1] == ';') break;
97 if (ch[0] == 0 && ch[1] == '#') break;
98 continue;
99 }
100 if (level == 1) { //section name
101 if (ch[0] == 0 && ch[1] == ']') {
102 if (buffer1used == 0) break;
103 if (Unicode) {
104 buffer1 = realloc(buffer1,buffer1used+2);
105 buffer1[buffer1used] = 0;
106 buffer1[buffer1used+1] = 0;
107 buffer1used = buffer1used + 2;
108 } else {
109 buffer1 = realloc(buffer1,buffer1used+1);
110 buffer1[buffer1used] = 0x00;
111 buffer1used = buffer1used + 1;
112 }
113 heading = (INI_Section *)malloc(sizeof(*heading));
114 if (heading == NULL) {
115 free(buffer); free(buffer1); free(buffer2);
116 fclose(f);
117 return NULL;
118 }
119 heading->SectionName = (char *)malloc(buffer1used);
120 memcpy(heading->SectionName,buffer1,buffer1used);
121 heading->Prev = INI_info;
122 heading->Next = NULL;
123 if (INI_info != NULL) {
124 INI_info->Next = heading;
125 } else {
126 INI_head = heading;
127 }
128 INI_info = heading;
129 INI_info->SubEntries = NULL;
130 level = 2;
131 // printf("[%s]\n",DecodeUnicodeConsole(buffer1));
132 break;
133 }
134 if (Unicode) {
135 buffer1 = realloc(buffer1,buffer1used+2);
136 buffer1[buffer1used] = ch[0];
137 buffer1[buffer1used+1] = ch[1];
138 buffer1used = buffer1used + 2;
139 } else {
140 buffer1 = realloc(buffer1,buffer1used+1);
141 buffer1[buffer1used] = ch[1];
142 buffer1used = buffer1used + 1;
143 }
144 continue;
145 }
146 if (level == 2) { //search for key name
147 if (ch[0] == 0 && ch[1] == ';') break;
148 if (ch[0] == 0 && ch[1] == '#') break;
149 if (ch[0] == 0 && ch[1] == '[') {
150 level = 1;
151 continue;
152 }
153 if (Unicode) {
154 if (myiswspace(ch)) continue;
155 } else {
156 if (isspace((int) ch[1])) continue;
157 }
158 level = 3;
159 }
160 if (level == 3) { //key name
161 if (ch[0] == 0 && ch[1] == '=') {
162 if (buffer1used == 0) break;
163 while(1) {
164 if (Unicode) {
165 if (!myiswspace(buffer1+(buffer1used-2))) break;
166 buffer1used = buffer1used - 2;
167 } else {
168 if (!isspace((int)buffer1[buffer1used-1])) break;
169 buffer1used = buffer1used - 1;
170 }
171 }
172 level = 4;
173 continue;
174 }
175 if (Unicode) {
176 buffer1 = realloc(buffer1,buffer1used+2);
177 buffer1[buffer1used] = ch[0];
178 buffer1[buffer1used+1] = ch[1];
179 buffer1used = buffer1used + 2;
180 } else {
181 buffer1 = realloc(buffer1,buffer1used+1);
182 buffer1[buffer1used] = ch[1];
183 buffer1used = buffer1used + 1;
184 }
185 }
186 if (level == 4) { //search for key value
187 if (Unicode) {
188 if (myiswspace(ch)) continue;
189 } else {
190 if (isspace((int) ch[1])) continue;
191 }
192 level = 5;
193 }
194 if (level == 5) { //key value
195 if (Unicode) {
196 buffer2 = realloc(buffer2,buffer2used+2);
197 buffer2[buffer2used] = ch[0];
198 buffer2[buffer2used+1] = ch[1];
199 buffer2used = buffer2used + 2;
200 } else {
201 buffer2 = realloc(buffer2,buffer2used+1);
202 buffer2[buffer2used] = ch[1];
203 buffer2used = buffer2used + 1;
204 }
205 }
206 }
207 if (level == 5) {
208 if (buffer2used == 0) continue;
209
210 entry = (INI_Entry *)malloc(sizeof(*entry));
211 if (entry == NULL) {
212 free(buffer); free(buffer1); free(buffer2);
213 fclose(f);
214 return NULL;
215 }
216 if (Unicode) {
217 buffer1 = realloc(buffer1,buffer1used+2);
218 buffer1[buffer1used] = 0;
219 buffer1[buffer1used+1] = 0;
220 buffer1used = buffer1used + 2;
221 buffer2 = realloc(buffer2,buffer2used+2);
222 buffer2[buffer2used] = 0;
223 buffer2[buffer2used+1] = 0;
224 buffer2used = buffer2used + 2;
225 } else {
226 buffer1 = realloc(buffer1,buffer1used+1);
227 buffer1[buffer1used] = 0x00;
228 buffer1used = buffer1used + 1;
229 buffer2 = realloc(buffer2,buffer2used+1);
230 buffer2[buffer2used] = 0x00;
231 buffer2used = buffer2used + 1;
232 }
233 // printf("\"%s\"=\"%s\"\n",buffer1,buffer2);
234 // printf("\"%s\"=",DecodeUnicodeConsole(buffer1));
235 // printf("\"%s\"\n",DecodeUnicodeConsole(buffer2));
236
237 entry->EntryName = (char *)malloc(buffer1used);
238 memcpy(entry->EntryName,buffer1,buffer1used);
239
240 entry->EntryValue = (char *)malloc(buffer2used);
241 memcpy(entry->EntryValue,buffer2,buffer2used);
242
243 entry->Prev = NULL;
244 entry->Next = INI_info->SubEntries;
245 if (INI_info->SubEntries != NULL) INI_info->SubEntries->Prev = entry;
246 INI_info->SubEntries = entry;
247 }
248 }
249 free(buffer); free(buffer1); free(buffer2);
250 fclose(f);
251 return INI_head;
252}
253
254/*
255 * Search for key value in file in Windows INI format style
256 * Returns found value or NULL
257 */
258unsigned char *INI_GetValue(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode)
259{
260 INI_Section *sec;
261 INI_Entry *ent;
262
263 if (cfg == NULL || section == NULL || key == NULL) return NULL;
264
265 if (Unicode) {
266 /* Search for section */
267 sec = cfg;
268 while (sec != NULL) {
269 if (mywstrncasecmp(section, sec->SectionName, 0)) {
270 /* Search for key inside section */
271 ent = sec->SubEntries;
272 while (ent != NULL) {
273 if (mywstrncasecmp(key,ent->EntryName,0)) {
274 return ent->EntryValue;
275 }
276 ent = ent->Next;
277 }
278 }
279 sec = sec->Next;
280 }
281 } else {
282 /* Search for section */
283 sec = cfg;
284 while (sec != NULL) {
285 if (mystrncasecmp(section, sec->SectionName, 0)) {
286 /* Search for key inside section */
287 ent = sec->SubEntries;
288 while (ent != NULL) {
289 if (mystrncasecmp(key,ent->EntryName,0)) {
290 return ent->EntryValue;
291 }
292 ent = ent->Next;
293 }
294 }
295 sec = sec->Next;
296 }
297 }
298 return NULL;
299}
300
301/* Return last value in specified section */
302INI_Entry *INI_FindLastSectionEntry(INI_Section *file_info, unsigned char *section, bool Unicode)
303{
304 INI_Section *h;
305 INI_Entry*e;
306
307 e = NULL;
308 /* First find our section */
309 for (h = file_info; h != NULL; h = h->Next) {
310 if (Unicode) {
311 if (mywstrncasecmp(section, h->SectionName, 0)) {
312 e = h->SubEntries;
313 break;
314 }
315 } else {
316 if (mystrncasecmp(section, h->SectionName, 0)) {
317 e = h->SubEntries;
318 break;
319 }
320 }
321 }
322
323 if (e == NULL) return NULL;
324
325 /* Goes into last value in section */
326 while (e->Next != NULL) e = e->Next;
327 return e;
328}
329
330/* How should editor hadle tabs in this file? Add editor commands here.
331 * vim: noexpandtab sw=8 ts=8 sts=8:
332 */
diff --git a/gammu/emb/common/misc/cfg.h b/gammu/emb/common/misc/cfg.h
new file mode 100644
index 0000000..edb9b09
--- a/dev/null
+++ b/gammu/emb/common/misc/cfg.h
@@ -0,0 +1,42 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef _cfg_h
4#define _cfg_h
5
6#include "misc.h"
7
8/* -------------------------------- structures ----------------------------- */
9
10typedef struct _INI_Entry INI_Entry;
11
12/*
13 * Structure used to save value for single key in INI style file
14 */
15struct _INI_Entry {
16 INI_Entry *Next, *Prev;
17 unsigned char *EntryName;
18 unsigned char *EntryValue;
19};
20
21typedef struct _INI_Section INI_Section;
22
23/*
24 * Structure used to save section in INI style file
25 */
26struct _INI_Section {
27 INI_Section *Next, *Prev;
28 INI_Entry *SubEntries;
29 unsigned char *SectionName;
30};
31
32/* ------------------------- function prototypes --------------------------- */
33
34 INI_Section *INI_ReadFile (char *FileName, bool Unicode);
35 INI_Entry *INI_FindLastSectionEntry (INI_Section *file_info, unsigned char *section, bool Unicode);
36 unsigned char *INI_GetValue (INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode);
37
38#endif
39
40/* How should editor hadle tabs in this file? Add editor commands here.
41 * vim: noexpandtab sw=8 ts=8 sts=8:
42 */
diff --git a/gammu/emb/common/misc/coding/coding.c b/gammu/emb/common/misc/coding/coding.c
new file mode 100644
index 0000000..62543ac
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/coding.c
@@ -0,0 +1,1409 @@
1/* (c) 2002-2004 by Marcin Wiacek, Michal Cihar and others */
2/* based on some work from MyGnokii and Gnokii */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <ctype.h>
8#include <locale.h>
9#ifndef __OpenBSD__
10# include <wctype.h>
11#endif
12#ifdef WIN32
13# include "windows.h"
14#endif
15
16#include "../misc.h"
17#include "coding.h"
18
19unsigned int UnicodeLength(const unsigned char *str)
20{
21 unsigned int len = 0;
22
23 if (str == NULL) return 0;
24
25 while(str[len*2] != 0 || str[len*2+1] != 0) len++;
26
27 return len;
28}
29
30/* Convert Unicode char saved in src to dest */
31unsigned int EncodeWithUnicodeAlphabet(const unsigned char *src, wchar_t *dest)
32{
33 char retval;
34
35 switch (retval = mbtowc(dest, src, MB_CUR_MAX)) {
36 case -1 :
37 case 0 : return 1;
38 default : return retval;
39 }
40}
41
42/* Convert Unicode char saved in src to dest */
43unsigned int DecodeWithUnicodeAlphabet(wchar_t src, unsigned char *dest)
44{
45 int retval;
46
47 switch (retval = wctomb(dest, src)) {
48 case -1:
49 *dest = '?';
50 return 1;
51 default:
52 return retval;
53 }
54}
55
56void DecodeUnicode (const unsigned char *src, unsigned char *dest)
57{
58 int i=0,o=0;
59 wchar_t wc;
60
61 while (src[(2*i)+1]!=0x00 || src[2*i]!=0x00) {
62 wc = src[(2*i)+1] | (src[2*i] << 8);
63 o += DecodeWithUnicodeAlphabet(wc, dest + o);
64 i++;
65 }
66 dest[o]=0;
67}
68
69/* Decode Unicode string and return as function result */
70unsigned char *DecodeUnicodeString (const unsigned char *src)
71{
72 static char dest[500];
73
74 DecodeUnicode(src,dest);
75 return dest;
76}
77
78/* Decode Unicode string to UTF8 or other console charset
79 * and return as function result
80 */
81unsigned char *DecodeUnicodeConsole(const unsigned char *src)
82{
83 static char dest[500];
84
85 if (di.coding[0] != 0) {
86 if (!strcmp(di.coding,"utf8")) {
87 EncodeUTF8(dest, src);
88 } else {
89#ifdef WIN32
90 setlocale(LC_ALL, di.coding);
91#endif
92 DecodeUnicode(src,dest);
93 }
94 } else {
95#ifdef WIN32
96 setlocale(LC_ALL, ".OCP");
97#endif
98 DecodeUnicode(src,dest);
99#ifdef WIN32
100 setlocale(LC_ALL, ".ACP");
101#endif
102 }
103 return dest;
104}
105
106/* Encode string to Unicode. Len is number of input chars */
107void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len)
108{
109 int i_len = 0, o_len;
110 wchar_t wc;
111
112 for (o_len = 0; i_len < len; o_len++) {
113 i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
114 dest[o_len*2] = (wc >> 8) & 0xff;
115 dest[(o_len*2)+1]= wc & 0xff;
116 }
117 dest[o_len*2] = 0;
118 dest[(o_len*2)+1]= 0;
119}
120
121unsigned char EncodeWithBCDAlphabet(int value)
122{
123 div_t division;
124
125 division=div(value,10);
126 return ( ( (value-division.quot*10) & 0x0f) << 4) | (division.quot & 0xf);
127}
128
129int DecodeWithBCDAlphabet(unsigned char value)
130{
131 return 10*(value & 0x0f)+(value >> 4);
132}
133
134void DecodeBCD (unsigned char *dest, const unsigned char *src, int len)
135{
136 int i,current=0,digit;
137
138 for (i = 0; i < len; i++) {
139 digit=src[i] & 0x0f;
140 if (digit<10) dest[current++]=digit + '0';
141 digit=src[i] >> 4;
142 if (digit<10) dest[current++]=digit + '0';
143 }
144 dest[current++]=0;
145}
146
147void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill)
148{
149 int i,current=0;
150
151 for (i = 0; i < len; i++) {
152 if (i & 0x01) {
153 dest[current]=dest[current] | ((src[i]-'0') << 4);
154 current++;
155 } else {
156 dest[current]=src[i]-'0';
157 }
158 }
159
160 /* When fill is set: if number consist of odd number of digits,
161 we fill last bits in last byte with 0x0f
162 */
163 if (fill && (len & 0x01)) dest[current]=dest[current] | 0xf0;
164}
165
166int DecodeWithHexBinAlphabet (unsigned char mychar)
167{
168 if (mychar>='A' && mychar<='F') return mychar-'A'+10;
169 if (mychar>='a' && mychar<='f') return mychar-'a'+10;
170 if (mychar>='0' && mychar<='9') return mychar-'0';
171 return -1;
172}
173
174unsigned char EncodeWithHexBinAlphabet (int digit)
175{
176 if (digit >= 0 && digit <= 9) return '0'+(digit);
177 if (digit >=10 && digit <=15) return 'A'+(digit-10);
178 return 0;
179}
180
181void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
182{
183 int i,current=0;
184 bool first = false;
185
186 if (len != 0 && src[0] == '0' && src[1] == '0') {
187 first = true;
188 } else if (len != 0 && src[2] == '0' && src[3] == '0') {
189 first = false;
190 } else {
191 first = (10 * (src[0] - '0') + (src[1] - '0')) < (10 * (src[2] - '0')+ (src[3] - '0'));
192 }
193 for (i = 0; i < len/4 ; i++) {
194 if (first) {
195 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
196 DecodeWithHexBinAlphabet(src[i*4+1]);
197 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
198 DecodeWithHexBinAlphabet(src[i*4+3]);
199 } else {
200 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+2])*16+
201 DecodeWithHexBinAlphabet(src[i*4+3]);
202 dest[current++] = DecodeWithHexBinAlphabet(src[i*4+0])*16+
203 DecodeWithHexBinAlphabet(src[i*4+1]);
204 }
205 }
206 dest[current++] = 0;
207 dest[current++] = 0;
208}
209
210void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len)
211{
212 int i,current=0;
213
214 for (i = 0; i < len; i++) {
215 dest[current++] = EncodeWithHexBinAlphabet(src[2*i] >> 0x04);
216 dest[current++] = EncodeWithHexBinAlphabet(src[2*i] & 0x0f);
217 dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] >> 0x04);
218 dest[current++] = EncodeWithHexBinAlphabet(src[2*i+1] & 0x0f);
219 }
220 dest[current++] = 0;
221}
222
223void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len)
224{
225 int i,current=0;
226
227 for (i = 0; i < len/2 ; i++) {
228 dest[current++] = DecodeWithHexBinAlphabet(src[i*2])*16+
229 DecodeWithHexBinAlphabet(src[i*2+1]);
230 }
231 dest[current++] = 0;
232}
233
234void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len)
235{
236 int i,current=0;
237
238 for (i = 0; i < len; i++) {
239 dest[current++] = EncodeWithHexBinAlphabet(src[i] >> 0x04);
240 dest[current++] = EncodeWithHexBinAlphabet(src[i] & 0x0f);
241 }
242 dest[current++] = 0;
243}
244
245/* ETSI GSM 03.38, section 6.2.1: Default alphabet for SMS messages */
246static unsigned char GSM_DefaultAlphabetUnicode[128+1][2] =
247{
248 {0x00,0x40},{0x00,0xa3},{0x00,0x24},{0x00,0xA5},
249 {0x00,0xE8},{0x00,0xE9},{0x00,0xF9},{0x00,0xEC},/*0x08*/
250 {0x00,0xF2},{0x00,0xC7},{0x00,'\n'},{0x00,0xD8},
251 {0x00,0xF8},{0x00,'\r'},{0x00,0xC5},{0x00,0xE5},
252 {0x03,0x94},{0x00,0x5f},{0x03,0xA6},{0x03,0x93},
253 {0x03,0x9B},{0x03,0xA9},{0x03,0xA0},{0x03,0xA8},
254 {0x03,0xA3},{0x03,0x98},{0x03,0x9E},{0x00,0xb9},
255 {0x00,0xC6},{0x00,0xE6},{0x00,0xDF},{0x00,0xC9},/*0x20*/
256 {0x00,' ' },{0x00,'!' },{0x00,'\"'},{0x00,'#' },
257 {0x00,0xA4},{0x00,'%' },{0x00,'&' },{0x00,'\''},
258 {0x00,'(' },{0x00,')' },{0x00,'*' },{0x00,'+' },
259 {0x00,',' },{0x00,'-' },{0x00,'.' },{0x00,'/' },/*0x30*/
260 {0x00,'0' },{0x00,'1' },{0x00,'2' },{0x00,'3' },
261 {0x00,'4' },{0x00,'5' },{0x00,'6' },{0x00,'7' },
262 {0x00,'8' },{0x00,'9' },{0x00,':' },{0x00,';' },
263 {0x00,'<' },{0x00,'=' },{0x00,'>' },{0x00,'?' },/*0x40*/
264 {0x00,0xA1},{0x00,'A' },{0x00,'B' },{0x00,'C' },
265 {0x00,'D' },{0x00,'E' },{0x00,'F' },{0x00,'G' },
266 {0x00,'H' },{0x00,'I' },{0x00,'J' },{0x00,'K' },
267 {0x00,'L' },{0x00,'M' },{0x00,'N' },{0x00,'O' },
268 {0x00,'P' },{0x00,'Q' },{0x00,'R' },{0x00,'S' },
269 {0x00,'T' },{0x00,'U' },{0x00,'V' },{0x00,'W' },
270 {0x00,'X' },{0x00,'Y' },{0x00,'Z' },{0x00,0xC4},
271 {0x00,0xD6},{0x00,0xD1},{0x00,0xDC},{0x00,0xA7},
272 {0x00,0xBF},{0x00,'a' },{0x00,'b' },{0x00,'c' },
273 {0x00,'d' },{0x00,'e' },{0x00,'f' },{0x00,'g' },
274 {0x00,'h' },{0x00,'i' },{0x00,'j' },{0x00,'k' },
275 {0x00,'l' },{0x00,'m' },{0x00,'n' },{0x00,'o' },
276 {0x00,'p' },{0x00,'q' },{0x00,'r' },{0x00,'s' },
277 {0x00,'t' },{0x00,'u' },{0x00,'v' },{0x00,'w' },
278 {0x00,'x' },{0x00,'y' },{0x00,'z' },{0x00,0xE4},
279 {0x00,0xF6},{0x00,0xF1},{0x00,0xFC},{0x00,0xE0},
280 {0x00,0x00}
281};
282
283/* ETSI GSM 3.38
284 * Some sequences of 2 default alphabet chars (for example,
285 * 0x1b, 0x65) are visible as one single additional char (for example,
286 * 0x1b, 0x65 gives Euro char saved in Unicode as 0x20, 0xAC)
287 * This table contains:
288 * 1. two first chars means sequence of chars from GSM default alphabet
289 * 2. two second is target (encoded) char saved in Unicode
290 */
291static unsigned char GSM_DefaultAlphabetCharsExtension[][4] =
292{
293 {0x1b,0x14,0x00,0x5e}, /* ^*/
294 {0x1b,0x28,0x00,0x7b}, /* {*/
295 {0x1b,0x29,0x00,0x7d}, /* }*/
296 {0x1b,0x2f,0x00,0x5c}, /* \*/
297 {0x1b,0x3c,0x00,0x5b}, /* [*/
298 {0x1b,0x3d,0x00,0x7E}, /* ~*/
299 {0x1b,0x3e,0x00,0x5d}, /* ]*/
300 {0x1b,0x40,0x00,0x7C}, /* |*/
301 {0x1b,0x65,0x20,0xAC},/* Euro */
302 {0x00,0x00,0x00,0x00}
303};
304
305void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet)
306{
307 int i,current=0,j;
308 boolFoundSpecial = false;
309
310#ifdef DEBUG
311 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, len);
312#endif
313
314 for (i = 0; i < len; i++) {
315 FoundSpecial = false;
316 if ((i < (len-1)) && UseExtensions) {
317 j=0;
318 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
319 if (GSM_DefaultAlphabetCharsExtension[j][0]==src[i] &&
320 GSM_DefaultAlphabetCharsExtension[j][1]==src[i+1]) {
321 FoundSpecial = true;
322 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][2];
323 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][3];
324 i++;
325 break;
326 }
327 j++;
328 }
329 }
330 if (ExtraAlphabet!=NULL && !FoundSpecial) {
331 j = 0;
332 while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
333 if (ExtraAlphabet[j] == src[i]) {
334 dest[current++] = ExtraAlphabet[j+1];
335 dest[current++] = ExtraAlphabet[j+2];
336 FoundSpecial = true;
337 break;
338 }
339 j=j+3;
340 }
341 }
342 if (!FoundSpecial) {
343 dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][0];
344 dest[current++] = GSM_DefaultAlphabetUnicode[src[i]][1];
345 }
346 }
347 dest[current++]=0;
348 dest[current++]=0;
349#ifdef DEBUG
350 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, UnicodeLength(dest)*2);
351#endif
352}
353
354/* There are many national chars with "adds". In phone they're normally
355 * changed to "plain" Latin chars. We have such functionality too.
356 * This table is automatically created from convert.txt file (see
357 * /docs/developers) using --makeconverttable. It contains such chars
358 * to replace in order:
359 * 1. original char (Unicode) 2. destination char (Unicode)
360 */
361static unsigned char ConvertTable[] =
362"\x00\xc0\x00\x41\x00\xe0\x00\x61\x00\xc1\x00\x41\x00\xe1\x00\x61\x00\xc2\x00\x41\x00\xe2\x00\x61\x00\xc3\x00\x41\x00\xe3\x00\x61\x1e\xa0\x00\x41\x1e\xa1\x00\x61\x1e\xa2\x00\x41\x1e\xa3\x00\x61\x1e\xa4\x00\x41\x1e\xa5\x00\x61\x1e\xa6\x00\x41\x1e\xa7\x00\x61\x1e\xa8\x00\x41\x1e\xa9\x00\x61\x1e\xaa\x00\x41\x1e\xab\x00\x61\x1e\xac\x00\x41\x1e\xad\x00\x61\x1e\xae\x00\x41\x1e\xaf\x00\x61\x1e\xb0\x00\x41\x1e\xb1\x00\x61\x1e\xb2\x00\x41\x1e\xb3\x00\x61\x1e\xb4\x00\x41\x1e\xb5\x00\x61\x1e\xb6\x00\x41\x1e\xb7\x00\x61\x01\xcd\x00\x41\x01\xce\x00\x61\x01\x00\x00\x41\x01\x01\x00\x61\x01\x02\x00\x41\x01\x03\x00\x61\x01\x04\x00\x41\x01\x05\x00\x61\x01\xfb\x00\x61\x01\x06\x00\x43\x01\x07\x00\x63\x01\x08\x00\x43\x01\x09\x00\x63\x01\x0a\x00\x43\x01\x0b\x00\x63\x01\x0c\x00\x43\x01\x0d\x00\x63\x00\xe7"\
363"\x00\x63\x01\x0e\x00\x44\x01\x0f\x00\x64\x01\x10\x00\x44\x01\x11\x00\x64\x00\xc8\x00\x45\x00\xca\x00\x45\x00\xea\x00\x65\x00\xcb\x00\x45\x00\xeb\x00\x65\x1e\xb8\x00\x45\x1e\xb9\x00\x65\x1e\xba\x00\x45\x1e\xbb\x00\x65\x1e\xbc\x00\x45\x1e\xbd\x00\x65\x1e\xbe\x00\x45\x1e\xbf\x00\x65\x1e\xc0\x00\x45\x1e\xc1\x00\x65\x1e\xc2\x00\x45\x1e\xc3\x00\x65\x1e\xc4\x00\x45\x1e\xc5\x00\x65\x1e\xc6\x00\x45\x1e\xc7\x00\x65\x01\x12\x00\x45\x01\x13\x00\x65\x01\x14\x00\x45\x01\x15\x00\x65\x01\x16\x00\x45\x01\x17\x00\x65\x01\x18\x00\x45\x01\x19\x00\x65\x01\x1a\x00\x45\x01\x1b\x00\x65\x01\x1c\x00\x47\x01\x1d\x00\x67\x01\x1e\x00\x47\x01\x1f\x00\x67\x01\x20\x00\x47\x01\x21\x00\x67\x01\x22\x00\x47\x01\x23\x00\x67\x01\x24\x00\x48\x01\x25\x00\x68\x01\x26\x00\x48\x01\x27\x00\x68\x00\xcc\x00\x49\x00\xcd\x00\x49\x00\xed"\
364"\x00\x69\x00\xce\x00\x49\x00\xee\x00\x69\x00\xcf\x00\x49\x00\xef\x00\x69\x01\x28\x00\x49\x01\x29\x00\x69\x01\x2a\x00\x49\x01\x2b\x00\x69\x01\x2c\x00\x49\x01\x2d\x00\x69\x01\x2e\x00\x49\x01\x2f\x00\x69\x01\x30\x00\x49\x01\x31\x00\x69\x01\xcf\x00\x49\x01\xd0\x00\x69\x1e\xc8\x00\x49\x1e\xc9\x00\x69\x1e\xca\x00\x49\x1e\xcb\x00\x69\x01\x34\x00\x4a\x01\x35\x00\x6a\x01\x36\x00\x4b\x01\x37\x00\x6b\x01\x39\x00\x4c\x01\x3a\x00\x6c\x01\x3b\x00\x4c\x01\x3c\x00\x6c\x01\x3d\x00\x4c\x01\x3e\x00\x6c\x01\x3f\x00\x4c\x01\x40\x00\x6c\x01\x41\x00\x4c\x01\x42\x00\x6c\x01\x43\x00\x4e\x01\x44\x00\x6e\x01\x45\x00\x4e\x01\x46\x00\x6e\x01\x47\x00\x4e\x01\x48\x00\x6e\x01\x49\x00\x6e\x00\xd2\x00\x4f\x00\xd3\x00\x4f\x00\xf3\x00\x6f\x00\xd4\x00\x4f\x00\xf4\x00\x6f\x00\xd5\x00\x4f\x00\xf5\x00\x6f\x01\x4c\x00\x4f\x01\x4d"\
365"\x00\x6f\x01\x4e\x00\x4f\x01\x4f\x00\x6f\x01\x50\x00\x4f\x01\x51\x00\x6f\x01\xa0\x00\x4f\x01\xa1\x00\x6f\x01\xd1\x00\x4f\x01\xd2\x00\x6f\x1e\xcc\x00\x4f\x1e\xcd\x00\x6f\x1e\xce\x00\x4f\x1e\xcf\x00\x6f\x1e\xd0\x00\x4f\x1e\xd1\x00\x6f\x1e\xd2\x00\x4f\x1e\xd3\x00\x6f\x1e\xd4\x00\x4f\x1e\xd5\x00\x6f\x1e\xd6\x00\x4f\x1e\xd7\x00\x6f\x1e\xd8\x00\x4f\x1e\xd9\x00\x6f\x1e\xda\x00\x4f\x1e\xdb\x00\x6f\x1e\xdc\x00\x4f\x1e\xdd\x00\x6f\x1e\xde\x00\x4f\x1e\xdf\x00\x6f\x1e\xe0\x00\x4f\x1e\xe1\x00\x6f\x1e\xe2\x00\x4f\x1e\xe3\x00\x6f\x01\x54\x00\x52\x01\x55\x00\x72\x01\x56\x00\x52\x01\x57\x00\x72\x01\x58\x00\x52\x01\x59\x00\x72\x01\x5a\x00\x53\x01\x5b\x00\x73\x01\x5c\x00\x53\x01\x5d\x00\x73\x01\x5e\x00\x53\x01\x5f\x00\x73\x01\x60\x00\x53\x01\x61\x00\x73\x01\x62\x00\x54\x01\x63\x00\x74\x01\x64\x00\x54\x01\x65"\
366"\x00\x74\x01\x66\x00\x54\x01\x67\x00\x74\x00\xd9\x00\x55\x00\xda\x00\x55\x00\xfa\x00\x75\x00\xdb\x00\x55\x00\xfb\x00\x75\x01\x68\x00\x55\x01\x69\x00\x75\x01\x6a\x00\x55\x01\x6b\x00\x75\x01\x6c\x00\x55\x01\x6d\x00\x75\x01\x6e\x00\x55\x01\x6f\x00\x75\x01\x70\x00\x55\x01\x71\x00\x75\x01\x72\x00\x55\x01\x73\x00\x75\x01\xaf\x00\x55\x01\xb0\x00\x75\x01\xd3\x00\x55\x01\xd4\x00\x75\x01\xd5\x00\x55\x01\xd6\x00\x75\x01\xd7\x00\x55\x01\xd8\x00\x75\x01\xd9\x00\x55\x01\xda\x00\x75\x01\xdb\x00\x55\x01\xdc\x00\x75\x1e\xe4\x00\x55\x1e\xe5\x00\x75\x1e\xe6\x00\x55\x1e\xe7\x00\x75\x1e\xe8\x00\x55\x1e\xe9\x00\x75\x1e\xea\x00\x55\x1e\xeb\x00\x75\x1e\xec\x00\x55\x1e\xed\x00\x75\x1e\xee\x00\x55\x1e\xef\x00\x75\x1e\xf0\x00\x55\x1e\xf1\x00\x75\x01\x74\x00\x57\x01\x75\x00\x77\x1e\x80\x00\x57\x1e\x81\x00\x77\x1e\x82"\
367"\x00\x57\x1e\x83\x00\x77\x1e\x84\x00\x57\x1e\x85\x00\x77\x00\xdd\x00\x59\x00\xfd\x00\x79\x00\xff\x00\x79\x01\x76\x00\x59\x01\x77\x00\x79\x01\x78\x00\x59\x1e\xf2\x00\x59\x1e\xf3\x00\x75\x1e\xf4\x00\x59\x1e\xf5\x00\x79\x1e\xf6\x00\x59\x1e\xf7\x00\x79\x1e\xf8\x00\x59\x1e\xf9\x00\x79\x01\x79\x00\x5a\x01\x7a\x00\x7a\x01\x7b\x00\x5a\x01\x7c\x00\x7a\x01\x7d\x00\x5a\x01\x7e\x00\x7a\x01\xfc\x00\xc6\x01\xfd\x00\xe6\x01\xfe\x00\xd8\x01\xff\x00\xf8\x00\x00";
368
369void EncodeDefault(unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet)
370{
371 int i,current=0,j,z;
372 char ret;
373 boolFoundSpecial,FoundNormal;
374
375#ifdef DEBUG
376 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, src, (*len)*2);
377#endif
378
379 for (i = 0; i < *len; i++) {
380 FoundSpecial = false;
381 j = 0;
382 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00 && UseExtensions) {
383 if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] &&
384 src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) {
385 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][0];
386 dest[current++] = GSM_DefaultAlphabetCharsExtension[j][1];
387 FoundSpecial = true;
388 break;
389 }
390 j++;
391 }
392 if (!FoundSpecial) {
393 ret = '?';
394 FoundNormal = false;
395 j = 0;
396 while (GSM_DefaultAlphabetUnicode[j][1]!=0x00) {
397 if (src[i*2]== GSM_DefaultAlphabetUnicode[j][0] &&
398 src[i*2+1]== GSM_DefaultAlphabetUnicode[j][1]) {
399 ret = j;
400 FoundNormal = true;
401 break;
402 }
403 j++;
404 }
405 if (ExtraAlphabet!=NULL && !FoundNormal) {
406 j = 0;
407 while (ExtraAlphabet[j] != 0x00 || ExtraAlphabet[j+1] != 0x00 || ExtraAlphabet[j+2] != 0x00) {
408 if (ExtraAlphabet[j+1] == src[i*2] &&
409 ExtraAlphabet[j+2] == src[i*2 + 1]) {
410 ret = ExtraAlphabet[j];
411 FoundSpecial= true;
412 break;
413 }
414 j=j+3;
415 }
416 }
417 if (!FoundNormal && !FoundSpecial) {
418 j = 0;
419 FoundNormal = false;
420 while (ConvertTable[j*4] != 0x00 ||
421 ConvertTable[j*4+1] != 0x00) {
422 if (src[i*2] == ConvertTable[j*4] &&
423 src[i*2+1] == ConvertTable[j*4+1]) {
424 z = 0;
425 while (GSM_DefaultAlphabetUnicode[z][1]!=0x00) {
426 if (ConvertTable[j*4+2]== GSM_DefaultAlphabetUnicode[z][0] &&
427 ConvertTable[j*4+3]== GSM_DefaultAlphabetUnicode[z][1]) {
428 ret = z;
429 FoundNormal = true;
430 break;
431 }
432 z++;
433 }
434 if (FoundNormal) break;
435 }
436 j++;
437 }
438 }
439 dest[current++]=ret;
440 }
441 }
442 dest[current]=0;
443#ifdef DEBUG
444 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, dest, current);
445#endif
446
447 *len = current;
448}
449
450/* You don't have to use ConvertTable here - 1 char is replaced there by 1 char */
451void FindDefaultAlphabetLen(const unsigned char *src, int *srclen, int *smslen, int maxlen)
452{
453 int current=0,j,i;
454 boolFoundSpecial;
455
456 i = 0;
457 while (src[i*2] != 0x00 || src[i*2+1] != 0x00) {
458 FoundSpecial = false;
459 j = 0;
460 while (GSM_DefaultAlphabetCharsExtension[j][0]!=0x00) {
461 if (src[i*2] == GSM_DefaultAlphabetCharsExtension[j][2] &&
462 src[i*2+1] == GSM_DefaultAlphabetCharsExtension[j][3]) {
463 FoundSpecial = true;
464 if (current+2 > maxlen) {
465 *srclen = i;
466 *smslen = current;
467 return;
468 }
469 current+=2;
470 break;
471 }
472 j++;
473 }
474 if (!FoundSpecial) {
475 if (current+1 > maxlen) {
476 *srclen = i;
477 *smslen = current;
478 return;
479 }
480 current++;
481 }
482 i++;
483 }
484 *srclen = i;
485 *smslen = current;
486}
487
488#ifndef ENABLE_LGPL
489# define ByteMask ((1 << Bits) - 1)
490#endif
491
492int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
493 unsigned char *input, unsigned char *output)
494{
495#ifndef ENABLE_LGPL
496 /* (c) by Pavel Janik and Pawel Kot */
497
498 unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
499 unsigned char *INPUT = input; /* Current pointer to the input buffer */
500 unsigned char Rest = 0x00;
501 int Bits;
502
503 Bits = offset ? offset : 7;
504
505 while ((INPUT - input) < in_length) {
506
507 *OUTPUT = ((*INPUT & ByteMask) << (7 - Bits)) | Rest;
508 Rest = *INPUT >> Bits;
509
510 /* If we don't start from 0th bit, we shouldn't go to the
511 next char. Under *OUTPUT we have now 0 and under Rest -
512 _first_ part of the char. */
513 if ((INPUT != input) || (Bits == 7)) OUTPUT++;
514 INPUT++;
515
516 if ((OUTPUT - output) >= out_length) break;
517
518 /* After reading 7 octets we have read 7 full characters but
519 we have 7 bits as well. This is the next character */
520 if (Bits == 1) {
521 *OUTPUT = Rest;
522 OUTPUT++;
523 Bits = 7;
524 Rest = 0x00;
525 } else {
526 Bits--;
527 }
528 }
529
530 return OUTPUT - output;
531#else
532 return 0;
533#endif
534}
535
536int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length)
537{
538#ifndef ENABLE_LGPL
539 /* (c) by Pavel Janik and Pawel Kot */
540
541 unsigned char *OUTPUT = output; /* Current pointer to the output buffer */
542 unsigned char *INPUT = input; /* Current pointer to the input buffer */
543 int Bits; /* Number of bits directly copied to
544 * the output buffer */
545 Bits = (7 + offset) % 8;
546
547 /* If we don't begin with 0th bit, we will write only a part of the
548 first octet */
549 if (offset) {
550 *OUTPUT = 0x00;
551 OUTPUT++;
552 }
553
554 while ((INPUT - input) < length) {
555 unsigned char Byte = *INPUT;
556
557 *OUTPUT = Byte >> (7 - Bits);
558 /* If we don't write at 0th bit of the octet, we should write
559 a second part of the previous octet */
560 if (Bits != 7)
561 *(OUTPUT-1) |= (Byte & ((1 << (7-Bits)) - 1)) << (Bits+1);
562
563 Bits--;
564
565 if (Bits == -1) Bits = 7; else OUTPUT++;
566
567 INPUT++;
568 }
569 return (OUTPUT - output);
570#else
571 return 0;
572#endif
573}
574
575void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet)
576{
577 unsigned char Buffer[50]= "";
578 int length = Number[0];
579
580 if (semioctet) {
581 /* Convert number of semioctets to number of chars */
582 if (length % 2) length++;
583 length=length / 2 + 1;
584 }
585
586 /*without leading byte with format of number*/
587 length--;
588
589 switch (Number[1]) {
590 case NUMBER_ALPHANUMERIC:
591 if (length > 6) length++;
592 dbgprintf("Alphanumeric number, length %i\n",length);
593 GSM_UnpackEightBitsToSeven(0, length, length, Number+2, Buffer);
594 Buffer[length]=0;
595 break;
596 case NUMBER_INTERNATIONAL:
597 dbgprintf("International number\n");
598 Buffer[0]='+';
599 DecodeBCD(Buffer+1,Number+2, length);
600 break;
601 default:
602 dbgprintf("Default number %02x\n",Number[1]);
603 DecodeBCD (Buffer, Number+2, length);
604 break;
605 }
606
607 EncodeUnicode(retval,Buffer,strlen(Buffer));
608}
609
610/**
611 * Packing some phone numbers (SMSC, SMS destination and others)
612 *
613 * See GSM 03.40 9.1.1:
614 * 1 byte - length of number given in semioctets or bytes (when given in
615 * bytes, includes one byte for byte with number format).
616 * Returned by function (set semioctet to true, if want result
617 * in semioctets).
618 * 1 byte - format of number (see GSM_NumberType in coding.h). Returned
619 * in unsigned char *Output.
620 * n bytes - 2n or 2n-1 semioctets with number. Returned in unsigned char
621 * *Output.
622 *
623 * 1 semioctet = 4 bits = half of byte
624 */
625int GSM_PackSemiOctetNumber(unsigned char *Number, unsigned char *Output, bool semioctet)
626{
627 unsigned charformat, buffer[50];
628 int length, i;
629
630 length=UnicodeLength(Number);
631 memcpy(buffer,DecodeUnicodeString(Number),length+1);
632
633 /* Checking for format number */
634 format = NUMBER_UNKNOWN;
635 for (i=0;i<length;i++) {
636 /* first byte is '+'. Number can be international */
637 if (i==0 && buffer[i]=='+') {
638 format=NUMBER_INTERNATIONAL;
639 } else {
640 /*char is not number. It must be alphanumeric*/
641 if (!isdigit(buffer[i])) format=NUMBER_ALPHANUMERIC;
642 }
643 }
644
645 /**
646 * First byte is used for saving type of number. See GSM 03.40
647 * section 9.1.2.5
648 */
649 Output[0]=format;
650
651 /* After number type we will have number. GSM 03.40 section 9.1.2 */
652 switch (format) {
653 case NUMBER_ALPHANUMERIC:
654 length=GSM_PackSevenBitsToEight(0, buffer, Output+1, strlen(buffer))*2;
655 if (strlen(buffer)==7) length--;
656 break;
657 case NUMBER_INTERNATIONAL:
658 length--;
659 EncodeBCD (Output+1, buffer+1, length, true);
660 break;
661 default:
662 EncodeBCD (Output+1, buffer, length, true);
663 break;
664 }
665
666 if (semioctet) return length;
667
668 /* Convert number of semioctets to number of chars */
669 if (length % 2) length++;
670 return length / 2 + 1;
671}
672
673void CopyUnicodeString(unsigned char *Dest, unsigned char *Source)
674{
675 int j = 0;
676
677 while (Source[j]!=0x00 || Source[j+1]!=0x00) {
678 Dest[j] = Source[j];
679 Dest[j+1]= Source[j+1];
680 j=j+2;
681 }
682 Dest[j] = 0;
683 Dest[j+1]= 0;
684}
685
686/* Changes minor/major order in Unicode string */
687void ReverseUnicodeString(unsigned char *String)
688{
689 int j = 0;
690 unsigned charbyte1, byte2;
691
692 while (String[j]!=0x00 || String[j+1]!=0x00) {
693 byte1 = String[j];
694 byte2 = String[j+1];
695 String[j+1]= byte1;
696 String[j]= byte2;
697 j=j+2;
698 }
699 String[j]= 0;
700 String[j+1]= 0;
701}
702
703/* All input is in Unicode. First char can show Unicode minor/major order.
704 Output is Unicode string in Gammu minor/major order */
705void ReadUnicodeFile(unsigned char *Dest, unsigned char *Source)
706{
707 int j = 0, current = 0;
708
709 if (Source[0] == 0xFF && Source[1] == 0xFE) j = 2;
710 if (Source[0] == 0xFE && Source[1] == 0xFF) j = 2;
711
712 while (Source[j]!=0x00 || Source[j+1]!=0x00) {
713 if (Source[0] == 0xFF) {
714 Dest[current++] = Source[j+1];
715 Dest[current++]= Source[j];
716 } else {
717 Dest[current++] = Source[j];
718 Dest[current++]= Source[j+1];
719 }
720 j=j+2;
721 }
722 Dest[current++] = 0;
723 Dest[current++]= 0;
724}
725
726int GetBit(unsigned char *Buffer, int BitNum)
727{
728 return Buffer[BitNum/8] & 1<<(7-(BitNum%8));
729}
730
731int SetBit(unsigned char *Buffer, int BitNum)
732{
733 return Buffer[BitNum/8] |= 1<<(7-(BitNum%8));
734}
735
736int ClearBit(unsigned char *Buffer, int BitNum)
737{
738 return Buffer[BitNum/8] &= 255 - (1 << (7-(BitNum%8)));
739}
740
741void BufferAlign(unsigned char *Destination, int *CurrentBit)
742{
743 int i=0;
744
745 while(((*CurrentBit) + i) % 8 != 0) {
746 ClearBit(Destination, (*CurrentBit)+i);
747 i++;
748 }
749
750 (*CurrentBit) = (*CurrentBit) + i;
751}
752
753void BufferAlignNumber(int *CurrentBit)
754{
755 int i=0;
756
757 while(((*CurrentBit) + i) % 8 != 0) {
758 i++;
759 }
760
761 (*CurrentBit) = (*CurrentBit) + i;
762}
763
764 void AddBuffer(unsigned char *Destination,
765 int *CurrentBit,
766 unsigned char *Source,
767 int BitsToProcess)
768{
769 int i=0;
770
771 while (i!=BitsToProcess) {
772 if (GetBit(Source, i)) {
773 SetBit(Destination, (*CurrentBit)+i);
774 } else {
775 ClearBit(Destination, (*CurrentBit)+i);
776 }
777 i++;
778 }
779 (*CurrentBit) = (*CurrentBit) + BitsToProcess;
780}
781
782void AddBufferByte(unsigned char *Destination,
783 int *CurrentBit,
784 unsigned char Source,
785 int BitsToProcess)
786{
787 unsigned char Byte;
788
789 Byte = Source;
790
791 AddBuffer(Destination, CurrentBit, &Byte, BitsToProcess);
792}
793
794void GetBuffer(unsigned char *Source,
795 int *CurrentBit,
796 unsigned char *Destination,
797 int BitsToProcess)
798{
799 int i=0;
800
801 while (i!=BitsToProcess) {
802 if (GetBit(Source, (*CurrentBit)+i)) {
803 SetBit(Destination, i);
804 } else {
805 ClearBit(Destination, i);
806 }
807 i++;
808 }
809 (*CurrentBit) = (*CurrentBit) + BitsToProcess;
810}
811
812void GetBufferInt(unsigned char *Source,
813 int *CurrentBit,
814 int *integer,
815 int BitsToProcess)
816{
817 int l=0,z=128,i=0;
818
819 while (i!=BitsToProcess) {
820 if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
821 z=z/2;
822 i++;
823 }
824 *integer=l;
825 (*CurrentBit) = (*CurrentBit) + i;
826}
827
828 void GetBufferI(unsigned char *Source,
829 int *CurrentBit,
830 int *result,
831 int BitsToProcess)
832{
833 int l=0,z,i=0;
834
835 z = 1<<(BitsToProcess-1);
836
837 while (i!=BitsToProcess) {
838 if (GetBit(Source, (*CurrentBit)+i)) l=l+z;
839 z=z>>1;
840 i++;
841 }
842 *result=l;
843 (*CurrentBit) = (*CurrentBit) + i;
844}
845
846/* Unicode char 0x00 0x01 makes blinking in some Nokia phones.
847 * We replace single ~ chars into it. When user give double ~, it's replaced
848 * to single ~
849 */
850void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
851{
852 int i,current = 0;
853 bool special=false;
854
855 for (i = 0; i < len; i++) {
856 if (special) {
857 if (src[i*2] == 0x00 && src[i*2+1] == '~') {
858 dest[current++]= 0x00;
859 dest[current++]= '~';
860 } else {
861 dest[current++]= 0x00;
862 dest[current++] = 0x01;
863 dest[current++]= src[i*2];
864 dest[current++]= src[i*2+1];
865 }
866 special = false;
867 } else {
868 if (src[i*2] == 0x00 && src[i*2+1] == '~') {
869 special = true;
870 } else {
871 dest[current++]= src[i*2];
872 dest[current++]= src[i*2+1];
873 }
874 }
875 }
876 if (special) {
877 dest[current++]= 0x00;
878 dest[current++]= 0x01;
879 }
880 dest[current++] = 0x00;
881 dest[current++] = 0x00;
882}
883
884void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len)
885{
886 int i=0,current=0;
887
888 for (i=0;i<len;i++) {
889 switch (src[2*i]) {
890 case 0x00:
891 switch (src[2*i+1]) {
892 case 0x01:
893 dest[current++] = 0x00;
894 dest[current++] = '~';
895 break;
896 case '~':
897 dest[current++] = 0x00;
898 dest[current++] = '~';
899 dest[current++] = 0x00;
900 dest[current++] = '~';
901 break;
902 default:
903 dest[current++] = src[i*2];
904 dest[current++] = src[i*2+1];
905 }
906 break;
907 default:
908 dest[current++] = src[i*2];
909 dest[current++] = src[i*2+1];
910 }
911 }
912 dest[current++] = 0x00;
913 dest[current++] = 0x00;
914}
915
916bool mystrncasecmp(unsigned const char *a, unsigned const char *b, int num)
917{
918 int i;
919
920 if (a == NULL || b == NULL) return false;
921
922 num--;
923
924 for (i = 0; i != num; i++) {
925 if (a[i] == 0x00 && b[i] == 0x00) return true;
926 if (a[i] == 0x00 || b[i] == 0x00) return false;
927 if (tolower(a[i]) != tolower(b[i])) return false;
928 }
929 return true;
930}
931
932/* Compares two Unicode strings without regarding to case.
933 * Return true, when they're equal
934 */
935bool mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
936{
937 int i;
938 wchar_t wc,wc2;
939
940 if (a == NULL || b == NULL) return false;
941
942 num--;
943
944 for (i = 0; i != num; i++) {
945 if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) && (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return true;
946 if ((a[i*2] == 0x00 && a[i*2+1] == 0x00) || (b[i*2] == 0x00 && b[i*2+1] == 0x00)) return false;
947 wc = a[i*2+1] | (a[i*2] << 8);
948 wc2 = b[i*2+1] | (b[i*2] << 8);
949 if (mytowlower(wc) != mytowlower(wc2)) return false;
950 }
951 return true;
952}
953
954/* wcscmp in Mandrake 9.0 is wrong */
955bool mywstrncmp(unsigned const char *a, unsigned const char *b, int num)
956{
957 int i=0;
958
959 while (1) {
960 if (a[i*2] != b[i*2] || a[i*2+1] != b[i*2+1]) return false;
961 if (a[i*2] == 0x00 && a[i*2+1] == 0x00) return true;
962 i++;
963 if (num == i) return true;
964 }
965}
966
967/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
968bool myiswspace(unsigned const char *src)
969{
970#ifndef HAVE_ISWSPACE
971 int o;
972 unsigned chardest[10];
973#endif
974 wchar_t wc;
975
976 wc = src[1] | (src[0] << 8);
977
978#ifndef HAVE_ISWSPACE
979 o = DecodeWithUnicodeAlphabet(wc, dest);
980 if (o == 1) {
981 if (isspace(((int)dest[0]))!=0) return true;
982 return false;
983 }
984 return false;
985#else
986 return iswspace(wc);
987#endif
988}
989
990/* FreeBSD boxes 4.7-STABLE does't have it, although it's ANSI standard */
991int mytowlower(wchar_t c)
992{
993#ifndef HAVE_TOWLOWER
994 unsigned char dest[10];
995
996 DecodeWithUnicodeAlphabet(c, dest);
997 return tolower(dest[0]);
998#else
999 return towlower(c);
1000#endif
1001}
1002
1003/*
1004 * Following code is based on wcsstr from the GNU C Library, original
1005 * comment follows:
1006 */
1007/*
1008 * The original strstr() file contains the following comment:
1009 *
1010 * My personal strstr() implementation that beats most other algorithms.
1011 * Until someone tells me otherwise, I assume that this is the
1012 * fastest implementation of strstr() in C.
1013 * I deliberately chose not to comment it. You should have at least
1014 * as much fun trying to understand it, as I had to write it :-).
1015 *
1016 * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
1017
1018unsigned char *mystrstr (const unsigned char *haystack, const unsigned char *needle)
1019{
1020/* One crazy define to convert unicode used in Gammu to standard wchar_t */
1021#define tolowerwchar(x) (mytowlower((wchar_t)( (((&(x))[0] & 0xff) << 8) | (((&(x))[1] & 0xff)) )))
1022 register wchar_t b, c;
1023
1024 if ((b = tolowerwchar(*needle)) != L'\0') {
1025 haystack -= 2; /* possible ANSI violation */
1026 do {
1027 haystack += 2;
1028 if ((c = tolowerwchar(*haystack)) == L'\0')
1029 goto ret0;
1030 } while (c != b);
1031
1032 needle += 2;
1033 if ((c = tolowerwchar(*needle)) == L'\0')
1034 goto foundneedle;
1035 needle += 2;
1036 goto jin;
1037
1038 for (;;) {
1039 register wchar_t a;
1040 register const unsigned char *rhaystack, *rneedle;
1041
1042 do {
1043 haystack += 2;
1044 if ((a = tolowerwchar(*haystack)) == L'\0')
1045 goto ret0;
1046 if (a == b)
1047 break;
1048 haystack += 2;
1049 if ((a = tolowerwchar(*haystack)) == L'\0')
1050 goto ret0;
1051 shloop: ;
1052 } while (a != b);
1053
1054 jin: haystack += 2;
1055 if ((a = tolowerwchar(*haystack)) == L'\0')
1056 goto ret0;
1057
1058 if (a != c)
1059 goto shloop;
1060
1061 rhaystack = haystack + 2;
1062 haystack -= 2;
1063 rneedle = needle;
1064 if (tolowerwchar(*rhaystack) == (a = tolowerwchar(*rneedle)))
1065 do {
1066 if (a == L'\0')
1067 goto foundneedle;
1068 rhaystack += 2;
1069 needle += 2;
1070 if (tolowerwchar(*rhaystack) != (a = tolowerwchar(*needle)))
1071 break ;
1072 if (a == L'\0')
1073 goto foundneedle;
1074 rhaystack += 2;
1075 needle += 2;
1076 } while (tolowerwchar(*rhaystack) == (a = tolowerwchar(*needle)));
1077
1078 needle = rneedle; /* took the register-poor approach */
1079
1080 if (a == L'\0')
1081 break;
1082 }
1083 }
1084foundneedle:
1085 return (unsigned char *)haystack;
1086ret0:
1087 return NULL;
1088#undef tolowerwchar
1089}
1090
1091void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen)
1092{
1093 OutBuffer[0] = 0;
1094 if (Buffer == NULL) return;
1095 while (1) {
1096 if ((*Pos) >= MaxLen) return;
1097 switch (Buffer[*Pos]) {
1098 case 0x00:
1099 return;
1100 case 0x0A:
1101 if (strlen(OutBuffer) != 0) return;
1102 break;
1103 case 0x0D:
1104 if (strlen(OutBuffer) != 0) return;
1105 break;
1106 default :
1107 OutBuffer[strlen(OutBuffer) + 1] = 0;
1108 OutBuffer[strlen(OutBuffer)] = Buffer[*Pos];
1109 }
1110 (*Pos)++;
1111 }
1112}
1113
1114void StringToDouble(char *text, double *d)
1115{
1116 bool before=true;
1117 double multiply = 1;
1118 unsigned int i;
1119
1120 *d = 0;
1121 for (i=0;i<strlen(text);i++) {
1122 if (isdigit(text[i])) {
1123 if (before) {
1124 (*d)=(*d)*10+(text[i]-'0');
1125 } else {
1126 multiply=multiply*0.1;
1127 (*d)=(*d)+(text[i]-'0')*multiply;
1128 }
1129 }
1130 if (text[i]=='.' || text[i]==',') before=false;
1131 }
1132}
1133
1134/* When char can be converted, convert it from Unicode to UTF8 */
1135bool EncodeWithUTF8Alphabet(unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2)
1136{
1137 unsigned charmychar3,mychar4;
1138 int j=0;
1139
1140 if (mychar1>0x00 || mychar2>128) {
1141 mychar3=0x00;
1142 mychar4=128;
1143 while (true) {
1144 if (mychar3==mychar1) {
1145 if (mychar4+64>=mychar2) {
1146 *ret1=j+0xc2;
1147 *ret2=0x80+(mychar2-mychar4);
1148 return true;
1149 }
1150 }
1151 if (mychar4==192) {
1152 mychar3++;
1153 mychar4=0;
1154 } else {
1155 mychar4=mychar4+64;
1156 }
1157 j++;
1158 }
1159 }
1160 return false;
1161}
1162
1163/* Make UTF8 string from Unicode input string */
1164bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src)
1165{
1166 int i,j=0;
1167 unsigned charmychar1, mychar2;
1168 bool retval = false;
1169
1170 for (i = 0; i < (int)(UnicodeLength(src)); i++) {
1171 if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
1172 sprintf(dest+j, "=%02X=%02X",mychar1,mychar2);
1173 j= j+6;
1174 retval = true;
1175 } else {
1176 j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
1177 }
1178 }
1179 dest[j++]=0;
1180 return retval;
1181}
1182
1183bool EncodeUTF8(unsigned char *dest, const unsigned char *src)
1184{
1185 int i,j=0;
1186 unsigned charmychar1, mychar2;
1187 bool retval = false;
1188
1189 for (i = 0; i < (int)(UnicodeLength(src)); i++) {
1190 if (EncodeWithUTF8Alphabet(src[i*2],src[i*2+1],&mychar1,&mychar2)) {
1191 sprintf(dest+j, "%c%c",mychar1,mychar2);
1192 j= j+2;
1193 retval = true;
1194 } else {
1195 j += DecodeWithUnicodeAlphabet(((wchar_t)(src[i*2]*256+src[i*2+1])), dest + j);
1196 }
1197 }
1198 dest[j++]=0;
1199 return retval;
1200}
1201
1202/* Decode UTF8 char to Unicode char */
1203wchar_t DecodeWithUTF8Alphabet(unsigned char mychar3, unsigned char mychar4)
1204{
1205 unsigned charmychar1, mychar2;
1206 int j;
1207
1208 mychar1=0x00;
1209 mychar2=128;
1210 for(j=0;j<mychar3-0xc2;j++) {
1211 if (mychar2==192) {
1212 mychar1++;
1213 mychar2 = 0;
1214 } else {
1215 mychar2 = mychar2+64;
1216 }
1217 }
1218 mychar2 = mychar2+(mychar4-0x80);
1219 return mychar2 | (mychar1 << 8);
1220}
1221
1222/* Make Unicode string from UTF8 string */
1223void DecodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src, int len)
1224{
1225 int i=0,j=0;
1226 unsigned charmychar1, mychar2;
1227 wchar_t ret;
1228
1229 while (i<=len) {
1230 if (len-6>=i) {
1231 /* Need to have correct chars */
1232 if (src[i] =='=' && DecodeWithHexBinAlphabet(src[i+1])!=-1
1233 && DecodeWithHexBinAlphabet(src[i+2])!=-1 &&
1234 src[i+3]=='=' && DecodeWithHexBinAlphabet(src[i+4])!=-1 &&
1235 DecodeWithHexBinAlphabet(src[i+5])!=-1) {
1236 mychar1= 16*DecodeWithHexBinAlphabet(src[i+1])+DecodeWithHexBinAlphabet(src[i+2]);
1237 mychar2= 16*DecodeWithHexBinAlphabet(src[i+4])+DecodeWithHexBinAlphabet(src[i+5]);
1238 ret = DecodeWithUTF8Alphabet(mychar1,mychar2);
1239 i = i+6;
1240 } else {
1241 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1242 }
1243 } else {
1244 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1245 }
1246 dest[j++] = (ret >> 8) & 0xff;
1247 dest[j++] = ret & 0xff;
1248 }
1249 dest[j++] = 0;
1250 dest[j++] = 0;
1251}
1252
1253void DecodeUTF8(unsigned char *dest, const unsigned char *src, int len)
1254{
1255 int i=0,j=0;
1256 wchar_t ret;
1257
1258 while (i<=len) {
1259 if (len-2>=i) {
1260 if (src[i] >= 0xC2) {
1261 ret = DecodeWithUTF8Alphabet(src[i],src[i+1]);
1262 i = i+2;
1263 } else {
1264 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1265 }
1266 } else {
1267 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1268 }
1269 dest[j++] = (ret >> 8) & 0xff;
1270 dest[j++] = ret & 0xff;
1271 }
1272 dest[j++] = 0;
1273 dest[j++] = 0;
1274}
1275
1276void DecodeUTF7(unsigned char *dest, const unsigned char *src, int len)
1277{
1278 int i=0,j=0,z,p;
1279 wchar_t ret;
1280
1281 while (i<=len) {
1282 if (len-5>=i) {
1283 if (src[i] == '+') {
1284 z=0;
1285 while (src[z+i+1] != '-' && z+i+1<len) z++;
1286 p=DecodeBASE64(src+i+1, dest+j, z);
1287 if (p%2 != 0) p--;
1288 j+=p;
1289 i+=z+2;
1290 } else {
1291 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1292 dest[j++] = (ret >> 8) & 0xff;
1293 dest[j++] = ret & 0xff;
1294 }
1295 } else {
1296 i+=EncodeWithUnicodeAlphabet(&src[i], &ret);
1297 dest[j++] = (ret >> 8) & 0xff;
1298 dest[j++] = ret & 0xff;
1299 }
1300 }
1301 dest[j++] = 0;
1302 dest[j++] = 0;
1303}
1304
1305/*
1306Bob Trower 08/04/01
1307Copyright (c) Trantor Standard Systems Inc., 2001
1308
1309Permission is hereby granted, free of charge, to any person
1310obtaining a copy of this software and associated
1311documentation files (the "Software"), to deal in the
1312Software without restriction, including without limitation
1313the rights to use, copy, modify, merge, publish, distribute,
1314sublicense, and/or sell copies of the Software, and to
1315permit persons to whom the Software is furnished to do so,
1316subject to the following conditions:
1317
1318The above copyright notice and this permission notice shall
1319be included in all copies or substantial portions of the
1320Software.
1321
1322THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
1323KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
1324WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1325PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
1326OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
1327OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1328OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1329SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1330*/
1331
1332static void EncodeBASE64Block(unsigned char in[3], unsigned char out[4], int len)
1333{
1334 /* BASE64 translation Table as described in RFC1113 */
1335 unsigned char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1336
1337 out[0] = cb64[ in[0] >> 2 ];
1338 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
1339 out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
1340 out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
1341}
1342
1343void EncodeBASE64(const unsigned char *Input, unsigned char *Output, int Length)
1344{
1345 unsigned char in[3], out[4];
1346 int i, pos = 0, len, outpos = 0;
1347
1348 while (pos < Length) {
1349 len = 0;
1350 for (i = 0; i < 3; i++) {
1351 in[i] = 0;
1352 if (pos < Length) {
1353 in[i] = Input[pos];
1354 len++;
1355 pos++;
1356 }
1357 }
1358 if(len) {
1359 EncodeBASE64Block(in, out, len);
1360 for (i = 0; i < 4; i++) Output[outpos++] = out[i];
1361 }
1362 }
1363
1364 Output[outpos++] = 0;
1365}
1366
1367static void DecodeBASE64Block(unsigned char in[4], unsigned char out[3])
1368{
1369 out[0] = (unsigned char) (in[0] << 2 | in[1] >> 4);
1370 out[1] = (unsigned char) (in[1] << 4 | in[2] >> 2);
1371 out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]);
1372}
1373
1374int DecodeBASE64(const unsigned char *Input, unsigned char *Output, int Length)
1375{
1376 unsigned char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
1377 unsigned char in[4], out[3], v;
1378 int i, len, pos = 0, outpos = 0;
1379
1380 while (pos < Length) {
1381 len = 0;
1382 for(i = 0; i < 4; i++) {
1383 v = 0;
1384 while(v == 0) {
1385 if (pos >= Length) break;
1386 v = (unsigned char) Input[pos++];
1387 v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
1388 if (v) v = (unsigned char) ((v == '$') ? 0 : v - 61);
1389 }
1390 if(pos<=Length) {
1391 if (v) {
1392 len++;
1393 in[i] = (unsigned char) (v - 1);
1394 }
1395 }
1396 }
1397 if (len) {
1398 DecodeBASE64Block(in, out);
1399 for(i = 0; i < len - 1; i++) Output[outpos++] = out[i];
1400 }
1401 }
1402 Output[outpos] = 0;
1403 return outpos;
1404}
1405
1406/* How should editor hadle tabs in this file? Add editor commands here.
1407 * vim: noexpandtab sw=8 ts=8 sts=8:
1408 */
1409
diff --git a/gammu/emb/common/misc/coding/coding.h b/gammu/emb/common/misc/coding/coding.h
new file mode 100644
index 0000000..d0c334d
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/coding.h
@@ -0,0 +1,133 @@
1/* (c) 2002-2004 by Marcin Wiacek and others */
2
3#ifndef __coding_h
4#define __coding_h
5
6#include <stdlib.h>
7
8#include "../misc.h"
9
10#ifdef __OpenBSD__
11 typedef int wint_t;
12#endif
13
14/* ---------------------------- Unicode ------------------------------------ */
15 bool mywstrncasecmp (unsigned const char *a, unsigned const char *b, int num);
16 unsigned char *mystrstr (unsigned const char *haystack, unsigned const char *needle);
17 bool mywstrncmp (unsigned const char *a, unsigned const char *b, int num);
18 bool myiswspace (unsigned const char *src);
19 int mytowlower (wchar_t c);
20
21 unsigned int EncodeWithUnicodeAlphabet(const unsigned char *value, wchar_t *dest);
22 unsigned int DecodeWithUnicodeAlphabet(wchar_t value, unsigned char *dest);
23
24 unsigned int UnicodeLength (const unsigned char *str);
25 unsigned char *DecodeUnicodeString (const unsigned char *src);
26 unsigned char *DecodeUnicodeConsole (const unsigned char *src);
27 void DecodeUnicode (const unsigned char *src, unsigned char *dest);
28 void EncodeUnicode (unsigned char *dest, const unsigned char *src, int len);
29
30 void CopyUnicodeString (unsigned char *Dest, unsigned char *Source);
31 void ReverseUnicodeString (unsigned char *String);
32
33 void ReadUnicodeFile (unsigned char *Dest, unsigned char *Source);
34
35 void DecodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len);
36 void EncodeUnicodeSpecialNOKIAChars(unsigned char *dest, const unsigned char *src, int len);
37
38/* ------------------------------- BCD ------------------------------------- */
39 unsigned char EncodeWithBCDAlphabet (int value);
40 int DecodeWithBCDAlphabet (unsigned char value);
41
42 void DecodeBCD (unsigned char *dest, const unsigned char *src, int len);
43 void EncodeBCD (unsigned char *dest, const unsigned char *src, int len, bool fill);
44
45/* ------------------------------ UTF7 ------------------------------------- */
46 void DecodeUTF7 (unsigned char *dest, const unsigned char *src, int len);
47
48/* ------------------------------ UTF8 ------------------------------------- */
49 wchar_t DecodeWithUTF8Alphabet (unsigned char mychar3, unsigned char mychar4);
50 bool EncodeWithUTF8Alphabet (unsigned char mychar1, unsigned char mychar2, unsigned char *ret1, unsigned char *ret2);
51
52 bool EncodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src);
53 void DecodeUTF8QuotedPrintable(unsigned char *dest, const unsigned char *src, int len);
54
55 bool EncodeUTF8 (unsigned char *dest, const unsigned char *src);
56 void DecodeUTF8 (unsigned char *dest, const unsigned char *src, int len);
57
58/* ------------------------------- BASE64 ---------------------------------- */
59 void EncodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
60 int DecodeBASE64 (const unsigned char *Input, unsigned char *Output, int Length);
61
62/* ----------------------------- HexBin ------------------------------------ */
63 void DecodeHexBin (unsigned char *dest, const unsigned char *src, int len);
64 void EncodeHexBin (unsigned char *dest, const unsigned char *src, int len);
65
66/* ----------------------------- HexUnicode -------------------------------- */
67 void DecodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
68 void EncodeHexUnicode (unsigned char *dest, const unsigned char *src, int len);
69
70/* ---------------------- DefaultAlphabet for SMS -------------------------- */
71 void EncodeDefault (unsigned char *dest, const unsigned char *src, int *len, bool UseExtensions, unsigned char *ExtraAlphabet);
72 void DecodeDefault (unsigned char *dest, const unsigned char *src, int len, bool UseExtensions, unsigned char *ExtraAlphabet);
73 void FindDefaultAlphabetLen (const unsigned char *src, int *srclen, int *smslen, int maxlen);
74
75 int GSM_PackSevenBitsToEight(int offset, unsigned char *input, unsigned char *output, int length);
76 int GSM_UnpackEightBitsToSeven(int offset, int in_length, int out_length,
77 unsigned char *input, unsigned char *output);
78
79/* ----------------- Phone numbers according to GSM specs ------------------ */
80
81/**
82 * Enum to handle types of phones numbers like
83 * specified in GSM 03.40 section 9.1.2.5
84 */
85typedef enum {
86 /**
87 * Unknown number type
88 */
89 NUMBER_UNKNOWN = 0x81,
90 /**
91 * International number (full number with code of country)
92 */
93 NUMBER_INTERNATIONAL= 0x91,
94 /**
95 * Alphanumeric number (with chars too)
96 */
97 NUMBER_ALPHANUMERIC= 0xD0
98
99 /* specification give also other values */
100} GSM_NumberType;
101
102 void GSM_UnpackSemiOctetNumber(unsigned char *retval, unsigned char *Number, bool semioctet);
103 int GSM_PackSemiOctetNumber (unsigned char *Number, unsigned char *Output, bool semioctet);
104
105/* ---------------------------- Bits --------------------------------------- */
106
107void BufferAlign (unsigned char *Destination, int *CurrentBit);
108void BufferAlignNumber(int *CurrentBit);
109
110 void AddBuffer (unsigned char *Destination, int *CurrentBit, unsigned char *Source, int BitsToProcess);
111void AddBufferByte(unsigned char *Destination, int *CurrentBit, unsigned char Source, int BitsToProcess);
112
113void GetBuffer (unsigned char *Source, int *CurrentBit, unsigned char *Destination, int BitsToProcess);
114void GetBufferInt (unsigned char *Source, int *CurrentBit, int *integer, int BitsToProcess);
115void GetBufferI (unsigned char *Source, int *CurrentBit, int *result, int BitsToProcess);
116
117int GetBit (unsigned char *Buffer, int BitNum);
118int SetBit (unsigned char *Buffer, int BitNum);
119int ClearBit (unsigned char *Buffer, int BitNum);
120
121/* ---------------------------- Other -------------------------------------- */
122
123 void StringToDouble(char *text, double *d);
124
125bool mystrncasecmp (unsigned const char *a, unsigned const char *b, int num);
126
127void MyGetLine(unsigned char *Buffer, int *Pos, unsigned char *OutBuffer, int MaxLen);
128
129#endif
130
131/* How should editor hadle tabs in this file? Add editor commands here.
132 * vim: noexpandtab sw=8 ts=8 sts=8:
133 */
diff --git a/gammu/emb/common/misc/coding/md5.c b/gammu/emb/common/misc/coding/md5.c
new file mode 100644
index 0000000..30fe33f
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/md5.c
@@ -0,0 +1,298 @@
1/* Taken from ReHash (see http://www.reichlsoft.de.vu/) and released
2 * under GPL/LGPL with permission from ReHash author
3 * Dominik Reichl <dominik.reichl@t-online.de>, Germany
4 */
5
6/*
7 **********************************************************************
8 ** MD5.cpp **
9 ** **
10 ** - Style modified by Tony Ray, January 2001 **
11 ** Added support for randomizing initialization constants **
12 ** - Style modified by Dominik Reichl, April 2003 **
13 ** Optimized code **
14 ** **
15 ** MD5.c **
16 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
17 ** Created: 2/17/90 RLR **
18 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
19 **********************************************************************
20 */
21
22/*
23 **********************************************************************
24 ** MD5.h -- Header file for implementation of MD5 **
25 ** RSA Data Security, Inc. MD5 Message Digest Algorithm **
26 ** Created: 2/17/90 RLR **
27 ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
28 ** Revised (for MD5): RLR 4/27/91 **
29 ** -- G modified to have y&~z instead of y&z **
30 ** -- FF, GG, HH modified to add in last register done **
31 ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
32 ** -- distinct additive constant for each step **
33 ** -- round 4 added, working mod 7 **
34 **********************************************************************
35 */
36
37/*
38 **********************************************************************
39 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
40 ** **
41 ** License to copy and use this software is granted provided that **
42 ** it is identified as the "RSA Data Security, Inc. MD5 Message **
43 ** Digest Algorithm" in all material mentioning or referencing this **
44 ** software or this function. **
45 ** **
46 ** License is also granted to make and use derivative works **
47 ** provided that such works are identified as "derived from the RSA **
48 ** Data Security, Inc. MD5 Message Digest Algorithm" in all **
49 ** material mentioning or referencing the derived work. **
50 ** **
51 ** RSA Data Security, Inc. makes no representations concerning **
52 ** either the merchantability of this software or the suitability **
53 ** of this software for any particular purpose. It is provided "as **
54 ** is" without express or implied warranty of any kind. **
55 ** **
56 ** These notices must be retained in any copies of any part of this **
57 ** documentation and/or software. **
58 **********************************************************************
59 */
60
61#include <stdio.h>
62#include <stdlib.h>
63
64#include "md5.h"
65
66/* Typedef a 32 bit type */
67#ifndef UINT4
68typedef unsigned long int UINT4;
69#endif
70
71/* Data structure for MD5 (Message Digest) computation */
72typedef struct {
73 UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */
74 UINT4 buf[4]; /* Scratch buffer */
75 unsigned char in[64]; /* Input buffer */
76 unsigned char digest[16]; /* Actual digest after MD5Final call */
77} MD5_CTX;
78
79/* Padding */
80static unsigned char MD5_PADDING[64] = {
81 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89};
90
91/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */
92#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
93#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
94#define MD5_H(x, y, z) ((x) ^ (y) ^ (z))
95#define MD5_I(x, y, z) ((y) ^ ((x) | (~z)))
96
97/* ROTATE_LEFT rotates x left n bits */
98#ifndef ROTATE_LEFT
99#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
100#endif
101
102/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */
103/* Rotation is separate from addition to prevent recomputation */
104#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); }
105#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); }
106#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); }
107#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); }
108
109/* Constants for transformation */
110#define MD5_S11 7 /* Round 1 */
111#define MD5_S12 12
112#define MD5_S13 17
113#define MD5_S14 22
114#define MD5_S21 5 /* Round 2 */
115#define MD5_S22 9
116#define MD5_S23 14
117#define MD5_S24 20
118#define MD5_S31 4 /* Round 3 */
119#define MD5_S32 11
120#define MD5_S33 16
121#define MD5_S34 23
122#define MD5_S41 6 /* Round 4 */
123#define MD5_S42 10
124#define MD5_S43 15
125#define MD5_S44 21
126
127/* Basic MD5 step. MD5_Transform buf based on in */
128static void MD5_Transform (UINT4 *buf, UINT4 *in)
129{
130 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
131
132 /* Round 1 */
133 MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */
134 MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */
135 MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */
136 MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */
137 MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */
138 MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */
139 MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */
140 MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */
141 MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */
142 MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */
143 MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */
144 MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */
145 MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */
146 MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */
147 MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */
148 MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */
149
150 /* Round 2 */
151 MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */
152 MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */
153 MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */
154 MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */
155 MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */
156 MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */
157 MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */
158 MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */
159 MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */
160 MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */
161 MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */
162 MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */
163 MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */
164 MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */
165 MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */
166 MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */
167
168 /* Round 3 */
169 MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */
170 MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */
171 MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */
172 MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */
173 MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */
174 MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */
175 MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */
176 MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */
177 MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */
178 MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */
179 MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */
180 MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */
181 MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */
182 MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */
183 MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */
184 MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */
185
186 /* Round 4 */
187 MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */
188 MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */
189 MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */
190 MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */
191 MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */
192 MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */
193 MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */
194 MD5_II ( b, c, d, a, in[ 1], MD5_S44, (UINT4) 2240044497u); /* 56 */
195 MD5_II ( a, b, c, d, in[ 8], MD5_S41, (UINT4) 1873313359u); /* 57 */
196 MD5_II ( d, a, b, c, in[15], MD5_S42, (UINT4) 4264355552u); /* 58 */
197 MD5_II ( c, d, a, b, in[ 6], MD5_S43, (UINT4) 2734768916u); /* 59 */
198 MD5_II ( b, c, d, a, in[13], MD5_S44, (UINT4) 1309151649u); /* 60 */
199 MD5_II ( a, b, c, d, in[ 4], MD5_S41, (UINT4) 4149444226u); /* 61 */
200 MD5_II ( d, a, b, c, in[11], MD5_S42, (UINT4) 3174756917u); /* 62 */
201 MD5_II ( c, d, a, b, in[ 2], MD5_S43, (UINT4) 718787259u); /* 63 */
202 MD5_II ( b, c, d, a, in[ 9], MD5_S44, (UINT4) 3951481745u); /* 64 */
203
204 buf[0] += a;
205 buf[1] += b;
206 buf[2] += c;
207 buf[3] += d;
208}
209
210// Set pseudoRandomNumber to zero for RFC MD5 implementation
211void MD5Init (MD5_CTX *mdContext, unsigned long pseudoRandomNumber)
212{
213 mdContext->i[0] = mdContext->i[1] = (UINT4)0;
214
215 /* Load magic initialization constants */
216 mdContext->buf[0] = (UINT4)0x67452301 + (pseudoRandomNumber * 11);
217 mdContext->buf[1] = (UINT4)0xefcdab89 + (pseudoRandomNumber * 71);
218 mdContext->buf[2] = (UINT4)0x98badcfe + (pseudoRandomNumber * 37);
219 mdContext->buf[3] = (UINT4)0x10325476 + (pseudoRandomNumber * 97);
220}
221
222void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
223{
224 UINT4 in[16];
225 int mdi = 0;
226 unsigned int i = 0, ii = 0;
227
228 /* Compute number of bytes mod 64 */
229 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
230
231 /* Update number of bits */
232 if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) mdContext->i[1]++;
233 mdContext->i[0] += ((UINT4)inLen << 3);
234 mdContext->i[1] += ((UINT4)inLen >> 29);
235
236 while (inLen--) {
237 /* Add new character to buffer, increment mdi */
238 mdContext->in[mdi++] = *inBuf++;
239
240 /* Transform if necessary */
241 if (mdi == 0x40) {
242 for (i = 0, ii = 0; i < 16; i++, ii += 4)
243 in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
244 (((UINT4)mdContext->in[ii+2]) << 16) |
245 (((UINT4)mdContext->in[ii+1]) << 8) |
246 ((UINT4)mdContext->in[ii]);
247
248 MD5_Transform (mdContext->buf, in);
249 mdi = 0;
250 }
251 }
252}
253
254void MD5Final (MD5_CTX *mdContext)
255{
256 UINT4 in[16];
257 int mdi = 0;
258 unsigned int i = 0, ii = 0, padLen = 0;
259
260 /* Save number of bits */
261 in[14] = mdContext->i[0];
262 in[15] = mdContext->i[1];
263
264 /* Compute number of bytes mod 64 */
265 mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
266
267 /* Pad out to 56 mod 64 */
268 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
269 MD5Update (mdContext, MD5_PADDING, padLen);
270
271 /* Append length in bits and transform */
272 for (i = 0, ii = 0; i < 14; i++, ii += 4)
273 in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
274 (((UINT4)mdContext->in[ii+2]) << 16) |
275 (((UINT4)mdContext->in[ii+1]) << 8) |
276 ((UINT4)mdContext->in[ii]);
277 MD5_Transform (mdContext->buf, in);
278
279 /* Store buffer in digest */
280 for (i = 0, ii = 0; i < 4; i++, ii += 4) {
281 mdContext->digest[ii] = (unsigned char)( mdContext->buf[i] & 0xFF);
282 mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
283 mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
284 mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
285 }
286}
287
288void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum)
289{
290 int i;
291 MD5_CTX m_md5;
292
293 MD5Init(&m_md5, 0);
294 MD5Update(&m_md5, buffer, length);
295 MD5Final(&m_md5);
296
297 for (i = 0; i < 16; i++) sprintf(checksum+i*2,"%02X", m_md5.digest[i]);
298}
diff --git a/gammu/emb/common/misc/coding/md5.h b/gammu/emb/common/misc/coding/md5.h
new file mode 100644
index 0000000..9da9229
--- a/dev/null
+++ b/gammu/emb/common/misc/coding/md5.h
@@ -0,0 +1,6 @@
1#ifndef __md5_h
2#define __md5_h
3
4void CalculateMD5(unsigned char *buffer, int length, unsigned char *checksum);
5
6#endif
diff --git a/gammu/emb/common/misc/misc.c b/gammu/emb/common/misc/misc.c
new file mode 100644
index 0000000..c2f09e4
--- a/dev/null
+++ b/gammu/emb/common/misc/misc.c
@@ -0,0 +1,591 @@
1/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
2/* Checking used compiler (c) 2002 by Michal Cihar */
3
4#include <string.h>
5#include <ctype.h>
6#include <time.h>
7#include <stdarg.h>
8#include <stdio.h>
9#include <locale.h>
10#include <sys/timeb.h>
11#ifdef WIN32
12# include "windows.h"
13#endif
14
15#include "../gsmstate.h"
16#include "misc.h"
17
18/* Based on article in Polish PC-Kurier 8/1998 page 104
19 * Archive on http://www.pckurier.pl
20 */
21char *DayOfWeek (int year, int month, int day)
22{
23 int p,q,r,w;
24 static char DayOfWeekChar[10];
25
26 p=(14-month) / 12;
27 q=month+12*p-2;
28 r=year-p;
29 w=(day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
30 strcpy(DayOfWeekChar,"");
31 switch (w) {
32 case 0: strcpy(DayOfWeekChar,"Sun"); break;
33 case 1: strcpy(DayOfWeekChar,"Mon"); break;
34 case 2: strcpy(DayOfWeekChar,"Tue"); break;
35 case 3: strcpy(DayOfWeekChar,"Wed"); break;
36 case 4: strcpy(DayOfWeekChar,"Thu"); break;
37 case 5: strcpy(DayOfWeekChar,"Fri"); break;
38 case 6: strcpy(DayOfWeekChar,"Sat"); break;
39 }
40 return DayOfWeekChar;
41}
42
43void Fill_GSM_DateTime(GSM_DateTime *Date, time_t timet)
44{
45 struct tm *now;
46
47 now = localtime(&timet);
48 Date->Year= now->tm_year;
49 Date->Month= now->tm_mon+1;
50 Date->Day= now->tm_mday;
51 Date->Hour= now->tm_hour;
52 Date->Minute= now->tm_min;
53 Date->Second = now->tm_sec;
54}
55
56void GSM_GetCurrentDateTime (GSM_DateTime *Date)
57{
58 Fill_GSM_DateTime(Date, time(NULL));
59 if (Date->Year<1900) {
60 if (Date->Year>90) Date->Year = Date->Year+1900;
61 else Date->Year = Date->Year+2000;
62 }
63}
64
65time_t Fill_Time_T(GSM_DateTime DT, int TZ)
66{
67 struct tm tm_starttime;
68 unsigned char buffer[30];
69
70 dbgprintf(" StartTime : %02i-%02i-%04i %02i:%02i:%02i\n",
71 DT.Day,DT.Month,DT.Year,DT.Hour,DT.Minute,DT.Second);
72
73 if (TZ != 0) {
74#if defined(WIN32) || defined(__SVR4)
75 sprintf(buffer,"TZ=PST+%i",TZ);
76 putenv(buffer);
77#else
78 sprintf(buffer,"PST+%i",TZ);
79 setenv("TZ",buffer,1);
80#endif
81 }
82 tzset();
83
84 memset(&tm_starttime, 0, sizeof(tm_starttime));
85 tm_starttime.tm_year = DT.Year - 1900;
86 tm_starttime.tm_mon = DT.Month - 1;
87 tm_starttime.tm_mday = DT.Day;
88 tm_starttime.tm_hour = DT.Hour;
89 tm_starttime.tm_min = DT.Minute;
90 tm_starttime.tm_sec = DT.Second;
91 tm_starttime.tm_isdst= 0;
92
93 return mktime(&tm_starttime);
94}
95
96void GetTimeDifference(unsigned long diff, GSM_DateTime *DT, bool Plus, int multi)
97{
98 time_t t_time;
99
100 t_time = Fill_Time_T(*DT,8);
101
102 if (Plus) {
103 t_time += diff*multi;
104 } else {
105 t_time -= diff*multi;
106 }
107
108 Fill_GSM_DateTime(DT, t_time);
109 DT->Year = DT->Year + 1900;
110 dbgprintf(" EndTime : %02i-%02i-%04i %02i:%02i:%02i\n",
111 DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second);
112}
113
114char *OSDateTime (GSM_DateTime dt, bool TimeZone)
115{
116 struct tm timeptr;
117 static char retval[200],retval2[200];
118 int p,q,r,w;
119
120#ifdef WIN32
121 setlocale(LC_ALL, ".OCP");
122#endif
123
124 /* Based on article in Polish PC-Kurier 8/1998 page 104
125 * Archive on http://www.pckurier.pl
126 */
127 p=(14-dt.Month) / 12;
128 q=dt.Month+12*p-2;
129 r=dt.Year-p;
130 w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
131
132 timeptr.tm_yday = 0; /* FIXME */
133 timeptr.tm_isdst = -1; /* FIXME */
134 timeptr.tm_year = dt.Year - 1900;
135 timeptr.tm_mon = dt.Month - 1;
136 timeptr.tm_mday = dt.Day;
137 timeptr.tm_hour = dt.Hour;
138 timeptr.tm_min = dt.Minute;
139 timeptr.tm_sec = dt.Second;
140 timeptr.tm_wday = w;
141#ifdef _BSD_SOURCE
142 timeptr.tm_zone = NULL;
143#endif
144
145#ifdef WIN32
146 strftime(retval2, 200, "%#c", &timeptr);
147#else
148 strftime(retval2, 200, "%c", &timeptr);
149#endif
150 if (TimeZone) {
151 if (dt.Timezone >= 0) {
152 sprintf(retval," +%02i00",dt.Timezone);
153 } else {
154 sprintf(retval," -%02i00",dt.Timezone);
155 }
156 strcat(retval2,retval);
157 }
158 /* If don't have weekday name, include it */
159 strftime(retval, 200, "%A", &timeptr);
160 if (strstr(retval2,retval)==NULL) {
161 /* Check for abbreviated weekday */
162 strftime(retval, 200, "%a", &timeptr);
163 if (strstr(retval2,retval)==NULL) {
164 strcat(retval2," (");
165 strcat(retval2,retval);
166 strcat(retval2,")");
167 }
168 }
169
170#ifdef WIN32
171 setlocale(LC_ALL, ".ACP");
172#endif
173
174 return retval2;
175}
176
177char *OSDate (GSM_DateTime dt)
178{
179 struct tm timeptr;
180 static char retval[200],retval2[200];
181 int p,q,r,w;
182
183#ifdef WIN32
184 setlocale(LC_ALL, ".OCP");
185#endif
186
187 /* Based on article in Polish PC-Kurier 8/1998 page 104
188 * Archive on http://www.pckurier.pl
189 */
190 p=(14-dt.Month) / 12;
191 q=dt.Month+12*p-2;
192 r=dt.Year-p;
193 w=(dt.Day+(31*q) / 12 + r + r / 4 - r / 100 + r / 400) % 7;
194
195 timeptr.tm_yday = 0; /* FIXME */
196 timeptr.tm_isdst = -1; /* FIXME */
197 timeptr.tm_year = dt.Year - 1900;
198 timeptr.tm_mon = dt.Month - 1;
199 timeptr.tm_mday = dt.Day;
200 timeptr.tm_hour = dt.Hour;
201 timeptr.tm_min = dt.Minute;
202 timeptr.tm_sec = dt.Second;
203 timeptr.tm_wday = w;
204#ifdef _BSD_SOURCE
205 timeptr.tm_zone = NULL;
206#endif
207
208#ifdef WIN32
209 strftime(retval2, 200, "%#x", &timeptr);
210#else
211 strftime(retval2, 200, "%x", &timeptr);
212#endif
213 /* If don't have weekday name, include it */
214 strftime(retval, 200, "%A", &timeptr);
215 if (strstr(retval2,retval)==NULL) {
216 /* Check also for short name */
217 strftime(retval, 200, "%a", &timeptr);
218 if (strstr(retval2,retval)==NULL) {
219 strcat(retval2," (");
220 strcat(retval2,retval);
221 strcat(retval2,")");
222 }
223 }
224
225#ifdef WIN32
226 setlocale(LC_ALL, ".ACP");
227#endif
228
229 return retval2;
230}
231
232bool CheckDate(GSM_DateTime *date)
233{
234 /* FIXME: This could also check if day is correct for selected month */
235 return date->Year != 0 &&
236 date->Month >= 1 && date->Month <= 12 &&
237 date->Day >= 1 && date->Day <= 31;
238}
239
240bool CheckTime(GSM_DateTime *date)
241{
242 return date->Hour <= 23 && date->Hour >= 0 &&
243 date->Minute <= 59 && date->Minute >= 0 &&
244 date->Second <= 59 && date->Second >= 0;
245}
246
247int GetLine(FILE *File, char *Line, int count)
248{
249 int num;
250
251 if (fgets(Line, count, File) != NULL) {
252 num = strlen(Line) - 1;
253 while(1) {
254 if (Line[num] != '\n' && Line[num] != '\r') break;
255 if (num == 0) break;
256 Line[num--] = 0;
257 }
258 return strlen(Line);
259 }
260 return -1;
261}
262
263void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot)
264{
265 int i,number=0,j;
266 bool whitespace=true, nowwhite;
267
268 for (i=0;i<MAX_LINES*2;i++) lines->numbers[i]=0;
269
270 for (i=0;i<messagesize;i++) {
271 nowwhite = false;
272 for (j=0;j<spaceslen;j++) {
273 if (whitespaces[j] == message[i]) {
274 nowwhite = true;
275 break;
276 }
277 }
278 if (whitespace) {
279 if (!nowwhite) {
280 lines->numbers[number]=i;
281 number++;
282 whitespace=false;
283 }
284 } else {
285 if (nowwhite) {
286 lines->numbers[number]=i;
287 number++;
288 whitespace=true;
289 }
290
291 }
292 }
293 if (eot && !whitespace) lines->numbers[number]=messagesize;
294}
295
296char *GetLineString(unsigned char *message, GSM_Lines lines, int start)
297{
298 static char retval[800];
299
300 memcpy(retval,message + lines.numbers[start*2-2],lines.numbers[start*2-2+1]-lines.numbers[start*2-2]);
301 retval[lines.numbers[start*2-2+1]-lines.numbers[start*2-2]]=0;
302
303 return retval;
304}
305
306void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start)
307{
308 memcpy(dest,GetLineString(src, lines, start),strlen(GetLineString(src, lines, start)));
309 dest[strlen(GetLineString(src, lines, start))] = 0;
310}
311
312Debug_Info di = {0,NULL,false,""};
313
314#ifdef DEBUG
315#ifdef __GNUC__
316__attribute__((format(printf, 1, 2)))
317#endif
318int dbgprintf(const char *format, ...)
319{
320 va_list argp;
321 int result;
322 static unsigned char nextline[2000]="";
323 unsigned char buffer[2000];
324 GSM_DateTime date_time;
325
326 if (di.df != NULL && (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE)) {
327 va_start(argp, format);
328 result = vsprintf(buffer, format, argp);
329 strcat(nextline, buffer);
330 if (strstr(buffer, "\n")) {
331 if (di.dl == DL_TEXTALLDATE) {
332 GSM_GetCurrentDateTime(&date_time);
333 fprintf(di.df,"%s %4d/%02d/%02d %02d:%02d:%02d: %s",
334 DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
335 date_time.Year, date_time.Month, date_time.Day,
336 date_time.Hour, date_time.Minute, date_time.Second,nextline);
337 } else {
338 fprintf(di.df,"%s",nextline);
339 }
340 strcpy(nextline, "");
341 }
342 fflush(di.df);
343 va_end(argp);
344 return result;
345 }
346 return 0;
347}
348#endif
349
350/* assumption: if \n is present it is always the last char,
351 * string never of the form "......\n..."
352 */
353#ifdef __GNUC__
354__attribute__((format(printf, 3, 4)))
355#endif
356int smfprintf(FILE *f, Debug_Level dl, const char *format, ...)
357{
358 va_list argp;
359 int result=0;
360 static unsigned char prevline[2000] = "", nextline[2000]="";
361 static unsigned int linecount=0;
362 unsigned char buffer[2000];
363 GSM_DateTime date_time;
364
365 if (f == NULL) return 0;
366 va_start(argp, format);
367 result = vsprintf(buffer, format, argp);
368 strcat(nextline, buffer);
369 if (strstr(buffer, "\n")) {
370 if (ftell(f) < 5000000) {
371 GSM_GetCurrentDateTime(&date_time);
372 if (linecount > 0) {
373 if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) {
374 fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: <%i> %s",
375 DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
376 date_time.Year, date_time.Month, date_time.Day,
377 date_time.Hour, date_time.Minute, date_time.Second,linecount,prevline);
378 } else {
379 fprintf(f,"%s",prevline);
380 }
381 }
382 linecount=0;
383 if (dl == DL_TEXTALLDATE || dl == DL_TEXTERRORDATE || dl == DL_TEXTDATE) {
384 fprintf(f,"%s %4d/%02d/%02d %02d:%02d:%02d: %s",
385 DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
386 date_time.Year, date_time.Month, date_time.Day,
387 date_time.Hour, date_time.Minute, date_time.Second,nextline);
388 } else {
389 fprintf(f,"%s",nextline);
390 }
391 strcpy(prevline, nextline);
392 }
393 strcpy(nextline, "");
394 fflush(f);
395 }
396 va_end(argp);
397 return result;
398}
399
400bool GSM_SetDebugLevel(char *info, Debug_Info *di)
401{
402 if (!strcmp(info,"nothing")) {di->dl = 0; return true;}
403 if (!strcmp(info,"text")) {di->dl = DL_TEXT; return true;}
404 if (!strcmp(info,"textall")) {di->dl = DL_TEXTALL; return true;}
405 if (!strcmp(info,"binary")) {di->dl = DL_BINARY; return true;}
406 if (!strcmp(info,"errors")) {di->dl = DL_TEXTERROR; return true;}
407 if (!strcmp(info,"textdate")) {di->dl = DL_TEXTDATE; return true;}
408 if (!strcmp(info,"textalldate")) {di->dl = DL_TEXTALLDATE; return true;}
409 if (!strcmp(info,"errorsdate")) {di->dl = DL_TEXTERRORDATE; return true;}
410 return false;
411}
412
413/* Dumps a message */
414void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize)
415{
416 int i,j=0,len=16;
417 unsigned charbuffer[200];
418
419 if (df==NULL || messagesize == 0) return;
420
421 smfprintf(df, dl, "\n");
422
423 memset(buffer,0x20,sizeof(buffer));
424 buffer[len*5-1]=0;
425
426 for (i = 0; i < messagesize; i++) {
427 sprintf(buffer+j*4,"%02X",message[i]);
428 buffer[j*4+2] = 0x20;
429 if (isprint(message[i]) && message[i]!=0x09) {
430 if (j != len-1) buffer[j*4+2] = message[i];
431 buffer[(len-1)*4+j+3] = message[i];
432 } else {
433 buffer[(len-1)*4+j+3] = '.';
434 }
435 if (j != len-1 && i != messagesize-1) buffer[j*4+3] = '|';
436 if (j == len-1) {
437 smfprintf(df, dl, "%s\n", buffer);
438 memset(buffer,0x20,sizeof(buffer));
439 buffer[len*5-1]=0;
440 j = 0;
441 } else {
442 j++;
443 }
444 }
445 if (j != 0) smfprintf(df, dl, "%s\n", buffer);
446}
447
448char *GetOS(void)
449{
450#ifdef WIN32
451 OSVERSIONINFOEX Ver;
452 bool Extended = true;
453#endif
454 static char Buffer[100] = {0x00};
455
456#ifdef WIN32
457 memset(&Ver,sizeof(OSVERSIONINFOEX),0);
458 Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
459
460 if (!GetVersionEx((OSVERSIONINFO *)&Ver)) {
461 Extended = false;
462 Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
463 if (!GetVersionEx((OSVERSIONINFO *)&Ver)) {
464//#ifdef _MSC_VER
465 // Ver.dwMajorVersion = _winmajor;
466 // Ver.dwMinorVersion = _winminor;
467 // Ver.dwBuildNumber = _osver;
468//#else
469 sprintf(Buffer, "Windows");
470 return Buffer;
471//#endif
472 }
473 }
474
475 /* ----------------- 9x family ------------------ */
476
477 /* no info about Win95 SP1, Win95 OSR2.1, Win95 OSR2.5.... */
478 if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 950) {
479 sprintf(Buffer,"Win 95");
480 } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1111) {
481 sprintf(Buffer,"Win 95 OSR2.x");
482
483 /* no info about Win98 SP1.... */
484 } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 1998) {
485 sprintf(Buffer,"Win 98");
486 } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 10 && Ver.dwBuildNumber == 2222) {
487 sprintf(Buffer,"Win 98 SE");
488
489 } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 90 && Ver.dwBuildNumber == 3000) {
490 sprintf(Buffer,"Win ME");
491
492 /* ---------------- NT family ------------------- */
493
494 } else if (Ver.dwMajorVersion == 4 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 1381) {
495 sprintf(Buffer,"Win NT 4.0");
496
497 } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 0 && Ver.dwBuildNumber == 2195) {
498 sprintf(Buffer,"Win 2000");
499
500 } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 1 && Ver.dwBuildNumber == 2600) {
501 sprintf(Buffer,"Win XP");
502#if _MSC_VER > 1200 //6.0 has it undeclared
503 if (Extended) {
504 if (Ver.wSuiteMask & VER_SUITE_PERSONAL) {
505 sprintf(Buffer+strlen(Buffer)," Home");
506 } else {
507 sprintf(Buffer+strlen(Buffer)," Pro");
508 }
509 }
510#endif
511
512 } else if (Ver.dwMajorVersion == 5 && Ver.dwMinorVersion == 2) {
513 sprintf(Buffer,"Win 2003");
514
515 } else {
516 sprintf(Buffer, "Windows %i.%i.%i",Ver.dwMajorVersion,Ver.dwMinorVersion,Ver.dwBuildNumber);
517 }
518
519 if (Extended && Ver.wServicePackMajor != 0) {
520 sprintf(Buffer+strlen(Buffer)," SP%i",Ver.wServicePackMajor);
521 }
522#elif defined(linux) || defined(__linux) || defined(__linux__)
523 sprintf(Buffer, "Linux");
524#elif defined(__FreeBSD__)
525 sprintf(Buffer, "FreeBSD");
526#elif defined(__NetBSD__)
527 sprintf(Buffer, "NetBSD");
528#elif defined(__OpenBSD__)
529 sprintf(Buffer, "OpenBSD");
530#elif defined(__GNU__)
531 sprintf(Buffer, "GNU/Hurd");
532#elif defined(sun) || defined(__sun) || defined(__sun__)
533# ifdef __SVR4
534 sprintf(Buffer, "Sun Solaris");
535# else
536 sprintf(Buffer, "SunOS");
537# endif
538#elif defined(hpux) || defined(__hpux) || defined(__hpux__)
539 sprintf(Buffer, "HP-UX");
540#elif defined(ultrix) || defined(__ultrix) || defined(__ultrix__)
541 sprintf(Buffer, "DEC Ultrix");
542#elif defined(sgi) || defined(__sgi)
543 sprintf(Buffer, "SGI Irix");
544#elif defined(__osf__)
545 sprintf(Buffer, "OSF Unix");
546#elif defined(bsdi) || defined(__bsdi__)
547 sprintf(Buffer, "BSDI Unix");
548#elif defined(_AIX)
549 sprintf(Buffer, "AIX Unix");
550#elif defined(_UNIXWARE)
551 sprintf(Buffer, "SCO Unixware");
552#elif defined(DGUX)
553 sprintf(Buffer, "DG Unix");
554#elif defined(__QNX__)
555 sprintf(Buffer, "QNX");
556#endif
557 return Buffer;
558}
559
560char *GetCompiler(void)
561{
562 static char Buffer[100] = {0x00};
563
564#ifdef WIN32
565# ifdef _MSC_VER
566 if (_MSC_VER == 1200) { //?
567 sprintf(Buffer, "MS VC 6.0");
568 } else if (_MSC_VER == 1300) {
569 sprintf(Buffer, "MS VC .NET 2002");
570 } else if (_MSC_VER == 1310) {
571 sprintf(Buffer, "MS VC .NET 2003");
572 } else {
573 sprintf(Buffer, "MS VC %i",_MSC_VER);
574 }
575# elif defined(__BORLANDC__)
576 sprintf(Buffer, "Borland C++ %i",__BORLANDC__);
577# endif
578#elif defined(DJGPP)
579 sprintf(Buffer, "djgpp");
580#elif defined(__GNUC__)
581 sprintf(Buffer, "gcc %i.%i", __GNUC__, __GNUC_MINOR__);
582#elif defined(__SUNPRO_CC)
583 sprintf(Buffer, "Sun C++ %x", __SUNPRO_CC);
584#endif
585
586 return Buffer;
587}
588
589/* How should editor hadle tabs in this file? Add editor commands here.
590 * vim: noexpandtab sw=8 ts=8 sts=8:
591 */
diff --git a/gammu/emb/common/misc/misc.h b/gammu/emb/common/misc/misc.h
new file mode 100644
index 0000000..8b46170
--- a/dev/null
+++ b/gammu/emb/common/misc/misc.h
@@ -0,0 +1,137 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __misc_h
4#define __misc_h
5
6#include <stdio.h>
7#include <time.h>
8#ifdef WIN32
9# include <windows.h>
10#endif
11
12#include "../config.h"
13
14#ifndef __cplusplus
15#ifndef false
16# define false 0
17#endif
18#ifndef true
19 # define true !0
20#endif
21#ifndef bool
22 # define boolchar
23#endif
24#endif /* __cplusplus */
25
26#ifdef WIN32
27# define my_sleep(x) ((x)<1000 ? Sleep(1) : Sleep((x)/1000))
28#else
29# define my_sleep(x) usleep(x)
30#endif
31
32#undef MAX
33#define MAX(a,b) ((a)>(b) ? (a) : (b))
34#undef MIN
35#define MIN(a,b) ((a)<(b) ? (a) : (b))
36
37/* ------------------------------------------------------------------------- */
38
39#define MAX_LINES 50
40
41int GetLine(FILE *File, char *Line, int count);
42
43typedef struct {
44 int numbers[MAX_LINES*2];
45} GSM_Lines;
46
47void SplitLines(unsigned char *message, int messagesize, GSM_Lines *lines, unsigned char *whitespaces, int spaceslen, bool eot);
48char *GetLineString(unsigned char *message, GSM_Lines lines, int start);
49void CopyLineString(unsigned char *dest, unsigned char *src, GSM_Lines lines, int start);
50
51/* ------------------------------------------------------------------------- */
52
53typedef enum {
54 DL_BINARY = 1, /* Binary transmission dump */
55 DL_TEXT, /* Text transmission dump*/
56 DL_TEXTALL, /* Everything */
57 DL_TEXTERROR, /* Only errors */
58 DL_TEXTDATE, /* Text transmission dump*/
59 DL_TEXTALLDATE, /* Everything */
60 DL_TEXTERRORDATE /* Only errors */
61} Debug_Level;
62
63typedef struct {
64 Debug_Leveldl;
65 FILE *df;
66 bool use_global;
67 char *coding;
68} Debug_Info;
69
70 extern Debug_Infodi;
71
72#ifdef DEBUG
73#ifdef __GNUC__
74__attribute__((format(printf, 1, 2)))
75#endif
76int dbgprintf(const char *format, ...);
77#else
78# ifndef WIN32
79# define dbgprintf(a...) do { } while (0)
80# else
81# define dbgprintf
82# endif
83#endif
84
85#ifdef __GNUC__
86__attribute__((format(printf, 3, 4)))
87#endif
88int smfprintf(FILE *f, Debug_Level dl, const char *format, ...);
89
90void DumpMessage(FILE *df, Debug_Level dl, const unsigned char *message, int messagesize);
91
92bool GSM_SetDebugLevel(char *info, Debug_Info *di);
93
94/* ------------------------------------------------------------------------- */
95
96/**
97 * Structure used for saving date and time
98 */
99typedef struct {
100 /**
101 * The difference between local time and GMT in hours
102 */
103 int Timezone;
104
105 unsigned int Second;
106 unsigned int Minute;
107 unsigned int Hour;
108
109 unsigned int Day;
110 /**
111 * January = 1, February = 2, etc.
112 */
113 unsigned int Month;
114 /**
115 * Complete year number. Not 03, but 2003
116 */
117 unsigned int Year;
118} GSM_DateTime;
119
120 void GSM_GetCurrentDateTime (GSM_DateTime *Date);
121 char *OSDateTime (GSM_DateTime dt, bool TimeZone);
122 char *OSDate (GSM_DateTime dt);
123 char *DayOfWeek (int year, int month, int day);
124 time_t Fill_Time_T (GSM_DateTime DT, int TZ);
125 void GetTimeDifference (unsigned long diff, GSM_DateTime *DT, bool Plus, int multi);
126 void Fill_GSM_DateTime (GSM_DateTime *Date, time_t timet);
127 bool CheckDate (GSM_DateTime *date);
128 bool CheckTime (GSM_DateTime *date);
129
130 char *GetCompiler(void);
131 char *GetOS(void);
132
133#endif
134
135/* How should editor hadle tabs in this file? Add editor commands here.
136 * vim: noexpandtab sw=8 ts=8 sts=8:
137 */
diff --git a/gammu/emb/common/phone/alcatel/alcatel.c b/gammu/emb/common/phone/alcatel/alcatel.c
new file mode 100644
index 0000000..f004ad4
--- a/dev/null
+++ b/gammu/emb/common/phone/alcatel/alcatel.c
@@ -0,0 +1,3991 @@
1/* (c) 2002-2004 by Michal Cihar */
2
3/*
4 * High level functions for communication with Alcatel One Touch 501 and
5 * compatible mobile phone.
6 *
7 * This code implements functions to communicate with Alcatel phones,
8 * currently seem to work:
9 * - BE5 series (501/701)
10 * - BF5 series (715)
11 * - BH4 series (535/735)
12 * For some functions it uses normal AT mode (not implemented here, look at
13 * ../at/atgen.[ch]) for others it switches into binary mode and initialises
14 * underlaying protocol (see ../../protocol/alcatel/alcabus.[ch]) and
15 * communicates over it. Don't ask me why Alcatel uses such silly thing...
16 *
17 * Notes for future features:
18 * - max phone number length is 61 (BE5)
19 * - max name length is 50 (BE5)
20 */
21
22#include "../../gsmstate.h"
23
24#ifdef GSM_ENABLE_ALCATEL
25#ifdef GSM_ENABLE_ATGEN
26
27#include <string.h>
28#include <time.h>
29
30#include "../../gsmcomon.h"
31#include "../../misc/coding/coding.h"
32#include "../../misc/misc.h"
33#include "../../service/sms/gsmsms.h"
34#include "../pfunc.h"
35#include "alcatel.h"
36
37/* Timeout for GSM_WaitFor calls. */
38 #define ALCATEL_TIMEOUT 64
39
40/* Some magic numbers for protocol follow */
41
42/* synchronisation types (for everything except begin transfer): */
43 #define ALCATEL_SYNC_TYPE_CALENDAR0x64
44 #define ALCATEL_SYNC_TYPE_TODO 0x68
45 #define ALCATEL_SYNC_TYPE_CONTACTS0x6C
46
47/* synchronisation types (for begin transfer): */
48 #define ALCATEL_BEGIN_SYNC_CALENDAR0x00
49 #define ALCATEL_BEGIN_SYNC_TODO 0x02
50 #define ALCATEL_BEGIN_SYNC_CONTACTS0x01
51
52/* category types */
53 #define ALCATEL_LIST_TODO_CAT 0x9B
54 #define ALCATEL_LIST_CONTACTS_CAT0x96
55
56
57/* We need lot of ATGEN functions, because Alcatel is an AT device. */
58
59extern GSM_Reply_Function ALCATELReplyFunctions[];
60extern GSM_Reply_Function ATGENReplyFunctions[];
61
62 extern GSM_Error ATGEN_Initialise (GSM_StateMachine *s);
63 extern GSM_Error ATGEN_Terminate (GSM_StateMachine *s);
64 extern GSM_Error ATGEN_GetIMEI (GSM_StateMachine *s);
65 extern GSM_Error ATGEN_GetFirmware (GSM_StateMachine *s);
66 extern GSM_Error ATGEN_GetModel (GSM_StateMachine *s);
67 extern GSM_Error ATGEN_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
68 extern GSM_Error ATGEN_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
69 extern GSM_Error ATGEN_GetNextMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start);
70 extern GSM_Error ATGEN_SetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
71 extern GSM_Error ATGEN_AddMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
72 extern GSM_Error ATGEN_DeleteMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry);
73 extern GSM_Error ATGEN_GetMemoryStatus (GSM_StateMachine *s, GSM_MemoryStatus *Status);
74 extern GSM_Error ATGEN_GetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc);
75 extern GSM_Error ATGEN_SetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc);
76 extern GSM_Error ATGEN_GetSMSFolders (GSM_StateMachine *s, GSM_SMSFolders *folders);
77 extern GSM_Error ATGEN_GetSMSStatus (GSM_StateMachine *s, GSM_SMSMemoryStatus *status);
78 extern GSM_Error ATGEN_GetSMS (GSM_StateMachine *s, GSM_MultiSMSMessage *sms);
79 extern GSM_Error ATGEN_GetNextSMS (GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start);
80 extern GSM_Error ATGEN_SendSavedSMS (GSM_StateMachine *s, int Folder, int Location);
81 extern GSM_Error ATGEN_SendSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
82 extern GSM_Error ATGEN_DeleteSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
83 extern GSM_Error ATGEN_AddSMS (GSM_StateMachine *s, GSM_SMSMessage *sms);
84 extern GSM_Error ATGEN_GetBatteryCharge (GSM_StateMachine *s, GSM_BatteryCharge *bat);
85 extern GSM_Error ATGEN_GetSignalQuality (GSM_StateMachine *s, GSM_SignalQuality *sig);
86 extern GSM_Error ATGEN_DialVoice (GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber);
87 extern GSM_Error ATGEN_AnswerCall (GSM_StateMachine *s, int ID, bool all);
88 extern GSM_Error ATGEN_CancelCall (GSM_StateMachine *s, int ID, bool all);
89 extern GSM_Error ATGEN_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
90 extern GSM_Error ATGEN_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code);
91 extern GSM_Error ATGEN_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status);
92 extern GSM_Error ATGEN_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type);
93 extern GSM_Error ATGEN_SendDTMF (GSM_StateMachine *s, char *sequence);
94 extern GSM_Error ATGEN_GetSIMIMSI (GSM_StateMachine *s, char *IMSI);
95 extern GSM_Error ATGEN_HandleCMSError (GSM_StateMachine *s);
96 extern GSM_Error ATGEN_GetNetworkInfo (GSM_StateMachine *s, GSM_NetworkInfo *netinfo);
97 extern GSM_Error ATGEN_Reset (GSM_StateMachine *s, bool hard);
98 extern GSM_Error ATGEN_PressKey (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
99 extern GSM_Error ATGEN_GetDisplayStatus (GSM_StateMachine *s, GSM_DisplayFeatures *features);
100 extern GSM_Error ATGEN_SetAutoNetworkLogin(GSM_StateMachine *s);
101 extern GSM_Error ATGEN_DeleteAllMemory (GSM_StateMachine *s, GSM_MemoryType type);
102
103 extern GSM_Error ATGEN_DispatchMessage (GSM_StateMachine *s);
104 extern GSM_Error ATGEN_SetIncomingCB (GSM_StateMachine *s, bool enable);
105 extern GSM_Error ATGEN_SetIncomingSMS (GSM_StateMachine *s, bool enable);
106
107/**
108 * Alcatel uses some 8-bit characters in contacts, calendar etc.. This table
109 * attempts to decode it, it is probably not complete, here are just chars
110 * that I found...
111 */
112unsigned char GSM_AlcatelAlphabet[] =
113{
114 /* in phone unicode description*/
115 0x80, 0x00,0x20, /* empty */
116 0x81, 0x00,0x20, /* empty*/
117 0x82, 0x00,0x20, /* empty*/
118 0x83, 0x00,0x20, /* empty*/
119
120 0x84, 0x00,0xe7, /* c cedilla*/
121 0x85, 0x20,0x26, /* ... */
122 0x86, 0x03,0xc0, /* pi */
123 0x87, 0x01,0x3e, /* l caron*/
124 0x88, 0x00,0xc0, /* A grave*/
125 0x89, 0x00,0xc1, /* A acute*/
126 0x8a, 0x00,0xc2, /* A circumflex*/
127 0x8b, 0x00,0xc3, /* A tilde*/
128 0x8c, 0x00,0xc8, /* E grave*/
129 0x8d, 0x00,0xca, /* E circumflex*/
130 0x8e, 0x00,0xcb, /* E diaresis*/
131 0x8f, 0x00,0xcc, /* I grave*/
132 0x90, 0x00,0xcd, /* I acute*/
133 0x91, 0x00,0xd0, /* ETH */
134 0x92, 0x00,0xd2, /* O grave*/
135 0x93, 0x00,0xd3, /* O acute*/
136 0x94, 0x00,0xd4, /* O circumflex*/
137 0x95, 0x00,0xd5, /* O tilde*/
138 0x96, 0x00,0xd9, /* U grave*/
139 0x97, 0x00,0xda, /* U acute*/
140 0x98, 0x00,0xe1, /* a acute*/
141 0x99, 0x00,0xe2, /* a circumflex*/
142 0x9a, 0x00,0xe3, /* a tilde*/
143 0x9b, 0x00,0xea, /* e circumflex*/
144 0x9c, 0x00,0xeb, /* e diaresis*/
145 0x9d, 0x00,0xed, /* i acute*/
146 0x9e, 0x00,0xee, /* i circumflex*/
147 0x9f, 0x00,0xef, /* i diaresis*/
148 0xa0, 0x00,0xf3, /* o acute*/
149 0xa1, 0x00,0xf4, /* o circumflex*/
150 0xa2, 0x00,0xf5, /* o tilde*/
151 0xa3, 0x00,0xfa, /* u acute*/
152 0xa4, 0x00,0xa2, /* cent */
153 0xa5, 0x00,0x5b, /* [ */
154 0xa6, 0x01,0x59, /* r caron*/
155 0xa7, 0x01,0x0d, /* c caron*/
156 0xa8, 0x01,0x61, /* s caron*/
157 0xa9, 0x01,0x1b, /* e caron*/
158 0xaa, 0x01,0x6f, /* u ring*/
159 0xab, 0x00,0xfd, /* y acute*/
160 0xac, 0x00,0xf0, /* eth */
161 0xad, 0x01,0x07, /* c acute*/
162 0xae, 0x01,0x19, /* e ogonek*/
163 0xaf, 0x01,0x05, /* a ogonek*/
164 0xb0, 0x01,0x7c, /* z dot*/
165 0xb1, 0x01,0x7a, /* z acute*/
166 0xb2, 0x01,0x5b, /* s acute*/
167 0xb3, 0x01,0x44, /* n acute*/
168 0xb4, 0x01,0x42, /* l stroke*/
169
170 0xb5, 0x00,0x20, /* empty*/
171
172 0xb6, 0x01,0x48, /* n caron*/
173 0xb7, 0x01,0x65, /* t caron*/
174
175 0xb8, 0x00,0x20, /* empty*/
176
177 0xb9, 0x01,0x7e, /* z caron*/
178 0xba, 0x01,0xe7, /* g caron*/
179
180 0xbb, 0x00,0x20, /* empty*/
181 0xbc, 0x00,0x20, /* empty*/
182
183 0xbd, 0x1e,0x20, /* G macron*/
184 0xbe, 0x1e,0x21, /* g macron*/
185 0xbf, 0x01,0x5e, /* S cedilla*/
186 0xc0, 0x01,0x5f, /* s cedilla*/
187 0xc1, 0x01,0x2f, /* i ogonek*/ /* FIXME: not sure with this, it look like normal i */
188 0xc2, 0x01,0x31, /* i dotless*/
189 0xc3, 0x01,0x68, /* U tilde*/
190 0xc4, 0x01,0x50, /* O dbl acute*/
191 0xc5, 0x01,0x69, /* u tilde*/
192 0xc6, 0x01,0x51, /* o dbl acute*/
193 0xc7, 0x27,0xa9, /* => */
194 0xc8, 0x27,0xa8, /* filled =>*/
195 0xc9, 0x00,0xd7, /* x */
196 0xca, 0x00,0x5d, /* ] */
197 0xcb, 0x26,0x0f, /* phone*/
198 0xcc, 0x01,0x0f, /* d caron*/
199
200 0xcd, 0x00,0x20, /* empty*/
201
202 0xce, 0x00,0x7e, /* ~ */
203 0xcf, 0x00,0x5c, /* \ */
204 0xd0, 0x00,0x5e, /* ^ */
205
206 0xd1, 0x00,0x20, /* empty*/
207
208 0xd2, 0x00,0x7b, /* { */
209 0xd3, 0x00,0x7c, /* | */
210 0xd4, 0x00,0x7d, /* } */
211
212 0xd5, 0x00,0x20, /* empty*/
213
214 0xd6, 0x01,0x63, /* t cedilla*/
215
216 0xd7, 0x00,0x20, /* empty*/
217 0xd8, 0x00,0x20, /* empty*/
218 0xd9, 0x00,0x20, /* empty*/
219 0xda, 0x00,0x20, /* empty*/
220 0xdb, 0x00,0x20, /* empty*/
221 0xdc, 0x00,0x20, /* empty*/
222 0xdd, 0x00,0x20, /* empty*/
223 0xde, 0x00,0x20, /* empty*/
224 0xdf, 0x00,0x20, /* empty*/
225 0xe0, 0x00,0x20, /* empty*/
226
227 0xe1, 0x00,0x20, /* two candles*/ /* FIXME */
228
229 0xe2, 0x00,0x20, /* empty*/
230 0xe3, 0x00,0x20, /* empty*/
231 0xe4, 0x00,0x20, /* empty*/
232
233 0xe5, 0x01,0xce, /* a caron*/
234 0xe6, 0x01,0x01, /* a macron*/
235 0xe7, 0x01,0x13, /* e macron*/
236 0xe8, 0x01,0x2b, /* i macron*/
237 0xe9, 0x01,0x4d, /* o macron*/
238 0xea, 0x01,0x6b, /* u macron*/
239 0xeb, 0x00,0x41, /* A */
240 0xec, 0x00,0x40, /* @ */
241 0xed, 0x00,0x20,/* some strange char :-) */ /* FIXME */
242
243 0xee, 0x00,0x20, /* big key stroken*/ /* FIXME */
244 0xef, 0x00,0x20, /* big key*/ /* FIXME */
245
246 0xf0, 0x00,0x20, /* empty*/
247
248 0xf1, 0x00,0x31, /* 1 */
249 0xf2, 0x00,0x21, /* bold !*/
250 0xf3, 0x26,0x0e, /* black phone*/
251 0xf4, 0x00,0x26, /* & */
252 0xf5, 0x23,0x7e, /* bell */
253 0xf6, 0x26,0x6a, /* note */
254
255 0xf7, 0x27,0x13, /* okay inv*/ /* FIXME */
256 0xf8, 0x27,0x13, /* okay */
257
258 0xf9, 0x00,0x20, /* empty*/
259
260 0xfa, 0x00,0x20, /* key */ /* FIXME */
261
262 0xfb, 0x00,0x20, /* empty*/
263
264 0xfc, 0x20,0xac, /* Euro */
265 0xfd, 0x21,0x97, /* NE arrow*/
266 0xfe, 0x21,0x98, /* SE arrow*/
267
268 0xff, 0x00,0x20, /* empty*/
269
270 0x00, 0x00,0x00
271};
272
273/* This is being called from atgen */
274 GSM_Error ALCATEL_ProtocolVersionReply(GSM_Protocol_Message msg, GSM_StateMachine *s)
275{
276 char *str, *str2;
277/*
278 * Reply received here looks like:
279 * 1 "AT+CPROT=?"
280 * 2 "+CPROT: 0,"V1.0",1"
281 * 3 "+CPROT: 16,"V1.1",16"
282 * 4 "OK"
283 */
284 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
285 case AT_Reply_OK:
286 str = strstr(msg.Buffer, "\"V");
287 if (str == NULL) return ERR_UNKNOWNRESPONSE;
288 str += 2;
289 while((str2 = strstr(str, "\"V")) != NULL) str = str2 + 2;
290 if (strncmp(str, "1.0", 3) == 0) {
291 s->Phone.Data.Priv.ALCATEL.ProtocolVersion = V_1_0;
292 } else if (strncmp(str, "1.1", 3) == 0) {
293 s->Phone.Data.Priv.ALCATEL.ProtocolVersion = V_1_1;
294 } else {
295 smprintf(s, "Unknown protocol version. Please send debug log and phone info to author.\n");
296 return ERR_NOTIMPLEMENTED;
297 }
298 return ERR_NONE;
299 case AT_Reply_Error:
300 case AT_Reply_CMSError:
301 return ATGEN_HandleCMSError(s);
302 default:
303 return ERR_UNKNOWNRESPONSE;
304 }
305}
306
307static GSM_Error ALCATEL_SetBinaryMode(GSM_StateMachine *s)
308{
309 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
310 GSM_Error error;
311
312 if (Priv->Mode == ModeBinary) return ERR_NONE;
313
314 dbgprintf ("Changing to binary mode\n");
315
316 error=GSM_WaitFor (s, "AT+IFC=2,2\r", 11, 0x02, 4, ID_SetFlowControl);
317 if (error != ERR_NONE) return error;
318
319 error=GSM_WaitFor (s, "AT+CPROT=?\r", 11, 0x02, 4, ID_AlcatelProtocol);
320 if (error != ERR_NONE) return error;
321
322 if (Priv->ProtocolVersion == V_1_0) {
323 error=GSM_WaitFor (s, "AT+CPROT=16,\"V1.0\",16\r", 22, 0x00, 4, ID_AlcatelConnect);
324 } else {
325 error=GSM_WaitFor (s, "AT+CPROT=16,\"V1.1\",16\r", 22, 0x00, 4, ID_AlcatelConnect);
326 }
327
328 if (error == ERR_TIMEOUT && s->Speed != 19200) {
329 smprintf(s, "HINT: Try changing speed to 19200, it is sometimes needed for Alcatel binary mode.\n");
330 }
331
332 if (error != ERR_NONE) return error;
333
334 dbgprintf ("Changing protocol to Alcabus\n");
335
336 s->Protocol.Functions = &ALCABUSProtocol;
337 error = s->Protocol.Functions->Initialise(s);
338 if (error != ERR_NONE) {
339 s->Protocol.Functions = &ATProtocol;
340 return error;
341 }
342 s->Phone.Functions->ReplyFunctions= ALCATELReplyFunctions;
343 Priv->Mode = ModeBinary;
344 Priv->BinaryItem = 0;
345 Priv->BinaryType = 0;
346 Priv->BinaryState = StateAttached;
347 return ERR_NONE;
348}
349
350static GSM_Error ALCATEL_GoToBinaryState(GSM_StateMachine *s, GSM_Alcatel_BinaryState state, GSM_Alcatel_BinaryType type, int item) {
351 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
352 GSM_Error error;
353 unsigned char attach_buffer[] = {0x00, 0x00, 0x7C ,0x20};
354 unsigned char detach_buffer[] = {0x00, 0x01, 0x7C ,0x00};
355 unsigned char start_buffer[] =
356 {0x00, 0x04, 0x7C, 0x80, /* 4 byte database id follows */
357 0x12, 0x34, 0x56, 0x78};
358 unsigned char end_buffer[] =
359 {0x00, 0x04, 0x7C, 0x82,
360 0x00, /* type */
361 0x00, 0x00, 0x00, 0x00}; /* TimeStamp */
362 unsigned char close_buffer[] =
363 {0x00, 0x04,
364 0x00, /*type */
365 0x23, 0x01};
366 unsigned char select1_buffer[] =
367 {0x00, 0x00,
368 0x00, /*type */
369 0x20};
370 unsigned char select2_buffer[] =
371 {0x00, 0x04,
372 0x00, /*type */
373 0x22, 0x01, 0x00};
374 unsigned char begin_buffer[] =
375 {0x00, 0x04, 0x7C, 0x81,
376 0x00, /*type */
377 0x00, 0x85, 0x00};
378 unsigned char commit_buffer[] =
379 {0x00, 0x04,
380 0x00, /*type */
381 0x20, 0x01};
382
383 smprintf(s, "Alcatel state switcher: %d -> %d, %d -> %d, %d -> %d\n", Priv->BinaryState, state, Priv->BinaryType, type, Priv->BinaryItem, item);
384 error = ALCATEL_SetBinaryMode(s);
385 if (error != ERR_NONE) return error;
386
387 /* Do we need to do anything? */
388 if ((state == Priv->BinaryState) && (type == Priv->BinaryType) && (item == Priv->BinaryItem)) return ERR_NONE;
389
390 /* We're editing, but the next state is not the same. so commit editing */
391 if (Priv->BinaryState == StateEdit) {
392 /* Something has changed, we will have to reread fields! */
393 Priv->CurrentFieldsItem = -1;
394 switch (Priv->BinaryType) {
395 case TypeCalendar:
396 commit_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
397 break;
398 case TypeContacts:
399 commit_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
400 break;
401 case TypeToDo:
402 commit_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
403 break;
404 }
405 dbgprintf ("Commiting edited record\n");
406 error=GSM_WaitFor (s, commit_buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelCommit);
407 if (error != ERR_NONE) return error;
408 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelCommit2);
409 if (error != ERR_NONE) return error;
410 Priv->BinaryState = StateSession;
411 Priv->BinaryItem = 0;
412 }
413
414 /* Do we want to edit something of same type? */
415 if ((state == StateEdit) && (type == Priv->BinaryType)) {
416 /* Edit state doesn't need any switching, it is needed only for
417 * indication that e have to commit record before we switch to other
418 * mode.
419 */
420 Priv->BinaryState = StateEdit;
421 Priv->BinaryItem = item;
422 return ERR_NONE;
423 }
424
425 /* Now we can be only in Attached or Session state, so if states and types matches, just keep them as they are */
426 if ((state == Priv->BinaryState) && (type == Priv->BinaryType)) {
427 return ERR_NONE;
428 }
429
430 /* Do we need to close session? */
431 if (Priv->BinaryState == StateSession) {
432 dbgprintf ("Ending session\n");
433 switch (Priv->BinaryType) {
434 case TypeCalendar:
435 end_buffer[4] = ALCATEL_BEGIN_SYNC_CALENDAR;
436 break;
437 case TypeContacts:
438 end_buffer[4] = ALCATEL_BEGIN_SYNC_CONTACTS;
439 break;
440 case TypeToDo:
441 end_buffer[4] = ALCATEL_BEGIN_SYNC_TODO;
442 break;
443 }
444 error=GSM_WaitFor (s, end_buffer, 9, 0x02, ALCATEL_TIMEOUT, ID_AlcatelEnd);
445 if (error != ERR_NONE) return error;
446
447 switch (Priv->BinaryType) {
448 case TypeCalendar:
449 close_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
450 break;
451 case TypeContacts:
452 close_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
453 break;
454 case TypeToDo:
455 close_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
456 break;
457 }
458 dbgprintf ("Closing session\n");
459 error=GSM_WaitFor (s, close_buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelClose);
460 if (error != ERR_NONE) return error;
461
462 dbgprintf ("Detaching binary mode\n");
463 GSM_WaitFor (s, detach_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDetach);
464
465 Priv->BinaryState = StateAttached;
466 Priv->BinaryType = 0;
467 }
468
469 /* Do we need to open session? */
470 if (state == StateSession || state == StateEdit) {
471 dbgprintf ("Starting session for %s\n",
472 (type == TypeCalendar ? "Calendar" :
473 (type == TypeToDo ? "Todo" :
474 (type == TypeContacts ? "Contacts" :
475 "Unknown!"))));
476 /* Fill up buffers */
477 switch (type) {
478 case TypeCalendar:
479 select1_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
480 select2_buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
481 begin_buffer[4] = ALCATEL_BEGIN_SYNC_CALENDAR;
482 break;
483 case TypeContacts:
484 select1_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
485 select2_buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
486 begin_buffer[4] = ALCATEL_BEGIN_SYNC_CONTACTS;
487 break;
488 case TypeToDo:
489 select1_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
490 select2_buffer[2] = ALCATEL_SYNC_TYPE_TODO;
491 begin_buffer[4] = ALCATEL_BEGIN_SYNC_TODO;
492 break;
493 }
494 dbgprintf ("Attaching in binary mode\n");
495
496 /* Communicate */
497 error=GSM_WaitFor (s, attach_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelAttach);
498 if (error != ERR_NONE) return error;
499
500 smprintf(s,"Start session\n");
501 error=GSM_WaitFor (s, start_buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelStart);
502 if (error != ERR_NONE) return error;
503
504 smprintf(s,"Select type\n");
505 error=GSM_WaitFor (s, select1_buffer, 4, 0x02, ALCATEL_TIMEOUT, ID_AlcatelSelect1);
506 if (error != ERR_NONE) return error;
507 error=GSM_WaitFor (s, select2_buffer, 6, 0x02, ALCATEL_TIMEOUT, ID_AlcatelSelect2);
508 if (error != ERR_NONE) return error;
509 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelSelect3);
510 if (error != ERR_NONE) return error;
511
512 smprintf(s,"Begin transfer\n");
513 error=GSM_WaitFor (s, begin_buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelBegin1);
514 if (error != ERR_NONE) return error;
515 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelBegin2);
516 if (error != ERR_NONE) return error;
517
518 Priv->BinaryState = StateSession;
519 Priv->BinaryType = type;
520 /* Do we want to edit something of same type? */
521 if ((state == StateEdit) && (type == Priv->BinaryType)) {
522 Priv->BinaryState = StateEdit;
523 Priv->BinaryItem = item;
524 return ERR_NONE;
525 }
526 }
527 return ERR_NONE;
528}
529
530static GSM_Error ALCATEL_SetATMode(GSM_StateMachine *s)
531{
532 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
533 GSM_Error error;
534
535 if (Priv->Mode == ModeAT) return ERR_NONE;
536
537 error = ALCATEL_GoToBinaryState(s, StateAttached, 0, 0);
538 if (error != ERR_NONE) return error;
539
540 error = s->Protocol.Functions->Terminate(s);
541 if (error != ERR_NONE) return error;
542
543 dbgprintf ("Changing protocol to AT\n");
544 s->Protocol.Functions = &ATProtocol;
545 s->Phone.Functions->ReplyFunctions= ATGENReplyFunctions;
546 Priv->Mode = ModeAT;
547
548 my_sleep(100);
549
550 /* In case we don't send AT command short after closing binary mode,
551 * phone takes VERY long to react next time. The error code in
552 * intetionally ignored.
553 */
554 GSM_WaitFor (s, "AT\r", 3, 0x00, 0, ID_IncomingFrame);
555
556 return ERR_NONE;
557}
558
559static GSM_Error ALCATEL_Initialise(GSM_StateMachine *s)
560{
561 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
562 GSM_Error error;
563
564 Priv->Mode = ModeAT;
565
566 Priv->CalendarItems = NULL;
567 Priv->ContactsItems = NULL;
568 Priv->ToDoItems = NULL;
569 Priv->CalendarItemsCount = 0;
570 Priv->ToDoItemsCount = 0;
571 Priv->ContactsItemsCount = 0;
572 Priv->CurrentFields[0] = 0;
573 Priv->CurrentFieldsCount = 0;
574 Priv->CurrentFieldsItem = 0;
575 Priv->CurrentFieldsType = 0;
576 Priv->ProtocolVersion = V_1_0;
577 Priv->CurrentFieldsItem = -1;
578
579 Priv->CurrentCategoriesCount = 0;
580 Priv->CurrentCategoriesType = 0;
581
582 s->Protocol.Functions = &ATProtocol;
583 s->Phone.Functions->ReplyFunctions= ATGENReplyFunctions;
584
585 if (ATGEN_Initialise(s) != ERR_NONE || GSM_WaitFor (s, "AT\r", 3, 0x00, 2, ID_IncomingFrame) != ERR_NONE) {
586 smprintf(s,"AT initialisation failed, trying to stop binary mode...\n");
587 s->Protocol.Functions = &ALCABUSProtocol;
588 error = s->Protocol.Functions->Terminate(s);
589 s->Protocol.Functions = &ATProtocol;
590
591 error = ATGEN_Initialise(s);
592 if (error != ERR_NONE) return error;
593 }
594
595 return ERR_NONE;
596}
597
598static GSM_Error ALCATEL_Terminate(GSM_StateMachine *s)
599{
600 GSM_Error error;
601 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
602
603 free(Priv->CalendarItems);
604 free(Priv->ContactsItems);
605 free(Priv->ToDoItems);
606 error = ALCATEL_SetATMode(s);
607 return ATGEN_Terminate(s);
608}
609
610/* finds whether id is set in the phone */
611static GSM_Error ALCATEL_IsIdAvailable(GSM_StateMachine *s, int id) {
612 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
613 int i;
614
615 if (id > ALCATEL_MAX_LOCATION) return ERR_INVALIDLOCATION;
616
617 switch (Priv->BinaryType) {
618 case TypeCalendar:
619 Priv->CurrentList = &(Priv->CalendarItems);
620 Priv->CurrentCount = &(Priv->CalendarItemsCount);
621 break;
622 case TypeContacts:
623 Priv->CurrentList = &(Priv->ContactsItems);
624 Priv->CurrentCount = &(Priv->ContactsItemsCount);
625 break;
626 case TypeToDo:
627 Priv->CurrentList = &(Priv->ToDoItems);
628 Priv->CurrentCount = &(Priv->ToDoItemsCount);
629 break;
630 }
631
632 for (i=0; i<*Priv->CurrentCount; i++) {
633 if ((*Priv->CurrentList)[i] == id) return ERR_NONE;
634 }
635
636 return ERR_EMPTY;
637}
638
639/* finds next id that is available in the phone */
640static GSM_Error ALCATEL_GetNextId(GSM_StateMachine *s, int *id) {
641 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
642 int i = 0;
643 int next = ALCATEL_MAX_LOCATION;
644
645 switch (Priv->BinaryType) {
646 case TypeCalendar:
647 Priv->CurrentList = &(Priv->CalendarItems);
648 Priv->CurrentCount = &(Priv->CalendarItemsCount);
649 break;
650 case TypeContacts:
651 Priv->CurrentList = &(Priv->ContactsItems);
652 Priv->CurrentCount = &(Priv->ContactsItemsCount);
653 break;
654 case TypeToDo:
655 Priv->CurrentList = &(Priv->ToDoItems);
656 Priv->CurrentCount = &(Priv->ToDoItemsCount);
657 break;
658 }
659
660 for (i=0; i<*Priv->CurrentCount; i++) {
661 if (((*Priv->CurrentList)[i] > *id) && ((*Priv->CurrentList)[i] < next )) {
662 next = (*Priv->CurrentList)[i];
663 }
664 }
665 if (next == ALCATEL_MAX_LOCATION) {
666 return ERR_EMPTY;
667 } else {
668 *id = next;
669 return ERR_NONE;
670 }
671}
672
673static GSM_Error ALCATEL_ReplyGetIds(GSM_Protocol_Message msg, GSM_StateMachine *s)
674{
675 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
676 int count,i,pos;
677
678 count = msg.Buffer[10];
679 *Priv->CurrentCount += count;
680
681 *Priv->CurrentList = (int *)realloc(*Priv->CurrentList, (*Priv->CurrentCount + 1)* sizeof(int));
682 if (*Priv->CurrentList == NULL) return ERR_MOREMEMORY;
683
684 for (i = 0; i < count; i++) {
685 pos = 11 + (4 * i);
686 (*Priv->CurrentList)[*Priv->CurrentCount - count + i] = msg.Buffer[pos + 3] +
687 (msg.Buffer[pos + 2] << 8) +
688 (msg.Buffer[pos + 1] << 16) +
689 (msg.Buffer[pos] << 24);
690 }
691 (*Priv->CurrentList)[*Priv->CurrentCount] = 0;
692
693 /* If last byte is 0, then we transmitted all items */
694 Priv->TransferCompleted = msg.Buffer[4 + msg.Buffer[4]] == 0;
695 return ERR_NONE;
696}
697
698static GSM_Error ALCATEL_GetAvailableIds(GSM_StateMachine *s, bool refresh)
699{
700 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
701 GSM_Error error;
702 int i;
703 unsigned char buffer[] =
704 {0x00, 0x04,
705 0x00, /*type */
706 0x2F, 0x01};
707
708 if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
709
710 switch (Priv->BinaryType) {
711 case TypeCalendar:
712 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
713 Priv->CurrentList= &(Priv->CalendarItems);
714 Priv->CurrentCount= &(Priv->CalendarItemsCount);
715 break;
716 case TypeContacts:
717 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
718 Priv->CurrentList= &(Priv->ContactsItems);
719 Priv->CurrentCount= &(Priv->ContactsItemsCount);
720 break;
721 case TypeToDo:
722 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
723 Priv->CurrentList= &(Priv->ToDoItems);
724 Priv->CurrentCount= &(Priv->ToDoItemsCount);
725 break;
726 }
727
728 if (*Priv->CurrentList != NULL) {
729 if (!refresh) return ERR_NONE;
730 free(*Priv->CurrentList);
731 *Priv->CurrentList = NULL;
732 }
733 smprintf(s,"Reading items list\n");
734
735 *Priv->CurrentCount = 0;
736 Priv->TransferCompleted = false;
737
738 error=GSM_WaitFor (s, buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetIds1);
739 if (error != ERR_NONE) return error;
740
741 while (!Priv->TransferCompleted) {
742 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetIds2);
743 if (error != ERR_NONE) return error;
744 }
745
746 i = 0;
747 smprintf(s,"Received %d ids: ", *Priv->CurrentCount);
748 for (i=0; i < *Priv->CurrentCount; i++) {
749 smprintf(s,"%x ", (*Priv->CurrentList)[i]);
750 }
751 smprintf(s,"\n");
752
753 return ERR_NONE;
754}
755
756static GSM_Error ALCATEL_ReplyGetFields(GSM_Protocol_Message msg, GSM_StateMachine *s)
757{
758 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
759 int i;
760
761 if (msg.Buffer[14] > GSM_PHONEBOOK_ENTRIES) {
762 smprintf(s, "WARNING: Field list truncated, you should increase GSM_PHONEBOOK_ENTRIES to at least %d\n", msg.Buffer[14]);
763 Priv->CurrentFieldsCount = GSM_PHONEBOOK_ENTRIES;
764 } else {
765 Priv->CurrentFieldsCount = msg.Buffer[14];
766 }
767
768 Priv->CurrentFields[Priv->CurrentFieldsCount] = 0;
769
770 for (i = 0; i < Priv->CurrentFieldsCount; i++) {
771 Priv->CurrentFields[i] = msg.Buffer[15 + i];
772 }
773
774 return ERR_NONE;
775}
776
777static GSM_Error ALCATEL_GetFields(GSM_StateMachine *s, int id) {
778 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
779 GSM_Error error;
780 int i;
781 unsigned char buffer[] =
782 {0x00, 0x04,
783 0x00, /* type */
784 0x30, 0x01,
785 0x00, 0x00, 0x00, 0x00}; /* item */
786
787 if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
788 if ((Priv->CurrentFieldsItem == id) && (Priv->CurrentFieldsType == Priv->BinaryType)) return ERR_NONE;
789
790 smprintf(s,"Reading item fields (%d)\n", id);
791
792 buffer[5] = (id >> 24);
793 buffer[6] = ((id >> 16) & 0xff);
794 buffer[7] = ((id >> 8) & 0xff);
795 buffer[8] = (id & 0xff);
796
797 switch (Priv->BinaryType) {
798 case TypeCalendar:
799 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
800 break;
801 case TypeContacts:
802 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
803 break;
804 case TypeToDo:
805 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
806 break;
807 }
808
809 Priv->CurrentFieldsItem = id;
810 Priv->CurrentFieldsType = Priv->BinaryType;
811
812 error=GSM_WaitFor (s, buffer, 9, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetFields1);
813 if (error != ERR_NONE) return error;
814 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetFields2);
815 if (error != ERR_NONE) return error;
816
817 i = 0;
818 smprintf(s,"Received %d fields: ", Priv->CurrentFieldsCount);
819 for (i=0; i < Priv->CurrentFieldsCount; i++) {
820 smprintf(s,"%x ", Priv->CurrentFields[i]);
821 }
822 smprintf(s,"\n");
823
824 return ERR_NONE;
825}
826
827static GSM_Error ALCATEL_ReplyGetFieldValue(GSM_Protocol_Message msg, GSM_StateMachine *s)
828{
829 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
830 unsigned char *buffer = &(msg.Buffer[16]);
831
832 if (buffer[1] == 0x05 && buffer[2] == 0x67) {
833 /* date */
834 Priv->ReturnType = Alcatel_date;
835 Priv->ReturnDateTime.Day= buffer[4];
836 Priv->ReturnDateTime.Month= buffer[5];
837 Priv->ReturnDateTime.Year= buffer[7] + (buffer[6] << 8);
838 Priv->ReturnDateTime.Timezone= 0; /* FIXME: how to acquire this? */
839
840 Priv->ReturnDateTime.Hour= 0;
841 Priv->ReturnDateTime.Minute= 0;
842 Priv->ReturnDateTime.Second= 0;
843 } else if (buffer[1] == 0x06 && buffer[2] == 0x68) {
844 /* time */
845 Priv->ReturnType = Alcatel_time;
846 Priv->ReturnDateTime.Hour= buffer[4];
847 Priv->ReturnDateTime.Minute= buffer[5];
848 Priv->ReturnDateTime.Second= buffer[6];
849
850 Priv->ReturnDateTime.Day= 0;
851 Priv->ReturnDateTime.Month= 0;
852 Priv->ReturnDateTime.Year= 0;
853 Priv->ReturnDateTime.Timezone= 0;
854 } else if (buffer[1] == 0x08 && buffer[2] == 0x3C) {
855 /* string */
856 Priv->ReturnType = Alcatel_string;
857 if (GSM_PHONEBOOK_TEXT_LENGTH < buffer[3])
858 smprintf(s, "WARNING: Text truncated, you should increase GSM_PHONEBOOK_TEXT_LENGTH to at least %d\n", buffer[3] + 1);
859 if (Priv->ProtocolVersion == V_1_0) {
860 DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
861 } else if(Priv->ProtocolVersion == V_1_1 && (buffer[4] & 0x80)) {
862 memcpy(Priv->ReturnString, buffer + 5, buffer[3]);
863 Priv->ReturnString[buffer[3] + 1] = 0;
864 Priv->ReturnString[buffer[3] + 2] = 0;
865 ReverseUnicodeString(Priv->ReturnString);
866 } else {
867 DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
868 }
869 } else if (buffer[1] == 0x07 && buffer[2] == 0x3C) {
870 /* phone */
871 Priv->ReturnType = Alcatel_phone;
872 if (GSM_PHONEBOOK_TEXT_LENGTH < buffer[3])
873 smprintf(s, "WARNING: Text truncated, you should increase GSM_PHONEBOOK_TEXT_LENGTH to at least %d\n", buffer[3] + 1);
874 if (Priv->ProtocolVersion == V_1_0) {
875 DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
876 } else if(Priv->ProtocolVersion == V_1_1 && (buffer[4] & 0x80)) {
877 memcpy(Priv->ReturnString, buffer + 5, buffer[3]);
878 Priv->ReturnString[buffer[3] + 1] = 0;
879 Priv->ReturnString[buffer[3] + 2] = 0;
880 ReverseUnicodeString(Priv->ReturnString);
881 } else {
882 DecodeDefault( Priv->ReturnString, buffer + 4, MIN(GSM_PHONEBOOK_TEXT_LENGTH, buffer[3]), false, GSM_AlcatelAlphabet);
883 }
884 } else if (buffer[1] == 0x03 && buffer[2] == 0x3B) {
885 /* boolean */
886 Priv->ReturnType = Alcatel_bool;
887 Priv->ReturnInt = buffer[3];
888 } else if (buffer[1] == 0x02 && buffer[2] == 0x3A) {
889 /* integer */
890 Priv->ReturnType = Alcatel_int;
891 Priv->ReturnInt = buffer[6] + (buffer[5] << 8) + (buffer[4] << 16) + (buffer[3] << 24);
892 } else if (buffer[1] == 0x04 && buffer[2] == 0x38) {
893 /* enumeration */
894 Priv->ReturnType = Alcatel_enum;
895 Priv->ReturnInt = buffer[3];
896 } else if (buffer[1] == 0x00 && buffer[2] == 0x38) {
897 /* byte */
898 Priv->ReturnType = Alcatel_byte;
899 Priv->ReturnInt = buffer[3];
900 } else {
901 smprintf(s, "WARNING: Uknown data type received (%02X,%02X)\n", buffer[1], buffer[2]);
902 return ERR_UNKNOWNRESPONSE;
903 }
904 return ERR_NONE;
905}
906
907static GSM_Error ALCATEL_GetFieldValue(GSM_StateMachine *s, int id, int field)
908{
909 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
910 GSM_Error error;
911 unsigned char buffer[] =
912 {0x00, 0x04,
913 0x00, /* type */
914 0x1f, 0x01,
915 0x00, 0x00, 0x00, 0x00,/* here follows 4byte id */
916 0x00}; /* field */
917
918 smprintf(s,"Reading item value (%08x.%02x)\n", id, field);
919
920 switch (Priv->BinaryType) {
921 case TypeCalendar:
922 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
923 break;
924 case TypeContacts:
925 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
926 break;
927 case TypeToDo:
928 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
929 break;
930 }
931
932 buffer[5] = (id >> 24);
933 buffer[6] = ((id >> 16) & 0xff);
934 buffer[7] = ((id >> 8) & 0xff);
935 buffer[8] = (id & 0xff);
936 buffer[9] = (field & 0xff);
937
938 error=GSM_WaitFor (s, buffer, 10, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetFieldValue1);
939 if (error != ERR_NONE) return error;
940 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetFieldValue2);
941 if (error != ERR_NONE) return error;
942
943 return ERR_NONE;
944}
945
946static GSM_Error ALCATEL_ReplyGetCategories(GSM_Protocol_Message msg, GSM_StateMachine *s)
947{
948 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
949 int i;
950
951 /* Did we get any category? */
952 if (msg.Buffer[4] == 6) {
953 Priv->CurrentCategoriesCount = 0;
954 return ERR_NONE;
955 }
956 if (msg.Buffer[12] > ALCATEL_MAX_CATEGORIES) {
957 smprintf(s, "WARNING: Field list truncated, you should increase ALCATEL_MAX_CATEGORIES to at least %d\n", msg.Buffer[12]);
958 Priv->CurrentCategoriesCount = ALCATEL_MAX_CATEGORIES;
959 } else {
960 Priv->CurrentCategoriesCount = msg.Buffer[12];
961 }
962
963 for (i = 0; i < Priv->CurrentCategoriesCount; i++) {
964 Priv->CurrentCategories[i] = msg.Buffer[13 + i];
965 Priv->CurrentCategoriesCache[i][0] = '\000';
966 Priv->CurrentCategoriesCache[i][1] = '\000';
967 }
968
969 return ERR_NONE;
970}
971
972static GSM_Error ALCATEL_GetAvailableCategoryIds(GSM_StateMachine *s) {
973 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
974 GSM_Error error;
975 int i;
976 unsigned char buffer[] =
977 {0x00, 0x04,
978 0x00 /*type */,
979 0x0b,
980 0x00 /* list */};
981
982 if (Priv->BinaryState != StateSession) return ERR_UNKNOWN;
983 if (Priv->CurrentCategoriesType == Priv->BinaryType) return ERR_NONE;
984 switch (Priv->BinaryType) {
985 case TypeContacts:
986 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
987 buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
988 break;
989 case TypeToDo:
990 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
991 buffer[4] = ALCATEL_LIST_TODO_CAT;
992 break;
993 default:
994 return ERR_NOTSUPPORTED;
995 }
996
997 Priv->CurrentCategoriesType = Priv->BinaryType;
998
999 smprintf(s,"Reading category list\n");
1000
1001 error=GSM_WaitFor (s, buffer, 5, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetCategories1);
1002 if (error != ERR_NONE) return error;
1003
1004 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetCategories2);
1005 if (error != ERR_NONE) return error;
1006
1007 i = 0;
1008 smprintf(s,"Received %d ids: ", Priv->CurrentCategoriesCount);
1009 for (i=0; i < Priv->CurrentCategoriesCount; i++) {
1010 smprintf(s,"%i ", Priv->CurrentCategories[i]);
1011 }
1012 smprintf(s,"\n");
1013
1014 return ERR_NONE;
1015}
1016
1017static GSM_Error ALCATEL_IsCategoryIdAvailable(GSM_StateMachine *s, int id) {
1018 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1019 int i = 0;
1020
1021 if (Priv->CurrentCategoriesType != Priv->BinaryType) return ERR_UNKNOWN;
1022
1023 for (i = 0; i< Priv->CurrentCategoriesCount; i++) {
1024 if (Priv->CurrentCategories[i] == id) return ERR_NONE;
1025 }
1026 return ERR_EMPTY;
1027}
1028
1029static GSM_Error ALCATEL_ReplyAddCategoryText(GSM_Protocol_Message msg, GSM_StateMachine *s)
1030{
1031 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
1032
1033 Priv->ReturnInt = msg.Buffer[12];
1034
1035 return ERR_NONE;
1036}
1037
1038static GSM_Error ALCATEL_AddCategoryText(GSM_StateMachine *s, const unsigned char *str) {
1039 unsigned char buffer[200] = {0x00, 0x04, 0x00 /*type*/, 0x0d, 0x00 /*list*/, 0x0b };
1040 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1041 GSM_Error error;
1042 int len;
1043
1044 smprintf(s,"Creating category\n");
1045 len = UnicodeLength(str);
1046 EncodeDefault(buffer + 8, str, &len, true, GSM_AlcatelAlphabet);
1047 buffer[6] = len + 1;
1048 buffer[7] = len;
1049
1050 switch (Priv->BinaryType) {
1051 case TypeContacts:
1052 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1053 buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
1054 break;
1055 case TypeToDo:
1056 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1057 buffer[4] = ALCATEL_LIST_TODO_CAT;
1058 break;
1059 default:
1060 return ERR_NOTSUPPORTED;
1061 }
1062
1063 error=GSM_WaitFor (s, buffer, 8 + len, 0x02, ALCATEL_TIMEOUT, ID_AlcatelAddCategoryText1);
1064 if (error != ERR_NONE) return error;
1065 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelAddCategoryText2);
1066 if (error != ERR_NONE) return error;
1067
1068 /* Refresh list */
1069 Priv->CurrentCategoriesType = 0;
1070 return ALCATEL_GetAvailableCategoryIds(s);
1071}
1072
1073static GSM_Error ALCATEL_ReplyGetCategoryText(GSM_Protocol_Message msg, GSM_StateMachine *s)
1074{
1075 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
1076 int len;
1077
1078 len = msg.Buffer[14];
1079 if (len > GSM_MAX_CATEGORY_NAME_LENGTH) {
1080 smprintf(s, "WARNING: Category name truncated, you should increase GSM_MAX_CATEGORY_NAME_LENGTH to at least %d\n", len);
1081 }
1082 if (Priv->ProtocolVersion == V_1_0) {
1083 DecodeDefault( Priv->ReturnString, msg.Buffer + 15, MIN(GSM_MAX_CATEGORY_NAME_LENGTH, len), false, GSM_AlcatelAlphabet);
1084 } else if(Priv->ProtocolVersion == V_1_1 && (msg.Buffer[15] & 0x80)) {
1085 memcpy(Priv->ReturnString, msg.Buffer + 16, len);
1086 Priv->ReturnString[len + 1] = 0;
1087 Priv->ReturnString[len + 2] = 0;
1088 ReverseUnicodeString(Priv->ReturnString);
1089 } else {
1090 DecodeDefault( Priv->ReturnString, msg.Buffer + 15, MIN(GSM_MAX_CATEGORY_NAME_LENGTH, len), false, GSM_AlcatelAlphabet);
1091 }
1092 return ERR_NONE;
1093}
1094
1095static GSM_Error ALCATEL_GetCategoryText(GSM_StateMachine *s, int id) {
1096 unsigned char buffer[] = {0x00, 0x04, 0x00 /*type*/, 0x0c, 0x00 /*list*/, 0x0A, 0x01, 0x00 /*item*/ };
1097 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1098 GSM_Error error;
1099
1100 if (Priv->CurrentCategoriesCache[id][0] != '\000' || Priv->CurrentCategoriesCache[id][1] != '\000') {
1101 CopyUnicodeString(Priv->ReturnString, Priv->CurrentCategoriesCache[id]);
1102 return ERR_NONE;
1103 }
1104
1105 smprintf(s,"Reading category %d\n", id);
1106
1107 switch (Priv->BinaryType) {
1108 case TypeContacts:
1109 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1110 buffer[4] = ALCATEL_LIST_CONTACTS_CAT;
1111 break;
1112 case TypeToDo:
1113 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1114 buffer[4] = ALCATEL_LIST_TODO_CAT;
1115 break;
1116 default:
1117 return ERR_NOTSUPPORTED;
1118 }
1119
1120 buffer[7] = (id & 0xff);
1121
1122 error=GSM_WaitFor (s, buffer, 8, 0x02, ALCATEL_TIMEOUT, ID_AlcatelGetCategoryText1);
1123 if (error != ERR_NONE) return error;
1124 error=GSM_WaitFor (s, 0, 0, 0x00, ALCATEL_TIMEOUT, ID_AlcatelGetCategoryText2);
1125 if (error != ERR_NONE) return error;
1126
1127 CopyUnicodeString(Priv->CurrentCategoriesCache[id], Priv->ReturnString);
1128
1129 return ERR_NONE;
1130}
1131
1132static GSM_Error ALCATEL_DeleteField(GSM_StateMachine *s, int id, int field) {
1133 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1134 GSM_Error error;
1135 unsigned char buffer[] =
1136 {0x00, 0x04,
1137 0x00, /* type */
1138 0x26, 0x01,
1139 0x00, 0x00, 0x00, 0x00,/* here follows 4byte id */
1140 0x65, 0x01,
1141 0x00, /* field */
1142 0x01};
1143
1144 smprintf(s,"Deleting field (%08x.%02x)\n", id, field);
1145
1146 switch (Priv->BinaryType) {
1147 case TypeCalendar:
1148 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
1149 break;
1150 case TypeContacts:
1151 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1152 break;
1153 case TypeToDo:
1154 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1155 break;
1156 }
1157
1158 buffer[5] = (id >> 24);
1159 buffer[6] = ((id >> 16) & 0xff);
1160 buffer[7] = ((id >> 8) & 0xff);
1161 buffer[8] = (id & 0xff);
1162 buffer[11] = (field & 0xff);
1163
1164 error=GSM_WaitFor (s, buffer, 13, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDeleteField);
1165 if (error != ERR_NONE) return error;
1166
1167 return ERR_NONE;
1168}
1169
1170static GSM_Error ALCATEL_DeleteItem(GSM_StateMachine *s, int id) {
1171 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1172 GSM_Error error;
1173 unsigned char buffer[] =
1174 {0x00, 0x04,
1175 0x00, /* type */
1176 0x27, 0x01,
1177 0x00, 0x00, 0x00, 0x00,/* here follows 4byte id */
1178 0x42};
1179
1180 smprintf(s,"Deleting item (%08x)\n", id);
1181
1182 switch (Priv->BinaryType) {
1183 case TypeCalendar:
1184 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
1185 break;
1186 case TypeContacts:
1187 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1188 break;
1189 case TypeToDo:
1190 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1191 break;
1192 }
1193
1194 buffer[5] = (id >> 24);
1195 buffer[6] = ((id >> 16) & 0xff);
1196 buffer[7] = ((id >> 8) & 0xff);
1197 buffer[8] = (id & 0xff);
1198
1199 error=GSM_WaitFor (s, buffer, 10, 0x02, ALCATEL_TIMEOUT, ID_AlcatelDeleteItem1);
1200 if (error != ERR_NONE) return error;
1201
1202 error=GSM_WaitFor (s, 0, 0, 0x0, ALCATEL_TIMEOUT, ID_AlcatelDeleteItem2);
1203 if (error != ERR_NONE) return error;
1204
1205 return ERR_NONE;
1206}
1207
1208static GSM_Error ALCATEL_ReplyDeleteItem(GSM_Protocol_Message msg, GSM_StateMachine *s)
1209{
1210 if (msg.Buffer[8] != 0x25) return ERR_UNKNOWNRESPONSE;
1211 return ERR_NONE;
1212}
1213
1214static GSM_Error ALCATEL_BuildWriteBuffer(unsigned char * buffer, GSM_Alcatel_FieldType type, int field, void *data) {
1215 int len;
1216
1217 buffer[1] = field & 0xff;
1218
1219 switch(type) {
1220 case Alcatel_date:
1221 if (!CheckDate((GSM_DateTime *)data)) return ERR_INVALIDDATETIME;
1222
1223 buffer[3] = 0x05;
1224 buffer[4] = 0x67;
1225
1226 buffer[0] = 0x09;
1227 buffer[5] = 0x04;
1228 buffer[6] = ((GSM_DateTime *)data)->Day & 0xff;
1229 buffer[7] = ((GSM_DateTime *)data)->Month & 0xff;
1230 buffer[8] = ((GSM_DateTime *)data)->Year >> 8;
1231 buffer[9] = ((GSM_DateTime *)data)->Year & 0xff;
1232 buffer[10] = 0x00;
1233 break;
1234 case Alcatel_time:
1235 if (!CheckTime((GSM_DateTime *)data)) return ERR_INVALIDDATETIME;
1236
1237 buffer[3] = 0x06;
1238 buffer[4] = 0x68;
1239
1240 buffer[0] = 0x08;
1241 buffer[5] = 0x03;
1242 buffer[6] = ((GSM_DateTime *)data)->Hour & 0xff;
1243 buffer[7] = ((GSM_DateTime *)data)->Minute & 0xff;
1244 buffer[8] = ((GSM_DateTime *)data)->Second & 0xff;
1245 buffer[9] = 0x00;
1246 break;
1247 case Alcatel_string:
1248 buffer[3] = 0x08;
1249 buffer[4] = 0x3c;
1250
1251 len = MIN(UnicodeLength((char *)data),62);
1252 EncodeDefault(buffer + 6, (char *)data, &len, true, GSM_AlcatelAlphabet);
1253 buffer[5] = len;
1254 buffer[0] = 5 + len;
1255 buffer[6 + len] = 0x00;
1256 break;
1257 case Alcatel_phone:
1258 buffer[3] = 0x07;
1259 buffer[4] = 0x3c;
1260
1261 len = MIN(UnicodeLength((char *)data),50);
1262 EncodeDefault(buffer + 6, (char *)data, &len, true, GSM_AlcatelAlphabet);
1263 buffer[5] = len;
1264 buffer[0] = 5 + len;
1265 buffer[6 + len] = 0x00;
1266 break;
1267 case Alcatel_enum:
1268 buffer[3] = 0x04;
1269 buffer[4] = 0x38;
1270
1271 buffer[0] = 0x05;
1272 buffer[5] = *(int *)data & 0xff;
1273 buffer[6] = 0x00;
1274 break;
1275 case Alcatel_bool:
1276 buffer[3] = 0x03;
1277 buffer[4] = 0x3b;
1278
1279 buffer[0] = 0x05;
1280 buffer[5] = *(int *)data & 0xff;
1281 buffer[6] = 0x00;
1282 break;
1283 case Alcatel_int:
1284 buffer[3] = 0x02;
1285 buffer[4] = 0x3a;
1286
1287 buffer[0] = 0x08;
1288 buffer[5] = *(unsigned int *)data >> 24;
1289 buffer[6] = (*(unsigned int *)data >> 16) & 0xff;
1290 buffer[7] = (*(unsigned int *)data >> 8) & 0xff;
1291 buffer[8] = *(unsigned int *)data & 0xff;
1292 buffer[9] = 0x00;
1293 break;
1294 case Alcatel_byte:
1295 buffer[3] = 0x00;
1296 buffer[4] = 0x38;
1297
1298 buffer[0] = 0x05;
1299 buffer[5] = *(int *)data & 0xff;
1300 buffer[6] = 0x00;
1301 break;
1302 }
1303 return ERR_NONE;
1304}
1305
1306static GSM_Error ALCATEL_CreateField(GSM_StateMachine *s, GSM_Alcatel_FieldType type, int field, void *data) {
1307 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1308 GSM_Error error;
1309 unsigned char buffer[200] =
1310 {0x00, 0x04,
1311 0x00, /* type */
1312 0x25, 0x01, 0x65,
1313 0x00, /* length of remaining part */
1314 0x00, /* field */
1315 0x37}; /* data follows here */
1316
1317 smprintf(s,"Creating field (%02x)\n", field);
1318
1319 switch (Priv->BinaryType) {
1320 case TypeCalendar:
1321 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
1322 break;
1323 case TypeContacts:
1324 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1325 break;
1326 case TypeToDo:
1327 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1328 break;
1329 }
1330 error = ALCATEL_BuildWriteBuffer(buffer + 6, type, field, data);
1331 if (error != ERR_NONE) return error;
1332
1333 error = GSM_WaitFor (s, buffer, 8 + buffer[6], 0x02, ALCATEL_TIMEOUT, ID_AlcatelCreateField);
1334 if (error != ERR_NONE) return error;
1335
1336 return ERR_NONE;
1337}
1338
1339static GSM_Error ALCATEL_UpdateField(GSM_StateMachine *s, GSM_Alcatel_FieldType type, int id, int field, void *data) {
1340 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1341 GSM_Error error;
1342 unsigned char buffer[200] =
1343 {0x00, 0x04,
1344 0x00, /* type */
1345 0x26, 0x01,
1346 0x00, 0x00, 0x00, 0x00,/* id */
1347 0x65,
1348 0x00, /* length of remaining part */
1349 0x00, /* field */
1350 0x37}; /* data follows here */
1351
1352 smprintf(s,"Updating field (%08x.%02x)\n", id, field);
1353
1354 buffer[5] = (id >> 24);
1355 buffer[6] = ((id >> 16) & 0xff);
1356 buffer[7] = ((id >> 8) & 0xff);
1357 buffer[8] = (id & 0xff);
1358
1359 switch (Priv->BinaryType) {
1360 case TypeCalendar:
1361 buffer[2] = ALCATEL_SYNC_TYPE_CALENDAR;
1362 break;
1363 case TypeContacts:
1364 buffer[2] = ALCATEL_SYNC_TYPE_CONTACTS;
1365 break;
1366 case TypeToDo:
1367 buffer[2] = ALCATEL_SYNC_TYPE_TODO;
1368 break;
1369 }
1370 error = ALCATEL_BuildWriteBuffer(buffer + 10, type, field, data);
1371 if (error != ERR_NONE) return error;
1372
1373 error = GSM_WaitFor (s, buffer, 12 + buffer[10], 0x02, ALCATEL_TIMEOUT, ID_AlcatelUpdateField);
1374 if (error != ERR_NONE) return error;
1375
1376 return ERR_NONE;
1377}
1378
1379static GSM_Error ALCATEL_GetManufacturer(GSM_StateMachine *s)
1380{
1381 strcpy(s->Phone.Data.Manufacturer, "Alcatel");
1382 return ERR_NONE;
1383}
1384
1385static GSM_Error ALCATEL_GetIMEI (GSM_StateMachine *s)
1386{
1387 GSM_Error error;
1388
1389 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1390 return ATGEN_GetIMEI(s);
1391}
1392
1393static GSM_Error ALCATEL_GetFirmware(GSM_StateMachine *s)
1394{
1395 GSM_Error error;
1396
1397 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1398 return ATGEN_GetFirmware(s);
1399}
1400
1401static GSM_Error ALCATEL_GetModel(GSM_StateMachine *s)
1402{
1403 GSM_Error error;
1404
1405 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1406 return ATGEN_GetModel(s);
1407}
1408
1409static GSM_Error ALCATEL_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
1410{
1411 GSM_Error error;
1412
1413 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1414 return ATGEN_GetDateTime(s, date_time);
1415}
1416
1417static GSM_Error ALCATEL_GetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1418{
1419 GSM_Error error;
1420 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1421 int i;
1422 int j = 0;
1423
1424 if (entry->MemoryType == MEM_ME) {
1425 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
1426 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
1427 if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
1428 entry->EntriesNum = 0;
1429 return error;
1430 }
1431 if ((error = ALCATEL_GetFields(s, entry->Location))!= ERR_NONE) return error;
1432
1433 entry->EntriesNum = Priv->CurrentFieldsCount;
1434
1435 for (i=0; i<Priv->CurrentFieldsCount; i++) {
1436 if ((error = ALCATEL_GetFieldValue(s, entry->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
1437 entry->Entries[i].VoiceTag = 0;
1438 entry->Entries[i].SMSList[0] = 0;
1439 switch (Priv->CurrentFields[i]) {
1440 case 0:
1441 if (Priv->ReturnType != Alcatel_string) {
1442 smprintf(s,"WARNING: Received unexpected type %02X for field 0, ignoring\n", Priv->ReturnType);
1443 entry->EntriesNum--;
1444 j++;
1445 break;
1446 }
1447 entry->Entries[i - j].EntryType = PBK_Text_LastName;
1448 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1449 break;
1450 case 1:
1451 if (Priv->ReturnType != Alcatel_string) {
1452 smprintf(s,"WARNING: Received unexpected type %02X for field 1, ignoring\n", Priv->ReturnType);
1453 entry->EntriesNum--;
1454 j++;
1455 break;
1456 }
1457 entry->Entries[i - j].EntryType = PBK_Text_FirstName;
1458 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1459 break;
1460 case 2:
1461 if (Priv->ReturnType != Alcatel_string) {
1462 smprintf(s,"WARNING: Received unexpected type %02X for field 2, ignoring\n", Priv->ReturnType);
1463 entry->EntriesNum--;
1464 j++;
1465 break;
1466 }
1467 entry->Entries[i - j].EntryType = PBK_Text_Company;
1468 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1469 break;
1470 case 3:
1471 if (Priv->ReturnType != Alcatel_string) {
1472 smprintf(s,"WARNING: Received unexpected type %02X for field 3, ignoring\n", Priv->ReturnType);
1473 entry->EntriesNum--;
1474 j++;
1475 break;
1476 }
1477 entry->Entries[i - j].EntryType = PBK_Text_JobTitle;
1478 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1479 break;
1480 case 4:
1481 if (Priv->ReturnType != Alcatel_string) {
1482 smprintf(s,"WARNING: Received unexpected type %02X for field 4, ignoring\n", Priv->ReturnType);
1483 entry->EntriesNum--;
1484 j++;
1485 break;
1486 }
1487 entry->Entries[i - j].EntryType = PBK_Text_Note;
1488 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1489 break;
1490 case 5:
1491 if (Priv->ReturnType != Alcatel_byte) {
1492 smprintf(s,"WARNING: Received unexpected type %02X for field 5, ignoring\n", Priv->ReturnType);
1493 entry->EntriesNum--;
1494 j++;
1495 break;
1496 }
1497 entry->Entries[i - j].EntryType = PBK_Category;
1498 entry->Entries[i - j].Number = Priv->ReturnInt;
1499 break;
1500 case 6:
1501 if (Priv->ReturnType != Alcatel_bool) {
1502 smprintf(s,"WARNING: Received unexpected type %02X for field 6, ignoring\n", Priv->ReturnType);
1503 entry->EntriesNum--;
1504 j++;
1505 break;
1506 }
1507 entry->Entries[i - j].EntryType = PBK_Private;
1508 entry->Entries[i - j].Number = Priv->ReturnInt;
1509 break;
1510 case 7:
1511 if (Priv->ReturnType != Alcatel_phone) {
1512 smprintf(s,"WARNING: Received unexpected type %02X for field 7, ignoring\n", Priv->ReturnType);
1513 entry->EntriesNum--;
1514 j++;
1515 break;
1516 }
1517 entry->Entries[i - j].EntryType = PBK_Number_Work;
1518 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1519 break;
1520 case 8:
1521 if (Priv->ReturnType != Alcatel_phone) {
1522 smprintf(s,"WARNING: Received unexpected type %02X for field 8, ignoring\n", Priv->ReturnType);
1523 entry->EntriesNum--;
1524 j++;
1525 break;
1526 }
1527 entry->Entries[i - j].EntryType = PBK_Number_General;
1528 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1529 break;
1530 case 9:
1531 if (Priv->ReturnType != Alcatel_phone) {
1532 smprintf(s,"WARNING: Received unexpected type %02X for field 9, ignoring\n", Priv->ReturnType);
1533 entry->EntriesNum--;
1534 j++;
1535 break;
1536 }
1537 entry->Entries[i - j].EntryType = PBK_Number_Fax;
1538 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1539 break;
1540 case 10:
1541 if (Priv->ReturnType != Alcatel_phone) {
1542 smprintf(s,"WARNING: Received unexpected type %02X for field 10, ignoring\n", Priv->ReturnType);
1543 entry->EntriesNum--;
1544 j++;
1545 break;
1546 }
1547 entry->Entries[i - j].EntryType = PBK_Number_Other;
1548 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1549 break;
1550 case 11:
1551 if (Priv->ReturnType != Alcatel_phone) {
1552 smprintf(s,"WARNING: Received unexpected type %02X for field 11, ignoring\n", Priv->ReturnType);
1553 entry->EntriesNum--;
1554 j++;
1555 break;
1556 }
1557 entry->Entries[i - j].EntryType = PBK_Number_Pager;
1558 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1559 break;
1560 case 12:
1561 if (Priv->ReturnType != Alcatel_phone) {
1562 smprintf(s,"WARNING: Received unexpected type %02X for field 12, ignoring\n", Priv->ReturnType);
1563 entry->EntriesNum--;
1564 j++;
1565 break;
1566 }
1567 entry->Entries[i - j].EntryType = PBK_Number_Mobile;
1568 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1569 break;
1570 case 13:
1571 if (Priv->ReturnType != Alcatel_phone) {
1572 smprintf(s,"WARNING: Received unexpected type %02X for field 13, ignoring\n", Priv->ReturnType);
1573 entry->EntriesNum--;
1574 j++;
1575 break;
1576 }
1577 entry->Entries[i - j].EntryType = PBK_Number_Home;
1578 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1579 break;
1580 case 14:
1581 if (Priv->ReturnType != Alcatel_string) {
1582 smprintf(s,"WARNING: Received unexpected type %02X for field 14, ignoring\n", Priv->ReturnType);
1583 entry->EntriesNum--;
1584 j++;
1585 break;
1586 }
1587 entry->Entries[i - j].EntryType = PBK_Text_Email;
1588 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1589 break;
1590 case 15:
1591 if (Priv->ReturnType != Alcatel_string) {
1592 smprintf(s,"WARNING: Received unexpected type %02X for field 15, ignoring\n", Priv->ReturnType);
1593 entry->EntriesNum--;
1594 j++;
1595 break;
1596 }
1597 entry->Entries[i - j].EntryType = PBK_Text_Email2;
1598 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1599 break;
1600 case 16:
1601 if (Priv->ReturnType != Alcatel_string) {
1602 smprintf(s,"WARNING: Received unexpected type %02X for field 16, ignoring\n", Priv->ReturnType);
1603 entry->EntriesNum--;
1604 j++;
1605 break;
1606 }
1607 entry->Entries[i - j].EntryType = PBK_Text_StreetAddress;
1608 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1609 break;
1610 case 17:
1611 if (Priv->ReturnType != Alcatel_string) {
1612 smprintf(s,"WARNING: Received unexpected type %02X for field 17, ignoring\n", Priv->ReturnType);
1613 entry->EntriesNum--;
1614 j++;
1615 break;
1616 }
1617 entry->Entries[i - j].EntryType = PBK_Text_City;
1618 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1619 break;
1620 case 18:
1621 if (Priv->ReturnType != Alcatel_string) {
1622 smprintf(s,"WARNING: Received unexpected type %02X for field 18, ignoring\n", Priv->ReturnType);
1623 entry->EntriesNum--;
1624 j++;
1625 break;
1626 }
1627 entry->Entries[i - j].EntryType = PBK_Text_State;
1628 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1629 break;
1630 case 19:
1631 if (Priv->ReturnType != Alcatel_string) {
1632 smprintf(s,"WARNING: Received unexpected type %02X for field 19, ignoring\n", Priv->ReturnType);
1633 entry->EntriesNum--;
1634 j++;
1635 break;
1636 }
1637 entry->Entries[i - j].EntryType = PBK_Text_Zip;
1638 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1639 break;
1640 case 20:
1641 if (Priv->ReturnType != Alcatel_string) {
1642 smprintf(s,"WARNING: Received unexpected type %02X for field 20, ignoring\n", Priv->ReturnType);
1643 entry->EntriesNum--;
1644 j++;
1645 break;
1646 }
1647 entry->Entries[i - j].EntryType = PBK_Text_Country;
1648 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1649 break;
1650 case 21:
1651 if (Priv->ReturnType != Alcatel_string) {
1652 smprintf(s,"WARNING: Received unexpected type %02X for field 21, ignoring\n", Priv->ReturnType);
1653 entry->EntriesNum--;
1654 j++;
1655 break;
1656 }
1657 entry->Entries[i - j].EntryType = PBK_Text_Custom1;
1658 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1659 break;
1660 case 22:
1661 if (Priv->ReturnType != Alcatel_string) {
1662 smprintf(s,"WARNING: Received unexpected type %02X for field 22, ignoring\n", Priv->ReturnType);
1663 entry->EntriesNum--;
1664 j++;
1665 break;
1666 }
1667 entry->Entries[i - j].EntryType = PBK_Text_Custom2;
1668 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1669 break;
1670 case 23:
1671 if (Priv->ReturnType != Alcatel_string) {
1672 smprintf(s,"WARNING: Received unexpected type %02X for field 23, ignoring\n", Priv->ReturnType);
1673 entry->EntriesNum--;
1674 j++;
1675 break;
1676 }
1677 entry->Entries[i - j].EntryType = PBK_Text_Custom3;
1678 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1679 break;
1680 case 24:
1681 if (Priv->ReturnType != Alcatel_string) {
1682 smprintf(s,"WARNING: Received unexpected type %02X for field 24, ignoring\n", Priv->ReturnType);
1683 entry->EntriesNum--;
1684 j++;
1685 break;
1686 }
1687 entry->Entries[i - j].EntryType = PBK_Text_Custom4;
1688 CopyUnicodeString(entry->Entries[i - j].Text, Priv->ReturnString);
1689 break;
1690 case 25:
1691 if (Priv->ReturnType != Alcatel_int) {
1692 smprintf(s,"WARNING: Received unexpected type %02X for field 25, ignoring\n", Priv->ReturnType);
1693 entry->EntriesNum--;
1694 j++;
1695 break;
1696 }
1697 if (Priv->ReturnInt != 0) {
1698 entry->Entries[i - j].EntryType = PBK_PictureID;
1699 entry->Entries[i - j].Number = Priv->ReturnInt;
1700 } else {
1701 entry->EntriesNum--;
1702 j++;
1703 }
1704 break;
1705 default:
1706 entry->EntriesNum--;
1707 j++;
1708 smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
1709 switch (Priv->ReturnType) {
1710 case Alcatel_date:
1711 smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
1712 break;
1713 case Alcatel_time:
1714 smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
1715 break;
1716 case Alcatel_string:
1717 case Alcatel_phone:
1718 smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
1719 break;
1720 case Alcatel_enum:
1721 case Alcatel_bool:
1722 case Alcatel_int:
1723 case Alcatel_byte:
1724 smprintf(s, "%d", Priv->ReturnInt);
1725 break;
1726 }
1727 smprintf(s,"\n");
1728 }
1729 }
1730 return ERR_NONE;
1731 } else {
1732 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1733 return ATGEN_GetMemory(s, entry);
1734 }
1735}
1736
1737static GSM_Error ALCATEL_GetNextMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start)
1738{
1739 GSM_Error error;
1740 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1741
1742 if (entry->MemoryType == MEM_ME) {
1743 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
1744 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
1745 if (Priv->ContactsItemsCount == 0) return ERR_EMPTY;
1746
1747 if (start) entry->Location = 0;
1748 if ((error = ALCATEL_GetNextId(s, &(entry->Location))) != ERR_NONE) return error;
1749
1750 return ALCATEL_GetMemory(s, entry);
1751 } else {
1752 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1753 return ATGEN_GetNextMemory(s, entry, start);
1754 }
1755}
1756
1757static GSM_Error ALCATEL_AddMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1758{
1759 GSM_Error error;
1760 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1761 int NamePosition = -1;
1762 bool NameSet = false;
1763 int i;
1764
1765
1766 if (entry->MemoryType == MEM_ME) {
1767 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
1768 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeContacts, 0))!= ERR_NONE) return error;
1769 for (i = 0; i < entry->EntriesNum; i++) {
1770 switch (entry->Entries[i].EntryType) {
1771 case PBK_Number_General:
1772 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 8, entry->Entries[i].Text)) != ERR_NONE) return error;
1773 break;
1774 case PBK_Number_Mobile:
1775 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 12, entry->Entries[i].Text)) != ERR_NONE) return error;
1776 break;
1777 case PBK_Number_Work:
1778 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 7, entry->Entries[i].Text)) != ERR_NONE) return error;
1779 break;
1780 case PBK_Number_Fax:
1781 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, entry->Entries[i].Text)) != ERR_NONE) return error;
1782 break;
1783 case PBK_Number_Home:
1784 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 13, entry->Entries[i].Text)) != ERR_NONE) return error;
1785 break;
1786 case PBK_Number_Pager:
1787 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 11, entry->Entries[i].Text)) != ERR_NONE) return error;
1788 break;
1789 case PBK_Number_Other:
1790 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 10, entry->Entries[i].Text)) != ERR_NONE) return error;
1791 break;
1792 case PBK_Text_Note:
1793 if ((error = ALCATEL_CreateField(s, Alcatel_string, 4, entry->Entries[i].Text)) != ERR_NONE) return error;
1794 break;
1795 case PBK_Text_Email:
1796 if ((error = ALCATEL_CreateField(s, Alcatel_string, 14, entry->Entries[i].Text)) != ERR_NONE) return error;
1797 break;
1798 case PBK_Text_Email2:
1799 if ((error = ALCATEL_CreateField(s, Alcatel_string, 15, entry->Entries[i].Text)) != ERR_NONE) return error;
1800 break;
1801 case PBK_Text_LastName:
1802 if ((error = ALCATEL_CreateField(s, Alcatel_string, 0, entry->Entries[i].Text)) != ERR_NONE) return error;
1803 NameSet = true;
1804 break;
1805 case PBK_Text_FirstName:
1806 if ((error = ALCATEL_CreateField(s, Alcatel_string, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
1807 NameSet = true;
1808 break;
1809 case PBK_Text_Company:
1810 if ((error = ALCATEL_CreateField(s, Alcatel_string, 2, entry->Entries[i].Text)) != ERR_NONE) return error;
1811 break;
1812 case PBK_Text_JobTitle:
1813 if ((error = ALCATEL_CreateField(s, Alcatel_string, 3, entry->Entries[i].Text)) != ERR_NONE) return error;
1814 break;
1815 case PBK_Category:
1816 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 5, &(entry->Entries[i].Number))) != ERR_NONE) return error;
1817 break;
1818 case PBK_Private:
1819 if ((error = ALCATEL_CreateField(s, Alcatel_bool, 6, &(entry->Entries[i].Number))) != ERR_NONE) return error;
1820 break;
1821 case PBK_Text_StreetAddress:
1822 if ((error = ALCATEL_CreateField(s, Alcatel_string, 16, entry->Entries[i].Text)) != ERR_NONE) return error;
1823 break;
1824 case PBK_Text_City:
1825 if ((error = ALCATEL_CreateField(s, Alcatel_string, 17, entry->Entries[i].Text)) != ERR_NONE) return error;
1826 break;
1827 case PBK_Text_State:
1828 if ((error = ALCATEL_CreateField(s, Alcatel_string, 18, entry->Entries[i].Text)) != ERR_NONE) return error;
1829 break;
1830 case PBK_Text_Zip:
1831 if ((error = ALCATEL_CreateField(s, Alcatel_string, 19, entry->Entries[i].Text)) != ERR_NONE) return error;
1832 break;
1833 case PBK_Text_Country:
1834 if ((error = ALCATEL_CreateField(s, Alcatel_string, 20, entry->Entries[i].Text)) != ERR_NONE) return error;
1835 break;
1836 case PBK_Text_Custom1:
1837 if ((error = ALCATEL_CreateField(s, Alcatel_string, 21, entry->Entries[i].Text)) != ERR_NONE) return error;
1838 break;
1839 case PBK_Text_Custom2:
1840 if ((error = ALCATEL_CreateField(s, Alcatel_string, 22, entry->Entries[i].Text)) != ERR_NONE) return error;
1841 break;
1842 case PBK_Text_Custom3:
1843 if ((error = ALCATEL_CreateField(s, Alcatel_string, 23, entry->Entries[i].Text)) != ERR_NONE) return error;
1844 break;
1845 case PBK_Text_Custom4:
1846 if ((error = ALCATEL_CreateField(s, Alcatel_string, 24, entry->Entries[i].Text)) != ERR_NONE) return error;
1847 break;
1848 case PBK_PictureID:
1849 if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
1850 if ((error = ALCATEL_CreateField(s, Alcatel_int, 25, &(entry->Entries[i].Number))) != ERR_NONE) return error;
1851 } else {
1852 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
1853 }
1854 break;
1855
1856 case PBK_Text_Name: NamePosition = i; break;
1857 /* Following fields are not supported: */
1858 case PBK_Text_UserID:
1859 case PBK_SMSListID:
1860 case PBK_RingtoneFileSystemID:
1861 case PBK_Date:
1862 case PBK_Caller_Group:
1863 case PBK_RingtoneID:
1864 case PBK_Text_Postal:
1865 case PBK_Text_URL:
1866 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
1867 break;
1868 }
1869 }
1870 if (NamePosition != -1) {
1871 if (NameSet) {
1872 smprintf(s,"WARNING: Ignoring name, not supported by phone\n");
1873 } else {
1874 if ((error = ALCATEL_CreateField(s, Alcatel_string, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
1875 }
1876 }
1877 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
1878 entry->Location = Priv->CommitedRecord;
1879 /* Refresh list */
1880 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
1881 return ERR_NONE;
1882 } else {
1883 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
1884 return ATGEN_AddMemory(s, entry);
1885 }
1886}
1887
1888static GSM_Error ALCATEL_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1889{
1890 GSM_Error error;
1891 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
1892 int NamePosition = -1;
1893 bool NameSet = false;
1894 int i;
1895 bool UpdatedFields[26];
1896
1897 if (entry->Location == 0) return ERR_INVALIDLOCATION;
1898
1899 if (entry->MemoryType == MEM_ME) {
1900 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
1901 /* Save modified entry */
1902 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
1903 if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
1904 /* Entry doesn't exist, we will create new one */
1905 return ALCATEL_AddMemory(s, entry);
1906 }
1907 /* Get fields for current item */
1908 if ((error = ALCATEL_GetFields(s, entry->Location))!= ERR_NONE) return error;
1909
1910 for (i = 0; i < 26; i++) { UpdatedFields[i] = false; }
1911
1912 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeContacts, entry->Location))!= ERR_NONE) return error;
1913 for (i = 0; i < entry->EntriesNum; i++) {
1914 switch (entry->Entries[i].EntryType) {
1915 case PBK_Number_General:
1916 UpdatedFields[8] = true;
1917 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 8, entry->Entries[i].Text)) != ERR_NONE) return error;
1918 break;
1919 case PBK_Number_Mobile:
1920 UpdatedFields[12] = true;
1921 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 12, entry->Entries[i].Text)) != ERR_NONE) return error;
1922 break;
1923 case PBK_Number_Work:
1924 UpdatedFields[7] = true;
1925 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 7, entry->Entries[i].Text)) != ERR_NONE) return error;
1926 break;
1927 case PBK_Number_Fax:
1928 UpdatedFields[9] = true;
1929 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 9, entry->Entries[i].Text)) != ERR_NONE) return error;
1930 break;
1931 case PBK_Number_Home:
1932 UpdatedFields[13] = true;
1933 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 13, entry->Entries[i].Text)) != ERR_NONE) return error;
1934 break;
1935 case PBK_Number_Pager:
1936 UpdatedFields[11] = true;
1937 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 11, entry->Entries[i].Text)) != ERR_NONE) return error;
1938 break;
1939 case PBK_Number_Other:
1940 UpdatedFields[10] = true;
1941 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, entry->Location, 10, entry->Entries[i].Text)) != ERR_NONE) return error;
1942 break;
1943 case PBK_Text_Note:
1944 UpdatedFields[4] = true;
1945 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 4, entry->Entries[i].Text)) != ERR_NONE) return error;
1946 break;
1947 case PBK_Text_Email:
1948 UpdatedFields[14] = true;
1949 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 14, entry->Entries[i].Text)) != ERR_NONE) return error;
1950 break;
1951 case PBK_Text_Email2:
1952 UpdatedFields[15] = true;
1953 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 15, entry->Entries[i].Text)) != ERR_NONE) return error;
1954 break;
1955 case PBK_Text_LastName:
1956 UpdatedFields[0] = true;
1957 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 0, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
1958 break;
1959 case PBK_Text_FirstName:
1960 UpdatedFields[1] = true;
1961 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 1, entry->Entries[i].Text)) != ERR_NONE) return error; NameSet = true;
1962 break;
1963 case PBK_Text_Company:
1964 UpdatedFields[2] = true;
1965 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 2, entry->Entries[i].Text)) != ERR_NONE) return error;
1966 break;
1967 case PBK_Text_JobTitle:
1968 UpdatedFields[3] = true;
1969 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 3, entry->Entries[i].Text)) != ERR_NONE) return error;
1970 break;
1971 case PBK_Category:
1972 UpdatedFields[5] = true;
1973 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, entry->Location, 5, &(entry->Entries[i].Number))) != ERR_NONE) return error;
1974 break;
1975 case PBK_Private:
1976 UpdatedFields[6] = true;
1977 if ((error = ALCATEL_UpdateField(s, Alcatel_bool, entry->Location, 6, &(entry->Entries[i].Number))) != ERR_NONE) return error;
1978 break;
1979 case PBK_Text_StreetAddress:
1980 UpdatedFields[16] = true;
1981 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 16, entry->Entries[i].Text)) != ERR_NONE) return error;
1982 break;
1983 case PBK_Text_City:
1984 UpdatedFields[17] = true;
1985 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 17, entry->Entries[i].Text)) != ERR_NONE) return error;
1986 break;
1987 case PBK_Text_State:
1988 UpdatedFields[18] = true;
1989 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 18, entry->Entries[i].Text)) != ERR_NONE) return error;
1990 break;
1991 case PBK_Text_Zip:
1992 UpdatedFields[19] = true;
1993 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 19, entry->Entries[i].Text)) != ERR_NONE) return error;
1994 break;
1995 case PBK_Text_Country:
1996 UpdatedFields[20] = true;
1997 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 20, entry->Entries[i].Text)) != ERR_NONE) return error;
1998 break;
1999 case PBK_Text_Custom1:
2000 UpdatedFields[21] = true;
2001 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 21, entry->Entries[i].Text)) != ERR_NONE) return error;
2002 break;
2003 case PBK_Text_Custom2:
2004 UpdatedFields[22] = true;
2005 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 22, entry->Entries[i].Text)) != ERR_NONE) return error;
2006 break;
2007 case PBK_Text_Custom3:
2008 UpdatedFields[23] = true;
2009 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 23, entry->Entries[i].Text)) != ERR_NONE) return error;
2010 break;
2011 case PBK_Text_Custom4:
2012 UpdatedFields[24] = true;
2013 if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 24, entry->Entries[i].Text)) != ERR_NONE) return error
2014 ; break;
2015 case PBK_PictureID:
2016 if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
2017 UpdatedFields[25] = true;
2018 if ((error = ALCATEL_UpdateField(s, Alcatel_int, entry->Location, 25, &(entry->Entries[i].Number))) != ERR_NONE) return error;
2019 } else {
2020 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
2021 }
2022 break;
2023
2024 case PBK_Text_Name: NamePosition = i; break;
2025 /* Following fields are not supported: */
2026 case PBK_SMSListID:
2027 case PBK_Text_UserID:
2028 case PBK_RingtoneFileSystemID:
2029 case PBK_Date:
2030 case PBK_Caller_Group:
2031 case PBK_RingtoneID:
2032 case PBK_Text_Postal:
2033 case PBK_Text_URL:
2034 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", entry->Entries[i].EntryType);
2035 break;
2036 }
2037 }
2038 if (NamePosition != -1) {
2039 if (NameSet) {
2040 smprintf(s,"WARNING: Ignoring name, not supported by phone\n");
2041 } else {
2042 UpdatedFields[1] = true; if ((error = ALCATEL_UpdateField(s, Alcatel_string, entry->Location, 1, entry->Entries[i].Text)) != ERR_NONE) return error;
2043 }
2044 }
2045 /* If we didn't update some field, we have to delete it... */
2046 for (i=0; i<Priv->CurrentFieldsCount; i++) {
2047 if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, entry->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
2048 }
2049 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2050 entry->Location = Priv->CommitedRecord;
2051 return ERR_NONE;
2052 } else {
2053 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2054 return ATGEN_SetMemory(s, entry);
2055 }
2056}
2057
2058static GSM_Error ALCATEL_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
2059{
2060 GSM_Error error;
2061
2062 if (entry->MemoryType == MEM_ME) {
2063 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2064 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2065 if ((error = ALCATEL_IsIdAvailable(s, entry->Location))!= ERR_NONE) {
2066 /* Entry was empty => no error */
2067 return ERR_NONE;
2068 }
2069 /* Do real delete */
2070 error = ALCATEL_DeleteItem(s, entry->Location);
2071 if (error != ERR_NONE) return error;
2072
2073 /* Refresh list */
2074 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2075 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2076
2077 return ERR_NONE;
2078 } else {
2079 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2080 return ATGEN_DeleteMemory(s, entry);
2081 }
2082}
2083
2084static GSM_Error ALCATEL_DeleteAllMemory(GSM_StateMachine *s, GSM_MemoryType type)
2085{
2086 GSM_Error error;
2087 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2088 int i;
2089
2090 if (type == MEM_ME) {
2091 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2092 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2093
2094 for (i=0; i<Priv->ContactsItemsCount; i++) {
2095 error = ALCATEL_DeleteItem(s, Priv->ContactsItems[i]);
2096 if (error != ERR_NONE) return error;
2097 }
2098
2099 /* Refresh list */
2100 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2101 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2102
2103 return ERR_NONE;
2104 } else {
2105 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2106 return ATGEN_DeleteAllMemory(s, type);
2107 }
2108}
2109
2110static GSM_Error ALCATEL_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
2111{
2112 GSM_Error error;
2113
2114 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2115 return ATGEN_GetSMSC(s, smsc);
2116}
2117
2118
2119static GSM_Error ALCATEL_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
2120{
2121 GSM_Phone_ALCATELData *Priv = &s->Phone.Data.Priv.ALCATEL;
2122 GSM_Error error;
2123
2124 if (Status->MemoryType == MEM_ME) {
2125 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeContacts, 0))!= ERR_NONE) return error;
2126 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2127 Status->MemoryUsed = Priv->ContactsItemsCount;
2128 Status->MemoryFree = ALCATEL_FREE_MEMORY;
2129 return ERR_NONE;
2130 } else {
2131 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2132 return ATGEN_GetMemoryStatus(s, Status);
2133 }
2134}
2135
2136static GSM_Error ALCATEL_GetSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
2137{
2138 GSM_Error error;
2139
2140 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2141 return ATGEN_GetSMS(s, sms);
2142}
2143
2144static GSM_Error ALCATEL_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2145{
2146 GSM_Error error;
2147
2148 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2149 return ATGEN_DeleteSMS(s, sms);
2150}
2151
2152static GSM_Error ALCATEL_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2153{
2154 GSM_Error error;
2155
2156 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2157 return ATGEN_AddSMS(s, sms);
2158}
2159
2160static GSM_Error ALCATEL_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
2161{
2162 GSM_Error error;
2163
2164 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2165 return ATGEN_GetBatteryCharge(s, bat);
2166}
2167
2168static GSM_Error ALCATEL_GetSignalStrength(GSM_StateMachine *s, GSM_SignalQuality *sig)
2169{
2170 GSM_Error error;
2171
2172 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2173 return ATGEN_GetSignalQuality(s, sig);
2174}
2175
2176static GSM_Error ALCATEL_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
2177{
2178 GSM_Error error;
2179
2180 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2181 return ATGEN_GetSMSFolders(s, folders);
2182}
2183
2184static GSM_Error ALCATEL_GetNextSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
2185{
2186 GSM_Error error;
2187
2188 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2189 return ATGEN_GetNextSMS(s, sms, start);
2190}
2191
2192static GSM_Error ALCATEL_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
2193{
2194 GSM_Error error;
2195
2196 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2197 return ATGEN_GetSMSStatus(s, status);
2198}
2199
2200static GSM_Error ALCATEL_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
2201{
2202 GSM_Error error;
2203
2204 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2205 return ATGEN_DialVoice(s, number, ShowNumber);
2206}
2207
2208static GSM_Error ALCATEL_AnswerCall(GSM_StateMachine *s, int ID, bool all)
2209{
2210 GSM_Error error;
2211
2212 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2213 return ATGEN_AnswerCall(s,ID,all);
2214}
2215
2216static GSM_Error ALCATEL_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
2217{
2218 GSM_Error error;
2219
2220 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2221 return ATGEN_GetNetworkInfo(s, netinfo);
2222}
2223
2224static GSM_Error ALCATEL_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
2225{
2226 GSM_Error error;
2227
2228 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2229 return ATGEN_GetDisplayStatus(s, features);
2230}
2231
2232static GSM_Error ALCATEL_SetAutoNetworkLogin(GSM_StateMachine *s)
2233{
2234 GSM_Error error;
2235
2236 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2237 return ATGEN_SetAutoNetworkLogin(s);
2238}
2239
2240static GSM_Error ALCATEL_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
2241{
2242 GSM_Error error;
2243
2244 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2245 return ATGEN_PressKey(s, Key, Press);
2246}
2247
2248static GSM_Error ALCATEL_Reset(GSM_StateMachine *s, bool hard)
2249{
2250 GSM_Error error;
2251
2252 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2253 return ATGEN_Reset(s, hard);
2254}
2255
2256static GSM_Error ALCATEL_CancelCall(GSM_StateMachine *s, int ID, bool all)
2257{
2258 GSM_Error error;
2259
2260 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2261 return ATGEN_CancelCall(s,ID,all);
2262}
2263
2264static GSM_Error ALCATEL_SendSavedSMS(GSM_StateMachine *s, int Folder, int Location)
2265{
2266 GSM_Error error;
2267
2268 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2269 return ATGEN_SendSavedSMS(s, Folder, Location);
2270}
2271
2272static GSM_Error ALCATEL_SendSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2273{
2274 GSM_Error error;
2275
2276 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2277 return ATGEN_SendSMS(s, sms);
2278}
2279
2280static GSM_Error ALCATEL_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
2281{
2282 GSM_Error error;
2283
2284 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2285 return ATGEN_SetDateTime(s, date_time);
2286}
2287
2288static GSM_Error ALCATEL_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
2289{
2290 GSM_Error error;
2291
2292 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2293 return ATGEN_SetSMSC(s, smsc);
2294}
2295
2296static GSM_Error ALCATEL_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
2297{
2298 GSM_Error error;
2299
2300 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2301 return ATGEN_EnterSecurityCode(s, Code);
2302}
2303
2304static GSM_Error ALCATEL_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
2305{
2306 GSM_Error error;
2307
2308 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2309 return ATGEN_GetSecurityStatus(s, Status);
2310}
2311
2312static GSM_Error ALCATEL_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type)
2313{
2314 GSM_Error error;
2315
2316 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2317 return ATGEN_ResetPhoneSettings(s, Type);
2318}
2319
2320static GSM_Error ALCATEL_SendDTMF(GSM_StateMachine *s, char *sequence)
2321{
2322 GSM_Error error;
2323
2324 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2325 return ATGEN_SendDTMF(s, sequence);
2326}
2327
2328static GSM_Error ALCATEL_GetSIMIMSI(GSM_StateMachine *s, char *IMSI)
2329{
2330 GSM_Error error;
2331
2332 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
2333 return ATGEN_GetSIMIMSI(s, IMSI);
2334}
2335
2336static GSM_Error ALCATEL_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *status)
2337{
2338 GSM_Error error;
2339 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2340
2341 status->Used = 0;
2342
2343 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2344 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2345
2346 status->Used = Priv->CalendarItemsCount;
2347 return ERR_NONE;
2348}
2349
2350static GSM_Error ALCATEL_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2351{
2352 GSM_Error error;
2353 GSM_DateTime *dt = NULL;
2354 GSM_DateTime evdate;
2355 bool evdateused = true;
2356 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2357 int i;
2358 int j=0;
2359
2360 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2361 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2362 if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
2363 Note->EntriesNum = 0;
2364 return error;
2365 }
2366 if ((error = ALCATEL_GetFields(s, Note->Location))!= ERR_NONE) return error;
2367
2368 Note->EntriesNum = Priv->CurrentFieldsCount;
2369
2370 for (i=0; i < Priv->CurrentFieldsCount; i++) {
2371 if ((error = ALCATEL_GetFieldValue(s, Note->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
2372 switch (Priv->CurrentFields[i]) {
2373 case 0:
2374 if (Priv->ReturnType != Alcatel_date) {
2375 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2376 Note->EntriesNum--;
2377 j++;
2378 break;
2379 }
2380 if (!CheckDate(&(Priv->ReturnDateTime))) {
2381 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
2382 Note->EntriesNum--;
2383 j++;
2384 break;
2385 }
2386 j++;
2387 Note->EntriesNum--;
2388 evdate = Priv->ReturnDateTime;
2389 evdateused = false;
2390 break;
2391 case 1:
2392 if (Priv->ReturnType != Alcatel_time) {
2393 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2394 Note->EntriesNum--;
2395 j++;
2396 break;
2397 }
2398 if (!CheckTime(&(Priv->ReturnDateTime))) {
2399 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
2400 Note->EntriesNum--;
2401 j++;
2402 break;
2403 }
2404 Note->Entries[i-j].EntryType = CAL_START_DATETIME;
2405 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2406 Note->Entries[i-j].Date.Day = evdate.Day;
2407 Note->Entries[i-j].Date.Month = evdate.Month;
2408 Note->Entries[i-j].Date.Year = evdate.Year;
2409 Note->Entries[i-j].Date.Timezone = evdate.Timezone;
2410 evdateused = true;
2411 break;
2412 case 2:
2413 if (Priv->ReturnType != Alcatel_time) {
2414 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2415 Note->EntriesNum--;
2416 j++;
2417 break;
2418 }
2419 if (!CheckTime(&(Priv->ReturnDateTime))) {
2420 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
2421 Note->EntriesNum--;
2422 j++;
2423 break;
2424 }
2425 Note->Entries[i-j].EntryType = CAL_END_DATETIME;
2426 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2427 Note->Entries[i-j].Date.Day = evdate.Day;
2428 Note->Entries[i-j].Date.Month = evdate.Month;
2429 Note->Entries[i-j].Date.Year = evdate.Year;
2430 Note->Entries[i-j].Date.Timezone = evdate.Timezone;
2431 evdateused = true;
2432 break;
2433 case 3:
2434 if (Priv->ReturnType != Alcatel_date) {
2435 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2436 Note->EntriesNum--;
2437 j++;
2438 break;
2439 }
2440 if (!CheckDate(&(Priv->ReturnDateTime))) {
2441 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
2442 Note->EntriesNum--;
2443 j++;
2444 break;
2445 }
2446 if (dt == NULL) {
2447 Note->Entries[i-j].EntryType = CAL_ALARM_DATETIME;
2448 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2449 dt = &(Note->Entries[i-j].Date);
2450 } else {
2451 j++;
2452 Note->EntriesNum--;
2453 dt->Day = Priv->ReturnDateTime.Day;
2454 dt->Month = Priv->ReturnDateTime.Month;
2455 dt->Year = Priv->ReturnDateTime.Year;
2456 dt->Timezone = Priv->ReturnDateTime.Timezone;
2457 dt = NULL;
2458 }
2459 break;
2460 case 4:
2461 if (Priv->ReturnType != Alcatel_time) {
2462 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2463 Note->EntriesNum--;
2464 j++;
2465 break;
2466 }
2467 if (!CheckTime(&(Priv->ReturnDateTime))) {
2468 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
2469 Note->EntriesNum--;
2470 j++;
2471 break;
2472 }
2473 if (dt == NULL) {
2474 Note->Entries[i-j].EntryType = CAL_ALARM_DATETIME;
2475 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2476 dt = &(Note->Entries[i-j].Date);
2477 } else {
2478 j++;
2479 Note->EntriesNum--;
2480 dt->Hour = Priv->ReturnDateTime.Hour;
2481 dt->Minute = Priv->ReturnDateTime.Minute;
2482 dt->Second = Priv->ReturnDateTime.Second;
2483 dt = NULL;
2484 }
2485 break;
2486 case 5:
2487 if (Priv->ReturnType != Alcatel_string) {
2488 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2489 Note->EntriesNum--;
2490 j++;
2491 break;
2492 }
2493 Note->Entries[i-j].EntryType = CAL_TEXT;
2494 CopyUnicodeString(Note->Entries[i-j].Text, Priv->ReturnString);
2495 break;
2496 case 6:
2497 if (Priv->ReturnType != Alcatel_bool) {
2498 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2499 Note->EntriesNum--;
2500 j++;
2501 break;
2502 }
2503 Note->Entries[i-j].EntryType = CAL_PRIVATE;
2504 Note->Entries[i-j].Number = Priv->ReturnInt;
2505 break;
2506 case 7:
2507 if (Priv->ReturnType != Alcatel_enum) {
2508 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2509 Note->EntriesNum--;
2510 j++;
2511 break;
2512 }
2513 switch (Priv->ReturnInt) {
2514 case 0:
2515 Note->Type = GSM_CAL_MEETING;
2516 break;
2517 case 2:
2518 Note->Type = GSM_CAL_BIRTHDAY;
2519 break;
2520 case 3:
2521 Note->Type = GSM_CAL_CALL;
2522 break;
2523 case 4:
2524 Note->Type = GSM_CAL_ALARM;
2525 break;
2526 case 5:
2527 Note->Type = GSM_CAL_DAILY_ALARM;
2528 break;
2529 case 9:
2530 /* I'd call this repeating event, but it makes no sense creating one more type ... */
2531 Note->Type = GSM_CAL_MEETING;
2532 break;
2533 default:
2534 smprintf(s,"WARNING: Received unknown event type %02X!\n", Priv->ReturnInt);
2535 break;
2536 }
2537 j++;
2538 Note->EntriesNum--;
2539 break;
2540 case 8:
2541 if (Priv->ReturnType != Alcatel_int) {
2542 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2543 Note->EntriesNum--;
2544 j++;
2545 break;
2546 }
2547 /* 0xffffffff indicates that there is phone (BF5), 0 means none (BF5, BE5)*/
2548 if (Priv->ReturnInt == 0xffffffff || Priv->ReturnInt == 0) {
2549 j++;
2550 Note->EntriesNum--;
2551 } else {
2552 Note->Entries[i-j].EntryType = CAL_CONTACTID;
2553 Note->Entries[i-j].Number = Priv->ReturnInt;
2554 }
2555 break;
2556 case 9:
2557 if (Priv->ReturnType != Alcatel_phone) {
2558 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2559 Note->EntriesNum--;
2560 j++;
2561 break;
2562 }
2563 Note->Entries[i-j].EntryType = CAL_PHONE;
2564 CopyUnicodeString(Note->Entries[i-j].Text, Priv->ReturnString);
2565 break;
2566 case 10:
2567 if (Priv->ReturnType != Alcatel_byte) {
2568 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2569 Note->EntriesNum--;
2570 j++;
2571 break;
2572 }
2573 Note->Entries[i-j].EntryType = CAL_REPEAT_DAYOFWEEK;
2574 Note->Entries[i-j].Number = Priv->ReturnInt;
2575 break;
2576 case 11:
2577 if (Priv->ReturnType != Alcatel_byte) {
2578 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2579 Note->EntriesNum--;
2580 j++;
2581 break;
2582 }
2583 Note->Entries[i-j].EntryType = CAL_REPEAT_DAY;
2584 Note->Entries[i-j].Number = Priv->ReturnInt;
2585 break;
2586 case 12:
2587 if (Priv->ReturnType != Alcatel_byte) {
2588 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2589 Note->EntriesNum--;
2590 j++;
2591 break;
2592 }
2593 Note->Entries[i-j].EntryType = CAL_REPEAT_WEEKOFMONTH;
2594 Note->Entries[i-j].Number = Priv->ReturnInt;
2595 break;
2596 case 13:
2597 if (Priv->ReturnType != Alcatel_byte) {
2598 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2599 Note->EntriesNum--;
2600 j++;
2601 break;
2602 }
2603 Note->Entries[i-j].EntryType = CAL_REPEAT_MONTH;
2604 Note->Entries[i-j].Number = Priv->ReturnInt;
2605 break;
2606 case 17:
2607 if (Priv->ReturnType != Alcatel_byte) {
2608 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2609 Note->EntriesNum--;
2610 j++;
2611 break;
2612 }
2613 /* In BF5 birthday has frequency = 1 */
2614 if (Note->Type == GSM_CAL_BIRTHDAY) {
2615 Note->EntriesNum--;
2616 j++;
2617 } else {
2618 Note->Entries[i-j].EntryType = CAL_REPEAT_FREQUENCY;
2619 Note->Entries[i-j].Number = Priv->ReturnInt;
2620 }
2621 break;
2622 case 18:
2623 if (Priv->ReturnType != Alcatel_date) {
2624 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2625 Note->EntriesNum--;
2626 j++;
2627 break;
2628 }
2629 if (!CheckDate(&(Priv->ReturnDateTime))) {
2630 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
2631 Note->EntriesNum--;
2632 j++;
2633 break;
2634 }
2635 Note->Entries[i-j].EntryType = CAL_REPEAT_STARTDATE;
2636 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2637 break;
2638 case 19:
2639 if (Priv->ReturnType != Alcatel_date) {
2640 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2641 Note->EntriesNum--;
2642 j++;
2643 break;
2644 }
2645 if (!CheckDate(&(Priv->ReturnDateTime))) {
2646 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
2647 Note->EntriesNum--;
2648 j++;
2649 break;
2650 }
2651 Note->Entries[i-j].EntryType = CAL_REPEAT_STOPDATE;
2652 Note->Entries[i-j].Date = Priv->ReturnDateTime;
2653 break;
2654 case 20:
2655 if (Priv->ReturnType != Alcatel_date) {
2656 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2657 Note->EntriesNum--;
2658 j++;
2659 break;
2660 }
2661 if (!CheckDate(&(Priv->ReturnDateTime))) {
2662 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
2663 Note->EntriesNum--;
2664 j++;
2665 break;
2666 }
2667 /* This entry had always same value as the 3rd (alarm date) */
2668 j++;
2669 Note->EntriesNum--;
2670 break;
2671 case 21:
2672 if (Priv->ReturnType != Alcatel_time) {
2673 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
2674 Note->EntriesNum--;
2675 j++;
2676 break;
2677 }
2678 if (!CheckTime(&(Priv->ReturnDateTime))) {
2679 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
2680 Note->EntriesNum--;
2681 j++;
2682 break;
2683 }
2684 /* This entry had always same value as the 4th (alarm time) */
2685 j++;
2686 Note->EntriesNum--;
2687 break;
2688 default:
2689 Note->EntriesNum--;
2690 j++;
2691 smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
2692 switch (Priv->ReturnType) {
2693 case Alcatel_date:
2694 smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
2695 break;
2696 case Alcatel_time:
2697 smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
2698 break;
2699 case Alcatel_string:
2700 case Alcatel_phone:
2701 smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
2702 break;
2703 case Alcatel_enum:
2704 case Alcatel_bool:
2705 case Alcatel_int:
2706 case Alcatel_byte:
2707 smprintf(s, "%d", Priv->ReturnInt);
2708 break;
2709 }
2710 smprintf(s,"\n");
2711 }
2712 }
2713 /* The event didn't have start/stop time -> we need only date */
2714 if (!evdateused) {
2715 Note->EntriesNum++;
2716 Note->Entries[i-j].EntryType = CAL_START_DATETIME;
2717 Note->Entries[i-j].Date = evdate;
2718 }
2719 return ERR_NONE;
2720}
2721
2722static GSM_Error ALCATEL_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
2723{
2724 GSM_Error error;
2725 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2726
2727 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2728 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2729 if (Priv->CalendarItemsCount == 0) return ERR_EMPTY;
2730
2731 if (start) Note->Location = 0;
2732 if ((error = ALCATEL_GetNextId(s, &(Note->Location))) != ERR_NONE) return error;
2733
2734 return ALCATEL_GetCalendar(s, Note);
2735}
2736
2737
2738static GSM_Error ALCATEL_DeleteCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2739{
2740 GSM_Error error;
2741
2742 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2743 /* Delete Calendar */
2744 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2745 if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
2746 /* Entry was empty => no error */
2747 return ERR_NONE;
2748 }
2749 error = ALCATEL_DeleteItem(s, Note->Location);
2750 if (error != ERR_NONE) return error;
2751 /* Refresh list */
2752 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2753 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2754 return ERR_NONE;
2755}
2756
2757
2758static GSM_Error ALCATEL_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2759{
2760 GSM_Error error;
2761 unsigned int val;
2762 bool contact_set = false;
2763 bool phone_set = false;
2764 bool date_set = false;
2765 bool repeating = false;
2766 int i;
2767 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2768
2769 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2770 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeCalendar, 0))!= ERR_NONE) return error;
2771
2772 for (i = 0; i < Note->EntriesNum; i++) {
2773 switch (Note->Entries[i].EntryType) {
2774 case CAL_START_DATETIME:
2775 if (!date_set) {
2776 if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2777 date_set = true;
2778 }
2779 if ((error = ALCATEL_CreateField(s, Alcatel_time, 1, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2780 break;
2781 case CAL_END_DATETIME:
2782 if (!date_set) {
2783 if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2784 date_set = true;
2785 }
2786 if ((error = ALCATEL_CreateField(s, Alcatel_time, 2, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2787 break;
2788 case CAL_ALARM_DATETIME:
2789 if ((error = ALCATEL_CreateField(s, Alcatel_date, 3, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2790 if ((error = ALCATEL_CreateField(s, Alcatel_time, 4, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2791 if (Note->Type == GSM_CAL_ALARM || Note->Type == GSM_CAL_DAILY_ALARM) {
2792 if ((error = ALCATEL_CreateField(s, Alcatel_date, 20, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2793 if ((error = ALCATEL_CreateField(s, Alcatel_time, 21, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2794 }
2795 break;
2796 case CAL_TEXT:
2797 if ((error = ALCATEL_CreateField(s, Alcatel_string, 5, Note->Entries[i].Text)) != ERR_NONE) return error;
2798 break;
2799 case CAL_PRIVATE:
2800 if ((error = ALCATEL_CreateField(s, Alcatel_bool, 6, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2801 break;
2802 case CAL_CONTACTID:
2803 if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2804 contact_set = true;
2805 break;
2806 case CAL_PHONE:
2807 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, Note->Entries[i].Text)) != ERR_NONE) return error;
2808 phone_set = true;
2809 break;
2810 case CAL_REPEAT_DAYOFWEEK:
2811 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 10, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2812 repeating = true;
2813 break;
2814 case CAL_REPEAT_DAY:
2815 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 11, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2816 repeating = true;
2817 break;
2818 case CAL_REPEAT_WEEKOFMONTH:
2819 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 12, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2820 repeating = true;
2821 break;
2822 case CAL_REPEAT_MONTH:
2823 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 13, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2824 repeating = true;
2825 break;
2826 case CAL_REPEAT_FREQUENCY:
2827 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 17, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2828 repeating = true;
2829 break;
2830 case CAL_REPEAT_STARTDATE:
2831 if ((error = ALCATEL_CreateField(s, Alcatel_date, 18, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2832 repeating = true;
2833 break;
2834 case CAL_REPEAT_STOPDATE:
2835 if ((error = ALCATEL_CreateField(s, Alcatel_date, 19, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2836 repeating = true;
2837 break;
2838 case CAL_SILENT_ALARM_DATETIME:
2839 case CAL_RECURRANCE:
2840 case CAL_LOCATION:
2841 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", Note->Entries[i].EntryType);
2842 break;
2843 }
2844 }
2845
2846 switch (Note->Type) {
2847 case GSM_CAL_CALL:
2848 val = 3;
2849 break;
2850 case GSM_CAL_BIRTHDAY:
2851 val = 2;
2852 break;
2853 case GSM_CAL_ALARM:
2854 val = 4;
2855 break;
2856 case GSM_CAL_DAILY_ALARM:
2857 val = 5;
2858 break;
2859 default:
2860 if (repeating) {
2861 val = 9;
2862 } else {
2863 val = 0;
2864 }
2865 }
2866 if ((error = ALCATEL_CreateField(s, Alcatel_enum, 7, &val)) != ERR_NONE) return error;
2867
2868 if (!contact_set) {
2869 if (phone_set) {
2870 val = 0xffffffff;
2871 } else {
2872 val = 0;
2873 }
2874 if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &val)) != ERR_NONE) return error;
2875 }
2876 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2877 Note->Location = Priv->CommitedRecord;
2878 /* Refresh list */
2879 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
2880 return ERR_NONE;
2881}
2882
2883static GSM_Error ALCATEL_SetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2884{
2885 GSM_Error error;
2886 unsigned int val;
2887 bool contact_set = false;
2888 bool phone_set = false;
2889 bool date_set = false;
2890 bool repeating = false;
2891 int i;
2892 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
2893 bool UpdatedFields[22];
2894
2895 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
2896 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
2897 if ((error = ALCATEL_IsIdAvailable(s, Note->Location))!= ERR_NONE) {
2898 /* Entry doesn't exist, we will create new one */
2899 return ALCATEL_AddCalendar(s, Note);
2900 }
2901 /* Get fields for current item */
2902 if ((error = ALCATEL_GetFields(s, Note->Location))!= ERR_NONE) return error;
2903
2904 for (i = 0; i < 22; i++) { UpdatedFields[i] = false; }
2905
2906 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeCalendar, Note->Location))!= ERR_NONE) return error;
2907
2908 for (i = 0; i < Note->EntriesNum; i++) {
2909 switch (Note->Entries[i].EntryType) {
2910 case CAL_START_DATETIME:
2911 if (!date_set) {
2912 UpdatedFields[0] = true;
2913 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2914 date_set = true;
2915 }
2916 UpdatedFields[1] = true;
2917 if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 1, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2918 break;
2919 case CAL_END_DATETIME:
2920 if (!date_set) {
2921 UpdatedFields[0] = true;
2922 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 0, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2923 date_set = true;
2924 }
2925 UpdatedFields[2] = true; if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 2, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2926 break;
2927 case CAL_ALARM_DATETIME:
2928 UpdatedFields[3] = true;
2929 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 3, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2930 UpdatedFields[4] = true;
2931 if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 4, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2932 if (Note->Type == GSM_CAL_ALARM || Note->Type == GSM_CAL_DAILY_ALARM) {
2933 UpdatedFields[20] = true;
2934 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 20, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2935 UpdatedFields[21] = true;
2936 if ((error = ALCATEL_UpdateField(s, Alcatel_time, Note->Location, 21, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2937 }
2938 break;
2939 case CAL_TEXT:
2940 UpdatedFields[5] = true;
2941 if ((error = ALCATEL_UpdateField(s, Alcatel_string, Note->Location, 5, Note->Entries[i].Text)) != ERR_NONE) return error;
2942 break;
2943 case CAL_PRIVATE:
2944 UpdatedFields[6] = true;
2945 if ((error = ALCATEL_UpdateField(s, Alcatel_bool, Note->Location, 6, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2946 break;
2947 case CAL_CONTACTID:
2948 UpdatedFields[8] = true;
2949 if ((error = ALCATEL_UpdateField(s, Alcatel_int, Note->Location, 8, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2950 contact_set = true;
2951 break;
2952 case CAL_PHONE:
2953 UpdatedFields[9] = true;
2954 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, Note->Location, 9, Note->Entries[i].Text)) != ERR_NONE) return error;
2955 phone_set = true;
2956 break;
2957 case CAL_REPEAT_DAYOFWEEK:
2958 UpdatedFields[10] = true;
2959 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 10, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2960 repeating = true;
2961 break;
2962 case CAL_REPEAT_DAY:
2963 UpdatedFields[11] = true;
2964 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 11, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2965 repeating = true;
2966 break;
2967 case CAL_REPEAT_WEEKOFMONTH:
2968 UpdatedFields[12] = true;
2969 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 12, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2970 repeating = true;
2971 break;
2972 case CAL_REPEAT_MONTH:
2973 UpdatedFields[13] = true;
2974 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 13, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2975 repeating = true;
2976 break;
2977 case CAL_REPEAT_FREQUENCY:
2978 UpdatedFields[17] = true;
2979 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, Note->Location, 17, &(Note->Entries[i].Number))) != ERR_NONE) return error;
2980 repeating = true;
2981 break;
2982 case CAL_REPEAT_STARTDATE:
2983 UpdatedFields[18] = true;
2984 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 18, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2985 repeating = true;
2986 break;
2987 case CAL_REPEAT_STOPDATE:
2988 UpdatedFields[19] = true;
2989 if ((error = ALCATEL_UpdateField(s, Alcatel_date, Note->Location, 19, &(Note->Entries[i].Date))) != ERR_NONE) return error;
2990 repeating = true;
2991 break;
2992 case CAL_SILENT_ALARM_DATETIME:
2993 case CAL_RECURRANCE:
2994 case CAL_LOCATION:
2995 smprintf(s,"WARNING: Ignoring entry %d, not supported by phone\n", Note->Entries[i].EntryType);
2996 break;
2997 }
2998 }
2999
3000 switch (Note->Type) {
3001 case GSM_CAL_CALL:
3002 val = 3;
3003 break;
3004 case GSM_CAL_BIRTHDAY:
3005 val = 2;
3006 break;
3007 case GSM_CAL_ALARM:
3008 val = 4;
3009 break;
3010 case GSM_CAL_DAILY_ALARM:
3011 val = 5;
3012 break;
3013 default:
3014 if (repeating) {
3015 val = 9;
3016 } else {
3017 val = 0;
3018 }
3019 }
3020 UpdatedFields[7] = true;
3021 if ((error = ALCATEL_UpdateField(s, Alcatel_enum, Note->Location, 7, &val)) != ERR_NONE) return error;
3022
3023 if (!contact_set) {
3024 if (phone_set) {
3025 val = 0xffffffff;
3026 } else {
3027 val = 0;
3028 }
3029 UpdatedFields[8] = true;
3030 if ((error = ALCATEL_UpdateField(s, Alcatel_int, Note->Location, 8, &val)) != ERR_NONE) return error;
3031 }
3032 /* If we didn't update some field, we have to delete it... */
3033 for (i=0; i<Priv->CurrentFieldsCount; i++) {
3034 if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, Note->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
3035 }
3036 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
3037 return ERR_NONE;
3038}
3039
3040static GSM_Error ALCATEL_DeleteAllCalendar (GSM_StateMachine *s)
3041{
3042 GSM_Error error;
3043 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3044 int i;
3045
3046 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
3047 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3048
3049 for (i=0; i<Priv->CalendarItemsCount; i++) {
3050 error = ALCATEL_DeleteItem(s, Priv->CalendarItems[i]);
3051 if (error != ERR_NONE) return error;
3052 }
3053
3054 /* Refresh list */
3055 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
3056 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
3057
3058 return ERR_NONE;
3059}
3060
3061
3062static GSM_Error ALCATEL_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
3063{
3064 GSM_Error error;
3065 GSM_CalendarEntryNote;
3066 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3067 int i;
3068 bool Found = false;
3069 bool DateSet = false;
3070 int alarm_number = alarm->Location;
3071 static GSM_DateTimenulldt = {0,0,0,0,0,0,0};
3072
3073 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
3074 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3075
3076 for (i=0; i<Priv->CalendarItemsCount; i++) {
3077 if ((error = ALCATEL_GetFieldValue(s, Priv->CalendarItems[i], 7))!= ERR_NONE) return error;
3078 if (Priv->ReturnType != Alcatel_enum) {
3079 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3080 continue;
3081 }
3082 if (Priv->ReturnInt == 4 || Priv->ReturnInt == 5) {
3083 alarm_number--;
3084 if (alarm_number == 0) {
3085 Found = true;
3086 break;
3087 }
3088 }
3089 }
3090
3091 if (!Found) return ERR_EMPTY;
3092
3093 Note.Location = Priv->CalendarItems[i];
3094
3095 if ((error = ALCATEL_GetCalendar(s, &Note))!= ERR_NONE) return error;
3096
3097 if (Note.Type == GSM_CAL_ALARM) {
3098 alarm->Repeating = false;
3099 } else {
3100 alarm->Repeating = true;
3101 }
3102
3103 alarm->Text[0] = 0; alarm->Text[1] = 0;
3104
3105
3106 for (i = 0; i < Note.EntriesNum; i++) {
3107 if (Note.Entries[i].EntryType == CAL_TEXT) {
3108 CopyUnicodeString(alarm->Text, Note.Entries[i].Text);
3109 } else if (Note.Entries[i].EntryType == CAL_ALARM_DATETIME) {
3110 alarm->DateTime = Note.Entries[i].Date;
3111 DateSet = false;
3112 }
3113 }
3114 if (!DateSet) {
3115 alarm->DateTime = nulldt;
3116 }
3117
3118 return ERR_NONE;
3119}
3120
3121
3122static GSM_Error ALCATEL_SetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm)
3123{
3124 GSM_Error error;
3125 GSM_CalendarEntryNote;
3126 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3127 GSM_DateTime dt;
3128 int i;
3129 bool Found = false;
3130 int alarm_number = alarm->Location;
3131
3132 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeCalendar, 0))!= ERR_NONE) return error;
3133 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3134
3135 for (i=0; i<Priv->CalendarItemsCount; i++) {
3136 if ((error = ALCATEL_GetFieldValue(s, Priv->CalendarItems[i], 7))!= ERR_NONE) return error;
3137 if (Priv->ReturnType != Alcatel_enum) {
3138 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3139 continue;
3140 }
3141 if (Priv->ReturnInt == 4 || Priv->ReturnInt == 5) {
3142 alarm_number--;
3143 if (alarm_number == 0) {
3144 Found = true;
3145 break;
3146 }
3147 }
3148 }
3149
3150 if (Found) {
3151 Note.Location = Priv->CalendarItems[i];
3152 }
3153
3154 Note.EntriesNum = 1;
3155
3156 Note.Entries[0].EntryType = CAL_ALARM_DATETIME;
3157 Note.Entries[0].Date = alarm->DateTime;
3158
3159 if (alarm->Repeating) {
3160 Note.Type = GSM_CAL_DAILY_ALARM;
3161 GSM_GetCurrentDateTime(&dt);
3162 Note.Entries[0].Date.Day = dt.Day;
3163 Note.Entries[0].Date.Month = dt.Month;
3164 Note.Entries[0].Date.Year = dt.Year;
3165 } else {
3166 Note.Type = GSM_CAL_ALARM;
3167 }
3168
3169 if (alarm->Text[0] != 0 || alarm->Text[1] != 0) {
3170 Note.EntriesNum++;
3171 Note.Entries[1].EntryType = CAL_TEXT;
3172 CopyUnicodeString(Note.Entries[1].Text, alarm->Text);
3173 }
3174
3175 if (Found) {
3176 return ALCATEL_SetCalendar(s, &Note);
3177 } else {
3178 return ALCATEL_AddCalendar(s, &Note);
3179 }
3180}
3181
3182
3183static GSM_Error ALCATEL_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
3184{
3185 GSM_Error error;
3186 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3187
3188 status->Used = 0;
3189
3190 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3191 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
3192
3193 status->Used = Priv->ToDoItemsCount;
3194 return ERR_NONE;
3195}
3196
3197static GSM_Error ALCATEL_GetToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
3198{
3199 GSM_Error error;
3200 GSM_DateTime *dt = NULL;
3201 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3202 int i;
3203 int j=0;
3204
3205 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3206 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3207 if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
3208 ToDo->EntriesNum = 0;
3209 return error;
3210 }
3211 if ((error = ALCATEL_GetFields(s, ToDo->Location))!= ERR_NONE) return error;
3212
3213 ToDo->EntriesNum = Priv->CurrentFieldsCount;
3214
3215 for (i=0; i < Priv->CurrentFieldsCount; i++) {
3216 if ((error = ALCATEL_GetFieldValue(s, ToDo->Location, Priv->CurrentFields[i]))!= ERR_NONE) return error;
3217 switch (Priv->CurrentFields[i]) {
3218 case 0:
3219 if (Priv->ReturnType != Alcatel_date) {
3220 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3221 ToDo->EntriesNum--;
3222 j++;
3223 break;
3224 }
3225 if (!CheckDate(&(Priv->ReturnDateTime))) {
3226 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
3227 ToDo->EntriesNum--;
3228 j++;
3229 break;
3230 }
3231 ToDo->Entries[i-j].EntryType = TODO_END_DATETIME;
3232 ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
3233 break;
3234 case 1:
3235 if (Priv->ReturnType != Alcatel_bool) {
3236 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3237 ToDo->EntriesNum--;
3238 j++;
3239 break;
3240 }
3241 ToDo->Entries[i-j].EntryType = TODO_COMPLETED;
3242 ToDo->Entries[i-j].Number = Priv->ReturnInt;
3243 break;
3244 case 2:
3245 if (Priv->ReturnType != Alcatel_date) {
3246 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3247 ToDo->EntriesNum--;
3248 j++;
3249 break;
3250 }
3251 if (!CheckDate(&(Priv->ReturnDateTime))) {
3252 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
3253 ToDo->EntriesNum--;
3254 j++;
3255 break;
3256 }
3257 if (dt == NULL) {
3258 ToDo->Entries[i-j].EntryType = TODO_ALARM_DATETIME;
3259 ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
3260 dt = &(ToDo->Entries[i-j].Date);
3261 } else {
3262 j++;
3263 ToDo->EntriesNum--;
3264 dt->Day = Priv->ReturnDateTime.Day;
3265 dt->Month = Priv->ReturnDateTime.Month;
3266 dt->Year = Priv->ReturnDateTime.Year;
3267 dt->Timezone = Priv->ReturnDateTime.Timezone;
3268 dt = NULL;
3269 }
3270 break;
3271 case 3:
3272 if (Priv->ReturnType != Alcatel_time) {
3273 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3274 ToDo->EntriesNum--;
3275 j++;
3276 break;
3277 }
3278 if (!CheckTime(&(Priv->ReturnDateTime))) {
3279 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
3280 ToDo->EntriesNum--;
3281 j++;
3282 break;
3283 }
3284 if (dt == NULL) {
3285 ToDo->Entries[i-j].EntryType = TODO_ALARM_DATETIME;
3286 ToDo->Entries[i-j].Date = Priv->ReturnDateTime;
3287 dt = &(ToDo->Entries[i-j].Date);
3288 } else {
3289 j++;
3290 ToDo->EntriesNum--;
3291 dt->Hour = Priv->ReturnDateTime.Hour;
3292 dt->Minute = Priv->ReturnDateTime.Minute;
3293 dt->Second = Priv->ReturnDateTime.Second;
3294 dt = NULL;
3295 }
3296 break;
3297 case 4:
3298 if (Priv->ReturnType != Alcatel_string) {
3299 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3300 ToDo->EntriesNum--;
3301 j++;
3302 break;
3303 }
3304 ToDo->Entries[i-j].EntryType = TODO_TEXT;
3305 CopyUnicodeString(ToDo->Entries[i-j].Text, Priv->ReturnString);
3306 break;
3307 case 5:
3308 if (Priv->ReturnType != Alcatel_bool) {
3309 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3310 ToDo->EntriesNum--;
3311 j++;
3312 break;
3313 }
3314 ToDo->Entries[i-j].EntryType = TODO_PRIVATE;
3315 ToDo->Entries[i-j].Number = Priv->ReturnInt;
3316 break;
3317 case 6:
3318 if (Priv->ReturnType != Alcatel_byte) {
3319 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3320 ToDo->EntriesNum--;
3321 j++;
3322 break;
3323 }
3324 if (Priv->ReturnInt == 255) {
3325 /* 255 means no category */
3326 j++;
3327 ToDo->EntriesNum--;
3328 } else {
3329 ToDo->Entries[i-j].EntryType = TODO_CATEGORY;
3330 ToDo->Entries[i-j].Number = Priv->ReturnInt;
3331 }
3332 break;
3333 case 7:
3334 /* This one seems to be byte for BF5 and enum for BE5 */
3335 if (Priv->ReturnType != Alcatel_enum && Priv->ReturnType != Alcatel_byte) {
3336 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3337 ToDo->EntriesNum--;
3338 j++;
3339 break;
3340 }
3341 switch (Priv->ReturnInt) {
3342 case 0:
3343 ToDo->Priority = GSM_Priority_High;
3344 break;
3345 case 1:
3346 ToDo->Priority = GSM_Priority_Medium;
3347 break;
3348 case 2:
3349 ToDo->Priority = GSM_Priority_Low;
3350 break;
3351 default:
3352 ToDo->Priority = 0;
3353 smprintf(s,"WARNING: Received unexpected priority %02X, ignoring\n", Priv->ReturnInt);
3354 }
3355 j++;
3356 ToDo->EntriesNum--;
3357 break;
3358 case 8:
3359 if (Priv->ReturnType != Alcatel_int) {
3360 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3361 ToDo->EntriesNum--;
3362 j++;
3363 break;
3364 }
3365 /* 0xffffffff indicates that there is phone, 0 means none */
3366 if (Priv->ReturnInt == 0xffffffff || Priv->ReturnInt == 0) {
3367 j++;
3368 ToDo->EntriesNum--;
3369 } else {
3370 ToDo->Entries[i-j].EntryType = TODO_CONTACTID;
3371 ToDo->Entries[i-j].Number = Priv->ReturnInt;
3372 }
3373 break;
3374 case 9:
3375 if (Priv->ReturnType != Alcatel_phone) {
3376 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3377 ToDo->EntriesNum--;
3378 j++;
3379 break;
3380 }
3381 ToDo->Entries[i-j].EntryType = TODO_PHONE;
3382 CopyUnicodeString(ToDo->Entries[i-j].Text, Priv->ReturnString);
3383 break;
3384 case 10:
3385 if (Priv->ReturnType != Alcatel_date) {
3386 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3387 ToDo->EntriesNum--;
3388 j++;
3389 break;
3390 }
3391 if (!CheckDate(&(Priv->ReturnDateTime))) {
3392 smprintf(s,"WARNING: Invalid date in phone, ignoring\n");
3393 ToDo->EntriesNum--;
3394 j++;
3395 break;
3396 }
3397 /* This entry had always same value as the 2nd (alarm date) */
3398 j++;
3399 ToDo->EntriesNum--;
3400 break;
3401 case 11:
3402 if (Priv->ReturnType != Alcatel_time) {
3403 smprintf(s,"WARNING: Received unexpected type %02X, ignoring\n", Priv->ReturnType);
3404 ToDo->EntriesNum--;
3405 j++;
3406 break;
3407 }
3408 if (!CheckTime(&(Priv->ReturnDateTime))) {
3409 smprintf(s,"WARNING: Invalid time in phone, ignoring\n");
3410 ToDo->EntriesNum--;
3411 j++;
3412 break;
3413 }
3414 /* This entry had always same value as the 3rd (alarm time) */
3415 j++;
3416 ToDo->EntriesNum--;
3417 break;
3418 default:
3419 ToDo->EntriesNum--;
3420 j++;
3421 smprintf(s,"WARNING: Received unknown field %02X, ignoring. Type = %02X. Value = ", Priv->CurrentFields[i], Priv->ReturnType);
3422 switch (Priv->ReturnType) {
3423 case Alcatel_date:
3424 smprintf(s, "%d.%d.%d", Priv->ReturnDateTime.Day, Priv->ReturnDateTime.Month, Priv->ReturnDateTime.Year);
3425 break;
3426 case Alcatel_time:
3427 smprintf(s, "%d:%d:%d", Priv->ReturnDateTime.Hour, Priv->ReturnDateTime.Minute, Priv->ReturnDateTime.Second);
3428 break;
3429 case Alcatel_string:
3430 case Alcatel_phone:
3431 smprintf(s, "\"%s\"",DecodeUnicodeString(Priv->ReturnString));
3432 break;
3433 case Alcatel_enum:
3434 case Alcatel_bool:
3435 case Alcatel_int:
3436 case Alcatel_byte:
3437 smprintf(s, "%d", Priv->ReturnInt);
3438 break;
3439 }
3440 smprintf(s,"\n");
3441 }
3442 }
3443 return ERR_NONE;
3444}
3445
3446static GSM_Error ALCATEL_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start)
3447{
3448 GSM_Error error;
3449 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3450
3451 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3452 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3453 if (Priv->ToDoItemsCount == 0) return ERR_EMPTY;
3454
3455 if (start) ToDo->Location = 0;
3456 if ((error = ALCATEL_GetNextId(s, &(ToDo->Location))) != ERR_NONE) return error;
3457
3458 return ALCATEL_GetToDo(s, ToDo);
3459}
3460
3461static GSM_Error ALCATEL_DeleteAllToDo (GSM_StateMachine *s)
3462{
3463 GSM_Error error;
3464 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3465 int i;
3466
3467 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3468 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3469
3470 for (i=0; i<Priv->ToDoItemsCount; i++) {
3471 error = ALCATEL_DeleteItem(s, Priv->ToDoItems[i]);
3472 if (error != ERR_NONE) return error;
3473 }
3474
3475 /* Refresh list */
3476 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3477 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
3478
3479 return ERR_NONE;
3480}
3481
3482static GSM_Error ALCATEL_AddToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
3483{
3484 GSM_Error error;
3485 unsigned int val;
3486 bool contact_set = false;
3487 bool phone_set = false;
3488 int i;
3489 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3490
3491 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3492 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeToDo, 0))!= ERR_NONE) return error;
3493
3494 switch (ToDo->Priority) {
3495 case GSM_Priority_High:
3496 val = 0;
3497 break;
3498 case GSM_Priority_Low:
3499 val = 2;
3500 break;
3501 case GSM_Priority_Medium:
3502 default:
3503 val = 1;
3504 break;
3505 }
3506 /* This one seems to be byte for BF5 and enum for BE5 */
3507 if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
3508 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 7, &val)) != ERR_NONE) return error;
3509 } else {
3510 if ((error = ALCATEL_CreateField(s, Alcatel_enum, 7, &val)) != ERR_NONE) return error;
3511 }
3512
3513 for (i = 0; i < ToDo->EntriesNum; i++) {
3514 switch (ToDo->Entries[i].EntryType) {
3515 case TODO_END_DATETIME:
3516 if ((error = ALCATEL_CreateField(s, Alcatel_date, 0, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3517 break;
3518 case TODO_COMPLETED:
3519 if ((error = ALCATEL_CreateField(s, Alcatel_bool, 1, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3520 break;
3521 case TODO_ALARM_DATETIME:
3522 if ((error = ALCATEL_CreateField(s, Alcatel_date, 2, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3523 if ((error = ALCATEL_CreateField(s, Alcatel_time, 3, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3524 if ((error = ALCATEL_CreateField(s, Alcatel_date, 10, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3525 if ((error = ALCATEL_CreateField(s, Alcatel_time, 11, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3526 break;
3527 case TODO_TEXT:
3528 if ((error = ALCATEL_CreateField(s, Alcatel_string, 4, ToDo->Entries[i].Text)) != ERR_NONE) return error;
3529 break;
3530 case TODO_PRIVATE:
3531 if ((error = ALCATEL_CreateField(s, Alcatel_bool, 5, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3532 break;
3533 case TODO_CATEGORY:
3534 if ((error = ALCATEL_CreateField(s, Alcatel_byte, 6, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3535 break;
3536 case TODO_CONTACTID:
3537 if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3538 contact_set = true;
3539 break;
3540 case TODO_PHONE:
3541 if ((error = ALCATEL_CreateField(s, Alcatel_phone, 9, ToDo->Entries[i].Text)) != ERR_NONE) return error;
3542 phone_set = true;
3543 break;
3544 default:
3545 break;
3546 }
3547 }
3548 if (!contact_set) {
3549 if (phone_set) {
3550 val = 0xffffffff;
3551 } else {
3552 val = 0;
3553 }
3554 if ((error = ALCATEL_CreateField(s, Alcatel_int, 8, &val)) != ERR_NONE) return error;
3555 }
3556 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3557 ToDo->Location = Priv->CommitedRecord;
3558 /* Refresh list */
3559 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
3560 return ERR_NONE;
3561}
3562
3563static GSM_Error ALCATEL_SetToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
3564{
3565 GSM_Error error;
3566 unsigned int val;
3567 bool contact_set = false;
3568 bool phone_set = false;
3569 bool UpdatedFields[12];
3570 int i;
3571 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3572
3573 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3574 /* Save modified ToDo */
3575 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3576 if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
3577 /* Entry doesn't exist, we will create new one */
3578 return ALCATEL_AddToDo(s, ToDo);
3579 }
3580 /* Get fields for current item */
3581 if ((error = ALCATEL_GetFields(s, ToDo->Location))!= ERR_NONE) return error;
3582
3583 for (i = 0; i < 12; i++) { UpdatedFields[i] = false; }
3584
3585 if ((error = ALCATEL_GoToBinaryState(s, StateEdit, TypeToDo, ToDo->Location))!= ERR_NONE) return error;
3586
3587 switch (ToDo->Priority) {
3588 case GSM_Priority_High:
3589 val = 0;
3590 break;
3591 case GSM_Priority_Low:
3592 val = 2;
3593 break;
3594 case GSM_Priority_Medium:
3595 default:
3596 val = 1;
3597 break;
3598 }
3599 /* This one seems to be byte for BF5 and enum for BE5 */
3600 if (s->Phone.Data.Priv.ALCATEL.ProtocolVersion == V_1_1) {
3601 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, ToDo->Location, 7, &val)) != ERR_NONE) return error;
3602 } else {
3603 if ((error = ALCATEL_UpdateField(s, Alcatel_enum, ToDo->Location, 7, &val)) != ERR_NONE) return error;
3604 }
3605 UpdatedFields[7] = true;
3606
3607 for (i = 0; i < ToDo->EntriesNum; i++) {
3608 switch (ToDo->Entries[i].EntryType) {
3609 case TODO_END_DATETIME:
3610 if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 0, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3611 UpdatedFields[0] = true;
3612 break;
3613 case TODO_COMPLETED:
3614 if ((error = ALCATEL_UpdateField(s, Alcatel_bool, ToDo->Location, 1, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3615 UpdatedFields[1] = true;
3616 break;
3617 case TODO_ALARM_DATETIME:
3618 if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 2, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3619 UpdatedFields[2] = true;
3620 if ((error = ALCATEL_UpdateField(s, Alcatel_time, ToDo->Location, 3, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3621 UpdatedFields[3] = true;
3622 if ((error = ALCATEL_UpdateField(s, Alcatel_date, ToDo->Location, 10, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3623 UpdatedFields[10] = true;
3624 if ((error = ALCATEL_UpdateField(s, Alcatel_time, ToDo->Location, 11, &(ToDo->Entries[i].Date))) != ERR_NONE) return error;
3625 UpdatedFields[11] = true;
3626 break;
3627 case TODO_TEXT:
3628 if ((error = ALCATEL_UpdateField(s, Alcatel_string, ToDo->Location, 4, ToDo->Entries[i].Text)) != ERR_NONE) return error;
3629 UpdatedFields[4] = true;
3630 break;
3631 case TODO_PRIVATE:
3632 if ((error = ALCATEL_UpdateField(s, Alcatel_bool, ToDo->Location, 5, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3633 UpdatedFields[5] = true;
3634 break;
3635 case TODO_CATEGORY:
3636 if ((error = ALCATEL_UpdateField(s, Alcatel_byte, ToDo->Location, 6, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3637 UpdatedFields[6] = true;
3638 break;
3639 case TODO_CONTACTID:
3640 if ((error = ALCATEL_UpdateField(s, Alcatel_int, ToDo->Location, 8, &(ToDo->Entries[i].Number))) != ERR_NONE) return error;
3641 UpdatedFields[8] = true;
3642 contact_set = true;
3643 break;
3644 case TODO_PHONE:
3645 if ((error = ALCATEL_UpdateField(s, Alcatel_phone, ToDo->Location, 9, ToDo->Entries[i].Text)) != ERR_NONE) return error;
3646 UpdatedFields[9] = true;
3647 phone_set = true;
3648 break;
3649 default:
3650 break;
3651 }
3652 }
3653 if (!contact_set) {
3654 if (phone_set) {
3655 val = 0xffffffff;
3656 } else {
3657 val = 0;
3658 }
3659 if ((error = ALCATEL_UpdateField(s, Alcatel_int, ToDo->Location, 8, &val)) != ERR_NONE) return error;
3660 UpdatedFields[8] = true;
3661 }
3662
3663
3664 /* If we didn't update some field, we have to delete it... */
3665 for (i=0; i<Priv->CurrentFieldsCount; i++) {
3666 if (!UpdatedFields[Priv->CurrentFields[i]]) if ((error = ALCATEL_DeleteField(s, ToDo->Location, Priv->CurrentFields[i])) != ERR_NONE) return error;
3667 }
3668 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3669 return ERR_NONE;
3670}
3671
3672static GSM_Error ALCATEL_DeleteToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
3673{
3674 GSM_Error error;
3675
3676 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3677 /* Delete ToDo */
3678 if ((error = ALCATEL_GetAvailableIds(s, false))!= ERR_NONE) return error;
3679 if ((error = ALCATEL_IsIdAvailable(s, ToDo->Location))!= ERR_NONE) {
3680 /* Entry was empty => no error */
3681 return ERR_NONE;
3682 }
3683 error = ALCATEL_DeleteItem(s, ToDo->Location);
3684 if (error != ERR_NONE) return error;
3685 /* Refresh list */
3686 if ((error = ALCATEL_GoToBinaryState(s, StateSession, TypeToDo, 0))!= ERR_NONE) return error;
3687 if ((error = ALCATEL_GetAvailableIds(s, true))!= ERR_NONE) return error;
3688 return ERR_NONE;
3689}
3690
3691static GSM_Error ALCATEL_GetCategoryStatus(GSM_StateMachine *s, GSM_CategoryStatus *Status)
3692{
3693 GSM_Alcatel_BinaryTypetype;
3694 GSM_Error error;
3695 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3696
3697 switch (Status->Type) {
3698 case Category_ToDo: type = TypeToDo; break;
3699 case Category_Phonebook: type = TypeContacts; break;
3700 default: return ERR_NOTSUPPORTED;
3701 }
3702 if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
3703 if ((error = ALCATEL_GetAvailableCategoryIds(s))!= ERR_NONE) return error;
3704
3705 Status->Used = Priv->CurrentCategoriesCount;
3706
3707 return ERR_NONE;
3708}
3709
3710static GSM_Error ALCATEL_GetCategory(GSM_StateMachine *s, GSM_Category *Category)
3711{
3712 GSM_Alcatel_BinaryTypetype;
3713 GSM_Error error;
3714 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3715
3716 switch (Category->Type) {
3717 case Category_ToDo: type = TypeToDo; break;
3718 case Category_Phonebook: type = TypeContacts; break;
3719 default: return ERR_NOTSUPPORTED;
3720 }
3721 if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
3722 if ((error = ALCATEL_GetAvailableCategoryIds(s))!= ERR_NONE) return error;
3723 if ((error = ALCATEL_IsCategoryIdAvailable(s, Category->Location))!= ERR_NONE) return error;
3724 if ((error = ALCATEL_GetCategoryText(s, Category->Location))!= ERR_NONE) return error;
3725
3726 CopyUnicodeString(Category->Name, Priv->ReturnString);
3727
3728 return ERR_NONE;
3729}
3730
3731static GSM_Error ALCATEL_AddCategory(GSM_StateMachine *s, GSM_Category *Category)
3732{
3733 GSM_Alcatel_BinaryTypetype;
3734 GSM_Error error;
3735 GSM_Phone_ALCATELData*Priv = &s->Phone.Data.Priv.ALCATEL;
3736
3737 switch (Category->Type) {
3738 case Category_ToDo: type = TypeToDo; break;
3739 case Category_Phonebook: type = TypeContacts; break;
3740 default: return ERR_NOTSUPPORTED;
3741 }
3742 if ((error = ALCATEL_GoToBinaryState(s, StateSession, type, 0))!= ERR_NONE) return error;
3743 if ((error = ALCATEL_AddCategoryText(s, Category->Name))!= ERR_NONE) return error;
3744
3745 Category->Location = Priv->ReturnInt;
3746
3747 return ERR_NONE;
3748}
3749
3750static GSM_Error ALCATEL_GetProductCode(GSM_StateMachine *s, char *value)
3751{
3752 strcpy(value, s->Phone.Data.ModelInfo->model);
3753 return ERR_NONE;
3754}
3755
3756static GSM_Error ALCATEL_DispatchMessage(GSM_StateMachine *s)
3757{
3758 if (s->Phone.Data.Priv.ALCATEL.Mode == ModeBinary) {
3759 return GSM_DispatchMessage(s);
3760 } else {
3761 return ATGEN_DispatchMessage(s);
3762 }
3763}
3764
3765static GSM_Error ALCATEL_ReplyGeneric(GSM_Protocol_Message msg, GSM_StateMachine *s)
3766{
3767 /* All error values are just VERY wild guesses, but these seems to work
3768 * almost as expected ...
3769 */
3770 switch (msg.Buffer[8]) {
3771 case 0x00: /* no error */
3772 return ERR_NONE;
3773 case 0x10: /* same thing opened in phone menus */
3774 return ERR_INSIDEPHONEMENU;
3775 case 0x13:
3776 /* This appears in more cases:
3777 *- phone needs PIN code
3778 *- we want to close not opened session
3779 * For normal users the second case shouldn't occur...
3780 */
3781 return ERR_SECURITYERROR;
3782 case 0x14: /* Bad data */
3783 case 0x2f: /* Closing session when not opened */
3784 case 0x1f: /* Bad in/out counter in packet/ack */
3785 case 0x0e: /* Openning session when not closed */
3786 case 0x0C: /* Bad id (item/database) */
3787 case 0x11: /* Bad list id */
3788 case 0x2A: /* Nonexistant field/item id */
3789 case 0x35: /* Too long text */
3790 return ERR_BUG;
3791 case 0x23: /* Session opened */
3792 case 0x80: /* Transfer started */
3793 return ERR_NONE;
3794 case 0x82: /* Transfer canceled */
3795 return ERR_CANCELED;
3796 default:
3797 smprintf(s, "WARNING: Packet seems to indicate some status by %02X, ignoring!\n", msg.Buffer[8]);
3798 return ERR_NONE;
3799 }
3800}
3801
3802static GSM_Error ALCATEL_ReplyCommit(GSM_Protocol_Message msg, GSM_StateMachine *s)
3803{
3804 s->Phone.Data.Priv.ALCATEL.CommitedRecord = msg.Buffer[12] + (msg.Buffer[11] << 8) + (msg.Buffer[10] << 16) + (msg.Buffer[9] << 24);
3805 smprintf(s, "Created record %08x\n", s->Phone.Data.Priv.ALCATEL.CommitedRecord);
3806 return ERR_NONE;
3807}
3808
3809static GSM_Error ALCATEL_SetIncomingCB (GSM_StateMachine *s, bool enable)
3810{
3811 GSM_Error error;
3812
3813 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
3814 return ATGEN_SetIncomingCB(s, enable);
3815}
3816
3817static GSM_Error ALCATEL_SetIncomingSMS (GSM_StateMachine *s, bool enable)
3818{
3819 GSM_Error error;
3820
3821 if ((error = ALCATEL_SetATMode(s))!= ERR_NONE) return error;
3822 return ATGEN_SetIncomingSMS(s, enable);
3823}
3824
3825static GSM_Reply_Function ALCATELReplyFunctions[] = {
3826 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelAttach },
3827 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDetach },
3828 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelCommit },
3829 {ALCATEL_ReplyCommit, "\x02",0x00,0x00, ID_AlcatelCommit2 },
3830 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelEnd },
3831 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelClose },
3832 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelStart },
3833 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect1 },
3834 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect2 },
3835 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelSelect3 },
3836 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelBegin1 },
3837 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelBegin2 },
3838 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetIds1 },
3839 {ALCATEL_ReplyGetIds, "\x02",0x00,0x00, ID_AlcatelGetIds2 },
3840 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetCategories1},
3841 {ALCATEL_ReplyGetCategories, "\x02",0x00,0x00, ID_AlcatelGetCategories2},
3842 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetCategoryText1},
3843 {ALCATEL_ReplyGetCategoryText, "\x02",0x00,0x00, ID_AlcatelGetCategoryText2},
3844 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelAddCategoryText1},
3845 {ALCATEL_ReplyAddCategoryText, "\x02",0x00,0x00, ID_AlcatelAddCategoryText2},
3846 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetFields1 },
3847 {ALCATEL_ReplyGetFields, "\x02",0x00,0x00, ID_AlcatelGetFields2 },
3848 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelGetFieldValue1},
3849 {ALCATEL_ReplyGetFieldValue, "\x02",0x00,0x00, ID_AlcatelGetFieldValue2},
3850 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDeleteField },
3851 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelDeleteItem1 },
3852 {ALCATEL_ReplyDeleteItem, "\x02",0x00,0x00, ID_AlcatelDeleteItem2 },
3853 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelCreateField },
3854 {ALCATEL_ReplyGeneric, "\x02",0x00,0x00, ID_AlcatelUpdateField },
3855 {NULL, "\x00",0x00,0x00, ID_None }
3856};
3857
3858GSM_Phone_Functions ALCATELPhone = {
3859 /* AFAIK, any 50[0123] phone should work, but I'm not sure whether all
3860 * they were ever really released, if yes add them here also.
3861 */
3862 "alcatel|OT501|OT701|OT715|OT535|OT735|BE5|BF5|BH4",
3863 ALCATELReplyFunctions,
3864 ALCATEL_Initialise,
3865 ALCATEL_Terminate,
3866 ALCATEL_DispatchMessage,
3867 NOTSUPPORTED, /* ShowStartInfo */
3868 ALCATEL_GetManufacturer,
3869 ALCATEL_GetModel,
3870 ALCATEL_GetFirmware,
3871 ALCATEL_GetIMEI,
3872 NOTSUPPORTED, /* GetOriginalIMEI */
3873 NOTSUPPORTED, /* GetManufactureMonth*/
3874 ALCATEL_GetProductCode,
3875 NOTSUPPORTED, /* GetHardware */
3876 NOTSUPPORTED, /* GetPPM */
3877 ALCATEL_GetSIMIMSI,
3878 ALCATEL_GetDateTime,
3879 ALCATEL_SetDateTime,
3880 ALCATEL_GetAlarm,
3881 ALCATEL_SetAlarm,
3882 NOTSUPPORTED, /* GetLocale */
3883 NOTSUPPORTED, /* SetLocale */
3884 ALCATEL_PressKey,
3885 ALCATEL_Reset,
3886 ALCATEL_ResetPhoneSettings,
3887 ALCATEL_EnterSecurityCode,
3888 ALCATEL_GetSecurityStatus,
3889 ALCATEL_GetDisplayStatus,
3890 ALCATEL_SetAutoNetworkLogin,
3891 ALCATEL_GetBatteryCharge,
3892 ALCATEL_GetSignalStrength,
3893 ALCATEL_GetNetworkInfo,
3894 ALCATEL_GetCategory,
3895 ALCATEL_AddCategory,
3896 ALCATEL_GetCategoryStatus,
3897 ALCATEL_GetMemoryStatus,
3898 ALCATEL_GetMemory,
3899 ALCATEL_GetNextMemory,
3900 ALCATEL_SetMemory,
3901 ALCATEL_AddMemory,
3902 ALCATEL_DeleteMemory,
3903 ALCATEL_DeleteAllMemory,
3904 NOTSUPPORTED, /* GetSpeedDial */
3905 NOTSUPPORTED, /* SetSpeedDial */
3906 ALCATEL_GetSMSC,
3907 ALCATEL_SetSMSC,
3908 ALCATEL_GetSMSStatus,
3909 ALCATEL_GetSMS,
3910 ALCATEL_GetNextSMS,
3911 NOTSUPPORTED, /* SetSMS */
3912 ALCATEL_AddSMS,
3913 ALCATEL_DeleteSMS,
3914 ALCATEL_SendSMS,
3915 ALCATEL_SendSavedSMS,
3916 ALCATEL_SetIncomingSMS,
3917 ALCATEL_SetIncomingCB,
3918 ALCATEL_GetSMSFolders,
3919 NOTSUPPORTED, /* AddSMSFolder */
3920 NOTSUPPORTED, /* DeleteSMSFolder */
3921 ALCATEL_DialVoice,
3922 ALCATEL_AnswerCall,
3923 ALCATEL_CancelCall,
3924 NOTSUPPORTED, /* HoldCall */
3925 NOTSUPPORTED, /* UnholdCall */
3926 NOTSUPPORTED, /* ConferenceCall */
3927 NOTSUPPORTED, /* SplitCall */
3928 NOTSUPPORTED, /* TransferCall */
3929 NOTSUPPORTED, /* SwitchCall */
3930 NOTSUPPORTED, /* GetCallDivert */
3931 NOTSUPPORTED, /* SetCallDivert */
3932 NOTSUPPORTED, /* CancelAllDiverts*/
3933 NONEFUNCTION, /* SetIncomingCall */
3934 NOTSUPPORTED, /* SetIncomingUSSD */
3935 ALCATEL_SendDTMF,
3936 NOTSUPPORTED, /* GetRingtone */
3937 NOTSUPPORTED, /* SetRingtone */
3938 NOTSUPPORTED, /* GetRingtonesInfo*/
3939 NOTSUPPORTED, /* DeleteUserRingtones*/
3940 NOTSUPPORTED, /* PlayTone */
3941 NOTSUPPORTED, /* GetWAPBookmark */
3942 NOTSUPPORTED, /* SetWAPBookmark */
3943 NOTSUPPORTED, /* DeleteWAPBookmark*/
3944 NOTSUPPORTED, /* GetWAPSettings */
3945 NOTSUPPORTED, /* SetWAPSettings */
3946 NOTSUPPORTED, /* GetMMSSettings */
3947 NOTSUPPORTED, /* SetMMSSettings */
3948 NOTSUPPORTED, /* GetSyncMLSettings*/
3949 NOTSUPPORTED, /* SetSyncMLSettings*/
3950 NOTSUPPORTED, /* GetChatSettings */
3951 NOTSUPPORTED, /* SetChatSettings */
3952 NOTSUPPORTED, /* GetBitmap */
3953 NOTSUPPORTED, /* SetBitmap */
3954 ALCATEL_GetToDoStatus,
3955 ALCATEL_GetToDo,
3956 ALCATEL_GetNextToDo,
3957 ALCATEL_SetToDo,
3958 ALCATEL_AddToDo,
3959 ALCATEL_DeleteToDo,
3960 ALCATEL_DeleteAllToDo,
3961 ALCATEL_GetCalendarStatus,
3962 ALCATEL_GetCalendar,
3963 ALCATEL_GetNextCalendar,
3964 ALCATEL_SetCalendar,
3965 ALCATEL_AddCalendar,
3966 ALCATEL_DeleteCalendar,
3967 ALCATEL_DeleteAllCalendar,
3968 NOTSUPPORTED, /* GetCalendarSettings*/
3969 NOTSUPPORTED, /* SetCalendarSettings*/
3970 NOTSUPPORTED, /* GetNote */
3971 NOTSUPPORTED, /* GetProfile */
3972 NOTSUPPORTED, /* SetProfile */
3973 NOTSUPPORTED, /* GetFMStation */
3974 NOTSUPPORTED, /* SetFMStation */
3975 NOTSUPPORTED, /* ClearFMStations */
3976 NOTSUPPORTED, /* GetNextFileFolder*/
3977 NOTSUPPORTED, /* GetFilePart */
3978 NOTSUPPORTED, /* AddFilePart */
3979 NOTSUPPORTED, /* GetFileSystemStatus*/
3980 NOTSUPPORTED, /* DeleteFile */
3981 NOTSUPPORTED, /* AddFolder */
3982 NOTSUPPORTED, /* GetGPRSAccessPoint*/
3983 NOTSUPPORTED /* SetGPRSAccessPoint*/
3984};
3985
3986#endif
3987#endif
3988
3989/* How should editor hadle tabs in this file? Add editor commands here.
3990 * vim: noexpandtab sw=8 ts=8 sts=8:
3991 */
diff --git a/gammu/emb/common/phone/alcatel/alcatel.h b/gammu/emb/common/phone/alcatel/alcatel.h
new file mode 100644
index 0000000..718f436
--- a/dev/null
+++ b/gammu/emb/common/phone/alcatel/alcatel.h
@@ -0,0 +1,286 @@
1/* (c) 2002-2004 by Michal Cihar */
2
3/*
4 * High level functions for communication with Alcatel One Touch 501 and
5 * compatible mobile phone.
6 *
7 * This code implements functions to communicate with Alcatel phones,
8 * currently seem to work:
9 * - BE5 series (501/701)
10 * - BF5 series (715)
11 * - BH4 series (535/735)
12 * For some functions it uses normal AT mode (not implemented here, look at
13 * ../at/atgen.[ch]) for others it switches into binary mode and initialises
14 * underlaying protocol (see ../../protocol/alcatel/alcabus.[ch]) and
15 * communicates over it. Don't ask me why Alcatel uses such silly thing...
16 */
17
18#ifndef alcatel_h
19#define alcatel_h
20
21#include "../../gsmcomon.h"
22
23#ifndef GSM_USED_AT
24# define GSM_USED_AT
25#endif
26#ifndef GSM_USED_ALCABUS
27# define GSM_USED_ALCABUS
28#endif
29
30/**
31 * Determines which mode is phone currently using.
32 */
33typedef enum {
34 /**
35 * Phone accepts normal AT commands.
36 */
37 ModeAT = 1,
38 /**
39 * Binary mode using proprietary protocol.
40 */
41 ModeBinary
42} GSM_Alcatel_Mode;
43
44/**
45 * Protocol version being used for binary mode.
46 */
47typedef enum {
48 /**
49 * Version 1.0 used in BE5 phones (501, 701).
50 */
51 V_1_0 = 1,
52 /**
53 * Version 1.1 used in BF5 phones (715, 535, 735).
54 */
55 V_1_1
56} GSM_Alcatel_ProtocolVersion;
57
58/**
59 * State of binary mode.
60 */
61typedef enum {
62 /**
63 * Binary mode is active. No type selected.
64 */
65 StateAttached = 1,
66 /**
67 * Opened session of some type.
68 */
69 StateSession,
70 /**
71 * Some item is being edited.
72 */
73 StateEdit
74} GSM_Alcatel_BinaryState;
75
76/**
77 * Type of active binary session.
78 */
79typedef enum {
80 /**
81 * Calendar events.
82 */
83 TypeCalendar = 1,
84 /**
85 * Contacts.
86 */
87 TypeContacts,
88 /**
89 * To do items.
90 */
91 TypeToDo
92} GSM_Alcatel_BinaryType;
93
94/**
95 * Alcatel internal types.
96 */
97typedef enum {
98 /**
99 * Date, stored as @ref GSM_DateTime.
100 */
101 Alcatel_date,
102 /**
103 * Time, stored as @ref GSM_DateTime.
104 */
105 Alcatel_time,
106 /**
107 * String, strored as chars
108 */
109 Alcatel_string, /* char*/
110 /**
111 * Phone number (can contain anything, but dialling it then may cause
112 * strange problems to phone) strored as chars.
113 */
114 Alcatel_phone,
115 /**
116 * Enumeration, usually used for user defined values (categories),
117 * stored as int.
118 */
119 Alcatel_enum,
120 /**
121 * Boolean, stored as int.
122 */
123 Alcatel_bool,
124 /**
125 * 32-bit unsigned integer, stored as int.
126 */
127 Alcatel_int,
128 /**
129 * 8-bit usigned integer, stored as int.
130 */
131 Alcatel_byte
132} GSM_Alcatel_FieldType;
133
134/**
135 * Return value for GetMemoryStatus. There is no way ho to determine free
136 * memory so we have to return some fixed value.
137 */
138 #define ALCATEL_FREE_MEMORY 100
139/**
140 * Maximum location, that will driver attempt to read. Because phone can have
141 * up to 2^32 locations, we want to limit this a bit.
142 */
143/* There COULD be 0xffffffff on next line, but this is IMHO enough */
144 #define ALCATEL_MAX_LOCATION 0xffff
145/**
146 * Maximum category count. Used for static cache size.
147 */
148 #define ALCATEL_MAX_CATEGORIES 100
149
150/**
151 * Alcatel driver private data.
152 */
153typedef struct {
154 /***********************************/
155 /* Communication state information */
156 /***********************************/
157 /**
158 * Mode of current communication.
159 */
160 GSM_Alcatel_ModeMode;
161 /**
162 * State of current communication if phone is in binary mode.
163 */
164 GSM_Alcatel_BinaryStateBinaryState;
165 /**
166 * Type of current communication if phone is in session or edit state,
167 * zero otherwise.
168 */
169 GSM_Alcatel_BinaryTypeBinaryType;
170 /**
171 * Currently edited item when phone is in edit state, zero otherwise.
172 */
173 int BinaryItem;
174 /**
175 * Protocol version being used.
176 */
177 GSM_Alcatel_ProtocolVersionProtocolVersion;
178
179 /*****************/
180 /* Return values */
181 /*****************/
182 /**
183 * Return value for commited record position.
184 */
185 int CommitedRecord;
186 /**
187 * Used for detecting end of large data data, that don't fit in one
188 * message.
189 */
190 bool TransferCompleted;
191 /**
192 * Type of currently received field.
193 */
194 GSM_Alcatel_FieldTypeReturnType;
195 /**
196 * Value of currently returned field (if it can be saved in DateTime).
197 */
198 GSM_DateTime ReturnDateTime;
199 /**
200 * Value of currently returned field (if it can be saved in int).
201 */
202 unsigned int ReturnInt;
203 /**
204 * Value of currently returned field (if it can be saved in string).
205 */
206 unsigned char ReturnString[(GSM_PHONEBOOK_TEXT_LENGTH+1)*2];
207
208 /***********/
209 /* Caches: */
210 /***********/
211 /* Listings of available items for each type */
212 /**
213 * Pointer to list of active items.
214 */
215 int **CurrentList;
216 /**
217 * Pointer to currently count of active items.
218 */
219 int *CurrentCount;
220 /**
221 * Items locations in calendar.
222 */
223 int *CalendarItems;
224 /**
225 * Items locations in to do list.
226 */
227 int *ToDoItems;
228 /**
229 * Items locations in contacts.
230 */
231 int *ContactsItems;
232 /**
233 * Count of calendar items stored in @ref CalendarItems.
234 */
235 int CalendarItemsCount;
236 /**
237 * Count of todo items stored in @ref ToDoItems.
238 */
239 int ToDoItemsCount;
240 /**
241 * Count of contacts items stored in @ref ContactsItems.
242 */
243 int ContactsItemsCount;
244 /**
245 * Fields of currently active item.
246 */
247 int CurrentFields[GSM_PHONEBOOK_ENTRIES+1];
248 /**
249 * Count of fields listed in @ref CurrentFields.
250 */
251 int CurrentFieldsCount;
252 /**
253 * Location of current (eg. which identifies @ref CurrentFieldsCount
254 * and @ref CurrentFields) item.
255 */
256 int CurrentFieldsItem;
257 /**
258 * Type of current (eg. which identifies @ref CurrentFieldsCount
259 * and @ref CurrentFields) item.
260 */
261 GSM_Alcatel_BinaryTypeCurrentFieldsType;
262
263 /**
264 * Listing of categories of current type.
265 */
266 int CurrentCategories[ALCATEL_MAX_CATEGORIES+1];
267 /**
268 * Cache for category names of current type. The index here is not
269 * same as in @ref CurrentCategories, it is id of category here.
270 */
271 char CurrentCategoriesCache[ALCATEL_MAX_CATEGORIES+1][(GSM_MAX_CATEGORY_NAME_LENGTH + 1)*2];
272 /**
273 * Count of entries in @ref CurrentCategories.
274 */
275 int CurrentCategoriesCount;
276 /**
277 * Type of current categories in @ref CurrentCategories etc.
278 */
279 GSM_Alcatel_BinaryTypeCurrentCategoriesType;
280
281} GSM_Phone_ALCATELData;
282#endif
283
284/* How should editor hadle tabs in this file? Add editor commands here.
285 * vim: noexpandtab sw=8 ts=8 sts=8:
286 */
diff --git a/gammu/emb/common/phone/at/atgen.c b/gammu/emb/common/phone/at/atgen.c
new file mode 100644
index 0000000..1834f15
--- a/dev/null
+++ b/gammu/emb/common/phone/at/atgen.c
@@ -0,0 +1,3669 @@
1/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_ATGEN
6
7#include <string.h>
8#include <time.h>
9#include <ctype.h>
10
11#include "../../gsmcomon.h"
12#include "../../misc/coding/coding.h"
13#include "../../service/sms/gsmsms.h"
14#include "../pfunc.h"
15#include "atgen.h"
16
17#ifdef GSM_ENABLE_ALCATEL
18 extern GSM_Error ALCATEL_ProtocolVersionReply(GSM_Protocol_Message msg, GSM_StateMachine *s);
19#endif
20
21 extern GSM_Error ATGEN_CMS35ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s);
22 extern GSM_Error ATGEN_CMS35ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s);
23 extern GSM_Error ATGEN_CMS35ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s);
24 extern GSM_Error ATGEN_CMS35ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s);
25 extern GSM_Error ATGEN_CMS35ReplyGetNextCal(GSM_Protocol_Message msg, GSM_StateMachine *s);
26 extern GSM_Error ATGEN_CMS35ReplySetCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s);
27 extern GSM_Error ATGEN_CMS35ReplyDeleteCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s);
28 extern GSM_Error ATGEN_SL45ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s);
29
30 extern GSM_Error ATGEN_GetRingtone (GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone);
31 extern GSM_Error ATGEN_SetRingtone (GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength);
32 extern GSM_Error ATGEN_GetBitmap (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
33 extern GSM_Error ATGEN_SetBitmap (GSM_StateMachine *s, GSM_Bitmap *Bitmap);
34 extern GSM_Error SIEMENS_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
35 extern GSM_Error SIEMENS_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note);
36 extern GSM_Error SIEMENS_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note);
37
38 extern GSM_Error SONYERIC_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start);
39 extern GSM_Error SONYERIC_GetNextToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start);
40 extern GSM_Error SONYERIC_GetToDoStatus (GSM_StateMachine *s, GSM_ToDoStatus *status);
41 extern GSM_Error SONYERIC_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note);
42 extern GSM_Error SONYERIC_AddToDo (GSM_StateMachine *s, GSM_ToDoEntry *ToDo);
43 extern GSM_Error SONYERIC_DeleteAllToDo (GSM_StateMachine *s);
44 extern GSM_Error SONYERIC_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note);
45 extern GSM_Error SONYERIC_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status);
46
47typedef struct {
48 int Number;
49 char Text[60];
50} ATErrorCode;
51
52static ATErrorCode CMSErrorCodes[] = {
53 /*
54 * Error codes not specified here were either undefined or reserved in my
55 * copy of specifications, if you have newer one, please fill in the gaps.
56 */
57 /* 0...127 from GSM 04.11 Annex E-2 */
58 {1, "Unassigned (unallocated) number"},
59 {8, "Operator determined barring"},
60 {10, "Call barred"},
61 {21, "Short message transfer rejected"},
62 {27, "Destination out of service"},
63 {28, "Unidentified subscriber"},
64 {29, "Facility rejected"},
65 {30, "Unknown subscriber"},
66 {38, "Network out of order"},
67 {41, "Temporary failure"},
68 {42, "Congestion"},
69 {47, "Resources unavailable, unspecified"},
70 {50, "Requested facility not subscribed"},
71 {69, "Requested facility not implemented"},
72 {81, "Invalid short message transfer reference value"},
73 {95, "Invalid message, unspecified"},
74 {96, "Invalid mandatory information"},
75 {97, "Message type non-existent or not implemented"},
76 {98, "Message not compatible with short message protocol state"},
77 {99, "Information element non-existent or not implemented"},
78 {111, "Protocol error, unspecified"},
79 {127, "Interworking, unspecified"},
80 /* 128...255 from GSM 03.40 subclause 9.2.3.22 */
81 {0x80, "Telematic interworking not supported"},
82 {0x81, "Short message Type 0 not supported"},
83 {0x82, "Cannot replace short message"},
84 {0x8F, "Unspecified TP-PID error"},
85 {0x90, "Data coding scheme (alphabet) not supported"},
86 {0x91, "Message class not supported"},
87 {0x9F, "Unspecified TP-DCS error"},
88 {0xA0, "Command cannot be actioned"},
89 {0xA1, "Command unsupported"},
90 {0xAF, "Unspecified TP-Command error"},
91 {0xB0, "TPDU not supported"},
92 {0xC0, "SC busy"},
93 {0xC1, "No SC subscription"},
94 {0xC2, "SC system failure"},
95 {0xC3, "Invalid SME address"},
96 {0xC4, "Destination SME barred"},
97 {0xC5, "SM Rejected-Duplicate SM"},
98 {0xC6, "TP-VPF not supported"},
99 {0xC7, "TP-VP not supported"},
100 {0xD0, "SIM SMS storage full"},
101 {0xD1, "No SMS storage capability in SIM"},
102 {0xD2, "Error in MS"},
103 {0xD3, "Memory Capacity Exceede"},
104 {0xD4, "SIM Application Toolkit Busy"},
105 {0xFF, "Unspecified error cause"},
106 /* 300...511 from GSM 07.05 subclause 3.2.5 */
107 {300, "ME failure"},
108 {301, "SMS service of ME reserved"},
109 {302, "operation not allowed"},
110 {303, "operation not supported"},
111 {304, "invalid PDU mode parameter"},
112 {305, "invalid text mode parameter"},
113 {310, "SIM not inserted"},
114 {311, "SIM PIN required"},
115 {312, "PH-SIM PIN required"},
116 {313, "SIM failure"},
117 {314, "SIM busy"},
118 {315, "SIM wrong"},
119 {316, "SIM PUK required"},
120 {317, "SIM PIN2 required"},
121 {318, "SIM PUK2 required"},
122 {320, "memory failure"},
123 {321, "invalid memory index"},
124 {322, "memory full"},
125 {330, "SMSC address unknown"},
126 {331, "no network service"},
127 {332, "network timeout"},
128 {340, "no CNMA acknowledgement expected"},
129 {500, "unknown error"},
130 /* > 512 are manufacturer specific according to GSM 07.05 subclause 3.2.5 */
131 {-1, ""}
132};
133
134static ATErrorCode CMEErrorCodes[] = {
135 /* CME Error codes from GSM 07.07 section 9.2 */
136 {0, "phone failure"},
137 {1, "no connection to phone"},
138 {2, "phone-adaptor link reserved"},
139 {3, "operation not allowed"},
140 {4, "operation not supported"},
141 {5, "PH-SIM PIN required"},
142 {10, "SIM not inserted"},
143 {11, "SIM PIN required"},
144 {12, "SIM PUK required"},
145 {13, "SIM failure"},
146 {14, "SIM busy"},
147 {15, "SIM wrong"},
148 {16, "incorrect password"},
149 {17, "SIM PIN2 required"},
150 {18, "SIM PUK2 required"},
151 {20, "memory full"},
152 {21, "invalid index"},
153 {22, "not found"},
154 {23, "memory failure"},
155 {24, "text string too long"},
156 {25, "invalid characters in text string"},
157 {26, "dial string too long"},
158 {27, "invalid characters in dial string"},
159 {30, "no network service"},
160 {31, "network timeout"},
161 {100, "unknown"},
162};
163
164
165GSM_Error ATGEN_HandleCMEError(GSM_StateMachine *s)
166{
167 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
168
169 if (Priv->ErrorCode == 0) {
170 smprintf(s, "CME Error occured, but it's type not detected\n");
171 } else if (Priv->ErrorText == NULL) {
172 smprintf(s, "CME Error %i, no description available\n", Priv->ErrorCode);
173 } else {
174 smprintf(s, "CME Error %i: \"%s\"\n", Priv->ErrorCode, Priv->ErrorText);
175 }
176 /* For error codes descriptions see table a bit above */
177 switch (Priv->ErrorCode) {
178 case 3:
179 return ERR_PERMISSION;
180 case 4:
181 return ERR_NOTSUPPORTED;
182 case 5:
183 case 11:
184 case 12:
185 case 16:
186 case 17:
187 case 18:
188 return ERR_SECURITYERROR;
189 case 20:
190 return ERR_FULL;
191 case 21:
192 return ERR_INVALIDLOCATION;
193 case 22:
194 return ERR_EMPTY;
195 case 23:
196 return ERR_MEMORY;
197 case 24:
198 case 25:
199 case 26:
200 case 27:
201 return ERR_INVALIDDATA;
202 default:
203 return ERR_UNKNOWN;
204 }
205}
206
207GSM_Error ATGEN_HandleCMSError(GSM_StateMachine *s)
208{
209 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
210
211 if (Priv->ErrorCode == 0) {
212 smprintf(s, "CMS Error occured, but it's type not detected\n");
213 } else if (Priv->ErrorText == NULL) {
214 smprintf(s, "CMS Error %i, no description available\n", Priv->ErrorCode);
215 } else {
216 smprintf(s, "CMS Error %i: \"%s\"\n", Priv->ErrorCode, Priv->ErrorText);
217 }
218 /* For error codes descriptions see table a bit above */
219 switch (Priv->ErrorCode) {
220 case 304:
221 return ERR_NOTSUPPORTED;
222 case 305:
223 return ERR_BUG;
224 case 311:
225 case 312:
226 case 316:
227 case 317:
228 case 318:
229 return ERR_SECURITYERROR;
230 case 322:
231 return ERR_FULL;
232 case 321:
233 return ERR_INVALIDLOCATION;
234 default:
235 return ERR_UNKNOWN;
236 }
237}
238
239/* FIXME: Function doesn't respect quoting of parameters and thus +FOO:
240 * "ab","cd,ef" will consider as three arguments: "ab" >> "cd >> ef"
241 */
242int ATGEN_ExtractOneParameter(unsigned char *input, unsigned char *output)
243{
244 int position=0;
245
246 while (*input!=',' && *input!=0x0d && *input!=0x00) {
247 *output=*input;
248 input++;
249 output++;
250 position++;
251 }
252 *output=0;
253 position++;
254 return position;
255}
256
257void ATGEN_DecodeDateTime(GSM_DateTime *dt, unsigned char *input)
258{
259 dt->Year=2000+(*input-'0')*10; input++;
260 dt->Year=dt->Year+(*input-'0'); input++;
261
262 input++;
263 dt->Month=(*input-'0')*10; input++;
264 dt->Month=dt->Month+(*input-'0'); input++;
265
266 input++;
267 dt->Day=(*input-'0')*10; input++;
268 dt->Day=dt->Day+(*input-'0'); input++;
269
270 input++;
271 dt->Hour=(*input-'0')*10; input++;
272 dt->Hour=dt->Hour+(*input-'0'); input++;
273
274 input++;
275 dt->Minute=(*input-'0')*10; input++;
276 dt->Minute=dt->Minute+(*input-'0');input++;
277
278 input++;
279 dt->Second=(*input-'0')*10; input++;
280 dt->Second=dt->Second+(*input-'0');input++;
281
282 if (input!=NULL) {
283 input++;
284 dt->Timezone=(*input-'0')*10; input++;
285 dt->Timezone=dt->Timezone+(*input-'0');input++;
286 input=input-2;
287 if (*input=='-') dt->Timezone=-dt->Timezone;
288 }
289}
290
291GSM_Error ATGEN_DispatchMessage(GSM_StateMachine *s)
292{
293 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
294 GSM_Protocol_Message *msg= s->Phone.Data.RequestMsg;
295 int i= 0, j, k;
296 char *err, *line;
297 ATErrorCode *ErrorCodes = NULL;
298
299 SplitLines(msg->Buffer, msg->Length, &Priv->Lines, "\x0D\x0A", 2, true);
300
301 /* Find number of lines */
302 while (Priv->Lines.numbers[i*2+1] != 0) {
303 /* FIXME: handle special chars correctly */
304 smprintf(s, "%i \"%s\"\n",i+1,GetLineString(msg->Buffer,Priv->Lines,i+1));
305 i++;
306 }
307
308 Priv->ReplyState = AT_Reply_Unknown;
309 Priv->ErrorText = NULL;
310 Priv->ErrorCode = 0;
311
312 line = GetLineString(msg->Buffer,Priv->Lines,i);
313 if (!strcmp(line,"OK")) Priv->ReplyState = AT_Reply_OK;
314 if (!strcmp(line,"> ")) Priv->ReplyState = AT_Reply_SMSEdit;
315 if (!strcmp(line,"CONNECT"))Priv->ReplyState = AT_Reply_Connect;
316 if (!strcmp(line,"ERROR" ))Priv->ReplyState = AT_Reply_Error;
317 if (!strncmp(line,"+CME ERROR:",11)) {
318 Priv->ReplyState = AT_Reply_CMEError;
319 ErrorCodes = CMEErrorCodes;
320 }
321 if (!strncmp(line,"+CMS ERROR:",11)) {
322 Priv->ReplyState = AT_Reply_CMSError;
323 ErrorCodes = CMSErrorCodes;
324 }
325 if (Priv->ReplyState == AT_Reply_CMEError || Priv->ReplyState == AT_Reply_CMSError) {
326 j = 0;
327 /* One char behind +CM[SE] ERROR */
328 err = line + 12;
329 while (err[j] && !isalnum(err[j])) j++;
330 if (isdigit(err[j])) {
331 Priv->ErrorCode = atoi(&(err[j]));
332 k = 0;
333 while (ErrorCodes[k].Number != -1) {
334 if (ErrorCodes[k].Number == Priv->ErrorCode) {
335 Priv->ErrorText = (char *)&(ErrorCodes[k].Text);
336 break;
337 }
338 k++;
339 }
340 } else if (isalpha(err[j])) {
341 k = 0;
342 while (ErrorCodes[k].Number != -1) {
343 if (!strncmp(err + j, ErrorCodes[k].Text, strlen(ErrorCodes[k].Text))) {
344 Priv->ErrorCode = ErrorCodes[k].Number;
345 Priv->ErrorText = (char *)&(ErrorCodes[k].Text);
346 break;
347 }
348 k++;
349 }
350 }
351 }
352 return GSM_DispatchMessage(s);
353}
354
355GSM_Error ATGEN_GenericReply(GSM_Protocol_Message msg, GSM_StateMachine *s)
356{
357 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
358 case AT_Reply_OK:
359 case AT_Reply_Connect:
360 return ERR_NONE;
361 case AT_Reply_Error:
362 return ERR_UNKNOWN;
363 case AT_Reply_CMSError:
364 return ATGEN_HandleCMSError(s);
365 case AT_Reply_CMEError:
366 return ATGEN_HandleCMEError(s);
367 default:
368 break;
369 }
370 return ERR_UNKNOWNRESPONSE;
371}
372
373GSM_Error ATGEN_ReplyGetModel(GSM_Protocol_Message msg, GSM_StateMachine *s)
374{
375 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
376 GSM_Phone_Data *Data = &s->Phone.Data;
377
378 if (s->Phone.Data.Priv.ATGEN.ReplyState != AT_Reply_OK) return ERR_NOTSUPPORTED;
379
380 if (strlen(GetLineString(msg.Buffer, Priv->Lines, 2)) <= MAX_MODEL_LENGTH) {
381 CopyLineString(Data->Model, msg.Buffer, Priv->Lines, 2);
382
383 /* Sometimes phone adds this before manufacturer (Sagem) */
384 if (strncmp("+CGMM: ", Data->Model, 7) == 0) {
385 memmove(Data->Model, Data->Model + 7, strlen(Data->Model + 7) + 1);
386 }
387
388 Data->ModelInfo = GetModelData(NULL,Data->Model,NULL);
389 if (Data->ModelInfo->number[0] == 0) Data->ModelInfo = GetModelData(NULL,NULL,Data->Model);
390 if (Data->ModelInfo->number[0] == 0) Data->ModelInfo = GetModelData(Data->Model,NULL,NULL);
391
392 if (Data->ModelInfo->number[0] != 0) strcpy(Data->Model,Data->ModelInfo->number);
393
394 if (strstr(msg.Buffer,"Nokia")) Priv->Manufacturer = AT_Nokia;
395 else if (strstr(msg.Buffer,"M20")) Priv->Manufacturer = AT_Siemens;
396 else if (strstr(msg.Buffer,"MC35")) Priv->Manufacturer = AT_Siemens;
397 else if (strstr(msg.Buffer, "iPAQ")) Priv->Manufacturer = AT_HP;
398
399 if (strstr(msg.Buffer,"M20")) strcpy(Data->Model,"M20");
400 else if (strstr(msg.Buffer,"MC35")) strcpy(Data->Model,"MC35");
401 else if (strstr(msg.Buffer, "iPAQ")) strcpy(Data->Model,"iPAQ");
402 } else {
403 smprintf(s, "WARNING: Model name too long, increase MAX_MODEL_LENGTH to at least %zd\n", strlen(GetLineString(msg.Buffer, Priv->Lines, 2)));
404 }
405
406 return ERR_NONE;
407}
408
409GSM_Error ATGEN_GetModel(GSM_StateMachine *s)
410{
411 GSM_Error error;
412
413 if (s->Phone.Data.Model[0] != 0) return ERR_NONE;
414
415 smprintf(s, "Getting model\n");
416 error=GSM_WaitFor (s, "AT+CGMM\r", 8, 0x00, 3, ID_GetModel);
417 if (error==ERR_NONE) {
418 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
419 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
420 smprintf(s, "[Connected model - \"%s\"]\n",s->Phone.Data.Model);
421 }
422 }
423 return error;
424}
425
426GSM_Error ATGEN_ReplyGetManufacturer(GSM_Protocol_Message msg, GSM_StateMachine *s)
427{
428 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
429
430 switch (Priv->ReplyState) {
431 case AT_Reply_OK:
432 smprintf(s, "Manufacturer info received\n");
433 Priv->Manufacturer = AT_Unknown;
434 if (strlen(GetLineString(msg.Buffer, Priv->Lines, 2)) <= MAX_MANUFACTURER_LENGTH) {
435 CopyLineString(s->Phone.Data.Manufacturer, msg.Buffer, Priv->Lines, 2);
436 } else {
437 smprintf(s, "WARNING: Manufacturer name too long, increase MAX_MANUFACTURER_LENGTH to at least %zd\n", strlen(GetLineString(msg.Buffer, Priv->Lines, 2)));
438 s->Phone.Data.Manufacturer[0] = 0;
439 }
440 /* Sometimes phone adds this before manufacturer (Sagem) */
441 if (strncmp("+CGMI: ", s->Phone.Data.Manufacturer, 7) == 0) {
442 memmove(s->Phone.Data.Manufacturer, s->Phone.Data.Manufacturer + 7, strlen(s->Phone.Data.Manufacturer + 7) + 1);
443 }
444 if (strstr(msg.Buffer,"Falcom")) {
445 smprintf(s, "Falcom\n");
446 strcpy(s->Phone.Data.Manufacturer,"Falcom");
447 Priv->Manufacturer = AT_Falcom;
448 if (strstr(msg.Buffer,"A2D")) {
449 strcpy(s->Phone.Data.Model,"A2D");
450 s->Phone.Data.ModelInfo = GetModelData(NULL,s->Phone.Data.Model,NULL);
451 smprintf(s, "Model A2D\n");
452 }
453 }
454 if (strstr(msg.Buffer,"Nokia")) {
455 smprintf(s, "Nokia\n");
456 strcpy(s->Phone.Data.Manufacturer,"Nokia");
457 Priv->Manufacturer = AT_Nokia;
458 }
459 if (strstr(msg.Buffer,"SIEMENS")) {
460 smprintf(s, "Siemens\n");
461 strcpy(s->Phone.Data.Manufacturer,"Siemens");
462 Priv->Manufacturer = AT_Siemens;
463 }
464 if (strstr(msg.Buffer,"ERICSSON")) {
465 smprintf(s, "Ericsson\n");
466 strcpy(s->Phone.Data.Manufacturer,"Ericsson");
467 Priv->Manufacturer = AT_Ericsson;
468 }
469 if (strstr(msg.Buffer,"iPAQ")) {
470 smprintf(s, "iPAQ\n");
471 strcpy(s->Phone.Data.Manufacturer,"HP");
472 Priv->Manufacturer = AT_HP;
473 }
474 if (strstr(msg.Buffer,"ALCATEL")) {
475 smprintf(s, "Alcatel\n");
476 strcpy(s->Phone.Data.Manufacturer,"Alcatel");
477 Priv->Manufacturer = AT_Alcatel;
478 }
479 if (strstr(msg.Buffer,"SAGEM")) {
480 smprintf(s, "Sagem\n");
481 strcpy(s->Phone.Data.Manufacturer,"Sagem");
482 Priv->Manufacturer = AT_Sagem;
483 }
484 return ERR_NONE;
485 case AT_Reply_CMSError:
486 return ATGEN_HandleCMSError(s);
487 default:
488 break;
489 }
490 return ERR_UNKNOWNRESPONSE;
491}
492
493GSM_Error ATGEN_GetManufacturer(GSM_StateMachine *s)
494{
495 if (s->Phone.Data.Manufacturer[0] != 0) return ERR_NONE;
496
497 return GSM_WaitFor (s, "AT+CGMI\r", 8, 0x00, 4, ID_GetManufacturer);
498}
499
500GSM_Error ATGEN_ReplyGetFirmwareCGMR(GSM_Protocol_Message msg, GSM_StateMachine *s)
501{
502 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
503 unsigned int i = 0;
504
505 strcpy(s->Phone.Data.Version,"unknown");
506 s->Phone.Data.VerNum = 0;
507 if (Priv->ReplyState == AT_Reply_OK) {
508 CopyLineString(s->Phone.Data.Version, msg.Buffer, Priv->Lines, 2);
509 /* Sometimes phone adds this before manufacturer (Sagem) */
510 if (strncmp("+CGMR: ", s->Phone.Data.Version, 7) == 0) {
511 memmove(s->Phone.Data.Version, s->Phone.Data.Version + 7, strlen(s->Phone.Data.Version + 7) + 1);
512 }
513 }
514 if (Priv->Manufacturer == AT_Ericsson) {
515 while (1) {
516 if (s->Phone.Data.Version[i] == 0x20) {
517 s->Phone.Data.Version[i] = 0x00;
518 break;
519 }
520 if (i == strlen(s->Phone.Data.Version)) break;
521 i++;
522 }
523 }
524 smprintf(s, "Received firmware version: \"%s\"\n",s->Phone.Data.Version);
525 GSM_CreateFirmwareNumber(s);
526 return ERR_NONE;
527}
528
529GSM_Error ATGEN_ReplyGetFirmwareATI(GSM_Protocol_Message msg, GSM_StateMachine *s)
530{
531 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
532
533 switch (Priv->ReplyState) {
534 case AT_Reply_OK:
535 // strcpy(Data->Version,"0.00");
536 // *Data->VersionNum=0;
537 // if (Data->Priv.ATGEN.ReplyState==AT_Reply_OK) {
538 // CopyLineString(Data->Version, msg.Buffer, Priv->Lines, 2);
539 // }
540 // smprintf(s, "Received firmware version: \"%s\"\n",Data->Version);
541 // GSM_CreateFirmwareNumber(Data);
542 // return ERR_NONE;
543 case AT_Reply_Error:
544 return ERR_NOTSUPPORTED;
545 case AT_Reply_CMSError:
546 return ATGEN_HandleCMSError(s);
547 default:
548 break;
549 }
550 return ERR_UNKNOWNRESPONSE;
551}
552
553GSM_Error ATGEN_GetFirmware(GSM_StateMachine *s)
554{
555 GSM_Error error;
556
557 if (s->Phone.Data.Version[0] != 0) return ERR_NONE;
558
559 error=ATGEN_GetManufacturer(s);
560 if (error != ERR_NONE) return error;
561
562 //smprintf(s, "Getting firmware - method 1\n");
563 //error=GSM_WaitFor (s, "ATI\r", 4, 0x00, 3, ID_GetFirmware);
564 //if (error != ERR_NONE) {
565 smprintf(s, "Getting firmware - method 2\n");
566 error=GSM_WaitFor (s, "AT+CGMR\r", 8, 0x00, 3, ID_GetFirmware);
567 //}
568 if (error==ERR_NONE) {
569 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
570 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
571 smprintf(s, "[Firmware version - \"%s\"]\n",s->Phone.Data.Version);
572 }
573 }
574 return error;
575}
576
577GSM_Error ATGEN_Initialise(GSM_StateMachine *s)
578{
579 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
580 GSM_Error error;
581 char buff[2];
582
583 Priv->SMSMode = 0;
584 Priv->Manufacturer = 0;
585 Priv->PhoneSMSMemory = 0;
586 Priv->CanSaveSMS = false;
587 Priv->SIMSMSMemory = 0;
588 Priv->SMSMemory = 0;
589 Priv->PBKMemory = 0;
590 Priv->PBKSBNR = 0;
591 Priv->PBKCharset = 0;
592 Priv->UCS2CharsetFailed = false;
593 Priv->NonUCS2CharsetFailed= false;
594 Priv->PBKMemories[0] = 0;
595 Priv->FirstCalendarPos = 0;
596 Priv->NextMemoryEntry = 0;
597 Priv->FirstMemoryEntry = 0;
598 Priv->file.Used = 0;
599 Priv->file.Buffer = NULL;
600 Priv->OBEX = false;
601 Priv->MemorySize = 0;
602 Priv->TextLength = 0;
603 Priv->NumberLength = 0;
604
605 Priv->ErrorText = NULL;
606
607 if (s->ConnectionType != GCT_IRDAAT && s->ConnectionType != GCT_BLUEAT) {
608 /* We try to escape AT+CMGS mode, at least Siemens M20
609 * then needs to get some rest
610 */
611 smprintf(s, "Escaping SMS mode\n");
612 error = s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
613 if (error!=ERR_NONE) return error;
614
615 /* Grab any possible garbage */
616 while (s->Device.Functions->ReadDevice(s, buff, 2) > 0) my_sleep(10);
617 }
618
619 /* When some phones (Alcatel BE5) is first time connected, it needs extra
620 * time to react, sending just AT wakes up the phone and it then can react
621 * to ATE1. We don't need to check whether this fails as it is just to
622 * wake up the phone and does nothing.
623 */
624 smprintf(s, "Sending simple AT command to wake up some devices\n");
625 GSM_WaitFor (s, "AT\r", 3, 0x00, 2, ID_IncomingFrame);
626
627 smprintf(s, "Enabling echo\n");
628 error = GSM_WaitFor (s, "ATE1\r", 5, 0x00, 3, ID_EnableEcho);
629 if (error != ERR_NONE) return error;
630
631 smprintf(s, "Enabling CME errors\n");
632 /* Try numeric errors */
633 if (GSM_WaitFor (s, "AT+CMEE=1\r", 10, 0x00, 3, ID_EnableErrorInfo) != ERR_NONE) {
634 /* Try textual errors */
635 if (GSM_WaitFor (s, "AT+CMEE=2\r", 10, 0x00, 3, ID_EnableErrorInfo) != ERR_NONE) {
636 smprintf(s, "CME errors could not be enabled, some error types won't be detected.\n");
637 }
638 }
639
640 error = ATGEN_GetModel(s);
641 if (error != ERR_NONE) return error;
642
643 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SLOWWRITE)) {
644 s->Protocol.Data.AT.FastWrite = true;
645 }
646
647 return error;
648}
649
650GSM_Error ATGEN_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
651{
652 unsigned char req[50];
653
654 if (smsc->Location!=1) return ERR_NOTSUPPORTED;
655
656 sprintf(req, "AT+CSCA=\"%s\"\r",DecodeUnicodeString(smsc->Number));
657
658 smprintf(s, "Setting SMSC\n");
659 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetSMSC);
660}
661
662GSM_Error ATGEN_ReplyGetSMSMemories(GSM_Protocol_Message msg, GSM_StateMachine *s)
663{
664 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
665 case AT_Reply_OK:
666 /* Reply here is:
667 * (memories for reading)[, (memories for writing)[, (memories for storing received messages)]]
668 * each memory is in quotes,
669 * Example: ("SM"), ("SM"), ("SM")
670 *
671 * We need to get from this supported memories. For this case
672 * we assume, that just appearence of memory makes it
673 * available for everything. Then we need to find out whether
674 * phone supports writing to memory. This is done by searching
675 * for "), (", which will appear between lists.
676 */
677 s->Phone.Data.Priv.ATGEN.CanSaveSMS = (strstr(msg.Buffer, "), (") != NULL);
678 if (strstr(msg.Buffer, "\"SM\"") != NULL) s->Phone.Data.Priv.ATGEN.SIMSMSMemory = AT_AVAILABLE;
679 else s->Phone.Data.Priv.ATGEN.SIMSMSMemory = AT_NOTAVAILABLE;
680 if (strstr(msg.Buffer, "\"ME\"") != NULL) s->Phone.Data.Priv.ATGEN.PhoneSMSMemory = AT_AVAILABLE;
681 else s->Phone.Data.Priv.ATGEN.PhoneSMSMemory = AT_NOTAVAILABLE;
682 smprintf(s, "Available SMS memories received, ME = %d, SM = %d\n", s->Phone.Data.Priv.ATGEN.PhoneSMSMemory, s->Phone.Data.Priv.ATGEN.SIMSMSMemory);
683 return ERR_NONE;
684 case AT_Reply_Error:
685 case AT_Reply_CMSError:
686 return ATGEN_HandleCMSError(s);
687 default:
688 return ERR_UNKNOWNRESPONSE;
689 }
690}
691
692GSM_Error ATGEN_GetSMSMemories(GSM_StateMachine *s)
693{
694 smprintf(s, "Getting available SMS memories\n");
695 return GSM_WaitFor (s, "AT+CPMS=?\r", 10, 0x00, 4, ID_GetSMSMemories);
696}
697
698GSM_Error ATGEN_SetSMSMemory(GSM_StateMachine *s, bool SIM)
699{
700 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
701 char req[] = "AT+CPMS=\"XX\",\"XX\"\r";
702 int reqlen = 18;
703 GSM_Error error;
704
705 if ((SIM && Priv->SIMSMSMemory == 0) || (!SIM && Priv->PhoneSMSMemory == 0)) {
706 /* We silently ignore error here, because when this fails, we can try to setmemory anyway */
707 ATGEN_GetSMSMemories(s);
708 }
709
710 /* If phone can not save SMS, don't try to set memory for saving */
711 if (!Priv->CanSaveSMS) {
712 req[12] = '\r';
713 reqlen = 13;
714 }
715
716 if (SIM) {
717 if (Priv->SMSMemory == MEM_SM) return ERR_NONE;
718 if (Priv->SIMSMSMemory == AT_NOTAVAILABLE) return ERR_NOTSUPPORTED;
719
720 req[9] = 'S'; req[10] = 'M';
721 req[14] = 'S'; req[15] = 'M';
722
723 smprintf(s, "Setting SMS memory type to SM\n");
724 error=GSM_WaitFor (s, req, reqlen, 0x00, 3, ID_SetMemoryType);
725 if (Priv->SIMSMSMemory == 0 && error == ERR_NONE) {
726 Priv->SIMSMSMemory = AT_AVAILABLE;
727 }
728 if (error == ERR_NOTSUPPORTED) {
729 smprintf(s, "Can't access SIM card?\n");
730 return ERR_SECURITYERROR;
731 }
732 if (error != ERR_NONE) return error;
733 Priv->SMSMemory = MEM_SM;
734 } else {
735 if (Priv->SMSMemory == MEM_ME) return ERR_NONE;
736 if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE) return ERR_NOTSUPPORTED;
737
738 req[9] = 'M'; req[10] = 'E';
739 req[14] = 'M'; req[15] = 'E';
740
741 smprintf(s, "Setting SMS memory type to ME\n");
742 error=GSM_WaitFor (s, req, reqlen, 0x00, 3, ID_SetMemoryType);
743 if (Priv->PhoneSMSMemory == 0 && error == ERR_NONE) {
744 Priv->PhoneSMSMemory = AT_AVAILABLE;
745 }
746 if (error == ERR_NONE) Priv->SMSMemory = MEM_ME;
747 }
748 return error;
749}
750
751GSM_Error ATGEN_GetSMSMode(GSM_StateMachine *s)
752{
753 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
754 GSM_Error error;
755
756 if (Priv->SMSMode != 0) return ERR_NONE;
757
758 smprintf(s, "Trying SMS PDU mode\n");
759 error=GSM_WaitFor (s, "AT+CMGF=0\r", 10, 0x00, 3, ID_GetSMSMode);
760 if (error==ERR_NONE) {
761 Priv->SMSMode = SMS_AT_PDU;
762 return ERR_NONE;
763 }
764
765 smprintf(s, "Trying SMS text mode\n");
766 error=GSM_WaitFor (s, "AT+CMGF=1\r", 10, 0x00, 3, ID_GetSMSMode);
767 if (error==ERR_NONE) {
768 smprintf(s, "Enabling displaying all parameters in text mode\n");
769 error=GSM_WaitFor (s, "AT+CSDH=1\r", 10, 0x00, 3, ID_GetSMSMode);
770 if (error == ERR_NONE) Priv->SMSMode = SMS_AT_TXT;
771 }
772
773 return error;
774}
775
776GSM_Error ATGEN_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
777{
778 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
779 int ifolderid, maxfolder;
780 GSM_Error error;
781
782 if (Priv->PhoneSMSMemory == 0) {
783 error = ATGEN_SetSMSMemory(s, false);
784 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
785 }
786 if (Priv->SIMSMSMemory == 0) {
787 error = ATGEN_SetSMSMemory(s, true);
788 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
789 }
790
791 if (Priv->SIMSMSMemory != AT_AVAILABLE && Priv->PhoneSMSMemory != AT_AVAILABLE) {
792 /* No SMS memory at all */
793 return ERR_NOTSUPPORTED;
794 }
795 if (Priv->SIMSMSMemory == AT_AVAILABLE && Priv->PhoneSMSMemory == AT_AVAILABLE) {
796 /* Both available */
797 maxfolder = 2;
798 } else {
799 /* One available */
800 maxfolder = 1;
801 }
802
803 /* simulate flat SMS memory */
804 if (sms->Folder == 0x00) {
805 ifolderid = sms->Location / PHONE_MAXSMSINFOLDER;
806 if (ifolderid + 1 > maxfolder) return ERR_NOTSUPPORTED;
807 *folderid = ifolderid + 1;
808 *location = sms->Location - ifolderid * PHONE_MAXSMSINFOLDER;
809 } else {
810 if (sms->Folder > 2 * maxfolder) return ERR_NOTSUPPORTED;
811 *folderid = sms->Folder <= 2 ? 1 : 2;
812 *location = sms->Location;
813 }
814 smprintf(s, "SMS folder %i & location %i -> ATGEN folder %i & location %i\n",
815 sms->Folder,sms->Location,*folderid,*location);
816
817 if (Priv->SIMSMSMemory == AT_AVAILABLE && *folderid == 1) {
818 return ATGEN_SetSMSMemory(s, true);
819 } else {
820 return ATGEN_SetSMSMemory(s, false);
821 }
822}
823
824void ATGEN_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
825{
826 sms->Folder= 0;
827 sms->Location= (folderid - 1) * PHONE_MAXSMSINFOLDER + location;
828 smprintf(s, "ATGEN folder %i & location %i -> SMS folder %i & location %i\n",
829 folderid,location,sms->Folder,sms->Location);
830}
831
832GSM_Error ATGEN_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
833{
834 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
835 GSM_SMSMessage *sms= &s->Phone.Data.GetSMSMessage->SMS[0];
836 int current = 0, current2, i;
837 unsigned char buffer[300],smsframe[800];
838 unsigned char firstbyte, TPDCS, TPUDL, TPStatus;
839 GSM_Error error;
840
841 switch (Priv->ReplyState) {
842 case AT_Reply_OK:
843 if (Priv->Lines.numbers[4] == 0x00) return ERR_EMPTY;
844 s->Phone.Data.GetSMSMessage->Number = 1;
845 s->Phone.Data.GetSMSMessage->SMS[0].Name[0] = 0;
846 s->Phone.Data.GetSMSMessage->SMS[0].Name[1]= 0;
847 switch (Priv->SMSMode) {
848 case SMS_AT_PDU:
849 CopyLineString(buffer, msg.Buffer, Priv->Lines, 2);
850 switch (buffer[7]) {
851 case '0': sms->State = SMS_UnRead; break;
852 case '1': sms->State = SMS_Read;break;
853 case '2': sms->State = SMS_UnSent;break;
854 default : sms->State = SMS_Sent;break;//case '3'
855 }
856 DecodeHexBin (buffer, GetLineString(msg.Buffer,Priv->Lines,3), strlen(GetLineString(msg.Buffer,Priv->Lines,3)));
857 /* Siemens MC35 (only ?) */
858 if (strstr(msg.Buffer,"+CMGR: 0,,0")!=NULL) return ERR_EMPTY;
859 /* Siemens M20 */
860 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
861 if (buffer[1]!=NUMBER_UNKNOWN && buffer[1]!=NUMBER_INTERNATIONAL &&
862 buffer[1]!=NUMBER_ALPHANUMERIC) {
863 /* Seems to be Delivery Report */
864 smprintf(s, "SMS type - status report (M20 style)\n");
865 sms->PDU = SMS_Status_Report;
866 sms->Folder = 1;/*INBOX SIM*/
867 sms->InboxFolder = true;
868
869 smsframe[12]=buffer[current++];
870 smsframe[PHONE_SMSStatusReport.TPMR]=buffer[current++];
871 current2=((buffer[current])+1)/2+1;
872 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSStatusReport.Number+i]=buffer[current++];
873 for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.DateTime+i]=buffer[current++];
874 smsframe[0] = 0;
875 for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.SMSCTime+i]=buffer[current++];
876 smsframe[PHONE_SMSStatusReport.TPStatus]=buffer[current];
877 GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSStatusReport);
878 return ERR_NONE;
879 }
880 }
881 /* We use locations from SMS layouts like in ../phone2.c(h) */
882 for(i=0;i<buffer[0]+1;i++) smsframe[i]=buffer[current++];
883 smsframe[12]=buffer[current++];
884 /* See GSM 03.40 section 9.2.3.1 */
885 switch (smsframe[12] & 0x03) {
886 case 0x00:
887 smprintf(s, "SMS type - deliver\n");
888 sms->PDU = SMS_Deliver;
889 if (Priv->SMSMemory == MEM_SM) {
890 sms->Folder = 1; /*INBOX SIM*/
891 } else {
892 sms->Folder = 3; /*INBOX ME*/
893 }
894 sms->InboxFolder = true;
895 current2=((buffer[current])+1)/2+1;
896 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
897 if (buffer[current+1]==NUMBER_ALPHANUMERIC) {
898 smprintf(s, "Trying to read alphanumeric number\n");
899 for(i=0;i<4;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
900 current+=6;
901 for(i=0;i<current2-3;i++) smsframe[PHONE_SMSDeliver.Number+i+4]=buffer[current++];
902 } else {
903 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
904 }
905 } else {
906 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
907 }
908 smsframe[PHONE_SMSDeliver.TPPID] = buffer[current++];
909 smsframe[PHONE_SMSDeliver.TPDCS] = buffer[current++];
910 for(i=0;i<7;i++) smsframe[PHONE_SMSDeliver.DateTime+i]=buffer[current++];
911 smsframe[PHONE_SMSDeliver.TPUDL] = buffer[current++];
912 for(i=0;i<smsframe[PHONE_SMSDeliver.TPUDL];i++) smsframe[i+PHONE_SMSDeliver.Text]=buffer[current++];
913 GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSDeliver);
914 return ERR_NONE;
915 case 0x01:
916 smprintf(s, "SMS type - submit\n");
917 sms->PDU = SMS_Submit;
918 if (Priv->SMSMemory == MEM_SM) {
919 sms->Folder = 2; /*OUTBOX SIM*/
920 smprintf(s, "Outbox SIM\n");
921 } else {
922 sms->Folder = 4; /*OUTBOX ME*/
923 }
924 sms->InboxFolder = false;
925 smsframe[PHONE_SMSSubmit.TPMR] = buffer[current++];
926 current2=((buffer[current])+1)/2+1;
927 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_M20SMS)) {
928 if (buffer[current+1]==NUMBER_ALPHANUMERIC) {
929 smprintf(s, "Trying to read alphanumeric number\n");
930 for(i=0;i<4;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
931 current+=6;
932 for(i=0;i<current2-3;i++) smsframe[PHONE_SMSSubmit.Number+i+4]=buffer[current++];
933 } else {
934 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
935 }
936 } else {
937 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSSubmit.Number+i]=buffer[current++];
938 }
939 smsframe[PHONE_SMSSubmit.TPPID] = buffer[current++];
940 smsframe[PHONE_SMSSubmit.TPDCS] = buffer[current++];
941 /* See GSM 03.40 9.2.3.3 - TPVP can not exist in frame */
942 if ((smsframe[12] & 0x18)!=0) current++; //TPVP is ignored now
943 smsframe[PHONE_SMSSubmit.TPUDL] = buffer[current++];
944 for(i=0;i<smsframe[PHONE_SMSSubmit.TPUDL];i++) smsframe[i+PHONE_SMSSubmit.Text]=buffer[current++];
945 GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSSubmit);
946 return ERR_NONE;
947 case 0x02:
948 smprintf(s, "SMS type - status report\n");
949 sms->PDU = SMS_Status_Report;
950 sms->Folder = 1;/*INBOX SIM*/
951 sms->InboxFolder = true;
952 smprintf(s, "TPMR is %02x\n",buffer[current]);
953 smsframe[PHONE_SMSStatusReport.TPMR] = buffer[current++];
954 current2=((buffer[current])+1)/2+1;
955 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSStatusReport.Number+i]=buffer[current++];
956 for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.DateTime+i]=buffer[current++];
957 for(i=0;i<7;i++) smsframe[PHONE_SMSStatusReport.SMSCTime+i]=buffer[current++];
958 smsframe[PHONE_SMSStatusReport.TPStatus]=buffer[current];
959 GSM_DecodeSMSFrame(sms,smsframe,PHONE_SMSStatusReport);
960 return ERR_NONE;
961 }
962 break;
963 case SMS_AT_TXT:
964 current = 0;
965 while (msg.Buffer[current]!='"') current++;
966 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
967 if (!strcmp(buffer,"\"0\"") || !strcmp(buffer,"\"REC UNREAD\"")) {
968 smprintf(s, "SMS type - deliver\n");
969 sms->State = SMS_UnRead;
970 sms->PDU = SMS_Deliver;
971 if (Priv->SMSMemory == MEM_SM) {
972 sms->Folder = 1; /*INBOX SIM*/
973 } else {
974 sms->Folder = 3; /*INBOX ME*/
975 }
976 sms->InboxFolder = true;
977 } else if (!strcmp(buffer,"\"1\"") || !strcmp(buffer,"\"REC READ\"")) {
978 smprintf(s, "SMS type - deliver\n");
979 sms->State = SMS_Read;
980 sms->PDU = SMS_Deliver;
981 if (Priv->SMSMemory == MEM_SM) {
982 sms->Folder = 1; /*INBOX SIM*/
983 } else {
984 sms->Folder = 3; /*INBOX ME*/
985 }
986 sms->InboxFolder = true;
987 } else if (!strcmp(buffer,"\"2\"") || !strcmp(buffer,"\"STO UNSENT\"")) {
988 smprintf(s, "SMS type - submit\n");
989 sms->State = SMS_UnSent;
990 sms->PDU = SMS_Submit;
991 if (Priv->SMSMemory == MEM_SM) {
992 sms->Folder = 2; /*OUTBOX SIM*/
993 } else {
994 sms->Folder = 4; /*OUTBOX ME*/
995 }
996 sms->InboxFolder = false;
997 } else if (!strcmp(buffer,"\"3\"") || !strcmp(buffer,"\"STO SENT\"")) {
998 smprintf(s, "SMS type - submit\n");
999 sms->State = SMS_Sent;
1000 sms->PDU = SMS_Submit;
1001 if (Priv->SMSMemory == MEM_SM) {
1002 sms->Folder = 2; /*OUTBOX SIM*/
1003 } else {
1004 sms->Folder = 4; /*OUTBOX ME*/
1005 }
1006 sms->InboxFolder = false;
1007 }
1008 current += ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1009 /* It's delivery report according to Nokia AT standards */
1010 if (sms->Folder==1 && buffer[0]!=0 && buffer[0]!='"') {
1011 /* ??? */
1012 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1013 /* format of sender number */
1014 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1015 /* Sender number */
1016 /* FIXME: support for all formats */
1017 EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
1018 smprintf(s, "Sender \"%s\"\n",DecodeUnicodeString(sms->Number));
1019 /* ??? */
1020 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1021 /* Sending datetime */
1022 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1023 i = strlen(buffer);
1024 buffer[i] = ',';
1025 i++;
1026 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
1027 smprintf(s, "\"%s\"\n",buffer);
1028 ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
1029 /* Date of SMSC response */
1030 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1031 i = strlen(buffer);
1032 buffer[i] = ',';
1033 i++;
1034 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
1035 smprintf(s, "\"%s\"\n",buffer);
1036 ATGEN_DecodeDateTime(&sms->SMSCTime, buffer+1);
1037 /* TPStatus */
1038 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1039 TPStatus=atoi(buffer);
1040 buffer[PHONE_SMSStatusReport.TPStatus] = TPStatus;
1041 error=GSM_DecodeSMSFrameStatusReportData(sms, buffer, PHONE_SMSStatusReport);
1042 if (error!=ERR_NONE) return error;
1043 /* NO SMSC number */
1044 sms->SMSC.Number[0]=0;
1045 sms->SMSC.Number[1]=0;
1046 sms->PDU = SMS_Status_Report;
1047 sms->ReplyViaSameSMSC=false;
1048 } else {
1049 /* Sender number */
1050 /* FIXME: support for all formats */
1051 EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
1052 /* Sender number in alphanumeric format ? */
1053 current += ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1054 if (strlen(buffer)!=0) EncodeUnicode(sms->Number,buffer+1,strlen(buffer)-2);
1055 smprintf(s, "Sender \"%s\"\n",DecodeUnicodeString(sms->Number));
1056 /* Sending datetime */
1057 if (sms->Folder==1 || sms->Folder==3) {
1058 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1059 /* FIXME: ATGEN_ExtractOneParameter() is broken as it doesn't respect
1060 * quoting of parameters and thus +FOO: "ab","cd,ef" will consider
1061 * as three arguments: "ab" >> "cd >> ef"
1062 */
1063 if (*buffer=='"') {
1064 i = strlen(buffer);
1065 buffer[i] = ',';
1066 i++;
1067 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer+i);
1068 }
1069 smprintf(s, "\"%s\"\n",buffer);
1070 if (*buffer)
1071 ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
1072 else {
1073 /* FIXME: What is the proper undefined GSM_DateTime ? */
1074 memset(&sms->DateTime, 0, sizeof(sms->DateTime));
1075 }
1076 ATGEN_DecodeDateTime(&sms->DateTime, buffer+1);
1077 }
1078 /* Sender number format */
1079 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1080 /* First byte */
1081 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1082 firstbyte=atoi(buffer);
1083 sms->ReplyViaSameSMSC=false;
1084 /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
1085 if ((firstbyte & 128)==128) sms->ReplyViaSameSMSC=true;
1086 /* TP PID */
1087 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1088 sms->ReplaceMessage = 0;
1089 if (atoi(buffer) > 0x40 && atoi(buffer) < 0x48) {
1090 sms->ReplaceMessage = atoi(buffer) - 0x40;
1091 }
1092 smprintf(s, "TPPID: %02x %i\n",atoi(buffer),atoi(buffer));
1093 /* TP DCS */
1094 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1095 TPDCS=atoi(buffer);
1096 if (sms->Folder==2 || sms->Folder==4) {
1097 /*TP VP */
1098 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1099 }
1100 /* SMSC number */
1101 /* FIXME: support for all formats */
1102 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1103 EncodeUnicode(sms->SMSC.Number,buffer+1,strlen(buffer)-2);
1104 /* Format of SMSC number */
1105 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1106 /* TPUDL */
1107 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1108 TPUDL=atoi(buffer);
1109 current++;
1110 sms->Coding = SMS_Coding_Default;
1111 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
1112 * and GSM 03.38 section 4
1113 */
1114 if ((TPDCS & 0xf4) == 0xf4) sms->Coding=SMS_Coding_8bit;
1115 if ((TPDCS & 0x08) == 0x08) sms->Coding=SMS_Coding_Unicode;
1116 sms->Class = -1;
1117 if ((TPDCS & 0xF3)==0xF0) sms->Class = 0;
1118 if ((TPDCS & 0xF3)==0xF1) sms->Class = 1;
1119 if ((TPDCS & 0xF3)==0xF2) sms->Class = 2;
1120 if ((TPDCS & 0xF3)==0xF3) sms->Class = 3;
1121 smprintf(s, "SMS class: %i\n",sms->Class);
1122 switch (sms->Coding) {
1123 case SMS_Coding_Default:
1124 /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
1125 /* If not SMS with UDH, it's coded normal */
1126 /* If UDH available, treat it as Unicode or 8 bit */
1127 if ((firstbyte & 0x40)!=0x40) {
1128 sms->UDH.Type= UDH_NoUDH;
1129 sms->Length= TPUDL;
1130 EncodeUnicode(sms->Text,msg.Buffer+Priv->Lines.numbers[2*2],TPUDL);
1131 break;
1132 }
1133 case SMS_Coding_Unicode:
1134 case SMS_Coding_8bit:
1135 DecodeHexBin(buffer+PHONE_SMSDeliver.Text, msg.Buffer+current, TPUDL*2);
1136 buffer[PHONE_SMSDeliver.firstbyte] = firstbyte;
1137 buffer[PHONE_SMSDeliver.TPDCS] = TPDCS;
1138 buffer[PHONE_SMSDeliver.TPUDL] = TPUDL;
1139 return GSM_DecodeSMSFrameText(sms, buffer, PHONE_SMSDeliver);
1140 }
1141 }
1142 return ERR_NONE;
1143 default:
1144 break;
1145 }
1146 break;
1147 case AT_Reply_CMSError:
1148 if (Priv->ErrorCode == 320 || Priv->ErrorCode == 500) {
1149 return ERR_EMPTY;
1150 } else {
1151 return ATGEN_HandleCMSError(s);
1152 }
1153 case AT_Reply_CMEError:
1154 return ATGEN_HandleCMEError(s);
1155 case AT_Reply_Error:
1156 /* A2D returns Error with empty location */
1157 return ERR_EMPTY;
1158 default:
1159 break;
1160 }
1161 return ERR_UNKNOWNRESPONSE;
1162}
1163
1164GSM_Error ATGEN_GetSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
1165{
1166 unsigned charreq[20], folderid;
1167 GSM_Errorerror;
1168 int location, getfolder, add = 0;
1169
1170 error=ATGEN_GetSMSLocation(s,&sms->SMS[0], &folderid, &location);
1171 if (error!=ERR_NONE) return error;
1172 if (s->Phone.Data.Priv.ATGEN.SMSMemory == MEM_ME && IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SMSME900)) add = 899;
1173 sprintf(req, "AT+CMGR=%i\r", location + add);
1174
1175 error=ATGEN_GetSMSMode(s);
1176 if (error != ERR_NONE) return error;
1177
1178 error=ATGEN_GetManufacturer(s);
1179 if (error != ERR_NONE) return error;
1180
1181 s->Phone.Data.GetSMSMessage=sms;
1182 smprintf(s, "Getting SMS\n");
1183 error=GSM_WaitFor (s, req, strlen(req), 0x00, 5, ID_GetSMSMessage);
1184 if (error==ERR_NONE) {
1185 getfolder = sms->SMS[0].Folder;
1186 // if (getfolder != 0 && getfolder != sms->SMS[0].Folder) return ERR_EMPTY;
1187 ATGEN_SetSMSLocation(s, &sms->SMS[0], folderid, location);
1188 sms->SMS[0].Folder = getfolder;
1189 sms->SMS[0].Memory = MEM_SM;
1190 if (getfolder > 2) sms->SMS[0].Memory = MEM_ME;
1191 }
1192 return error;
1193}
1194
1195GSM_Error ATGEN_GetNextSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
1196{
1197 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1198 GSM_Error error;
1199 int usedsms;
1200
1201 if (Priv->PhoneSMSMemory == 0) {
1202 error = ATGEN_SetSMSMemory(s, false);
1203 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
1204 }
1205 if (Priv->SIMSMSMemory == 0) {
1206 error = ATGEN_SetSMSMemory(s, true);
1207 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
1208 }
1209 if (Priv->SIMSMSMemory == AT_NOTAVAILABLE && Priv->PhoneSMSMemory == AT_NOTAVAILABLE) return ERR_NOTSUPPORTED;
1210
1211 if (start) {
1212 error=s->Phone.Functions->GetSMSStatus(s,&Priv->LastSMSStatus);
1213 if (error!=ERR_NONE) return error;
1214 Priv->LastSMSRead = 0;
1215 sms->SMS[0].Location = 0;
1216 }
1217 while (true) {
1218 sms->SMS[0].Location++;
1219 if (sms->SMS[0].Location < PHONE_MAXSMSINFOLDER) {
1220 if (Priv->SIMSMSMemory == AT_AVAILABLE) {
1221 usedsms = Priv->LastSMSStatus.SIMUsed;
1222 } else {
1223 usedsms = Priv->LastSMSStatus.PhoneUsed;
1224 }
1225
1226 if (Priv->LastSMSRead >= usedsms) {
1227 if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE || Priv->LastSMSStatus.PhoneUsed==0) return ERR_EMPTY;
1228 Priv->LastSMSRead= 0;
1229 sms->SMS[0].Location = PHONE_MAXSMSINFOLDER + 1;
1230 }
1231 } else {
1232 if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE) return ERR_EMPTY;
1233 if (Priv->LastSMSRead>=Priv->LastSMSStatus.PhoneUsed) return ERR_EMPTY;
1234 }
1235 sms->SMS[0].Folder = 0;
1236 error=s->Phone.Functions->GetSMS(s, sms);
1237 if (error==ERR_NONE) {
1238 Priv->LastSMSRead++;
1239 break;
1240 }
1241 if (error != ERR_EMPTY && error != ERR_INVALIDLOCATION) return error;
1242 }
1243 return error;
1244}
1245
1246GSM_Error ATGEN_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1247{
1248 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1249 GSM_SMSMemoryStatus*SMSStatus = s->Phone.Data.SMSStatus;
1250 char *start;
1251 int current = 0;
1252 unsigned char buffer[50];
1253
1254 switch (Priv->ReplyState) {
1255 case AT_Reply_OK:
1256 smprintf(s, "SMS status received\n");
1257 start = strstr(msg.Buffer, "+CPMS: ") + 7;
1258 if (strstr(msg.Buffer,"ME")!=NULL) {
1259 SMSStatus->PhoneUsed = atoi(start);
1260 current+=ATGEN_ExtractOneParameter(start+current, buffer);
1261 current+=ATGEN_ExtractOneParameter(start+current, buffer);
1262 SMSStatus->PhoneSize= atoi(buffer);
1263 smprintf(s, "Used : %i\n",SMSStatus->PhoneUsed);
1264 smprintf(s, "Size : %i\n",SMSStatus->PhoneSize);
1265 } else {
1266 SMSStatus->SIMUsed = atoi(start);
1267 current+=ATGEN_ExtractOneParameter(start+current, buffer);
1268 current+=ATGEN_ExtractOneParameter(start+current, buffer);
1269 SMSStatus->SIMSize= atoi(buffer);
1270 smprintf(s, "Used : %i\n",SMSStatus->SIMUsed);
1271 smprintf(s, "Size : %i\n",SMSStatus->SIMSize);
1272 if (SMSStatus->SIMSize == 0) {
1273 smprintf(s, "Can't access SIM card\n");
1274 return ERR_SECURITYERROR;
1275 }
1276 }
1277 return ERR_NONE;
1278 case AT_Reply_Error:
1279 if (strstr(msg.Buffer,"SM")!=NULL) {
1280 smprintf(s, "Can't access SIM card\n");
1281 return ERR_SECURITYERROR;
1282 }
1283 return ERR_NOTSUPPORTED;
1284 case AT_Reply_CMSError:
1285 return ATGEN_HandleCMSError(s);
1286 default:
1287 break;
1288 }
1289 return ERR_UNKNOWNRESPONSE;
1290}
1291
1292GSM_Error ATGEN_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
1293{
1294 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1295 GSM_Error error;
1296
1297 /* No templates at all */
1298 status->TemplatesUsed= 0;
1299
1300 status->SIMUsed = 0;
1301 status->SIMUnRead = 0;
1302 status->SIMSize = 0;
1303
1304 s->Phone.Data.SMSStatus=status;
1305
1306 if ((Priv->SIMSMSMemory == 0) || (Priv->PhoneSMSMemory == 0)) {
1307 /* We silently ignore error here, because when this fails, we can try to setmemory anyway */
1308 ATGEN_GetSMSMemories(s);
1309 }
1310
1311 if (Priv->PhoneSMSMemory == 0) {
1312 error = ATGEN_SetSMSMemory(s, false);
1313 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
1314 }
1315 if (Priv->SIMSMSMemory == 0) {
1316 error = ATGEN_SetSMSMemory(s, true);
1317 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
1318 }
1319
1320 if (Priv->SIMSMSMemory == AT_AVAILABLE) {
1321 smprintf(s, "Getting SIM SMS status\n");
1322 if (Priv->CanSaveSMS) {
1323 error=GSM_WaitFor (s, "AT+CPMS=\"SM\",\"SM\"\r", 18, 0x00, 4, ID_GetSMSStatus);
1324 } else {
1325 error=GSM_WaitFor (s, "AT+CPMS=\"SM\"\r", 13, 0x00, 4, ID_GetSMSStatus);
1326 }
1327 if (error!=ERR_NONE) return error;
1328 Priv->SMSMemory = MEM_SM;
1329 }
1330
1331 status->PhoneUsed= 0;
1332 status->PhoneUnRead = 0;
1333 status->PhoneSize= 0;
1334
1335 if (Priv->PhoneSMSMemory == AT_AVAILABLE) {
1336 smprintf(s, "Getting phone SMS status\n");
1337 if (Priv->CanSaveSMS) {
1338 error = GSM_WaitFor (s, "AT+CPMS=\"ME\",\"ME\"\r", 18, 0x00, 4, ID_GetSMSStatus);
1339 } else {
1340 error = GSM_WaitFor (s, "AT+CPMS=\"ME\"\r", 13, 0x00, 4, ID_GetSMSStatus);
1341 }
1342 if (error!=ERR_NONE) return error;
1343 Priv->SMSMemory = MEM_ME;
1344 }
1345
1346 return ERR_NONE;
1347}
1348
1349GSM_Error ATGEN_ReplyGetIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
1350{
1351 CopyLineString(s->Phone.Data.IMEI, msg.Buffer, s->Phone.Data.Priv.ATGEN.Lines, 2);
1352 smprintf(s, "Received IMEI %s\n",s->Phone.Data.IMEI);
1353 return ERR_NONE;
1354}
1355
1356GSM_Error ATGEN_GetIMEI (GSM_StateMachine *s)
1357{
1358 if (s->Phone.Data.IMEI[0] != 0) return ERR_NONE;
1359 smprintf(s, "Getting IMEI\n");
1360 return GSM_WaitFor (s, "AT+CGSN\r", 8, 0x00, 2, ID_GetIMEI);
1361}
1362
1363GSM_Error ATGEN_ReplyAddSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
1364{
1365 char *start;
1366 inti;
1367
1368 if (s->Protocol.Data.AT.EditMode) {
1369 if (s->Phone.Data.Priv.ATGEN.ReplyState != AT_Reply_SMSEdit) {
1370 return ATGEN_HandleCMSError(s);
1371 }
1372 s->Protocol.Data.AT.EditMode = false;
1373 return ERR_NONE;
1374 }
1375
1376 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
1377 case AT_Reply_OK:
1378 smprintf(s, "SMS saved OK\n");
1379 for(i=0;i<msg.Length;i++) {
1380 if (msg.Buffer[i] == 0x00) msg.Buffer[i] = 0x20;
1381 }
1382 start = strstr(msg.Buffer, "+CMGW: ");
1383 if (start == NULL) return ERR_UNKNOWN;
1384 s->Phone.Data.SaveSMSMessage->Location = atoi(start+7);
1385 smprintf(s, "Saved at location %i\n",s->Phone.Data.SaveSMSMessage->Location);
1386 return ERR_NONE;
1387 case AT_Reply_Error:
1388 smprintf(s, "Error\n");
1389 return ERR_NOTSUPPORTED;
1390 case AT_Reply_CMSError:
1391 /* This error occurs in case that phone couldn't save SMS */
1392 return ATGEN_HandleCMSError(s);
1393 default:
1394 break;
1395 }
1396 return ERR_UNKNOWNRESPONSE;
1397}
1398
1399GSM_Error ATGEN_MakeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *message, unsigned char *hexreq, int *current, int *length2)
1400{
1401 GSM_Error error;
1402 int i, length;
1403 unsigned char req[1000], buffer[1000];
1404 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1405 GSM_SMSC SMSC;
1406
1407 error=ATGEN_GetSMSMode(s);
1408 if (error != ERR_NONE) return error;
1409
1410 length = 0;
1411 *current = 0;
1412 switch (Priv->SMSMode) {
1413 case SMS_AT_PDU:
1414 if (message->PDU == SMS_Deliver) {
1415 smprintf(s, "SMS Deliver\n");
1416 error=PHONE_EncodeSMSFrame(s,message,buffer,PHONE_SMSDeliver,&length,true);
1417 if (error != ERR_NONE) return error;
1418 length = length - PHONE_SMSDeliver.Text;
1419 for (i=0;i<buffer[PHONE_SMSDeliver.SMSCNumber]+1;i++) {
1420 req[(*current)++]=buffer[PHONE_SMSDeliver.SMSCNumber+i];
1421 }
1422 req[(*current)++]=buffer[PHONE_SMSDeliver.firstbyte];
1423 for (i=0;i<((buffer[PHONE_SMSDeliver.Number]+1)/2+1)+1;i++) {
1424 req[(*current)++]=buffer[PHONE_SMSDeliver.Number+i];
1425 }
1426 req[(*current)++]=buffer[PHONE_SMSDeliver.TPPID];
1427 req[(*current)++]=buffer[PHONE_SMSDeliver.TPDCS];
1428 for(i=0;i<7;i++) req[(*current)++]=buffer[PHONE_SMSDeliver.DateTime+i];
1429 req[(*current)++]=buffer[PHONE_SMSDeliver.TPUDL];
1430 for(i=0;i<length;i++) req[(*current)++]=buffer[PHONE_SMSDeliver.Text+i];
1431 EncodeHexBin(hexreq, req, *current);
1432 *length2 = *current * 2;
1433 *current = *current - (req[PHONE_SMSDeliver.SMSCNumber]+1);
1434 } else {
1435 smprintf(s, "SMS Submit\n");
1436 error=PHONE_EncodeSMSFrame(s,message,buffer,PHONE_SMSSubmit,&length,true);
1437 if (error != ERR_NONE) return error;
1438 length = length - PHONE_SMSSubmit.Text;
1439 for (i=0;i<buffer[PHONE_SMSSubmit.SMSCNumber]+1;i++) {
1440 req[(*current)++]=buffer[PHONE_SMSSubmit.SMSCNumber+i];
1441 }
1442 req[(*current)++]=buffer[PHONE_SMSSubmit.firstbyte];
1443 req[(*current)++]=buffer[PHONE_SMSSubmit.TPMR];
1444 for (i=0;i<((buffer[PHONE_SMSSubmit.Number]+1)/2+1)+1;i++) {
1445 req[(*current)++]=buffer[PHONE_SMSSubmit.Number+i];
1446 }
1447 req[(*current)++]=buffer[PHONE_SMSSubmit.TPPID];
1448 req[(*current)++]=buffer[PHONE_SMSSubmit.TPDCS];
1449 req[(*current)++]=buffer[PHONE_SMSSubmit.TPVP];
1450 req[(*current)++]=buffer[PHONE_SMSSubmit.TPUDL];
1451 for(i=0;i<length;i++) req[(*current)++]=buffer[PHONE_SMSSubmit.Text+i];
1452 EncodeHexBin(hexreq, req, *current);
1453 *length2 = *current * 2;
1454 *current = *current - (req[PHONE_SMSSubmit.SMSCNumber]+1);
1455 }
1456 break;
1457 case SMS_AT_TXT:
1458 if (Priv->Manufacturer == 0) {
1459 error=ATGEN_GetManufacturer(s);
1460 if (error != ERR_NONE) return error;
1461 }
1462 if (Priv->Manufacturer != AT_Nokia) {
1463 if (message->Coding != SMS_Coding_Default) return ERR_NOTSUPPORTED;
1464 }
1465 error=PHONE_EncodeSMSFrame(s,message,req,PHONE_SMSDeliver,&i,true);
1466 if (error != ERR_NONE) return error;
1467 CopyUnicodeString(SMSC.Number,message->SMSC.Number);
1468 SMSC.Location=1;
1469 error=ATGEN_SetSMSC(s,&SMSC);
1470 if (error!=ERR_NONE) return error;
1471 sprintf(buffer, "AT+CSMP=%i,%i,%i,%i\r",
1472 req[PHONE_SMSDeliver.firstbyte],
1473 req[PHONE_SMSDeliver.TPVP],
1474 req[PHONE_SMSDeliver.TPPID],
1475 req[PHONE_SMSDeliver.TPDCS]);
1476 error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 4, ID_SetSMSParameters);
1477 if (error==ERR_NOTSUPPORTED) {
1478 /* Nokia Communicator 9000i doesn't support <vp> parameter */
1479 sprintf(buffer, "AT+CSMP=%i,,%i,%i\r",
1480 req[PHONE_SMSDeliver.firstbyte],
1481 req[PHONE_SMSDeliver.TPPID],
1482 req[PHONE_SMSDeliver.TPDCS]);
1483 error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 4, ID_SetSMSParameters);
1484 }
1485 if (error!=ERR_NONE) return error;
1486 switch (message->Coding) {
1487 case SMS_Coding_Default:
1488 /* If not SMS with UDH, it's as normal text */
1489 if (message->UDH.Type==UDH_NoUDH) {
1490 strcpy(hexreq,DecodeUnicodeString(message->Text));
1491 *length2 = UnicodeLength(message->Text);
1492 break;
1493 }
1494 case SMS_Coding_Unicode:
1495 case SMS_Coding_8bit:
1496 error=PHONE_EncodeSMSFrame(s,message,buffer,PHONE_SMSDeliver,current,true);
1497 if (error != ERR_NONE) return error;
1498 EncodeHexBin (hexreq, buffer+PHONE_SMSDeliver.Text, buffer[PHONE_SMSDeliver.TPUDL]);
1499 *length2 = buffer[PHONE_SMSDeliver.TPUDL] * 2;
1500 break;
1501 }
1502 break;
1503 }
1504 return ERR_NONE;
1505}
1506
1507GSM_Error ATGEN_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
1508{
1509 GSM_Error error, error2;
1510 int state,Replies,reply, current, current2;
1511 unsigned char buffer[1000], hexreq[1000];
1512 GSM_Phone_Data *Phone = &s->Phone.Data;
1513 unsigned char *statetxt;
1514
1515 /* This phone supports only sent/unsent messages on SIM */
1516 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_SMSONLYSENT)) {
1517 if (sms->Folder != 2) {
1518 smprintf(s, "This phone supports only folder = 2!\n");
1519 return ERR_NOTSUPPORTED;
1520 }
1521 }
1522
1523 sms->PDU = SMS_Submit;
1524 switch (sms->Folder) {
1525 case 1: sms->PDU = SMS_Deliver; /* Inbox SIM */
1526 error=ATGEN_SetSMSMemory(s, true);
1527 break;
1528 case 2: error=ATGEN_SetSMSMemory(s, true);/* Outbox SIM */
1529 break;
1530 case 3: sms->PDU = SMS_Deliver;
1531 error=ATGEN_SetSMSMemory(s, false);/* Inbox phone */
1532 break;
1533 case 4: error=ATGEN_SetSMSMemory(s, false);/* Outbox phone */
1534 break;
1535 default: return ERR_NOTSUPPORTED;
1536 }
1537 if (error!=ERR_NONE) return error;
1538
1539 error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
1540 if (error != ERR_NONE) return error;
1541
1542 switch (Phone->Priv.ATGEN.SMSMode) {
1543 case SMS_AT_PDU:
1544 if (sms->PDU == SMS_Deliver) {
1545 state = 0;
1546 if (sms->State == SMS_Read || sms->State == SMS_Sent) state = 1;
1547 } else {
1548 state = 2;
1549 if (sms->State == SMS_Read || sms->State == SMS_Sent) state = 3;
1550 }
1551 /* Siemens M20 */
1552 if (IsPhoneFeatureAvailable(Phone->ModelInfo, F_M20SMS)) {
1553 /* No (good and 100% working) support for alphanumeric numbers */
1554 if (sms->Number[1]!='+' && (sms->Number[1]<'0' || sms->Number[1]>'9')) {
1555 EncodeUnicode(sms->Number,"123",3);
1556 error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
1557 if (error != ERR_NONE) return error;
1558 }
1559 }
1560 sprintf(buffer, "AT+CMGW=%i,%i\r",current,state);
1561 break;
1562 case SMS_AT_TXT:
1563 if (sms->PDU == SMS_Deliver) {
1564 statetxt = "REC UNREAD";
1565 if (sms->State == SMS_Read || sms->State == SMS_Sent) statetxt = "REC READ";
1566 } else {
1567 statetxt = "STO UNSENT";
1568 if (sms->State == SMS_Read || sms->State == SMS_Sent) statetxt = "STO SENT";
1569 }
1570 /* Siemens M20 */
1571 if (IsPhoneFeatureAvailable(Phone->ModelInfo, F_M20SMS)) {
1572 /* No (good and 100% working) support for alphanumeric numbers */
1573 /* FIXME: Try to autodetect support for <stat> (statetxt) parameter although:
1574 * Siemens M20 supports +CMGW <stat> specification but on my model it just
1575 * reports ERROR (and <stat> is not respected).
1576 * Fortunately it will write "+CMGW: <index>\n" before and the message gets written
1577 */
1578 if (sms->Number[1]!='+' && (sms->Number[1]<'0' || sms->Number[1]>'9')) {
1579 sprintf(buffer, "AT+CMGW=\"123\",,\"%s\"\r",statetxt);
1580 } else {
1581 sprintf(buffer, "AT+CMGW=\"%s\",,\"%s\"\r",DecodeUnicodeString(sms->Number),statetxt);
1582 }
1583 } else {
1584 sprintf(buffer, "AT+CMGW=\"%s\",,\"%s\"\r",DecodeUnicodeString(sms->Number),statetxt);
1585 }
1586 }
1587
1588 Phone->SaveSMSMessage = sms;
1589
1590 for (reply=0;reply<s->ReplyNum;reply++) {
1591 if (reply!=0) {
1592 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
1593 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
1594 smprintf(s, "[Retrying %i]\n", reply+1);
1595 }
1596 }
1597 s->Protocol.Data.AT.EditMode = true;
1598 Replies = s->ReplyNum;
1599 s->ReplyNum = 1;
1600 smprintf(s,"Waiting for modem prompt\n");
1601 error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 3, ID_SaveSMSMessage);
1602 s->ReplyNum = Replies;
1603 if (error == ERR_NONE) {
1604 Phone->DispatchError = ERR_TIMEOUT;
1605 Phone->RequestID = ID_SaveSMSMessage;
1606 smprintf(s, "Saving SMS\n");
1607 error = s->Protocol.Functions->WriteMessage(s, hexreq, current2, 0x00);
1608 if (error!=ERR_NONE) return error;
1609 my_sleep(500);
1610 /* CTRL+Z ends entering */
1611 error = s->Protocol.Functions->WriteMessage(s, "\x1A", 1, 0x00);
1612 if (error!=ERR_NONE) return error;
1613 error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 4);
1614 if (error != ERR_TIMEOUT) return error;
1615 } else {
1616 smprintf(s, "Escaping SMS mode\n");
1617 error2 = s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
1618 if (error2 != ERR_NONE) return error2;
1619 return error;
1620 }
1621 }
1622
1623 return Phone->DispatchError;
1624}
1625
1626GSM_Error ATGEN_ReplySendSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
1627{
1628 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1629 char *start;
1630
1631 if (s->Protocol.Data.AT.EditMode) {
1632 if (s->Phone.Data.Priv.ATGEN.ReplyState != AT_Reply_SMSEdit) {
1633 return ERR_UNKNOWN;
1634 }
1635 s->Protocol.Data.AT.EditMode = false;
1636 return ERR_NONE;
1637 }
1638
1639 switch (Priv->ReplyState) {
1640 case AT_Reply_OK:
1641 smprintf(s, "SMS sent OK\n");
1642 if (s->User.SendSMSStatus!=NULL) {
1643 start = strstr(msg.Buffer, "+CMGW: ");
1644 if (start != NULL) {
1645 s->User.SendSMSStatus(s->CurrentConfig->Device,0,atoi(start+7));
1646 } else {
1647 s->User.SendSMSStatus(s->CurrentConfig->Device,0,0);
1648 }
1649 }
1650 return ERR_NONE;
1651 case AT_Reply_CMSError:
1652 smprintf(s, "Error %i\n",Priv->ErrorCode);
1653 if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,Priv->ErrorCode,0);
1654 return ATGEN_HandleCMSError(s);
1655 case AT_Reply_Error:
1656 return ERR_UNKNOWN;
1657 default:
1658 return ERR_UNKNOWNRESPONSE;
1659 }
1660}
1661
1662GSM_Error ATGEN_SendSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
1663{
1664 GSM_Error error,error2;
1665 int current, current2, Replies;
1666 unsigned char buffer[1000], hexreq[1000];
1667 GSM_Phone_Data *Phone = &s->Phone.Data;
1668
1669 if (sms->PDU == SMS_Deliver) sms->PDU = SMS_Submit;
1670
1671 error = ATGEN_MakeSMSFrame(s, sms, hexreq, &current, &current2);
1672 if (error != ERR_NONE) return error;
1673
1674 switch (Phone->Priv.ATGEN.SMSMode) {
1675 case SMS_AT_PDU:
1676 sprintf(buffer, "AT+CMGS=%i\r",current);
1677 break;
1678 case SMS_AT_TXT:
1679 sprintf(buffer, "AT+CMGS=\"%s\"\r",DecodeUnicodeString(sms->Number));
1680 }
1681
1682 s->Protocol.Data.AT.EditMode = true;
1683 Replies = s->ReplyNum;
1684 s->ReplyNum = 1;
1685 smprintf(s,"Waiting for modem prompt\n");
1686 error=GSM_WaitFor (s, buffer, strlen(buffer), 0x00, 3, ID_IncomingFrame);
1687 s->ReplyNum = Replies;
1688 if (error == ERR_NONE) {
1689 smprintf(s, "Sending SMS\n");
1690 error = s->Protocol.Functions->WriteMessage(s, hexreq, current2, 0x00);
1691 if (error!=ERR_NONE) return error;
1692 my_sleep(500);
1693 /* CTRL+Z ends entering */
1694 error=s->Protocol.Functions->WriteMessage(s, "\x1A", 1, 0x00);
1695 my_sleep(100);
1696 return error;
1697 } else {
1698 smprintf(s, "Escaping SMS mode\n");
1699 error2=s->Protocol.Functions->WriteMessage(s, "\x1B\r", 2, 0x00);
1700 if (error2 != ERR_NONE) return error2;
1701 }
1702 return error;
1703}
1704
1705GSM_Error ATGEN_SendSavedSMS(GSM_StateMachine *s, int Folder, int Location)
1706{
1707 GSM_Error error;
1708 int location;
1709 unsigned charsmsfolder;
1710 unsigned charreq[100];
1711 GSM_MultiSMSMessagemsms;
1712
1713 msms.Number = 0;
1714 msms.SMS[0].Folder = Folder;
1715 msms.SMS[0].Location = Location;
1716
1717 /* By reading SMS we check if it is really inbox/outbox */
1718 error = ATGEN_GetSMS(s, &msms);
1719 if (error != ERR_NONE) return error;
1720
1721 /* Can not send from other folder that outbox */
1722 if (msms.SMS[0].Folder != 2 && msms.SMS[0].Folder != 4) return ERR_NOTSUPPORTED;
1723
1724 error=ATGEN_GetSMSLocation(s, &msms.SMS[0], &smsfolder, &location);
1725 if (error != ERR_NONE) return error;
1726
1727 sprintf(req, "AT+CMSS=%i\r",location);
1728 return s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00);
1729}
1730
1731GSM_Error ATGEN_ReplyGetDateTime_Alarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
1732{
1733 int current= 19;
1734 GSM_Phone_Data *Data = &s->Phone.Data;
1735
1736 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
1737 case AT_Reply_OK:
1738 if (msg.Buffer[current]==0x0d || msg.Buffer[current-1]==0x0d) {
1739 smprintf(s, "Not set in phone\n");
1740 return ERR_EMPTY;
1741 } else {
1742 if (Data->RequestID == ID_GetDateTime) {
1743 ATGEN_DecodeDateTime(Data->DateTime, msg.Buffer+current);
1744 } else {
1745 ATGEN_DecodeDateTime(&(Data->Alarm->DateTime), msg.Buffer+current);
1746 }
1747 return ERR_NONE;
1748 }
1749 case AT_Reply_Error:
1750 return ERR_NOTSUPPORTED;
1751 case AT_Reply_CMSError:
1752 return ATGEN_HandleCMSError(s);
1753 default:
1754 break;
1755 }
1756 return ERR_UNKNOWNRESPONSE;
1757}
1758
1759GSM_Error ATGEN_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
1760{
1761 s->Phone.Data.DateTime=date_time;
1762 smprintf(s, "Getting date & time\n");
1763 return GSM_WaitFor (s, "AT+CCLK?\r", 9, 0x00, 4, ID_GetDateTime);
1764}
1765
1766GSM_Error ATGEN_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
1767{
1768 char req[128];
1769
1770 sprintf(req, "AT+CCLK=\"%02i/%02i/%02i,%02i:%02i:%02i+00\"\r",
1771 date_time->Year-2000,date_time->Month,date_time->Day,
1772 date_time->Hour,date_time->Minute,date_time->Second);
1773
1774 smprintf(s, "Setting date & time\n");
1775 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetDateTime);
1776}
1777
1778GSM_Error ATGEN_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
1779{
1780 if (alarm->Location != 1) return ERR_NOTSUPPORTED;
1781
1782 alarm->Repeating = true;
1783 alarm->Text[0] = 0; alarm->Text[1] = 0;
1784
1785 s->Phone.Data.Alarm = alarm;
1786 smprintf(s, "Getting alarm\n");
1787 return GSM_WaitFor (s, "AT+CALA?\r", 9, 0x00, 4, ID_GetAlarm);
1788}
1789
1790GSM_Error ATGEN_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
1791{
1792 GSM_SMSC *SMSC = s->Phone.Data.SMSC;
1793 int current;
1794 int len;
1795 unsigned char buffer[100];
1796
1797 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
1798 case AT_Reply_OK:
1799 smprintf(s, "SMSC info received\n");
1800
1801 current = 0;
1802 while (msg.Buffer[current]!='"') current++;
1803
1804 /* SMSC number */
1805 /* FIXME: support for all formats */
1806 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1807 /*
1808 * Some phones return this as unicode encoded when they are
1809 * switched to UCS2 mode, so we try to solve this correctly.
1810 */
1811 len = strlen(buffer + 1) - 1;
1812 buffer[len + 1] = 0;
1813 if ((len > 20) && (len % 4 == 0) && (strchr(buffer + 1, '+') == NULL)) {
1814 /* This is probably unicode encoded number */
1815 DecodeHexUnicode(SMSC->Number,buffer + 1,len);
1816 } else {
1817 EncodeUnicode(SMSC->Number,buffer + 1,len);
1818 }
1819 smprintf(s, "Number: \"%s\"\n",DecodeUnicodeString(SMSC->Number));
1820
1821 /* Format of SMSC number */
1822 current+=ATGEN_ExtractOneParameter(msg.Buffer+current, buffer);
1823 smprintf(s, "Format %s\n",buffer);
1824 /* International number */
1825 if (!strcmp(buffer,"145")) {
1826 sprintf(buffer+1,"%s",DecodeUnicodeString(SMSC->Number));
1827 if (strlen(buffer+1)!=0 && buffer[1] != '+') {
1828 /* Sony Ericsson issue */
1829 /* International number is without + */
1830 buffer[0] = '+';
1831 EncodeUnicode(SMSC->Number,buffer,strlen(buffer));
1832 }
1833 }
1834
1835 SMSC->Format = SMS_FORMAT_Text;
1836 SMSC->Validity.Format = SMS_Validity_RelativeFormat;
1837 SMSC->Validity.Relative= SMS_VALID_Max_Time;
1838 SMSC->Name[0] = 0;
1839 SMSC->Name[1] = 0;
1840 SMSC->DefaultNumber[0]= 0;
1841 SMSC->DefaultNumber[1]= 0;
1842 return ERR_NONE;
1843 case AT_Reply_CMSError:
1844 return ATGEN_HandleCMSError(s);
1845 default:
1846 break;
1847 }
1848 return ERR_UNKNOWNRESPONSE;
1849}
1850
1851GSM_Error ATGEN_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
1852{
1853 if (smsc->Location==0x00 || smsc->Location!=0x01) return ERR_INVALIDLOCATION;
1854
1855 s->Phone.Data.SMSC=smsc;
1856 smprintf(s, "Getting SMSC\n");
1857 return GSM_WaitFor (s, "AT+CSCA?\r", 9, 0x00, 4, ID_GetSMSC);
1858}
1859
1860GSM_Error ATGEN_ReplyGetNetworkLAC_CID(GSM_Protocol_Message msg, GSM_StateMachine *s)
1861{
1862 GSM_NetworkInfo *NetworkInfo = s->Phone.Data.NetworkInfo;
1863 GSM_Lines Lines;
1864 int i=0;
1865 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
1866 char *answer;
1867
1868 if (s->Phone.Data.RequestID == ID_IncomingFrame) {
1869 smprintf(s, "Incoming LAC & CID info\n");
1870 return ERR_NONE;
1871 }
1872
1873 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
1874 case AT_Reply_OK:
1875 break;
1876 case AT_Reply_CMSError:
1877 return ATGEN_HandleCMSError(s);
1878 default:
1879 return ERR_UNKNOWNRESPONSE;
1880 }
1881
1882 SplitLines(GetLineString(msg.Buffer,Priv->Lines,2),
1883 strlen(GetLineString(msg.Buffer,Priv->Lines,2)),
1884 &Lines, ",", 1, true);
1885
1886 /* Find number of lines */
1887 while (Lines.numbers[i*2+1] != 0) {
1888 /* FIXME: handle special chars correctly */
1889 smprintf(s, "%i \"%s\"\n",i+1,GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,i+1));
1890 i++;
1891 }
1892
1893 smprintf(s, "Network LAC & CID & state received\n");
1894 answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,2);
1895 while (*answer == 0x20) answer++;
1896#ifdef DEBUG
1897 switch (answer[0]) {
1898 case '0': smprintf(s, "Not registered into any network. Not searching for network\n"); break;
1899 case '1': smprintf(s, "Home network\n"); break;
1900 case '2': smprintf(s, "Not registered into any network. Searching for network\n"); break;
1901 case '3': smprintf(s, "Registration denied\n"); break;
1902 case '4': smprintf(s, "Unknown\n"); break;
1903 case '5': smprintf(s, "Registered in roaming network\n"); break;
1904 default : smprintf(s, "Unknown\n");
1905 }
1906#endif
1907 switch (answer[0]) {
1908 case '0': NetworkInfo->State = GSM_NoNetwork; break;
1909 case '1': NetworkInfo->State = GSM_HomeNetwork; break;
1910 case '2': NetworkInfo->State = GSM_RequestingNetwork; break;
1911 case '3': NetworkInfo->State = GSM_RegistrationDenied;break;
1912 case '4': NetworkInfo->State = GSM_NetworkStatusUnknown;break;
1913 case '5': NetworkInfo->State = GSM_RoamingNetwork; break;
1914 default : NetworkInfo->State = GSM_NetworkStatusUnknown;break;
1915 }
1916 if (NetworkInfo->State == GSM_HomeNetwork ||
1917 NetworkInfo->State == GSM_RoamingNetwork) {
1918 memset(NetworkInfo->CID,0,4);
1919 memset(NetworkInfo->LAC,0,4);
1920
1921 if (Lines.numbers[3*2+1]==0) return ERR_NONE;
1922
1923 answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,3);
1924 while (*answer == 0x20) answer++;
1925 sprintf(NetworkInfo->CID,"%c%c%c%c", answer[1], answer[2], answer[3], answer[4]);
1926
1927 answer = GetLineString(GetLineString(msg.Buffer,Priv->Lines,2),Lines,4);
1928 while (*answer == 0x20) answer++;
1929 sprintf(NetworkInfo->LAC,"%c%c%c%c", answer[1], answer[2], answer[3], answer[4]);
1930
1931 smprintf(s, "CID : %s\n",NetworkInfo->CID);
1932 smprintf(s, "LAC : %s\n",NetworkInfo->LAC);
1933 }
1934 return ERR_NONE;
1935}
1936
1937GSM_Error ATGEN_ReplyGetNetworkCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
1938{
1939 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
1940 GSM_NetworkInfo *NetworkInfo = s->Phone.Data.NetworkInfo;
1941
1942 switch (Priv->ReplyState) {
1943 case AT_Reply_OK:
1944 smprintf(s, "Network code received\n");
1945 if (Priv->Manufacturer == AT_Falcom) {
1946 NetworkInfo->NetworkCode[0] = msg.Buffer[22];
1947 NetworkInfo->NetworkCode[1] = msg.Buffer[23];
1948 NetworkInfo->NetworkCode[2] = msg.Buffer[24];
1949 NetworkInfo->NetworkCode[3] = ' ';
1950 NetworkInfo->NetworkCode[4] = msg.Buffer[25];
1951 NetworkInfo->NetworkCode[5] = msg.Buffer[26];
1952 } else {
1953 NetworkInfo->NetworkCode[0] = msg.Buffer[23];
1954 NetworkInfo->NetworkCode[1] = msg.Buffer[24];
1955 NetworkInfo->NetworkCode[2] = msg.Buffer[25];
1956 NetworkInfo->NetworkCode[3] = ' ';
1957 NetworkInfo->NetworkCode[4] = msg.Buffer[26];
1958 NetworkInfo->NetworkCode[5] = msg.Buffer[27];
1959 }
1960 NetworkInfo->NetworkCode[6] = 0;
1961 smprintf(s, " Network code : %s\n", NetworkInfo->NetworkCode);
1962 smprintf(s, " Network name for Gammu : %s ",
1963 DecodeUnicodeString(GSM_GetNetworkName(NetworkInfo->NetworkCode)));
1964 smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetworkInfo->NetworkCode)));
1965 return ERR_NONE;
1966 case AT_Reply_CMSError:
1967 return ATGEN_HandleCMSError(s);
1968 default:
1969 break;
1970 }
1971 return ERR_UNKNOWNRESPONSE;
1972}
1973
1974GSM_Error ATGEN_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
1975{
1976 GSM_Error error;
1977
1978 s->Phone.Data.NetworkInfo=netinfo;
1979
1980 netinfo->NetworkName[0] = 0;
1981 netinfo->NetworkName[1] = 0;
1982 netinfo->NetworkCode[0] = 0;
1983
1984 smprintf(s, "Enable full network info\n");
1985 error=GSM_WaitFor(s, "AT+CREG=2\r", 10, 0x00, 4, ID_GetNetworkInfo);
1986 if ((error != ERR_NONE) &&
1987 (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) &&
1988 (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Ericsson)) return error;
1989
1990 smprintf(s, "Getting network LAC and CID and state\n");
1991 error=GSM_WaitFor(s, "AT+CREG?\r", 9, 0x00, 4, ID_GetNetworkInfo);
1992 if (error != ERR_NONE) return error;
1993
1994 if (netinfo->State == GSM_HomeNetwork || netinfo->State == GSM_RoamingNetwork) {
1995 smprintf(s, "Setting short network name format\n");
1996 error=GSM_WaitFor(s, "AT+COPS=3,2\r", 12, 0x00, 4, ID_GetNetworkInfo);
1997
1998 error=ATGEN_GetManufacturer(s);
1999 if (error != ERR_NONE) return error;
2000
2001 smprintf(s, "Getting network code\n");
2002 error=GSM_WaitFor(s, "AT+COPS?\r", 9, 0x00, 4, ID_GetNetworkInfo);
2003 }
2004 return error;
2005}
2006
2007GSM_Error ATGEN_ReplyGetPBKMemories(GSM_Protocol_Message msg, GSM_StateMachine *s)
2008{
2009 smprintf(s, "PBK memories received\n");
2010 if (strlen(msg.Buffer) > AT_PBK_MAX_MEMORIES) {
2011 smprintf(s, "ERROR: Too long phonebook memories information received! (Recevided %d, AT_PBK_MAX_MEMORIES is %d\n", strlen(msg.Buffer), AT_PBK_MAX_MEMORIES);
2012 return ERR_MOREMEMORY;
2013 }
2014 memcpy(s->Phone.Data.Priv.ATGEN.PBKMemories,msg.Buffer,strlen(msg.Buffer));
2015 return ERR_NONE;
2016}
2017
2018GSM_Error ATGEN_SetPBKMemory(GSM_StateMachine *s, GSM_MemoryType MemType)
2019{
2020 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2021 char req[] = "AT+CPBS=\"XX\"\r";
2022 GSM_Error error;
2023
2024 if (Priv->PBKMemory == MemType) return ERR_NONE;
2025
2026 /* Zero values that are for actual memory */
2027 Priv->MemorySize = 0;
2028 Priv->FirstMemoryEntry = 0;
2029 Priv->NextMemoryEntry = 0;
2030 Priv->TextLength = 0;
2031 Priv->NumberLength = 0;
2032
2033 if (Priv->PBKMemories[0] == 0) {
2034 error=GSM_WaitFor (s, "AT+CPBS=?\r", 10, 0x00, 3, ID_SetMemoryType);
2035 if (error != ERR_NONE) return error;
2036 }
2037
2038 switch (MemType) {
2039 case MEM_SM:
2040 req[9] = 'S'; req[10] = 'M';
2041 break;
2042 case MEM_ME:
2043 if (strstr(Priv->PBKMemories,"ME")==NULL) return ERR_NOTSUPPORTED;
2044 req[9] = 'M'; req[10] = 'E';
2045 break;
2046 case MEM_RC:
2047 if (strstr(Priv->PBKMemories,"RC")==NULL) return ERR_NOTSUPPORTED;
2048 req[9] = 'R'; req[10] = 'C';
2049 break;
2050 case MEM_MC:
2051 if (strstr(Priv->PBKMemories,"MC")==NULL) return ERR_NOTSUPPORTED;
2052 req[9] = 'M'; req[10] = 'C';
2053 break;
2054 case MEM_ON:
2055 if (strstr(Priv->PBKMemories,"ON")==NULL) return ERR_NOTSUPPORTED;
2056 req[9] = 'O'; req[10] = 'N';
2057 break;
2058 case MEM_FD:
2059 if (strstr(Priv->PBKMemories,"FD")==NULL) return ERR_NOTSUPPORTED;
2060 req[9] = 'F'; req[10] = 'D';
2061 break;
2062 case MEM_DC:
2063 if (strstr(Priv->PBKMemories,"DC")!=NULL) {
2064 req[9] = 'D'; req[10] = 'C';
2065 break;
2066 }
2067 if (strstr(Priv->PBKMemories,"LD")!=NULL) {
2068 req[9] = 'L'; req[10] = 'D';
2069 break;
2070 }
2071 return ERR_NOTSUPPORTED;
2072 break;
2073 default:
2074 return ERR_NOTSUPPORTED;
2075 }
2076
2077 smprintf(s, "Setting memory type\n");
2078 error=GSM_WaitFor (s, req, 13, 0x00, 3, ID_SetMemoryType);
2079 if (error == ERR_NONE) Priv->PBKMemory = MemType;
2080 return error;
2081}
2082
2083GSM_Error ATGEN_ReplyGetCPBSMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
2084{
2085 GSM_MemoryStatus*MemoryStatus = s->Phone.Data.MemoryStatus;
2086 char *start;
2087
2088 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
2089 case AT_Reply_OK:
2090 smprintf(s, "Memory status received\n");
2091 MemoryStatus->MemoryUsed = 0;
2092 MemoryStatus->MemoryFree = 0;
2093 start = strchr(msg.Buffer, ',');
2094 if (start) {
2095 start++;
2096 MemoryStatus->MemoryUsed = atoi(start);
2097 start = strchr(start, ',');
2098 if (start) {
2099 start++;
2100 MemoryStatus->MemoryFree = atoi(start) - MemoryStatus->MemoryUsed;
2101 return ERR_NONE;
2102 } else return ERR_UNKNOWN;
2103 } else return ERR_UNKNOWN;
2104 case AT_Reply_CMSError:
2105 return ATGEN_HandleCMSError(s);
2106 default:
2107 break;
2108 }
2109 return ERR_UNKNOWNRESPONSE;
2110}
2111
2112GSM_Error ATGEN_ReplyGetCPBRMemoryInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
2113{
2114 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2115 char *pos;
2116
2117 switch (Priv->ReplyState) {
2118 case AT_Reply_OK:
2119 smprintf(s, "Memory info received\n");
2120 /* Parse +CPBR: (first-last),max_number_len,max_name_len */
2121
2122 /* Parse first location */
2123 pos = strchr(msg.Buffer, '(');
2124 if (!pos) return ERR_UNKNOWN;
2125 pos++;
2126 Priv->FirstMemoryEntry = atoi(pos);
2127
2128 /* Parse last location*/
2129 pos = strchr(pos, '-');
2130 if (!pos) return ERR_UNKNOWN;
2131 pos++;
2132 Priv->MemorySize = atoi(pos) + 1 - Priv->FirstMemoryEntry;
2133
2134 /* Parse number length*/
2135 pos = strchr(pos, ',');
2136 if (!pos) return ERR_UNKNOWN;
2137 pos++;
2138 Priv->NumberLength = atoi(pos);
2139
2140 /* Parse text length*/
2141 pos = strchr(pos, ',');
2142 if (!pos) return ERR_UNKNOWN;
2143 pos++;
2144 Priv->TextLength = atoi(pos);
2145
2146 return ERR_NONE;
2147 case AT_Reply_Error:
2148 return ERR_UNKNOWN;
2149 case AT_Reply_CMSError:
2150 return ATGEN_HandleCMSError(s);
2151 default:
2152 return ERR_UNKNOWNRESPONSE;
2153 }
2154}
2155
2156GSM_Error ATGEN_ReplyGetCPBRMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
2157{
2158 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2159 GSM_MemoryStatus*MemoryStatus = s->Phone.Data.MemoryStatus;
2160 int line=0;
2161 char *str;
2162 int cur;
2163
2164 switch (Priv->ReplyState) {
2165 case AT_Reply_OK:
2166 smprintf(s, "Memory entries received\n");
2167 /* Walk through lines with +CPBR: */
2168 while (Priv->Lines.numbers[line*2+1]!=0) {
2169 str = GetLineString(msg.Buffer,Priv->Lines,line+1);
2170 if (strncmp(str, "+CPBR: ", 7) == 0) {
2171 MemoryStatus->MemoryUsed++;
2172 if (sscanf(str, "+CPBR: %d,", &cur) == 1) {
2173 cur -= Priv->FirstMemoryEntry - 1;
2174 if (cur == Priv->NextMemoryEntry || Priv->NextMemoryEntry == 0)
2175 Priv->NextMemoryEntry = cur + 1;
2176 }
2177 }
2178 line++;
2179 }
2180 return ERR_NONE;
2181 case AT_Reply_Error:
2182 return ERR_UNKNOWN;
2183 case AT_Reply_CMSError:
2184 return ATGEN_HandleCMSError(s);
2185 default:
2186 return ERR_UNKNOWNRESPONSE;
2187 }
2188}
2189
2190GSM_Error ATGEN_GetMemoryInfo(GSM_StateMachine *s, GSM_MemoryStatus *Status, GSM_AT_NeededMemoryInfo NeededInfo)
2191{
2192 GSM_Error error;
2193 char req[20];
2194 int start;
2195 int end;
2196 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2197
2198 smprintf(s, "Getting memory information\n");
2199
2200 Priv->MemorySize = 0;
2201 Priv->TextLength = 0;
2202 Priv->NumberLength = 0;
2203
2204 error = GSM_WaitFor (s, "AT+CPBR=?\r", 10, 0x00, 4, ID_GetMemoryStatus);
2205 if (error != ERR_NONE) return error;
2206 if (NeededInfo == AT_Total || NeededInfo == AT_Sizes || NeededInfo == AT_First) return ERR_NONE;
2207
2208 smprintf(s, "Getting memory status by reading values\n");
2209
2210 s->Phone.Data.MemoryStatus= Status;
2211 Status->MemoryUsed = 0;
2212 Status->MemoryFree = 0;
2213 start = Priv->FirstMemoryEntry;
2214 Priv->NextMemoryEntry = 0;
2215 while (1) {
2216 end= start + 20;
2217 if (end > Priv->MemorySize) end = Priv->MemorySize;
2218 sprintf(req, "AT+CPBR=%i,%i\r", start, end);
2219 error= GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemoryStatus);
2220 if (error != ERR_NONE) return error;
2221 if (NeededInfo == AT_NextEmpty && Priv->NextMemoryEntry != 0 && Priv->NextMemoryEntry != end + 1) return ERR_NONE;
2222 if (end == Priv->MemorySize) {
2223 Status->MemoryFree = Priv->MemorySize - Status->MemoryUsed;
2224 return ERR_NONE;
2225 }
2226 start = end + 1;
2227 }
2228}
2229
2230GSM_Error ATGEN_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
2231{
2232 GSM_Error error;
2233
2234 error = ATGEN_SetPBKMemory(s, Status->MemoryType);
2235 if (error != ERR_NONE) return error;
2236
2237 s->Phone.Data.MemoryStatus=Status;
2238
2239 /* in some phones doesn't work or doesn't return memory status inside */
2240 /* Some workaround for buggy mobile, that hangs after "AT+CPBS?" for other
2241 * memory than SM.
2242 */
2243 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_BROKENCPBS) || (Status->MemoryType == MEM_SM)) {
2244 smprintf(s, "Getting memory status\n");
2245 error=GSM_WaitFor (s, "AT+CPBS?\r", 9, 0x00, 4, ID_GetMemoryStatus);
2246 if (error == ERR_NONE) return ERR_NONE;
2247 }
2248
2249 return ATGEN_GetMemoryInfo(s, Status, AT_Status);
2250}
2251
2252GSM_Error ATGEN_SetPBKCharset(GSM_StateMachine *s, bool PreferUnicode)
2253{
2254 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2255 GSM_Error error;
2256
2257 /* Have we already selected something? */
2258 if (Priv->PBKCharset!=0) {
2259 /* If we want unicode charset and we have it already or setting of it
2260 * failed, we have nothing to do. */
2261 if (PreferUnicode && (Priv->PBKCharset==AT_PBK_UCS2 || Priv->UCS2CharsetFailed)) return ERR_NONE;
2262
2263 /* If we don't need unicode charset and we have some (or have unicode
2264 * charset when other failed), we have nothing to do. */
2265 if (!PreferUnicode && (Priv->PBKCharset!=AT_PBK_UCS2 || Priv->NonUCS2CharsetFailed)) return ERR_NONE;
2266 }
2267
2268 error=ATGEN_GetManufacturer(s);
2269 if (error != ERR_NONE) return error;
2270
2271 if (PreferUnicode && !Priv->UCS2CharsetFailed) {
2272 smprintf(s, "Setting charset to UCS2\n");
2273 error=GSM_WaitFor (s, "AT+CSCS=\"UCS2\"\r", 15, 0x00, 3, ID_SetMemoryCharset);
2274 if (error == ERR_NONE) {
2275 Priv->PBKCharset = AT_PBK_UCS2;
2276 return ERR_NONE;
2277 } else {
2278 Priv->UCS2CharsetFailed = true;
2279 }
2280 }
2281
2282 smprintf(s, "Setting charset to HEX\n");
2283 error=GSM_WaitFor (s, "AT+CSCS=\"HEX\"\r", 14, 0x00, 3, ID_SetMemoryCharset);
2284 /* Falcom replies OK for HEX mode and send everything
2285 * in normal format */
2286 if (error == ERR_NONE && Priv->Manufacturer != AT_Falcom) {
2287 Priv->PBKCharset = AT_PBK_HEX;
2288 return ERR_NONE;
2289 }
2290
2291 smprintf(s, "Setting charset to GSM\n");
2292 error=GSM_WaitFor (s, "AT+CSCS=\"GSM\"\r", 14, 0x00, 3, ID_SetMemoryCharset);
2293 if (error == ERR_NONE) {
2294 Priv->PBKCharset = AT_PBK_GSM;
2295 return ERR_NONE;
2296 }
2297
2298 if (!Priv->UCS2CharsetFailed) {
2299 Priv->NonUCS2CharsetFailed = true;
2300 smprintf(s, "Setting charset to UCS2\n");
2301 error=GSM_WaitFor (s, "AT+CSCS=\"UCS2\"\r", 15, 0x00, 3, ID_SetMemoryCharset);
2302 if (error == ERR_NONE) {
2303 Priv->PBKCharset = AT_PBK_UCS2;
2304 return ERR_NONE;
2305 } else {
2306 Priv->UCS2CharsetFailed = true;
2307 }
2308 }
2309
2310 return error;
2311}
2312
2313GSM_Error ATGEN_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
2314{
2315 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2316 GSM_MemoryEntry *Memory = s->Phone.Data.Memory;
2317 char *pos;
2318 unsigned char buffer[500],buffer2[500];
2319 int len;
2320
2321 switch (Priv->ReplyState) {
2322 case AT_Reply_OK:
2323 smprintf(s, "Phonebook entry received\n");
2324 Memory->EntriesNum = 0;
2325 if (Priv->Lines.numbers[4]==0) return ERR_EMPTY;
2326 pos = strstr(msg.Buffer, "+CPBR:");
2327 if (pos == NULL) return ERR_UNKNOWN;
2328 /* Go after +CPBR: */
2329 pos += 6;
2330
2331 /* Location */
2332 while (*pos && !isdigit(*pos)) pos++;
2333 Memory->Location = atoi(pos) + 1 - Priv->FirstMemoryEntry;
2334 smprintf(s, "Location: %d\n", Memory->Location);
2335
2336 /* Number */
2337 while (*pos != '"') pos++;
2338 pos += ATGEN_ExtractOneParameter(pos, buffer);
2339 smprintf(s, "Number: %s\n",buffer);
2340 Memory->EntriesNum++;
2341 Memory->Entries[0].EntryType = PBK_Number_General;
2342 Memory->Entries[0].VoiceTag = 0;
2343 Memory->Entries[0].SMSList[0] = 0;
2344
2345 len = strlen(buffer + 1) - 1;
2346 if (Priv->PBKCharset == AT_PBK_HEX && (len > 10) && (len % 2 == 0) && (strchr(buffer + 1, '+') == NULL)) {
2347 /* This is probably hex encoded number */
2348 DecodeHexBin(buffer2, buffer+1, len);
2349 DecodeDefault(Memory->Entries[0].Text ,buffer2, strlen(buffer2), false, NULL);
2350 } else if (Priv->PBKCharset == AT_PBK_UCS2 && (len > 20) && (len % 4 == 0) && (strchr(buffer + 1, '+') == NULL)) {
2351 /* This is probably unicode encoded number */
2352 DecodeHexUnicode(Memory->Entries[0].Text, buffer + 1,len);
2353 } else {
2354 EncodeUnicode(Memory->Entries[0].Text, buffer + 1, len);
2355 }
2356
2357 /* Number format */
2358 pos += ATGEN_ExtractOneParameter(pos, buffer);
2359 smprintf(s, "Number format: %s\n",buffer);
2360
2361 /* International number */
2362 if (!strcmp(buffer,"145")) {
2363 sprintf(buffer+1,"%s",DecodeUnicodeString(Memory->Entries[0].Text));
2364 if (strlen(buffer+1)!=0 && buffer[1] != '+') {
2365 /* Sony Ericsson issue */
2366 /* International number is without + */
2367 buffer[0] = '+';
2368 EncodeUnicode(Memory->Entries[0].Text,buffer,strlen(buffer));
2369 }
2370 }
2371
2372 /* Name */
2373 pos += ATGEN_ExtractOneParameter(pos, buffer);
2374 smprintf(s, "Name text: %s\n",buffer);
2375 Memory->EntriesNum++;
2376 Memory->Entries[1].EntryType=PBK_Text_Name;
2377 switch (Priv->PBKCharset) {
2378 case AT_PBK_HEX:
2379 DecodeHexBin(buffer2,buffer+1,strlen(buffer)-2);
2380 DecodeDefault(Memory->Entries[1].Text,buffer2,strlen(buffer2),false,NULL);
2381 break;
2382 case AT_PBK_GSM:
2383 DecodeDefault(Memory->Entries[1].Text,buffer+1,strlen(buffer)-2,false,NULL);
2384 break;
2385 case AT_PBK_UCS2:
2386 DecodeHexUnicode(Memory->Entries[1].Text,buffer+1,strlen(buffer+1) - 1);
2387 break;
2388 }
2389 return ERR_NONE;
2390 case AT_Reply_CMEError:
2391 return ATGEN_HandleCMEError(s);
2392 case AT_Reply_Error:
2393 smprintf(s, "Error - too high location ?\n");
2394 return ERR_INVALIDLOCATION;
2395 case AT_Reply_CMSError:
2396 return ATGEN_HandleCMSError(s);
2397 default:
2398 break;
2399 }
2400 return ERR_UNKNOWNRESPONSE;
2401}
2402
2403GSM_Error ATGEN_PrivGetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, int endlocation)
2404{
2405 GSM_Error error;
2406 unsigned char req[20];
2407 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2408
2409 if (entry->Location==0x00) return ERR_INVALIDLOCATION;
2410
2411 if (entry->MemoryType == MEM_ME) {
2412 if (Priv->PBKSBNR == 0) {
2413 sprintf(req, "AT^SBNR=?\r");
2414 smprintf(s, "Checking availablity of SBNR\n");
2415 error=GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
2416 switch (error) {
2417 case ERR_NONE:
2418 Priv->PBKSBNR = AT_SBNR_AVAILABLE;
2419 break;
2420 case ERR_UNKNOWN:
2421 case ERR_NOTSUPPORTED:
2422 Priv->PBKSBNR = AT_SBNR_NOTAVAILABLE;
2423 break;
2424 default:
2425 return error;
2426 }
2427 }
2428 if (Priv->PBKSBNR == AT_SBNR_AVAILABLE) {
2429 sprintf(req, "AT^SBNR=vcf,%i\r",entry->Location-1);
2430 s->Phone.Data.Memory=entry;
2431 smprintf(s, "Getting phonebook entry\n");
2432 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
2433 }
2434 }
2435
2436 error=ATGEN_GetManufacturer(s);
2437 if (error != ERR_NONE) return error;
2438
2439 error=ATGEN_SetPBKMemory(s, entry->MemoryType);
2440 if (error != ERR_NONE) return error;
2441
2442 if (Priv->FirstMemoryEntry == 0) {
2443 error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
2444 if (error != ERR_NONE) return error;
2445 }
2446
2447
2448 error=ATGEN_SetPBKCharset(s, true); /* For reading we prefer unicode */
2449 if (error != ERR_NONE) return error;
2450
2451 if (endlocation == 0) {
2452 sprintf(req, "AT+CPBR=%i\r", entry->Location + Priv->FirstMemoryEntry - 1);
2453 } else {
2454 sprintf(req, "AT+CPBR=%i,%i\r", entry->Location + Priv->FirstMemoryEntry - 1, endlocation + Priv->FirstMemoryEntry - 1);
2455 }
2456
2457 s->Phone.Data.Memory=entry;
2458 smprintf(s, "Getting phonebook entry\n");
2459 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetMemory);
2460}
2461
2462GSM_Error ATGEN_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
2463{
2464 return ATGEN_PrivGetMemory(s, entry, 0);
2465}
2466
2467GSM_Error ATGEN_GetNextMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry, bool start)
2468{
2469 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2470 GSM_Error error;
2471 int step = 0;
2472
2473 if (Priv->MemorySize == 0) {
2474 error = ATGEN_GetMemoryInfo(s, NULL, AT_Total);
2475 if (error != ERR_NONE) return error;
2476 }
2477
2478 if (start) {
2479 entry->Location = 1;
2480 } else {
2481 entry->Location++;
2482 }
2483 while ((error = ATGEN_PrivGetMemory(s, entry, step == 0 ? 0 : MIN(Priv->MemorySize, entry->Location + step))) == ERR_EMPTY) {
2484 entry->Location += step + 1;
2485 if (entry->Location > Priv->MemorySize) break;
2486 /* SNBR works only for one location */
2487 if (entry->MemoryType != MEM_ME || Priv->PBKSBNR != AT_SBNR_AVAILABLE) step = MIN(step + 2, 20);
2488 }
2489 if (error == ERR_INVALIDLOCATION) return ERR_EMPTY;
2490 return error;
2491}
2492
2493GSM_Error ATGEN_DeleteAllMemory(GSM_StateMachine *s, GSM_MemoryType type)
2494{
2495 GSM_Error error;
2496 unsigned char req[100];
2497 int i;
2498 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2499
2500 error = ATGEN_SetPBKMemory(s, type);
2501 if (error != ERR_NONE) return error;
2502
2503 if (Priv->MemorySize == 0) {
2504 error = ATGEN_GetMemoryInfo(s, NULL, AT_Total);
2505 if (error != ERR_NONE) return error;
2506 }
2507
2508 if (Priv->FirstMemoryEntry == 0) {
2509 error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
2510 if (error != ERR_NONE) return error;
2511 }
2512
2513
2514 smprintf(s, "Deleting all phonebook entries\n");
2515 for (i = Priv->FirstMemoryEntry; i < Priv->FirstMemoryEntry + Priv->MemorySize; i++) {
2516 sprintf(req, "AT+CPBW=%d\r",i);
2517 error = GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetMemory);
2518 if (error != ERR_NONE) return error;
2519 }
2520 return ERR_NONE;
2521}
2522
2523GSM_Error ATGEN_ReplyDialVoice(GSM_Protocol_Message msg, GSM_StateMachine *s)
2524{
2525 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
2526 case AT_Reply_OK:
2527 smprintf(s, "Dial voice OK\n");
2528 return ERR_NONE;
2529 case AT_Reply_Error:
2530 smprintf(s, "Dial voice error\n");
2531 return ERR_UNKNOWN;
2532 case AT_Reply_CMSError:
2533 return ATGEN_HandleCMSError(s);
2534 default:
2535 break;
2536 }
2537 return ERR_UNKNOWNRESPONSE;
2538}
2539
2540GSM_Error ATGEN_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
2541{
2542 char req[39] = "ATDT";
2543
2544 if (ShowNumber != GSM_CALL_DefaultNumberPresence) return ERR_NOTSUPPORTED;
2545 if (strlen(number) > 32) return (ERR_UNKNOWN);
2546
2547 strcat(req, number);
2548 strcat(req, ";\r");
2549
2550 smprintf(s, "Making voice call\n");
2551 return GSM_WaitFor (s, req, 4+2+strlen(number), 0x00, 5, ID_DialVoice);
2552}
2553
2554GSM_Error ATGEN_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
2555{
2556 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
2557 case AT_Reply_OK:
2558 smprintf(s, "Security code was OK\n");
2559 return ERR_NONE;
2560 case AT_Reply_Error:
2561 smprintf(s, "Incorrect security code\n");
2562 return ERR_SECURITYERROR;
2563 case AT_Reply_CMSError:
2564 return ATGEN_HandleCMSError(s);
2565 default:
2566 break;
2567 }
2568 return ERR_UNKNOWNRESPONSE;
2569}
2570
2571GSM_Error ATGEN_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
2572{
2573 unsigned char req[50];
2574
2575 switch (Code.Type) {
2576 case SEC_Pin :
2577 sprintf(req, "AT+CPIN=\"%s\"\r" , Code.Code);
2578 break;
2579 case SEC_Pin2 :
2580 if (s->Phone.Data.Priv.ATGEN.Manufacturer == AT_Siemens) {
2581 sprintf(req, "AT+CPIN2=\"%s\"\r", Code.Code);
2582 } else {
2583 sprintf(req, "AT+CPIN=\"%s\"\r" , Code.Code);
2584 }
2585 break;
2586 default : return ERR_NOTIMPLEMENTED;
2587 }
2588
2589 smprintf(s, "Entering security code\n");
2590 return GSM_WaitFor (s, req, strlen(req), 0x00, 6, ID_EnterSecurityCode);
2591}
2592
2593GSM_Error ATGEN_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
2594{
2595 GSM_SecurityCodeType *Status = s->Phone.Data.SecurityStatus;
2596
2597 smprintf(s, "Security status received - ");
2598 if (strstr(msg.Buffer,"READY")) {
2599 *Status = SEC_None;
2600 smprintf(s, "nothing to enter\n");
2601 return ERR_NONE;
2602 }
2603 if (strstr(msg.Buffer,"PH_SIM PIN")) {
2604 smprintf(s, "no SIM inside or other error\n");
2605 return ERR_UNKNOWN;
2606 }
2607 if (strstr(msg.Buffer,"SIM PIN2")) {
2608 *Status = SEC_Pin2;
2609 smprintf(s, "waiting for PIN2\n");
2610 return ERR_NONE;
2611 }
2612 if (strstr(msg.Buffer,"SIM PUK2")) {
2613 *Status = SEC_Puk2;
2614 smprintf(s, "waiting for PUK2\n");
2615 return ERR_NONE;
2616 }
2617 if (strstr(msg.Buffer,"SIM PIN")) {
2618 *Status = SEC_Pin;
2619 smprintf(s, "waiting for PIN\n");
2620 return ERR_NONE;
2621 }
2622 if (strstr(msg.Buffer,"SIM PUK")) {
2623 *Status = SEC_Puk;
2624 smprintf(s, "waiting for PUK\n");
2625 return ERR_NONE;
2626 }
2627 smprintf(s, "unknown\n");
2628 return ERR_UNKNOWNRESPONSE;
2629}
2630
2631GSM_Error ATGEN_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
2632{
2633 s->Phone.Data.SecurityStatus=Status;
2634
2635 smprintf(s, "Getting security code status\n");
2636 /* Please note, that A2D doesn't return OK on the end.
2637 * Because of it ReplyGetSecurityStatus is called after receiving line
2638 * with +CPIN:
2639 */
2640 return GSM_WaitFor (s, "AT+CPIN?\r", 9, 0x00, 4, ID_GetSecurityStatus);
2641}
2642
2643GSM_Error ATGEN_AnswerCall(GSM_StateMachine *s, int ID, bool all)
2644{
2645 if (all) {
2646 smprintf(s, "Answering all calls\n");
2647 return GSM_WaitFor (s, "ATA\r", 4, 0x00, 4, ID_AnswerCall);
2648 }
2649 return ERR_NOTSUPPORTED;
2650}
2651
2652GSM_Error ATGEN_ReplyCancelCall(GSM_Protocol_Message msg, GSM_StateMachine *s)
2653{
2654 GSM_Call call;
2655
2656 switch(s->Phone.Data.Priv.ATGEN.ReplyState) {
2657 case AT_Reply_OK:
2658 smprintf(s, "Calls canceled\n");
2659 call.CallIDAvailable = false;
2660 call.Status = GSM_CALL_CallLocalEnd;
2661 if (s->User.IncomingCall) s->User.IncomingCall(s->CurrentConfig->Device, call);
2662
2663 return ERR_NONE;
2664 case AT_Reply_CMSError:
2665 return ATGEN_HandleCMSError(s);
2666 default:
2667 return ERR_UNKNOWN;
2668 }
2669}
2670
2671GSM_Error ATGEN_CancelCall(GSM_StateMachine *s, int ID, bool all)
2672{
2673 GSM_Error error;
2674
2675 if (all) {
2676 smprintf(s, "Dropping all calls\n");
2677 error = GSM_WaitFor (s, "ATH\r", 4, 0x00, 4, ID_CancelCall);
2678 if (error == ERR_UNKNOWN) {
2679 return GSM_WaitFor (s, "AT+CHUP\r", 8, 0x00, 4, ID_CancelCall);
2680 }
2681 return error;
2682 }
2683 return ERR_NOTSUPPORTED;
2684}
2685
2686GSM_Error ATGEN_ReplyReset(GSM_Protocol_Message msg, GSM_StateMachine *s)
2687{
2688 smprintf(s, "Reset done\n");
2689 return ERR_NONE;
2690}
2691
2692GSM_Error ATGEN_Reset(GSM_StateMachine *s, bool hard)
2693{
2694 GSM_Error error;
2695
2696 if (!hard) return ERR_NOTSUPPORTED;
2697
2698 smprintf(s, "Resetting device\n");
2699 /* Siemens 35 */
2700 error=GSM_WaitFor (s, "AT+CFUN=1,1\r", 12, 0x00, 8, ID_Reset);
2701 if (error != ERR_NONE) {
2702 /* Siemens M20 */
2703 error=GSM_WaitFor (s, "AT^SRESET\r", 10, 0x00, 8, ID_Reset);
2704 }
2705 return error;
2706}
2707
2708GSM_Error ATGEN_ReplyResetPhoneSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
2709{
2710 smprintf(s, "Reset done\n");
2711 return ERR_NONE;
2712}
2713
2714GSM_Error ATGEN_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type)
2715{
2716 smprintf(s, "Resetting settings to default\n");
2717 return GSM_WaitFor (s, "AT&F\r", 5, 0x00, 4, ID_ResetPhoneSettings);
2718}
2719
2720GSM_Error ATGEN_SetAutoNetworkLogin(GSM_StateMachine *s)
2721{
2722 smprintf(s, "Enabling automatic network login\n");
2723 return GSM_WaitFor (s, "AT+COPS=0\r", 10, 0x00, 4, ID_SetAutoNetworkLogin);
2724}
2725
2726GSM_Error ATGEN_SendDTMF(GSM_StateMachine *s, char *sequence)
2727{
2728 unsigned char req[80] = "AT+VTS=";
2729 int n;
2730
2731 for (n = 0; n < 32; n++) {
2732 if (sequence[n] == '\0') break;
2733 if (n != 0) req[6 + 2 * n] = ',';
2734 req[7 + 2 * n] = sequence[n];
2735 }
2736
2737 strcat(req, ";\r");
2738
2739 smprintf(s, "Sending DTMF\n");
2740 return GSM_WaitFor (s, req, 7+2+2*strlen(sequence), 0x00, 4, ID_SendDTMF);
2741}
2742
2743GSM_Error ATGEN_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
2744{
2745 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
2746 case AT_Reply_OK:
2747 smprintf(s, "SMS deleted OK\n");
2748 return ERR_NONE;
2749 case AT_Reply_Error:
2750 smprintf(s, "Invalid location\n");
2751 return ERR_INVALIDLOCATION;
2752 case AT_Reply_CMSError:
2753 return ATGEN_HandleCMSError(s);
2754 default:
2755 break;
2756 }
2757 return ERR_UNKNOWNRESPONSE;
2758}
2759
2760GSM_Error ATGEN_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2761{
2762 unsigned char req[20], folderid;
2763 GSM_Error error;
2764 int location;
2765 GSM_MultiSMSMessagemsms;
2766
2767 msms.Number = 0;
2768 msms.SMS[0] = *sms;
2769
2770 /* By reading SMS we check if it is really inbox/outbox */
2771 error = ATGEN_GetSMS(s, &msms);
2772 if (error != ERR_NONE) return error;
2773
2774 error = ATGEN_GetSMSLocation(s, sms, &folderid, &location);
2775 if (error != ERR_NONE) return error;
2776
2777 sprintf(req, "AT+CMGD=%i\r",location);
2778
2779 smprintf(s, "Deleting SMS\n");
2780 return GSM_WaitFor (s, req, strlen(req), 0x00, 5, ID_DeleteSMSMessage);
2781}
2782
2783GSM_Error ATGEN_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
2784{
2785 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
2786 GSM_Error error;
2787 int used = 0;
2788
2789 if (Priv->PhoneSMSMemory == 0) {
2790 error = ATGEN_SetSMSMemory(s, false);
2791 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
2792 }
2793 if (Priv->SIMSMSMemory == 0) {
2794 error = ATGEN_SetSMSMemory(s, true);
2795 if (error != ERR_NONE && error != ERR_NOTSUPPORTED) return error;
2796 }
2797
2798 folders->Number = 0;
2799 if (Priv->PhoneSMSMemory == AT_NOTAVAILABLE && Priv->SIMSMSMemory == AT_NOTAVAILABLE) {
2800 return ERR_NONE;
2801 }
2802
2803 PHONE_GetSMSFolders(s,folders);
2804
2805 if (Priv->SIMSMSMemory == AT_AVAILABLE) {
2806 used = 2;
2807 }
2808
2809 if (Priv->PhoneSMSMemory == AT_AVAILABLE) {
2810 if (used != 0) {
2811 CopyUnicodeString(folders->Folder[used ].Name,folders->Folder[0].Name);
2812 CopyUnicodeString(folders->Folder[used + 1].Name,folders->Folder[1].Name);
2813 folders->Folder[used ].InboxFolder = true;
2814 folders->Folder[used + 1].InboxFolder = false;
2815 }
2816 folders->Folder[used ].Memory = MEM_ME;
2817 folders->Folder[used + 1].Memory = MEM_ME;
2818 folders->Number += 2;
2819 used += 2;
2820 }
2821
2822 return ERR_NONE;
2823}
2824
2825GSM_Error ATGEN_ReplySetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
2826{
2827 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
2828 case AT_Reply_OK:
2829 smprintf(s, "Phonebook entry written OK\n");
2830 return ERR_NONE;
2831 case AT_Reply_CMSError:
2832 return ATGEN_HandleCMSError(s);
2833 case AT_Reply_CMEError:
2834 return ATGEN_HandleCMEError(s);
2835 case AT_Reply_Error:
2836 return ERR_INVALIDDATA;
2837 default:
2838 return ERR_UNKNOWNRESPONSE;
2839 }
2840}
2841
2842GSM_Error ATGEN_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
2843{
2844 GSM_Error error;
2845 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2846 unsigned char req[100];
2847
2848 if (entry->Location < 1) return ERR_INVALIDLOCATION;
2849
2850 error = ATGEN_SetPBKMemory(s, entry->MemoryType);
2851 if (error != ERR_NONE) return error;
2852
2853 if (Priv->FirstMemoryEntry == 0) {
2854 error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
2855 if (error != ERR_NONE) return error;
2856 }
2857
2858 sprintf(req, "AT+CPBW=%d\r",entry->Location + Priv->FirstMemoryEntry - 1);
2859
2860 smprintf(s, "Deleting phonebook entry\n");
2861 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_SetMemory);
2862}
2863
2864GSM_Error ATGEN_PrivSetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
2865{
2866 /* REQUEST_SIZE should be big enough to handle all possibl cases
2867 * correctly, especially with unicode entries */
2868 #define REQUEST_SIZE((4 * GSM_PHONEBOOK_TEXT_LENGTH) + 30)
2869 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2870 int Group, Name, Number,NumberType=0, len;
2871 GSM_Error error;
2872 unsigned char req[REQUEST_SIZE + 1];
2873 unsigned char name[2*(GSM_PHONEBOOK_TEXT_LENGTH + 1)];
2874 unsigned char uname[2*(GSM_PHONEBOOK_TEXT_LENGTH + 1)];
2875 unsigned char number[GSM_PHONEBOOK_TEXT_LENGTH + 1];
2876 int reqlen;
2877 bool PreferUnicode = false;
2878
2879 if (entry->Location == 0) return ERR_INVALIDLOCATION;
2880
2881 error = ATGEN_SetPBKMemory(s, entry->MemoryType);
2882 if (error != ERR_NONE) return error;
2883
2884 GSM_PhonebookFindDefaultNameNumberGroup(entry, &Name, &Number, &Group);
2885
2886 name[0] = 0;
2887 if (Name != -1) {
2888 len = UnicodeLength(entry->Entries[Name].Text);
2889
2890 /* Compare if we would loose some information when not using
2891 * unicode */
2892 EncodeDefault(name, entry->Entries[Name].Text, &len, true, NULL);
2893 DecodeDefault(uname, name, len, true, NULL);
2894 if (!mywstrncmp(uname, entry->Entries[Name].Text, len)) {
2895 /* Get maximal text length */
2896 if (Priv->TextLength == 0) {
2897 ATGEN_GetMemoryInfo(s, NULL, AT_Sizes);
2898 }
2899
2900 /* I char stored in GSM alphabet takes 7 bits, one
2901 * unicode 16, if storing in unicode would truncate
2902 * text, do not use it, otherwise we will use it */
2903 if ((Priv->TextLength != 0) && ((Priv->TextLength * 7 / 16) <= len)) {
2904 PreferUnicode = false;
2905 } else {
2906 PreferUnicode = true;
2907 }
2908 }
2909
2910 error = ATGEN_SetPBKCharset(s, PreferUnicode);
2911 if (error != ERR_NONE) return error;
2912
2913 switch (Priv->PBKCharset) {
2914 case AT_PBK_HEX:
2915 EncodeHexBin(name, DecodeUnicodeString(entry->Entries[Name].Text), UnicodeLength(entry->Entries[Name].Text));
2916 len = strlen(name);
2917 break;
2918 case AT_PBK_GSM:
2919 smprintf(s, "str: %s\n", DecodeUnicodeString(entry->Entries[Name].Text));
2920 len = UnicodeLength(entry->Entries[Name].Text);
2921 EncodeDefault(name, entry->Entries[Name].Text, &len, true, NULL);
2922 break;
2923 case AT_PBK_UCS2:
2924 EncodeHexUnicode(name, entry->Entries[Name].Text, UnicodeLength(entry->Entries[Name].Text));
2925 len = strlen(name);
2926 break;
2927 }
2928 } else {
2929 smprintf(s, "WARNING: No usable name found!\n");
2930 len = 0;
2931 }
2932
2933 if (Number != -1) {
2934 GSM_PackSemiOctetNumber(entry->Entries[Number].Text, number, false);
2935 NumberType = number[0];
2936 sprintf(number,"%s",DecodeUnicodeString(entry->Entries[Number].Text));
2937 } else {
2938 smprintf(s, "WARNING: No usable number found!\n");
2939 number[0] = 0;
2940 }
2941
2942 if (Priv->FirstMemoryEntry == 0) {
2943 error = ATGEN_GetMemoryInfo(s, NULL, AT_First);
2944 if (error != ERR_NONE) return error;
2945 }
2946
2947 /* We can't use here:
2948 * sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"%s\"\r",
2949 * entry->Location, number, NumberType, name);
2950 * because name can contain 0 when using GSM alphabet.
2951 */
2952 sprintf(req, "AT+CPBW=%d, \"%s\", %i, \"", entry->Location + Priv->FirstMemoryEntry - 1, number, NumberType);
2953 reqlen = strlen(req);
2954 if (reqlen + len > REQUEST_SIZE - 2) {
2955 smprintf(s, "WARNING: Text truncated to fit in buffer!\n");
2956 len = REQUEST_SIZE - 2 - reqlen;
2957 }
2958 memcpy(req + reqlen, name, len);
2959 reqlen += len;
2960 memcpy(req + reqlen, "\"\r", 2);
2961 reqlen += 2;
2962
2963 smprintf(s, "Writing phonebook entry\n");
2964 return GSM_WaitFor (s, req, reqlen, 0x00, 4, ID_SetMemory);
2965#undef REQUEST_SIZE
2966}
2967
2968GSM_Error ATGEN_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
2969{
2970 if (entry->Location == 0) return ERR_INVALIDLOCATION;
2971 return ATGEN_PrivSetMemory(s, entry);
2972}
2973
2974GSM_Error ATGEN_AddMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
2975{
2976 GSM_Error error;
2977 GSM_MemoryStatusStatus;
2978 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
2979
2980 /* Find out empty location */
2981 error = ATGEN_GetMemoryInfo(s, &Status, AT_NextEmpty);
2982 if (error != ERR_NONE) return error;
2983 if (Priv->NextMemoryEntry == 0) return ERR_FULL;
2984 entry->Location = Priv->NextMemoryEntry;
2985
2986 return ATGEN_PrivSetMemory(s, entry);
2987}
2988
2989/* Use ATGEN_ExtractOneParameter ?? */
2990void Extract_CLIP_number(char *dest, char *buf)
2991{
2992 char *start, *stop;
2993 int i = 0;
2994
2995 stop = strstr(buf, ",");
2996 if (stop != NULL) {
2997 start = strstr(buf, ":");
2998 if (start != NULL) {
2999 for (start = start + 2; start + i < stop; i++)
3000 dest[i] = start[i];
3001 }
3002 }
3003 dest[i] = 0; /* end the number */
3004
3005 return;
3006}
3007
3008GSM_Error ATGEN_ReplyIncomingCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
3009{
3010 char num[128];
3011 GSM_Call call;
3012
3013 smprintf(s, "Incoming call info\n");
3014 if (s->Phone.Data.EnableIncomingCall && s->User.IncomingCall!=NULL) {
3015 call.CallIDAvailable = false;
3016 num[0] = 0;
3017 if (strstr(msg.Buffer, "RING")) {
3018 call.Status = GSM_CALL_IncomingCall;
3019 Extract_CLIP_number(num, msg.Buffer);
3020 } else if (strstr(msg.Buffer, "NO CARRIER")) {
3021 call.Status = GSM_CALL_CallEnd;
3022 } else if (strstr(msg.Buffer, "COLP:")) {
3023 call.Status = GSM_CALL_CallStart;
3024 Extract_CLIP_number(num, msg.Buffer);
3025 } else {
3026 smprintf(s, "CLIP: error\n");
3027 return ERR_NONE;
3028 }
3029 EncodeUnicode(call.PhoneNumber, num, strlen(num));
3030
3031 s->User.IncomingCall(s->CurrentConfig->Device, call);
3032 }
3033
3034 return ERR_NONE;
3035}
3036
3037GSM_Error ATGEN_IncomingGPRS(GSM_Protocol_Message msg, GSM_StateMachine *s)
3038{
3039 /* "+CGREG: 1,1" */
3040 smprintf(s, "GPRS change\n");
3041 return ERR_NONE;
3042}
3043
3044GSM_Error ATGEN_IncomingBattery(GSM_Protocol_Message msg, GSM_StateMachine *s)
3045{
3046 int level = 0;
3047 char *p;
3048
3049 /* "_OBS: 92,1" */
3050 p = strstr(msg.Buffer, "_OBS:");
3051 if (p) level = atoi(p + 5);
3052 smprintf(s, "Battery level changed to %d\n", level);
3053 return ERR_NONE;
3054}
3055
3056GSM_Error ATGEN_IncomingNetworkLevel(GSM_Protocol_Message msg, GSM_StateMachine *s)
3057{
3058 int level = 0;
3059 char *p;
3060
3061 /* "_OSIGQ: 12,0" */
3062 p = strstr(msg.Buffer, "_OSIGQ: ");
3063 if (p) level = atoi(p + 7);
3064 smprintf(s, "Network level changed to %d\n", level);
3065 return ERR_NONE;
3066}
3067
3068GSM_Error ATGEN_ReplyGetSIMIMSI(GSM_Protocol_Message msg, GSM_StateMachine *s)
3069{
3070 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
3071 GSM_Phone_Data *Data = &s->Phone.Data;
3072 char *c;
3073
3074 switch (Priv->ReplyState) {
3075 case AT_Reply_OK:
3076 CopyLineString(Data->PhoneString, msg.Buffer, Priv->Lines, 2);
3077
3078 /* Read just IMSI also on phones that prepend it by "<IMSI>:" (Alcatel BE5) */
3079 c = strstr(Data->PhoneString, "<IMSI>:");
3080 if (c != NULL) {
3081 c += 7;
3082 memmove(Data->PhoneString, c, strlen(c) + 1);
3083 }
3084
3085 smprintf(s, "Received IMSI %s\n",Data->PhoneString);
3086 return ERR_NONE;
3087 case AT_Reply_Error:
3088 smprintf(s, "No access to SIM card or not supported by device\n");
3089 return ERR_SECURITYERROR;
3090 case AT_Reply_CMEError:
3091 return ATGEN_HandleCMEError(s);
3092 case AT_Reply_CMSError:
3093 return ATGEN_HandleCMSError(s);
3094 default:
3095 break;
3096 }
3097 return ERR_UNKNOWNRESPONSE;
3098}
3099
3100GSM_Error ATGEN_GetSIMIMSI(GSM_StateMachine *s, char *IMSI)
3101{
3102 s->Phone.Data.PhoneString = IMSI;
3103 smprintf(s, "Getting SIM IMSI\n");
3104 return GSM_WaitFor (s, "AT+CIMI\r", 8, 0x00, 4, ID_GetSIMIMSI);
3105}
3106
3107GSM_Error ATGEN_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
3108{
3109 return ERR_NOTSUPPORTED;
3110
3111 s->Phone.Data.DisplayFeatures = features;
3112 smprintf(s, "Getting display status\n");
3113 return GSM_WaitFor (s, "AT+CIND?\r",9, 0x00, 4, ID_GetDisplayStatus);
3114}
3115
3116GSM_Error ATGEN_IncomingSMSCInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
3117{
3118 return ERR_NONE;
3119}
3120
3121GSM_Error ATGEN_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
3122{
3123 GSM_Phone_Data *Data = &s->Phone.Data;
3124 int i;
3125
3126 Data->BatteryCharge->BatteryPercent = -1;
3127 Data->BatteryCharge->ChargeState = 0;
3128
3129 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
3130 case AT_Reply_OK:
3131 smprintf(s, "Battery level received\n");
3132 Data->BatteryCharge->BatteryPercent = atoi(msg.Buffer+17);
3133 i = atoi(msg.Buffer+14);
3134 if (i >= 0 && i <= 3) {
3135 Data->BatteryCharge->ChargeState = i + 1;
3136 }
3137 return ERR_NONE;
3138 case AT_Reply_Error:
3139 smprintf(s, "Can't get battery level\n");
3140 return ERR_UNKNOWN;
3141 case AT_Reply_CMSError:
3142 smprintf(s, "Can't get battery level\n");
3143 return ATGEN_HandleCMSError(s);
3144 default:
3145 break;
3146 }
3147 return ERR_UNKNOWNRESPONSE;
3148}
3149
3150GSM_Error ATGEN_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
3151{
3152 s->Phone.Data.BatteryCharge = bat;
3153 smprintf(s, "Getting battery charge\n");
3154 return GSM_WaitFor (s, "AT+CBC\r", 7, 0x00, 4, ID_GetBatteryCharge);
3155}
3156
3157GSM_Error ATGEN_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
3158{
3159 GSM_SignalQuality*Signal = s->Phone.Data.SignalQuality;
3160 int i;
3161 char *pos;
3162
3163 Signal->SignalStrength = -1;
3164 Signal->SignalPercent = -1;
3165 Signal->BitErrorRate = -1;
3166
3167 switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
3168 case AT_Reply_OK:
3169 smprintf(s, "Signal quality info received\n");
3170 i = atoi(msg.Buffer+15);
3171 if (i != 99) {
3172 /* from GSM 07.07 section 8.5 */
3173 Signal->SignalStrength = 2 * i - 113;
3174
3175 /* FIXME: this is wild guess and probably will be phone dependant */
3176 Signal->SignalPercent = 15 * i;
3177 if (Signal->SignalPercent > 100) Signal->SignalPercent = 100;
3178 }
3179 pos = strchr(msg.Buffer + 15, ',');
3180 if (pos != NULL) {
3181 i = atoi(pos + 1);
3182 /* from GSM 05.08 section 8.2.4 */
3183 switch (i) {
3184 case 0: Signal->BitErrorRate = 0; break; /* 0.14 */
3185 case 1: Signal->BitErrorRate = 0; break; /* 0.28 */
3186 case 2: Signal->BitErrorRate = 1; break; /* 0.57 */
3187 case 3: Signal->BitErrorRate = 1; break; /* 1.13 */
3188 case 4: Signal->BitErrorRate = 2; break; /* 2.26 */
3189 case 5: Signal->BitErrorRate = 5; break; /* 4.53 */
3190 case 6: Signal->BitErrorRate = 9; break; /* 9.05 */
3191 case 7: Signal->BitErrorRate = 18; break; /* 18.10 */
3192 }
3193 }
3194 return ERR_NONE;
3195 case AT_Reply_CMSError:
3196 return ATGEN_HandleCMSError(s);
3197 default:
3198 break;
3199 }
3200 return ERR_UNKNOWNRESPONSE;
3201}
3202
3203GSM_Error ATGEN_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
3204{
3205 s->Phone.Data.SignalQuality = sig;
3206 smprintf(s, "Getting signal quality info\n");
3207 return GSM_WaitFor (s, "AT+CSQ\r", 7, 0x00, 4, ID_GetSignalQuality);
3208}
3209
3210/* When use AT+CPIN?, A2D returns it without OK and because of it Gammu
3211 parses answer without it.
3212 MC35 and other return OK after answer for AT+CPIN?. Here we handle it.
3213 Any better idea ?
3214 */
3215GSM_Error ATGEN_ReplyOK(GSM_Protocol_Message msg, GSM_StateMachine *s)
3216{
3217 return ERR_NONE;
3218}
3219
3220static GSM_Error ATGEN_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
3221{
3222 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
3223
3224 if (Priv->Manufacturer==AT_Siemens ) return SIEMENS_GetNextCalendar(s,Note,start);
3225 if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_GetNextCalendar(s,Note,start);
3226 return ERR_NOTSUPPORTED;
3227}
3228
3229GSM_Error ATGEN_Terminate(GSM_StateMachine *s)
3230{
3231 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
3232
3233 free(Priv->file.Buffer);
3234 return ERR_NONE;
3235}
3236
3237GSM_Error ATGEN_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
3238{
3239 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
3240
3241 if (Priv->Manufacturer==AT_Siemens) return SIEMENS_AddCalendarNote(s, Note);
3242 if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_AddCalendarNote(s, Note);
3243 return ERR_NOTSUPPORTED;
3244}
3245
3246GSM_Error ATGEN_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
3247{
3248 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
3249
3250 if (Priv->Manufacturer==AT_Siemens) return SIEMENS_DelCalendarNote(s, Note);
3251 if (Priv->Manufacturer==AT_Ericsson) return SONYERIC_DelCalendarNote(s, Note);
3252 return ERR_NOTSUPPORTED;
3253}
3254
3255GSM_Error ATGEN_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
3256{
3257 GSM_Errorerror;
3258 unsigned char Frame[] = "AT+CKPD=\"?\"\r";
3259
3260 if (Press) {
3261 switch (Key) {
3262 case GSM_KEY_1 : Frame[9] = '1'; break;
3263 case GSM_KEY_2 : Frame[9] = '2'; break;
3264 case GSM_KEY_3 : Frame[9] = '3'; break;
3265 case GSM_KEY_4 : Frame[9] = '4'; break;
3266 case GSM_KEY_5 : Frame[9] = '5'; break;
3267 case GSM_KEY_6 : Frame[9] = '6'; break;
3268 case GSM_KEY_7 : Frame[9] = '7'; break;
3269 case GSM_KEY_8 : Frame[9] = '8'; break;
3270 case GSM_KEY_9 : Frame[9] = '9'; break;
3271 case GSM_KEY_0 : Frame[9] = '0'; break;
3272 case GSM_KEY_HASH : Frame[9] = '#'; break;
3273 case GSM_KEY_ASTERISK : Frame[9] = '*'; break;
3274 case GSM_KEY_POWER : return ERR_NOTSUPPORTED;
3275 case GSM_KEY_GREEN : Frame[9] = 'S'; break;
3276 case GSM_KEY_RED : Frame[9] = 'E'; break;
3277 case GSM_KEY_INCREASEVOLUME: Frame[9] = 'U'; break;
3278 case GSM_KEY_DECREASEVOLUME: Frame[9] = 'D'; break;
3279 case GSM_KEY_UP : Frame[9] = '^'; break;
3280 case GSM_KEY_DOWN : Frame[9] = 'V'; break;
3281 case GSM_KEY_MENU : Frame[9] = 'F'; break;
3282 case GSM_KEY_NAMES : Frame[9] = 'C'; break;
3283 default : return ERR_NOTSUPPORTED;
3284 }
3285 smprintf(s, "Pressing key\n");
3286 error = GSM_WaitFor (s, Frame, 12, 0x00, 4, ID_PressKey);
3287 if (error != ERR_NONE) return error;
3288
3289 /* Strange. My T310 needs it */
3290 return GSM_WaitFor (s, "ATE1\r", 5, 0x00, 4, ID_EnableEcho);
3291 } else {
3292 return ERR_NONE;
3293 }
3294}
3295
3296#ifdef GSM_ENABLE_CELLBROADCAST
3297
3298GSM_Error ATGEN_ReplyIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
3299{
3300 GSM_CBMessage CB;
3301 int i,j;
3302 char Buffer[300],Buffer2[300];
3303
3304 smprintf(s, "CB received\n");
3305 return ERR_NONE;
3306
3307 DecodeHexBin (Buffer,msg.Buffer+6,msg.Length-6);
3308 DumpMessage(stdout, di.dl ,Buffer,msg.Length-6);
3309
3310 CB.Channel = Buffer[4];
3311
3312 for (j=0;j<msg.Length;j++) {
3313 smprintf(s, "j=%i\n",j);
3314 i=GSM_UnpackEightBitsToSeven(0, msg.Buffer[6], msg.Buffer[6], msg.Buffer+j, Buffer2);
3315 //i = msg.Buffer[6] - 1;
3316 //while (i!=0) {
3317 // if (Buffer[i] == 13) i = i - 1; else break;
3318 //}
3319 DecodeDefault(CB.Text, Buffer2, msg.Buffer[6], false, NULL);
3320 smprintf(s, "Channel %i, text \"%s\"\n",CB.Channel,DecodeUnicodeString(CB.Text));
3321 }
3322 if (s->Phone.Data.EnableIncomingCB && s->User.IncomingCB!=NULL) {
3323 s->User.IncomingCB(s->CurrentConfig->Device,CB);
3324 }
3325 return ERR_NONE;
3326}
3327
3328#endif
3329
3330GSM_Error ATGEN_SetIncomingCB(GSM_StateMachine *s, bool enable)
3331{
3332#ifdef GSM_ENABLE_CELLBROADCAST
3333 if (s->Phone.Data.EnableIncomingCB!=enable) {
3334 s->Phone.Data.EnableIncomingCB = enable;
3335 if (enable) {
3336 smprintf(s, "Enabling incoming CB\n");
3337 return GSM_WaitFor(s, "AT+CNMI=3,,2\r", 13, 0x00, 4, ID_SetIncomingCB);
3338 } else {
3339 smprintf(s, "Disabling incoming CB\n");
3340 return GSM_WaitFor(s, "AT+CNMI=3,,0\r", 13, 0x00, 4, ID_SetIncomingCB);
3341 }
3342 }
3343 return ERR_NONE;
3344#else
3345 return ERR_SOURCENOTAVAILABLE;
3346#endif
3347}
3348
3349GSM_Error ATGEN_IncomingSMSInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
3350{
3351 smprintf(s, "Incoming SMS\n");
3352 return ERR_NONE;
3353}
3354
3355GSM_Error ATGEN_IncomingSMSDeliver(GSM_Protocol_Message msg, GSM_StateMachine *s)
3356{
3357 GSM_Phone_Data *Data = &s->Phone.Data;
3358 GSM_SMSMessage sms;
3359 int current = 0, current2, i=0;
3360 unsigned char buffer[300],smsframe[800];
3361
3362 smprintf(s, "Incoming SMS received (Deliver)\n");
3363 if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
3364 sms.State = SMS_UnRead;
3365 sms.InboxFolder = true;
3366 sms.PDU = SMS_Deliver;
3367
3368 /* T310 with larger SMS goes crazy and mix this incoming
3369 * frame with normal answers. PDU is always last frame
3370 * We find its' number and parse it */
3371 while (Data->Priv.ATGEN.Lines.numbers[i*2+1] != 0) {
3372 /* FIXME: handle special chars correctly */
3373 i++;
3374 }
3375 DecodeHexBin (buffer,
3376 GetLineString(msg.Buffer,Data->Priv.ATGEN.Lines,i),
3377 strlen(GetLineString(msg.Buffer,Data->Priv.ATGEN.Lines,i)));
3378
3379 /* We use locations from SMS layouts like in ../phone2.c(h) */
3380 for(i=0;i<buffer[0]+1;i++) smsframe[i]=buffer[current++];
3381 smsframe[12]=buffer[current++];
3382
3383 current2=((buffer[current])+1)/2+1;
3384 for(i=0;i<current2+1;i++) smsframe[PHONE_SMSDeliver.Number+i]=buffer[current++];
3385 smsframe[PHONE_SMSDeliver.TPPID] = buffer[current++];
3386 smsframe[PHONE_SMSDeliver.TPDCS] = buffer[current++];
3387 for(i=0;i<7;i++) smsframe[PHONE_SMSDeliver.DateTime+i]=buffer[current++];
3388 smsframe[PHONE_SMSDeliver.TPUDL] = buffer[current++];
3389 for(i=0;i<smsframe[PHONE_SMSDeliver.TPUDL];i++) smsframe[i+PHONE_SMSDeliver.Text]=buffer[current++];
3390 GSM_DecodeSMSFrame(&sms,smsframe,PHONE_SMSDeliver);
3391
3392 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
3393 }
3394 return ERR_NONE;
3395}
3396
3397/* I don't have phone able to do it and can't fill it */
3398GSM_Error ATGEN_IncomingSMSReport(GSM_Protocol_Message msg, GSM_StateMachine *s)
3399{
3400 smprintf(s, "Incoming SMS received (Report)\n");
3401 return ERR_NONE;
3402}
3403
3404GSM_Error ATGEN_SetIncomingSMS(GSM_StateMachine *s, bool enable)
3405{
3406 /* Nokia returns OK, but doesn't return anything */
3407 if (s->Phone.Data.Priv.ATGEN.Manufacturer == AT_Nokia) return ERR_NOTSUPPORTED;
3408
3409 if (s->Phone.Data.EnableIncomingSMS!=enable) {
3410 s->Phone.Data.EnableIncomingSMS = enable;
3411 if (enable) {
3412 smprintf(s, "Enabling incoming SMS\n");
3413
3414 /* Delivery reports */
3415 GSM_WaitFor(s, "AT+CNMI=3,,,1\r", 14, 0x00, 4, ID_SetIncomingSMS);
3416
3417 /* SMS deliver */
3418 return GSM_WaitFor(s, "AT+CNMI=3,3\r", 12, 0x00, 4, ID_SetIncomingSMS);
3419 } else {
3420 smprintf(s, "Disabling incoming SMS\n");
3421 return GSM_WaitFor(s, "AT+CNMI=3,0\r", 12, 0x00, 4, ID_SetIncomingSMS);
3422 }
3423 }
3424 return ERR_NONE;
3425}
3426
3427GSM_Reply_Function ATGENReplyFunctions[] = {
3428 {ATGEN_GenericReply, "AT\r" ,0x00,0x00,ID_IncomingFrame },
3429 {ATGEN_GenericReply, "ATE1" ,0x00,0x00,ID_EnableEcho },
3430 {ATGEN_GenericReply, "AT+CMEE=" ,0x00,0x00,ID_EnableErrorInfo },
3431 {ATGEN_GenericReply, "AT+CKPD=" ,0x00,0x00,ID_PressKey },
3432 {ATGEN_ReplyGetSIMIMSI, "AT+CIMI" ,0x00,0x00,ID_GetSIMIMSI },
3433 {ATGEN_GenericReply, "AT*EOBEX" ,0x00,0x00,ID_SetOBEX },
3434
3435#ifdef GSM_ENABLE_CELLBROADCAST
3436 {ATGEN_ReplyIncomingCB, "+CBM:" ,0x00,0x00,ID_IncomingFrame },
3437 {ATGEN_GenericReply, "AT+CNMI" ,0x00,0x00,ID_SetIncomingCB },
3438#endif
3439
3440 {ATGEN_IncomingBattery, "_OBS:" ,0x00,0x00,ID_IncomingFrame },
3441 {ATGEN_ReplyGetBatteryCharge, "AT+CBC" ,0x00,0x00,ID_GetBatteryCharge },
3442
3443 {ATGEN_ReplyGetModel, "AT+CGMM" ,0x00,0x00,ID_GetModel },
3444 {ATGEN_ReplyGetManufacturer, "AT+CGMI" ,0x00,0x00,ID_GetManufacturer },
3445 {ATGEN_ReplyGetFirmwareCGMR, "AT+CGMR" ,0x00,0x00,ID_GetFirmware },
3446 {ATGEN_ReplyGetFirmwareATI, "ATI" ,0x00,0x00,ID_GetFirmware },
3447 {ATGEN_ReplyGetIMEI, "AT+CGSN" ,0x00,0x00,ID_GetIMEI },
3448
3449 {ATGEN_ReplySendSMS, "AT+CMGS" ,0x00,0x00,ID_IncomingFrame },
3450 {ATGEN_ReplySendSMS, "AT+CMSS" ,0x00,0x00,ID_IncomingFrame },
3451 {ATGEN_GenericReply, "AT+CNMI" ,0x00,0x00,ID_SetIncomingSMS },
3452 {ATGEN_GenericReply, "AT+CMGF" ,0x00,0x00,ID_GetSMSMode },
3453 {ATGEN_GenericReply, "AT+CSDH" ,0x00,0x00,ID_GetSMSMode },
3454 {ATGEN_ReplyGetSMSMessage, "AT+CMGR" ,0x00,0x00,ID_GetSMSMessage },
3455 {ATGEN_GenericReply, "AT+CPMS" ,0x00,0x00,ID_SetMemoryType },
3456 {ATGEN_ReplyGetSMSStatus, "AT+CPMS" ,0x00,0x00,ID_GetSMSStatus },
3457 {ATGEN_ReplyGetSMSMemories, "AT+CPMS=?" ,0x00,0x00,ID_GetSMSMemories },
3458 {ATGEN_ReplyAddSMSMessage, "AT+CMGW" ,0x00,0x00,ID_SaveSMSMessage },
3459 {ATGEN_GenericReply, "AT+CSMP" ,0x00,0x00,ID_SetSMSParameters },
3460 {ATGEN_GenericReply, "AT+CSCA" ,0x00,0x00,ID_SetSMSC },
3461 {ATGEN_ReplyGetSMSC, "AT+CSCA?" ,0x00,0x00,ID_GetSMSC },
3462 {ATGEN_ReplyDeleteSMSMessage, "AT+CMGD" ,0x00,0x00,ID_DeleteSMSMessage },
3463 {ATGEN_GenericReply, "ATE1" ,0x00,0x00,ID_SetSMSParameters },
3464 {ATGEN_GenericReply, "\x1b\x0D" ,0x00,0x00,ID_SetSMSParameters },
3465 {ATGEN_IncomingSMSInfo, "+CMTI:" ,0x00,0x00,ID_IncomingFrame },
3466 {ATGEN_IncomingSMSDeliver, "+CMT:" ,0x00,0x00,ID_IncomingFrame },
3467 {ATGEN_IncomingSMSReport, "+CDS:" ,0x00,0x00,ID_IncomingFrame },
3468 {ATGEN_IncomingSMSCInfo, "^SCN:" ,0x00,0x00,ID_IncomingFrame },
3469
3470 {ATGEN_ReplyGetDateTime_Alarm, "AT+CCLK?" ,0x00,0x00,ID_GetDateTime },
3471 {ATGEN_GenericReply, "AT+CCLK=" ,0x00,0x00,ID_SetDateTime },
3472 {ATGEN_ReplyGetDateTime_Alarm, "AT+CALA?" ,0x00,0x00,ID_GetAlarm },
3473
3474 {ATGEN_ReplyGetNetworkLAC_CID, "AT+CREG?" ,0x00,0x00,ID_GetNetworkInfo },
3475 {ATGEN_GenericReply, "AT+CREG=2" ,0x00,0x00,ID_GetNetworkInfo },
3476 {ATGEN_GenericReply, "AT+COPS=" ,0x00,0x00,ID_GetNetworkInfo },
3477 {ATGEN_GenericReply, "AT+COPS=" ,0x00,0x00,ID_SetAutoNetworkLogin},
3478 {ATGEN_ReplyGetNetworkCode, "AT+COPS" ,0x00,0x00,ID_GetNetworkInfo },
3479 {ATGEN_ReplyGetSignalQuality, "AT+CSQ" ,0x00,0x00,ID_GetSignalQuality },
3480 {ATGEN_IncomingNetworkLevel, "_OSIGQ:" ,0x00,0x00,ID_IncomingFrame },
3481 {ATGEN_IncomingGPRS, "+CGREG:" ,0x00,0x00,ID_IncomingFrame },
3482 {ATGEN_ReplyGetNetworkLAC_CID, "+CREG:" ,0x00,0x00,ID_IncomingFrame },
3483
3484 {ATGEN_ReplyGetPBKMemories, "AT+CPBS=?" ,0x00,0x00,ID_SetMemoryType },
3485 {ATGEN_GenericReply, "AT+CPBS=" ,0x00,0x00,ID_SetMemoryType },
3486 {ATGEN_ReplyGetCPBSMemoryStatus,"AT+CPBS?" ,0x00,0x00,ID_GetMemoryStatus },
3487 {ATGEN_ReplyGetCPBRMemoryInfo, "AT+CPBR=?" ,0x00,0x00,ID_GetMemoryStatus },
3488 {ATGEN_ReplyGetCPBRMemoryStatus,"AT+CPBR=" ,0x00,0x00,ID_GetMemoryStatus },
3489 {ATGEN_GenericReply, "AT+CSCS=" ,0x00,0x00,ID_SetMemoryCharset },
3490 {ATGEN_ReplyGetMemory, "AT+CPBR=" ,0x00,0x00,ID_GetMemory },
3491 {ATGEN_GenericReply, "AT^SBNR=?" ,0x00,0x00,ID_GetMemory },
3492 {ATGEN_SL45ReplyGetMemory, "AT^SBNR" ,0x00,0x00,ID_GetMemory },
3493 {ATGEN_ReplySetMemory, "AT+CPBW" ,0x00,0x00,ID_SetMemory },
3494
3495 {ATGEN_CMS35ReplyGetBitmap, "AT^SBNR=\"bmp\"" ,0x00,0x00,ID_GetBitmap },
3496 {ATGEN_CMS35ReplySetBitmap, "AT^SBNW=\"bmp\"" ,0x00,0x00,ID_SetBitmap },
3497
3498 {ATGEN_CMS35ReplyGetRingtone, "AT^SBNR=\"mid\"" ,0x00,0x00,ID_GetRingtone },
3499 {ATGEN_CMS35ReplySetRingtone, "AT^SBNW=\"mid\"" ,0x00,0x00,ID_SetRingtone },
3500
3501 {ATGEN_CMS35ReplyGetNextCal, "AT^SBNR=\"vcs\"" ,0x00,0x00,ID_GetCalendarNote },
3502 {ATGEN_CMS35ReplySetCalendar, "AT^SBNW=\"vcs\"" ,0x00,0x00,ID_SetCalendarNote },
3503 {ATGEN_CMS35ReplyDeleteCalendar,"AT^SBNW=\"vcs\"",0x00,0x00,ID_DeleteCalendarNote },
3504
3505 {ATGEN_ReplyEnterSecurityCode, "AT+CPIN=" ,0x00,0x00,ID_EnterSecurityCode },
3506 {ATGEN_ReplyEnterSecurityCode, "AT+CPIN2=" ,0x00,0x00,ID_EnterSecurityCode },
3507 {ATGEN_ReplyGetSecurityStatus, "AT+CPIN?" ,0x00,0x00,ID_GetSecurityStatus },
3508 {ATGEN_ReplyOK, "OK" ,0x00,0x00,ID_IncomingFrame },
3509
3510 {ATGEN_GenericReply, "AT+VTS" ,0x00,0x00,ID_SendDTMF },
3511 {ATGEN_ReplyCancelCall, "AT+CHUP" ,0x00,0x00,ID_CancelCall },
3512 {ATGEN_ReplyDialVoice, "ATDT" ,0x00,0x00,ID_DialVoice },
3513 {ATGEN_ReplyCancelCall, "ATH" ,0x00,0x00,ID_CancelCall },
3514 {ATGEN_GenericReply, "AT+CLIP=1" ,0x00,0x00,ID_IncomingFrame },
3515 {ATGEN_ReplyIncomingCallInfo, "+CLIP" ,0x00,0x00,ID_IncomingFrame },
3516 {ATGEN_ReplyIncomingCallInfo, "+COLP" ,0x00,0x00,ID_IncomingFrame },
3517 {ATGEN_ReplyIncomingCallInfo, "RING" ,0x00,0x00,ID_IncomingFrame },
3518 {ATGEN_ReplyIncomingCallInfo, "NO CARRIER" ,0x00,0x00,ID_IncomingFrame },
3519
3520 {ATGEN_ReplyReset, "AT^SRESET" ,0x00,0x00,ID_Reset },
3521 {ATGEN_ReplyReset, "AT+CFUN=1,1" ,0x00,0x00,ID_Reset },
3522 {ATGEN_ReplyResetPhoneSettings, "AT&F" ,0x00,0x00,ID_ResetPhoneSettings },
3523
3524#ifdef GSM_ENABLE_ALCATEL
3525/* Why do I give Alcatel specific things here? It's simple, Alcatel needs
3526 * some AT commands to start it's binary mode, so this needs to be in AT
3527 * related stuff.
3528 *
3529 * XXX: AT+IFC could later move outside this ifdef, because it is not Alcatel
3530 * specific and it's part of ETSI specifications
3531 */
3532 {ATGEN_GenericReply, "AT+IFC" ,0x00,0x00,ID_SetFlowControl },
3533 {ALCATEL_ProtocolVersionReply, "AT+CPROT=?" ,0x00,0x00,ID_AlcatelProtocol },
3534 {ATGEN_GenericReply, "AT+CPROT" ,0x00,0x00,ID_AlcatelConnect },
3535#endif
3536
3537 {NULL, "\x00" ,0x00,0x00,ID_None }
3538};
3539
3540GSM_Phone_Functions ATGENPhone = {
3541 "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",
3542 ATGENReplyFunctions,
3543 ATGEN_Initialise,
3544 ATGEN_Terminate,
3545 ATGEN_DispatchMessage,
3546 NOTSUPPORTED, /* ShowStartInfo */
3547 ATGEN_GetManufacturer,
3548 ATGEN_GetModel,
3549 ATGEN_GetFirmware,
3550 ATGEN_GetIMEI,
3551 NOTSUPPORTED, /* GetOriginalIMEI */
3552 NOTSUPPORTED, /* GetManufactureMonth*/
3553 NOTSUPPORTED, /* GetProductCode */
3554 NOTSUPPORTED, /* GetHardware */
3555 NOTSUPPORTED, /* GetPPM */
3556 ATGEN_GetSIMIMSI,
3557 ATGEN_GetDateTime,
3558 ATGEN_SetDateTime,
3559 ATGEN_GetAlarm,
3560 NOTIMPLEMENTED, /* SetAlarm */
3561 NOTSUPPORTED, /* GetLocale */
3562 NOTSUPPORTED, /* SetLocale */
3563 ATGEN_PressKey,
3564 ATGEN_Reset,
3565 ATGEN_ResetPhoneSettings,
3566 ATGEN_EnterSecurityCode,
3567 ATGEN_GetSecurityStatus,
3568 ATGEN_GetDisplayStatus,
3569 ATGEN_SetAutoNetworkLogin,
3570 ATGEN_GetBatteryCharge,
3571 ATGEN_GetSignalQuality,
3572 ATGEN_GetNetworkInfo,
3573 NOTSUPPORTED, /* GetCategory */
3574 NOTSUPPORTED, /* AddCategory */
3575 NOTSUPPORTED, /* GetCategoryStatus */
3576 ATGEN_GetMemoryStatus,
3577 ATGEN_GetMemory,
3578 ATGEN_GetNextMemory,
3579 ATGEN_SetMemory,
3580 ATGEN_AddMemory,
3581 ATGEN_DeleteMemory,
3582 ATGEN_DeleteAllMemory,
3583 NOTSUPPORTED, /* GetSpeedDial */
3584 NOTSUPPORTED, /* SetSpeedDial */
3585 ATGEN_GetSMSC,
3586 ATGEN_SetSMSC,
3587 ATGEN_GetSMSStatus,
3588 ATGEN_GetSMS,
3589 ATGEN_GetNextSMS,
3590 NOTSUPPORTED, /* SetSMS */
3591 ATGEN_AddSMS,
3592 ATGEN_DeleteSMS,
3593 ATGEN_SendSMS,
3594 ATGEN_SendSavedSMS,
3595 ATGEN_SetIncomingSMS,
3596 ATGEN_SetIncomingCB,
3597 ATGEN_GetSMSFolders,
3598 NOTSUPPORTED, /* AddSMSFolder */
3599 NOTSUPPORTED, /* DeleteSMSFolder */
3600 ATGEN_DialVoice,
3601 ATGEN_AnswerCall,
3602 ATGEN_CancelCall,
3603 NOTSUPPORTED, /* HoldCall */
3604 NOTSUPPORTED, /* UnholdCall */
3605 NOTSUPPORTED, /* ConferenceCall */
3606 NOTSUPPORTED, /* SplitCall */
3607 NOTSUPPORTED, /* TransferCall */
3608 NOTSUPPORTED, /* SwitchCall */
3609 NOTSUPPORTED, /* GetCallDivert */
3610 NOTSUPPORTED, /* SetCallDivert */
3611 NOTSUPPORTED, /* CancelAllDiverts*/
3612 NONEFUNCTION, /* SetIncomingCall */
3613 NOTSUPPORTED, /* SetIncomingUSSD */
3614 ATGEN_SendDTMF,
3615 ATGEN_GetRingtone,
3616 ATGEN_SetRingtone,
3617 NOTSUPPORTED, /* GetRingtonesInfo*/
3618 NOTSUPPORTED, /* DeleteUserRingtones*/
3619 NOTSUPPORTED, /* PlayTone */
3620 NOTSUPPORTED, /* GetWAPBookmark */
3621 NOTSUPPORTED, /* SetWAPBookmark */
3622 NOTSUPPORTED, /* DeleteWAPBookmark */
3623 NOTSUPPORTED, /* GetWAPSettings */
3624 NOTSUPPORTED, /* SetWAPSettings */
3625 NOTSUPPORTED, /* GetMMSSettings */
3626 NOTSUPPORTED, /* SetMMSSettings */
3627 NOTSUPPORTED, /* GetSyncMLSettings*/
3628 NOTSUPPORTED, /* SetSyncMLSettings*/
3629 NOTSUPPORTED, /* GetChatSettings */
3630 NOTSUPPORTED, /* SetChatSettings */
3631 ATGEN_GetBitmap, /* GetBitmap */
3632 ATGEN_SetBitmap, /* SetBitmap */
3633 SONYERIC_GetToDoStatus,
3634 NOTSUPPORTED, /* GetToDo */
3635 SONYERIC_GetNextToDo,
3636 NOTSUPPORTED, /* SetToDo */
3637 SONYERIC_AddToDo,
3638 NOTSUPPORTED, /* DeleteToDo */
3639 SONYERIC_DeleteAllToDo,
3640 SONYERIC_GetCalendarStatus,
3641 NOTIMPLEMENTED, /* GetCalendar */
3642 ATGEN_GetNextCalendar,
3643 NOTIMPLEMENTED, /* SetCalendar */
3644 ATGEN_AddCalendarNote,
3645 ATGEN_DelCalendarNote,
3646 NOTIMPLEMENTED, /* DeleteAllCalendar*/
3647 NOTSUPPORTED, /* GetCalendarSettings*/
3648 NOTSUPPORTED, /* SetCalendarSettings*/
3649 NOTSUPPORTED, /* GetNote */
3650 NOTSUPPORTED, /* GetProfile */
3651 NOTSUPPORTED, /* SetProfile */
3652 NOTSUPPORTED, /* GetFMStation */
3653 NOTSUPPORTED, /* SetFMStation */
3654 NOTSUPPORTED, /* ClearFMStations */
3655 NOTSUPPORTED, /* GetNextFileFolder*/
3656 NOTSUPPORTED, /* GetFilePart */
3657 NOTSUPPORTED, /* AddFile */
3658 NOTSUPPORTED, /* GetFileSystemStatus*/
3659 NOTSUPPORTED, /* DeleteFile */
3660 NOTSUPPORTED, /* AddFolder */
3661 NOTSUPPORTED, /* GetGPRSAccessPoint*/
3662 NOTSUPPORTED /* SetGPRSAccessPoint*/
3663};
3664
3665#endif
3666
3667/* How should editor hadle tabs in this file? Add editor commands here.
3668 * vim: noexpandtab sw=8 ts=8 sts=8:
3669 */
diff --git a/gammu/emb/common/phone/at/atgen.h b/gammu/emb/common/phone/at/atgen.h
new file mode 100644
index 0000000..0e08ee4
--- a/dev/null
+++ b/gammu/emb/common/phone/at/atgen.h
@@ -0,0 +1,110 @@
1/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
2
3#ifndef atgen_h
4#define atgen_h
5
6#include "../../gsmcomon.h"
7#include "../../gsmstate.h"
8#include "../../service/sms/gsmsms.h"
9
10#ifndef GSM_USED_AT
11# define GSM_USED_AT
12#endif
13#ifndef GSM_USED_BLUEAT
14# define GSM_USED_BLUEAT
15#endif
16#ifndef GSM_USED_IRDAAT
17# define GSM_USED_IRDAAT
18#endif
19
20#define MAX_VCALENDAR_LOCATION 50
21
22typedef enum {
23 SMS_AT_PDU = 1,
24 SMS_AT_TXT
25} GSM_AT_SMS_Modes;
26
27typedef enum {
28 AT_Reply_OK = 1,
29 AT_Reply_Connect,
30 AT_Reply_Error,
31 AT_Reply_Unknown,
32 AT_Reply_CMSError,
33 AT_Reply_CMEError,
34 AT_Reply_SMSEdit
35} GSM_AT_Reply_State;
36
37typedef enum {
38 AT_Nokia = 1,
39 AT_Alcatel,
40 AT_Siemens,
41 AT_HP,
42 AT_Falcom,
43 AT_Ericsson,
44 AT_Sagem,
45 AT_Unknown
46} GSM_AT_Manufacturer;
47
48typedef enum {
49 AT_PBK_HEX = 1,
50 AT_PBK_GSM,
51 AT_PBK_UCS2
52} GSM_AT_PBK_Charset;
53
54typedef enum {
55 AT_AVAILABLE = 1,
56 AT_NOTAVAILABLE
57} GSM_AT_SMSMemory;
58
59typedef enum {
60 AT_SBNR_AVAILABLE = 1,
61 AT_SBNR_NOTAVAILABLE
62} GSM_AT_SBNR;
63
64typedef enum {
65 AT_Status,
66 AT_NextEmpty,
67 AT_Total,
68 AT_First,
69 AT_Sizes
70} GSM_AT_NeededMemoryInfo;
71
72 #define AT_PBK_MAX_MEMORIES200
73
74typedef struct {
75 GSM_AT_Manufacturer Manufacturer; /* Who is manufacturer */
76 GSM_Lines Lines; /* Allow to simply get each line in response */
77 GSM_AT_Reply_State ReplyState; /* What response type - error, OK, etc. */
78 int ErrorCode; /* Error codes from responses */
79 char *ErrorText; /* Error description */
80
81 GSM_MemoryType PBKMemory; /* Last read PBK memory */
82 char PBKMemories[AT_PBK_MAX_MEMORIES + 1]; /* Supported by phone PBK memories */
83 int NextMemoryEntry; /* Next empty memory entry */
84 int FirstMemoryEntry; /* First memory entry to be read */
85 GSM_AT_PBK_Charset PBKCharset; /* Last read PBK charset */
86 bool UCS2CharsetFailed; /* Whether setting of UCS2 charset has already failed */
87 bool NonUCS2CharsetFailed; /* Whether setting of non-UCS2 charset has already failed */
88 GSM_AT_SBNR PBKSBNR;
89 int NumberLength;
90 int TextLength;
91 int MemorySize;
92
93 GSM_SMSMemoryStatusLastSMSStatus;
94 int LastSMSRead;
95 int FirstCalendarPos;
96 bool CanSaveSMS;
97 GSM_AT_SMSMemory PhoneSMSMemory; /* Is phone SMS memory available ? */
98 GSM_AT_SMSMemory SIMSMSMemory; /* Is SIM SMS memory available ? */
99 GSM_MemoryType SMSMemory; /* Last read SMS memory */
100 GSM_AT_SMS_Modes SMSMode; /* PDU or TEXT mode for SMS ? */
101
102 bool OBEX;
103 GSM_File file;
104} GSM_Phone_ATGENData;
105
106#endif
107
108/* How should editor hadle tabs in this file? Add editor commands here.
109 * vim: noexpandtab sw=8 ts=8 sts=8:
110 */
diff --git a/gammu/emb/common/phone/at/siemens.c b/gammu/emb/common/phone/at/siemens.c
new file mode 100644
index 0000000..ab7dd2c
--- a/dev/null
+++ b/gammu/emb/common/phone/at/siemens.c
@@ -0,0 +1,320 @@
1/* (c) 2002-2003 by Walek */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_ATGEN
6
7#include <string.h>
8#include <time.h>
9#include <ctype.h>
10
11#include "../../misc/coding/coding.h"
12#include "../../gsmcomon.h"
13#include "../../service/sms/gsmsms.h"
14#include "../pfunc.h"
15
16extern GSM_Error ATGEN_HandleCMSError(GSM_StateMachine *s);
17
18GSM_Error ATGEN_CMS35ReplySetFunction (GSM_Protocol_Message msg, GSM_StateMachine *s,char *function)
19{
20 if (s->Protocol.Data.AT.EditMode) {
21 s->Protocol.Data.AT.EditMode = false;
22 return ERR_NONE;
23 }
24 dbgprintf ("Written %s",function);
25 if (s->Phone.Data.Priv.ATGEN.ReplyState == AT_Reply_OK){
26 dbgprintf (" - OK\n");
27 return ERR_NONE;
28 } else {
29 dbgprintf (" - error\n");
30 return ERR_UNKNOWN;
31 }
32}
33
34GSM_Error GetSiemensFrame(GSM_Protocol_Message msg, GSM_StateMachine *s, char *templ,
35 unsigned char *buffer, int *len)
36{
37 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
38 int i=2, pos=0, length=0;
39 unsigned char buf[512];
40
41 if (strstr(GetLineString(msg.Buffer,Priv->Lines,2),"OK")) return ERR_EMPTY;
42 if (!strstr(GetLineString(msg.Buffer,Priv->Lines,2),templ)) return ERR_UNKNOWN;
43
44 while (1) {
45 if (Priv->Lines.numbers[i*2+1]==0) break;
46 if ((!strstr(GetLineString(msg.Buffer,Priv->Lines,i+1),templ)) &&
47 (strstr(GetLineString(msg.Buffer,Priv->Lines,i),templ))){
48 length = strlen(GetLineString(msg.Buffer,Priv->Lines,i+1));
49 DecodeHexBin(buf, GetLineString(msg.Buffer,Priv->Lines,i+1),length);
50 length = length/2;
51 memcpy (buffer+pos,buf,length);
52 pos+=length;
53 }
54 i++;
55 }
56 *len = pos;
57 return ERR_NONE;
58}
59
60GSM_Error SetSiemensFrame (GSM_StateMachine *s, unsigned char *buff, char *templ,
61 int Location, GSM_Phone_RequestID RequestID, int len)
62{
63 GSM_Phone_Data *Phone = &s->Phone.Data;
64 GSM_Error error;
65 unsigned char req[20],req1[512],hexreq[2096];
66 int MaxFrame,CurrentFrame,size,sz,pos=0;
67
68 EncodeHexBin(hexreq,buff,len);
69 size = len * 2;
70 MaxFrame = size / 352;
71 if (size % 352) MaxFrame++;
72
73 for (CurrentFrame=0;CurrentFrame<MaxFrame;CurrentFrame++) {
74 pos=CurrentFrame*352;
75 if (pos+352 < size) sz = 352; else sz = size - pos;
76 sprintf(req, "AT^SBNW=\"%s\",%i,%i,%i\r",templ,Location,CurrentFrame+1,MaxFrame);
77 s->Protocol.Data.AT.EditMode = true;
78 error = GSM_WaitFor (s, req, strlen(req), 0x00, 3, RequestID);
79 s->Phone.Data.DispatchError=ERR_TIMEOUT;
80 s->Phone.Data.RequestID=RequestID;
81 if (error!=ERR_NONE) return error;
82 memcpy (req1,hexreq+pos,sz);
83 error = s->Protocol.Functions->WriteMessage(s, req1, sz, 0x00);
84 if (error!=ERR_NONE) return error;
85 error = s->Protocol.Functions->WriteMessage(s,"\x1A", 1, 0x00);
86 if (error!=ERR_NONE) return error;
87 error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 4);
88 if (error == ERR_TIMEOUT) return error;
89 }
90 return Phone->DispatchError;
91}
92
93GSM_Error ATGEN_CMS35ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
94{
95 unsigned char buffer[4096];
96 int length;
97 GSM_Error error;
98
99 error = GetSiemensFrame(msg,s,"bmp",buffer,&length);
100 if (error!=ERR_NONE) return error;
101 dbgprintf ("Operator logo received lenght=%i\n",length);
102 error = BMP2Bitmap (buffer,NULL,s->Phone.Data.Bitmap);
103 if (error==ERR_NONE) return error;
104 else return ERR_UNKNOWN;
105}
106
107GSM_Error ATGEN_CMS35ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s)
108{
109 return ATGEN_CMS35ReplySetFunction (msg, s, "Operator Logo");
110}
111
112GSM_Error ATGEN_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
113{
114 unsigned char req[32];
115
116 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
117 if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
118 if (Bitmap->Location-1 < 0) Bitmap->Location++;
119 s->Phone.Data.Bitmap=Bitmap;
120 sprintf(req, "AT^SBNR=\"bmp\",%i\r", Bitmap->Location-1);
121 smprintf(s, "Getting Bitmap\n");
122 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetBitmap);
123}
124
125GSM_Error ATGEN_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
126{
127 unsigned char buffer[4096];
128 int length;
129 GSM_Errorerror;
130
131 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
132 if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
133
134 error = Bitmap2BMP (buffer,NULL,Bitmap);
135 if (error!=ERR_NONE) return error;
136 length = 0x100 * buffer[3] + buffer[2];
137 buffer[58]=0xff; buffer[59]=0xff; buffer[60]=0xff;
138 if (Bitmap->Location-1 < 0) Bitmap->Location++;
139 s->Phone.Data.Bitmap=Bitmap;
140 return SetSiemensFrame(s, buffer,"bmp",Bitmap->Location-1,
141 ID_SetBitmap,length);
142}
143
144GSM_Error ATGEN_CMS35ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
145{
146 unsigned char buffer[32];
147 int length;
148 GSM_Error error;
149
150 error = GetSiemensFrame(msg,s,"mid",s->Phone.Data.Ringtone->NokiaBinary.Frame,&length);
151 if (error!=ERR_NONE) return error;
152 dbgprintf ("Midi ringtone received\n");
153
154 s->Phone.Data.Ringtone->Format = RING_MIDI;
155 s->Phone.Data.Ringtone->NokiaBinary.Length= length;
156 sprintf(buffer,"Individual");
157 EncodeUnicode (s->Phone.Data.Ringtone->Name,buffer,strlen(buffer));
158 return ERR_NONE;
159}
160
161GSM_Error ATGEN_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
162{
163 unsigned char req[32];
164
165 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
166
167 s->Phone.Data.Ringtone=Ringtone;
168 sprintf(req, "AT^SBNR=\"mid\",%i\r", Ringtone->Location-1);
169 smprintf(s, "Getting RingTone\n");
170 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetRingtone);
171}
172
173GSM_Error ATGEN_CMS35ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
174{
175 return ATGEN_CMS35ReplySetFunction (msg, s, "Ringtone");
176}
177
178GSM_Error ATGEN_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
179{
180 GSM_Phone_Data *Phone = &s->Phone.Data;
181
182 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
183
184 if (Ringtone->Location==255) Ringtone->Location=1;
185 if (Ringtone->Location-1 > 1) return ERR_INVALIDLOCATION;
186
187 s->Phone.Data.Ringtone= Ringtone;
188 Phone->Ringtone = Ringtone;
189 return SetSiemensFrame(s, Ringtone->NokiaBinary.Frame,"mid",Ringtone->Location-1,
190 ID_SetRingtone,Ringtone->NokiaBinary.Length);
191}
192
193GSM_Error ATGEN_CMS35ReplyGetNextCal(GSM_Protocol_Message msg, GSM_StateMachine *s)
194{
195 GSM_Phone_Data *Data = &s->Phone.Data;
196 GSM_CalendarEntry*Calendar = Data->Cal;
197 GSM_ToDoEntry ToDo;
198 GSM_Error error;
199 unsigned char buffer[354];
200 int len, pos=0;
201
202 if (Data->Priv.ATGEN.ReplyState != AT_Reply_OK) return ERR_UNKNOWN;
203
204 error = GetSiemensFrame(msg,s,"vcs",buffer,&len);
205 if (error!=ERR_NONE) return error;
206 error=GSM_DecodeVCALENDAR_VTODO(buffer,&pos,Calendar,&ToDo,Siemens_VCalendar,0);
207
208 return error;
209}
210
211GSM_Error SIEMENS_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
212{
213 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
214 GSM_Error error;
215 unsigned char req[32];
216 int Location;
217
218 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
219
220 if (start) Note->Location=Priv->FirstCalendarPos;
221 s->Phone.Data.Cal = Note;
222 Note->EntriesNum = 0;
223 smprintf(s, "Getting VCALENDAR\n");
224 Location = Note->Location;
225 while (1){
226 Location++;
227 sprintf(req, "AT^SBNR=\"vcs\",%i\r",Location);
228 error = GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetCalendarNote);
229 if ((error!=ERR_NONE) && (error!=ERR_EMPTY)) return ERR_INVALIDLOCATION;
230 Note->Location = Location;
231 Priv->FirstCalendarPos = Location;
232 if (Location > MAX_VCALENDAR_LOCATION) return ERR_EMPTY;
233 if (error==ERR_NONE) return error;
234 }
235 return error;
236}
237
238GSM_Error ATGEN_CMS35ReplySetCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
239{
240 return ATGEN_CMS35ReplySetFunction (msg, s, "Calendar Note");
241}
242
243GSM_Error ATGEN_CMS35ReplyDeleteCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
244{
245 GSM_Phone_Data *Data = &s->Phone.Data;
246
247 if (Data->Cal->Location > MAX_VCALENDAR_LOCATION) return ERR_UNKNOWN;
248
249 if (Data->Priv.ATGEN.ReplyState== AT_Reply_OK) {
250 smprintf(s, "Calendar note deleted\n");
251 return ERR_NONE;
252 } else {
253 smprintf(s, "Can't delete calendar note\n");
254 return ERR_UNKNOWN;
255 }
256}
257
258GSM_Error SIEMENS_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
259{
260 unsigned char req[32];
261
262 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
263 s->Phone.Data.Cal = Note;
264 sprintf(req, "AT^SBNW=\"vcs\",%i,0\r",Note->Location);
265 smprintf(s, "Deleting calendar note\n");
266 return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_DeleteCalendarNote);
267}
268
269GSM_Error SIEMENS_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
270{
271 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
272 GSM_Error error;
273 unsigned char req[500];
274 int size=0;
275
276 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
277 // if (Note->Location==0x00) return ERR_INVALIDLOCATION;
278
279 s->Phone.Data.Cal = Note;
280 error=GSM_EncodeVCALENDAR(req,&size,Note,true,Siemens_VCalendar);
281
282 return SetSiemensFrame (s,req,"vcs",Note->Location,ID_SetCalendarNote,size);
283}
284
285/* (c) by Timo Teras */
286GSM_Error ATGEN_SL45ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
287{
288#ifndef ENABLE_LGPL
289 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
290 GSM_MemoryEntry *Memory = s->Phone.Data.Memory;
291 unsigned char buffer[500],buffer2[500];
292
293 switch (Priv->ReplyState) {
294 case AT_Reply_OK:
295 smprintf(s, "Phonebook entry received\n");
296 CopyLineString(buffer, msg.Buffer, Priv->Lines, 3);
297 DecodeHexBin(buffer2,buffer,strlen(buffer));
298 Memory->EntriesNum = 0;
299 DecodeVCARD21Text(buffer2, Memory);
300 if (Memory->EntriesNum == 0) return ERR_EMPTY;
301 return ERR_NONE;
302 case AT_Reply_Error:
303 smprintf(s, "Error - too high location ?\n");
304 return ERR_INVALIDLOCATION;
305 case AT_Reply_CMSError:
306 return ATGEN_HandleCMSError(s);
307 default:
308 break;
309 }
310 return ERR_UNKNOWNRESPONSE;
311#else
312 return ERR_NOTIMPLEMENTED;
313#endif
314}
315
316#endif
317
318/* How should editor hadle tabs in this file? Add editor commands here.
319 * vim: noexpandtab sw=8 ts=8 sts=8:
320 */
diff --git a/gammu/emb/common/phone/at/sonyeric.c b/gammu/emb/common/phone/at/sonyeric.c
new file mode 100644
index 0000000..4b2670a
--- a/dev/null
+++ b/gammu/emb/common/phone/at/sonyeric.c
@@ -0,0 +1,411 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include "../../gsmstate.h"
4
5#ifdef GSM_ENABLE_ATGEN
6
7#include <string.h>
8#include <time.h>
9#include <ctype.h>
10
11#include "../../gsmcomon.h"
12#include "../../misc/coding/coding.h"
13
14 extern GSM_Reply_Function ATGENReplyFunctions[];
15 extern GSM_Error ATGEN_DispatchMessage(GSM_StateMachine *s);
16
17#ifdef GSM_ENABLE_OBEXGEN
18
19 extern GSM_Reply_Function OBEXGENReplyFunctions[];
20 extern GSM_Error OBEXGEN_GetFilePart(GSM_StateMachine *s, GSM_File *File);
21 extern GSM_Error OBEXGEN_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos);
22 extern GSM_Error OBEXGEN_Disconnect(GSM_StateMachine *s);
23
24#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
25
26static GSM_Error SONYERIC_SetOBEXMode(GSM_StateMachine *s)
27{
28 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
29 GSM_Error error;
30
31 if (Priv->OBEX) return ERR_NONE;
32
33 dbgprintf ("Changing to OBEX\n");
34
35 error=GSM_WaitFor (s, "AT*EOBEX\r", 9, 0x00, 4, ID_SetOBEX);
36 if (error != ERR_NONE) return error;
37
38 error = s->Protocol.Functions->Terminate(s);
39 if (error != ERR_NONE) return error;
40
41 s->Protocol.Functions = &OBEXProtocol;
42 error = s->Protocol.Functions->Initialise(s);
43 if (error != ERR_NONE) {
44 s->Protocol.Functions = &ATProtocol;
45 return error;
46 }
47 strcpy(s->CurrentConfig->Model,"seobex");
48 s->Phone.Data.Priv.OBEXGEN.Service = 0;
49 s->Phone.Functions->DispatchMessage= GSM_DispatchMessage;
50 s->Phone.Functions->ReplyFunctions= OBEXGENReplyFunctions;
51 Priv->OBEX = true;
52 return ERR_NONE;
53}
54
55static GSM_Error SONYERIC_SetATMode(GSM_StateMachine *s)
56{
57 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
58 GSM_Error error;
59
60 if (!Priv->OBEX) return ERR_NONE;
61
62 dbgprintf ("Changing to AT\n");
63
64 error = OBEXGEN_Disconnect(s);
65 if (error != ERR_NONE) return error;
66
67 error = s->Protocol.Functions->Terminate(s);
68 if (error != ERR_NONE) return error;
69
70 s->Protocol.Functions = &ATProtocol;
71 error = s->Protocol.Functions->Initialise(s);
72 if (error != ERR_NONE) {
73 s->Protocol.Functions = &OBEXProtocol;
74 return error;
75 }
76 strcpy(s->CurrentConfig->Model,"at");
77 s->Phone.Functions->DispatchMessage= ATGEN_DispatchMessage;
78 s->Phone.Functions->ReplyFunctions= ATGENReplyFunctions;
79 Priv->OBEX = false;
80 return ERR_NONE;
81}
82
83static GSM_Error SONYERIC_GetFile(GSM_StateMachine *s, GSM_File *File, unsigned char *FileName)
84{
85 GSM_Error error;
86
87 strcpy(File->ID_FullName,FileName);
88 File->Used = 0;
89 if (File->Buffer != NULL) free(File->Buffer);
90 File->Buffer = NULL;
91
92 error = SONYERIC_SetOBEXMode(s);
93 if (error != ERR_NONE) return error;
94
95 error = ERR_NONE;
96 while (error == ERR_NONE) error = OBEXGEN_GetFilePart(s,File);
97 if (error != ERR_EMPTY) return error;
98
99 return SONYERIC_SetATMode(s);
100}
101
102static GSM_Error SONYERIC_SetFile(GSM_StateMachine *s, unsigned char *FileName, unsigned char *Buffer, int Length)
103{
104 GSM_Errorerror;
105 GSM_File File;
106 int Pos = 0;
107
108 error = SONYERIC_SetOBEXMode(s);
109 if (error != ERR_NONE) return error;
110
111 strcpy(File.ID_FullName,FileName);
112 EncodeUnicode(File.Name,FileName,strlen(FileName));
113 File.Used = Length;
114 File.Buffer = malloc(Length);
115 memcpy(File.Buffer,Buffer,Length);
116
117 error = ERR_NONE;
118 while (error == ERR_NONE) error = OBEXGEN_AddFilePart(s,&File,&Pos);
119 free(File.Buffer);
120 if (error != ERR_EMPTY) return error;
121
122 return SONYERIC_SetATMode(s);
123}
124
125#endif
126
127GSM_Error SONYERIC_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
128{
129#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
130 GSM_Error error;
131 GSM_ToDoEntry ToDo;
132 int Pos, num, Loc;
133 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
134
135 if (start) {
136 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
137 if (error != ERR_NONE) return error;
138
139 Note->Location = 1;
140 } else {
141 Note->Location++;
142 }
143 smprintf(s, "Getting calendar note %i\n",Note->Location);
144
145 Loc = Note->Location;
146 Pos = 0;
147 num = 0;
148 while (1) {
149 error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, Note, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
150 if (error == ERR_EMPTY) break;
151 if (error != ERR_NONE) return error;
152 if (Note->EntriesNum != 0) {
153 num++;
154 if (num == Loc) return ERR_NONE;
155 }
156 }
157 return ERR_EMPTY;
158#else
159 return ERR_SOURCENOTAVAILABLE;
160#endif
161}
162
163GSM_Error SONYERIC_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool start)
164{
165#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
166 GSM_Error error;
167 GSM_CalendarEntryCalendar;
168 int Pos, num, Loc;
169 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
170
171 if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
172
173 if (start) {
174 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
175 if (error != ERR_NONE) return error;
176
177 ToDo->Location = 1;
178 } else {
179 ToDo->Location++;
180 }
181 smprintf(s,"Getting ToDo %i\n",ToDo->Location);
182
183 Loc = ToDo->Location;
184 Pos = 0;
185 num = 0;
186 while (1) {
187 error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
188 if (error == ERR_EMPTY) break;
189 if (error != ERR_NONE) return error;
190 if (ToDo->EntriesNum != 0) {
191 num++;
192 if (num == Loc) return ERR_NONE;
193 }
194 }
195
196 return ERR_EMPTY;
197#else
198 return ERR_SOURCENOTAVAILABLE;
199#endif
200}
201
202GSM_Error SONYERIC_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
203{
204#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
205 GSM_Error error;
206 GSM_ToDoEntry ToDo;
207 GSM_CalendarEntry Calendar;
208 int Pos;
209 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
210
211 if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
212
213 smprintf(s,"Getting ToDo status\n");
214
215 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
216 if (error != ERR_NONE) return error;
217
218 status->Used = 0;
219 Pos = 0;
220 while (1) {
221 error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
222 if (error == ERR_EMPTY) break;
223 if (error != ERR_NONE) return error;
224 if (ToDo.EntriesNum != 0) status->Used++;
225 }
226
227 return ERR_NONE;
228#else
229 return ERR_SOURCENOTAVAILABLE;
230#endif
231}
232
233GSM_Error SONYERIC_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
234{
235#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
236 unsigned char req[5000];
237 int size=0;
238
239 smprintf(s,"Adding calendar note\n");
240
241 GSM_EncodeVCALENDAR(req,&size,Note,true,SonyEricsson_VCalendar);
242
243 return SONYERIC_SetFile(s, "telecom/cal/luid/.vcs", req, size);
244#else
245 return ERR_SOURCENOTAVAILABLE;
246#endif
247}
248
249GSM_Error SONYERIC_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
250{
251#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
252 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
253 unsigned char req[5000];
254 int size=0;
255
256 if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
257
258 smprintf(s,"Adding ToDo\n");
259
260 GSM_EncodeVTODO(req,&size,ToDo,true,SonyEricsson_VToDo);
261
262 return SONYERIC_SetFile(s, "telecom/cal/luid/.vcs", req, size);
263#else
264 return ERR_SOURCENOTAVAILABLE;
265#endif
266}
267
268GSM_Error SONYERIC_DeleteAllToDo(GSM_StateMachine *s)
269{
270#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
271 GSM_Error error;
272 int Pos,Level = 0,Used;
273 unsigned char *Buf;
274 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
275 unsigned char Line[2000];
276
277 if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
278
279 smprintf(s,"Deleting all ToDo\n");
280
281 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
282 if (error != ERR_NONE) return error;
283
284 Pos = 0;
285 Buf = NULL;
286 Used = 0;
287 while (1) {
288 MyGetLine(Priv->file.Buffer, &Pos, Line, Priv->file.Used);
289 if (strlen(Line) == 0) break;
290 dbgprintf("Line is %s,%i,%i\n",Line,Priv->file.Used,Pos);
291 switch (Level) {
292 case 0:
293 if (strstr(Line,"BEGIN:VTODO")) {
294 Level = 2;
295 break;
296 }
297 Buf=(unsigned char *)realloc(Buf,Used+strlen(Line)+3);
298 strcpy(Buf+Used,Line);
299 Used=Used+strlen(Line)+3;
300 Buf[Used-3] = 13;
301 Buf[Used-2] = 10;
302 Buf[Used-1] = 0x00;
303 break;
304 case 2: /* ToDo note */
305 if (strstr(Line,"END:VTODO")) {
306 Level = 0;
307 }
308 break;
309 }
310 }
311
312 error = SONYERIC_SetFile(s, "telecom/cal.vcs", Buf, Used);
313 //if (Buf != NULL) free(Buf);
314 return error;
315#else
316 return ERR_SOURCENOTAVAILABLE;
317#endif
318}
319
320GSM_Error SONYERIC_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
321{
322#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
323 GSM_Error error;
324 int Pos,Level = 0,Loc=0,Used;
325 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
326 unsigned char Line[2000];
327 unsigned char *Buf;
328
329 smprintf(s, "Deleting calendar note %i\n",Note->Location);
330
331 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
332 if (error != ERR_NONE) return error;
333
334 Pos = 0;
335 Buf = NULL;
336 Used = 0;
337 while (1) {
338 MyGetLine(Priv->file.Buffer, &Pos, Line, Priv->file.Used);
339 if (strlen(Line) == 0) break;
340 dbgprintf("Line is %s,%i,%i\n",Line,Priv->file.Used,Pos);
341 switch (Level) {
342 case 0:
343 if (strstr(Line,"BEGIN:VEVENT")) {
344 Loc++;
345 if (Loc == Note->Location) {
346 Level = 1;
347 break;
348 }
349 }
350 Buf=(unsigned char *)realloc(Buf,Used+strlen(Line)+3);
351 strcpy(Buf+Used,Line);
352 Used=Used+strlen(Line)+3;
353 Buf[Used-3] = 13;
354 Buf[Used-2] = 10;
355 Buf[Used-1] = 0x00;
356 break;
357 case 1: /* Calendar note */
358 if (strstr(Line,"END:VEVENT")) {
359 Level = 0;
360 }
361 break;
362 }
363 }
364
365 DumpMessage(s->di.df, s->di.dl, Buf, Used);
366
367 error = SONYERIC_SetFile(s, "telecom/cal.vcs", Buf, Used);
368 if (Buf != NULL) free(Buf);
369 return error;
370#else
371 return ERR_SOURCENOTAVAILABLE;
372#endif
373}
374
375GSM_Error SONYERIC_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
376{
377#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
378 GSM_Error error;
379 GSM_ToDoEntry ToDo;
380 GSM_CalendarEntry Calendar;
381 int Pos;
382 GSM_Phone_ATGENData*Priv = &s->Phone.Data.Priv.ATGEN;
383
384 if (Priv->Manufacturer!=AT_Ericsson) return ERR_NOTSUPPORTED;
385
386 smprintf(s, "Getting calendar status\n");
387
388 error = SONYERIC_GetFile(s, &Priv->file, "telecom/cal.vcs");
389 if (error != ERR_NONE) return error;
390
391 Status->Used = 0;
392 Pos = 0;
393 while (1) {
394 error = GSM_DecodeVCALENDAR_VTODO(Priv->file.Buffer, &Pos, &Calendar, &ToDo, SonyEricsson_VCalendar, SonyEricsson_VToDo);
395 if (error == ERR_EMPTY) break;
396 if (error != ERR_NONE) return error;
397 if (Calendar.EntriesNum != 0) Status->Used++;
398 }
399
400 return ERR_NONE;
401#else
402 return ERR_SOURCENOTAVAILABLE;
403#endif
404}
405
406#endif
407#endif
408
409/* How should editor hadle tabs in this file? Add editor commands here.
410 * vim: noexpandtab sw=8 ts=8 sts=8:
411 */
diff --git a/gammu/emb/common/phone/nokia/dct3/dct3comm.h b/gammu/emb/common/phone/nokia/dct3/dct3comm.h
new file mode 100644
index 0000000..0b3e42e
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/dct3comm.h
@@ -0,0 +1,16 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef phone_nokia_dct3common_h
4#define phone_nokia_dct3common_h
5
6typedef struct {
7 int Locations[4];
8 intCurrentLocation;
9 intID;
10} DCT3_WAPSettings_Locations;
11
12#endif
13
14/* How should editor hadle tabs in this file? Add editor commands here.
15 * vim: noexpandtab sw=8 ts=8 sts=8:
16 */
diff --git a/gammu/emb/common/phone/nokia/dct3/dct3func.c b/gammu/emb/common/phone/nokia/dct3/dct3func.c
new file mode 100644
index 0000000..beef33c
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/dct3func.c
@@ -0,0 +1,1535 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Markus Plail, Pavel Janik, others and Gnokii */
3/* resetting DCT4 phones settings (c) by Walek */
4
5#include <string.h> /* memcpy only */
6#include <stdio.h>
7#include <ctype.h>
8
9#include "../../../gsmstate.h"
10#include "../../../misc/coding/coding.h"
11#include "../../../service/sms/gsmsms.h"
12#include "../../pfunc.h"
13#include "../nfunc.h"
14#include "dct3func.h"
15
16#ifdef GSM_ENABLE_NOKIA_DCT3
17
18GSM_Error DCT3_DeleteWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
19{
20 GSM_Error error;
21
22 /* We have to enable WAP frames in phone */
23 error=DCT3DCT4_EnableWAPFunctions(s);
24 if (error!=ERR_NONE) return error;
25
26 return DCT3DCT4_DeleteWAPBookmarkPart(s,bookmark);
27}
28
29GSM_Error DCT3_GetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
30{
31 GSM_Error error;
32
33 /* We have to enable WAP frames in phone */
34 error=DCT3DCT4_EnableWAPFunctions(s);
35 if (error!=ERR_NONE) return error;
36
37 return DCT3DCT4_GetWAPBookmarkPart(s,bookmark);
38}
39
40GSM_Error DCT3_ReplyPressKey(GSM_Protocol_Message msg, GSM_StateMachine *s)
41{
42 GSM_Phone_Data *Data = &s->Phone.Data;
43
44 switch (msg.Buffer[2]) {
45 case 0x46:
46 smprintf(s, "Pressing key OK\n");
47 if (Data->PressKey) return ERR_NONE;
48 break;
49 case 0x47:
50 smprintf(s, "Releasing key OK\n");
51 if (!Data->PressKey) return ERR_NONE;
52 break;
53 }
54 return ERR_UNKNOWNRESPONSE;
55}
56
57GSM_Error DCT3_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
58{
59 unsigned char PressReq[] = {0x00, 0x01, 0x46, 0x00, 0x01,
60 0x0a}; /* Key code */
61 unsigned char ReleaseReq[] = {0x00, 0x01, 0x47, 0x00, 0x01, 0x0c};
62
63 if (Press) {
64 PressReq[5] = Key;
65 s->Phone.Data.PressKey = true;
66 smprintf(s, "Pressing key\n");
67 return GSM_WaitFor (s, PressReq, 6, 0xd1, 4, ID_PressKey);
68 } else {
69 s->Phone.Data.PressKey = false;
70 smprintf(s, "Releasing key\n");
71 return GSM_WaitFor (s, ReleaseReq, 6, 0xd1, 4, ID_PressKey);
72 }
73}
74
75GSM_Error DCT3_ReplyPlayTone(GSM_Protocol_Message msg, GSM_StateMachine *s)
76{
77 smprintf(s, "Tone played\n");
78 return ERR_NONE;
79}
80
81GSM_Error DCT3_PlayTone(GSM_StateMachine *s, int Herz, unsigned char Volume, bool start)
82{
83 GSM_Error error;
84 unsigned char req[] = {0x00,0x01,0x8f,
85 0x00, /* Volume */
86 0x00, /* HerzLo */
87 0x00}; /* HerzHi */
88
89 if (start) {
90 error=DCT3_EnableSecurity (s, 0x01);
91 if (error!=ERR_NONE) return error;
92 }
93
94 /* For Herz==255*255 we have silent */
95 if (Herz!=255*255) {
96 req[3]=Volume;
97 req[5]=Herz%256;
98 req[4]=Herz/256;
99 } else {
100 req[3]=0;
101 req[5]=0;
102 req[4]=0;
103 }
104
105 return GSM_WaitFor (s, req, 6, 0x40, 4, ID_PlayTone);
106}
107
108#ifdef GSM_ENABLE_CELLBROADCAST
109
110GSM_Error DCT3_ReplyIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
111{
112 GSM_CBMessage CB;
113 int i;
114 char Buffer[300];
115
116 smprintf(s, "CB received\n");
117 CB.Channel = msg.Buffer[7];
118 i = GSM_UnpackEightBitsToSeven(0, msg.Buffer[9], msg.Buffer[9], msg.Buffer+10, Buffer);
119 i = msg.Buffer[9] - 1;
120 while (i!=0) {
121 if (Buffer[i] == 13) i = i - 1; else break;
122 }
123 DecodeDefault(CB.Text, Buffer, i + 1, false, NULL);
124 smprintf(s, "Channel %i, text \"%s\"\n",CB.Channel,DecodeUnicodeString(CB.Text));
125 if (s->Phone.Data.EnableIncomingCB && s->User.IncomingCB!=NULL) {
126 s->User.IncomingCB(s->CurrentConfig->Device,CB);
127 }
128 return ERR_NONE;
129}
130
131GSM_Error DCT3_ReplySetIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s)
132{
133 switch (msg.Buffer[3]) {
134 case 0x21:
135 smprintf(s, "CB set\n");
136 return ERR_NONE;
137 case 0x22:
138 smprintf(s, "CB not set\n");
139 return ERR_UNKNOWN;
140 case 0xCA:
141 smprintf(s, "No network and no CB\n");
142 return ERR_SECURITYERROR;
143 }
144 return ERR_UNKNOWNRESPONSE;
145}
146
147#endif
148
149GSM_Error DCT3_SetIncomingCB(GSM_StateMachine *s, bool enable)
150{
151#ifdef GSM_ENABLE_CELLBROADCAST
152 unsigned char reqOn[] = {N6110_FRAME_HEADER, 0x20, 0x01,
153 0x01, 0x00, 0x00, 0x01, 0x01};
154 unsigned char reqOff[] = {N6110_FRAME_HEADER, 0x20, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00};
156
157 if (s->Phone.Data.EnableIncomingCB!=enable) {
158 s->Phone.Data.EnableIncomingCB = enable;
159 if (enable) {
160 smprintf(s, "Enabling incoming CB\n");
161 return GSM_WaitFor(s, reqOn, 10, 0x02, 4, ID_SetIncomingCB);
162 } else {
163 smprintf(s, "Disabling incoming CB\n");
164 return GSM_WaitFor(s, reqOff, 10, 0x02, 4, ID_SetIncomingCB);
165 }
166 }
167 return ERR_NONE;
168#else
169 return ERR_SOURCENOTAVAILABLE;
170#endif
171}
172
173GSM_Error DCT3_ReplySetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
174{
175 smprintf(s, "SMSC set\n");
176 return ERR_NONE;
177}
178
179GSM_Error DCT3_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
180{
181 unsigned char req[100] = {N6110_FRAME_HEADER, 0x30, 0x64};
182
183 memset(req+6,100-6,0);
184
185 /* SMSC location */
186 req[5] = smsc->Location;
187
188 /* SMSC format */
189 switch (smsc->Format) {
190 case SMS_FORMAT_Text : req[7] = 0x00; break;
191 case SMS_FORMAT_Fax : req[7] = 0x22; break;
192 case SMS_FORMAT_Pager : req[7] = 0x26; break;
193 case SMS_FORMAT_Email : req[7] = 0x32; break;
194 }
195
196 /* SMS validity */
197 req[9] = smsc->Validity.Relative;
198
199 /* Default number for SMS messages */
200 req[10] = GSM_PackSemiOctetNumber(smsc->DefaultNumber, req+11, true);
201
202 /* SMSC number */
203 req[22] = GSM_PackSemiOctetNumber(smsc->Number, req+23, false);
204
205 /* SMSC name */
206 memcpy(req + 34, DecodeUnicodeString(smsc->Name),UnicodeLength(smsc->Name));
207
208 smprintf(s, "Setting SMSC\n");
209 return GSM_WaitFor (s, req, 35+UnicodeLength(smsc->Name), 0x02, 4, ID_SetSMSC);
210}
211
212GSM_Error DCT3_ReplyEnableSecurity(GSM_Protocol_Message msg, GSM_StateMachine *s)
213{
214 smprintf(s, "State of security commands set\n");
215 return ERR_NONE;
216}
217
218/* If you set make some things (for example, change Security Code from
219 * phone's menu, disable and enable phone), it won't answer for 0x40 frames
220 * and you won't be able to play tones, get netmonitor, etc.
221 * This function do thing called "Enabling extended security commands"
222 * and it enables 0x40 frame functions.
223 * This frame can also some other things - see below
224 */
225GSM_Error DCT3_EnableSecurity (GSM_StateMachine *s, unsigned char status)
226{
227 unsigned char req[] = {0x00, 0x01, 0x64,
228 0x01};/* 0x00/0x01 - off/on,
229 * 0x03/0x04 - soft/hard reset,
230 * 0x06 - CONTACT SERVICE
231 */
232
233 /* 0x06 MAKES CONTACT SERVICE! BE CAREFULL! */
234 /* When use 0x03 and had during session changed time & date
235 * some phones (like 6150 or 6210) can ask for time & date after reset
236 * or disable clock on the screen
237 */
238 if (status!=0x06) req[3] = status;
239 smprintf(s, "Setting state of security commands\n");
240 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_EnableSecurity);
241}
242
243GSM_Error DCT3_ReplyGetIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
244{
245 memcpy(s->Phone.Data.IMEI,msg.Buffer + 4, 16);
246 smprintf(s, "Received IMEI %s\n",s->Phone.Data.IMEI);
247 return ERR_NONE;
248}
249
250GSM_Error DCT3_GetIMEI (GSM_StateMachine *s)
251{
252 unsigned char req[] = {0x00, 0x01, 0x66, 0x00};
253 GSM_Error error;
254
255 if (strlen(s->Phone.Data.IMEI)!=0) return ERR_NONE;
256
257 error=DCT3_EnableSecurity (s, 0x01);
258 if (error!=ERR_NONE) return error;
259
260 smprintf(s, "Getting IMEI\n");
261 return GSM_WaitFor (s, req, 4, 0x40, 2, ID_GetIMEI);
262}
263
264GSM_Error DCT3_ReplySIMLogin(GSM_Protocol_Message msg, GSM_StateMachine *s)
265{
266 smprintf(s, "Login for SIM card\n");
267 return ERR_NONE;
268}
269
270GSM_Error DCT3_ReplySIMLogout(GSM_Protocol_Message msg, GSM_StateMachine *s)
271{
272 smprintf(s, "Logout for SIM card\n");
273 return ERR_NONE;
274}
275
276GSM_Error DCT3_ReplyGetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
277{
278 smprintf(s, "Date & time received\n");
279 if (msg.Buffer[4]==0x01) {
280 NOKIA_DecodeDateTime(s, msg.Buffer+8, s->Phone.Data.DateTime);
281 return ERR_NONE;
282 }
283 smprintf(s, "Not set in phone\n");
284 return ERR_EMPTY;
285}
286
287GSM_Error DCT3_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype)
288{
289 unsigned char req[] = {N6110_FRAME_HEADER, 0x62};
290
291 s->Phone.Data.DateTime=date_time;
292 smprintf(s, "Getting date & time\n");
293 return GSM_WaitFor (s, req, 4, msgtype, 4, ID_GetDateTime);
294}
295
296GSM_Error DCT3_ReplyGetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
297{
298 GSM_Phone_Data*Data = &s->Phone.Data;
299
300 smprintf(s, "Alarm: ");
301 if (msg.Buffer[8]==0x02) {
302 smprintf(s, "set to %02i:%02i\n", msg.Buffer[9], msg.Buffer[10]);
303 Data->Alarm->Repeating = true;
304 Data->Alarm->Text[0] = 0;
305 Data->Alarm->Text[1] = 0;
306 Data->Alarm->DateTime.Hour= msg.Buffer[9];
307 Data->Alarm->DateTime.Minute= msg.Buffer[10];
308 Data->Alarm->DateTime.Second= 0;
309 return ERR_NONE;
310 }
311 smprintf(s, "not set\n");
312 return ERR_EMPTY;
313}
314
315GSM_Error DCT3_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype)
316{
317 unsigned char req[] = {N6110_FRAME_HEADER, 0x6d};
318
319 if (alarm->Location!=1) return ERR_NOTSUPPORTED;
320
321 s->Phone.Data.Alarm=alarm;
322 smprintf(s, "Getting alarm\n");
323 return GSM_WaitFor (s, req, 4, msgtype, 4, ID_GetAlarm);
324}
325
326GSM_Error DCT3_ReplySetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
327{
328 smprintf(s, "Date & time: ");
329 if (msg.Buffer[4]==0x01) {
330 smprintf(s, "set OK\n");
331 return ERR_NONE;
332 }
333 smprintf(s, "error setting\n");
334 return ERR_UNKNOWN;
335}
336
337GSM_Error DCT3_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype)
338{
339 unsigned char req[] = {N6110_FRAME_HEADER, 0x60, 0x01, 0x01, 0x07,
340 0x00, 0x00, /* Year */
341 0x00, /* Month */
342 0x00, /* Day */
343 0x00, /* Hour */
344 0x00, /* Minute */
345 0x00}; /* Unknown. Not seconds */
346
347 NOKIA_EncodeDateTime(s, req+7, date_time);
348 smprintf(s, "Setting date & time\n");
349 return GSM_WaitFor (s, req, 14, msgtype, 4, ID_SetDateTime);
350}
351
352GSM_Error DCT3_ReplySetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
353{
354 smprintf(s, "Alarm: ");
355 if (msg.Buffer[4]==0x01) {
356 smprintf(s, "set OK\n");
357 return ERR_NONE;
358 }
359 smprintf(s, "error setting\n");
360 return ERR_UNKNOWN;
361}
362
363GSM_Error DCT3_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype)
364{
365 unsigned char req[] = {N6110_FRAME_HEADER, 0x6b, 0x01, 0x20, 0x03,
366 0x02, /* Unknown. Not for enabling/disabling */
367 0x00, /* Hour */
368 0x00, /* Minute */
369 0x00}; /* Unknown. Not seconds */
370
371 if (alarm->Location != 1) return ERR_NOTSUPPORTED;
372
373 req[8] = alarm->DateTime.Hour;
374 req[9] = alarm->DateTime.Minute;
375
376 smprintf(s, "Setting alarm\n");
377 return GSM_WaitFor (s, req, 11, msgtype, 4, ID_SetAlarm);
378}
379
380GSM_Error DCT3_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
381{
382 int i;
383 GSM_Phone_Data*Data = &s->Phone.Data;
384
385 switch (msg.Buffer[3]) {
386 case 0x34:
387 smprintf(s, "SMSC received\n");
388 Data->SMSC->Format = SMS_FORMAT_Text;
389 switch (msg.Buffer[6]) {
390 case 0x00: Data->SMSC->Format = SMS_FORMAT_Text; break;
391 case 0x22: Data->SMSC->Format = SMS_FORMAT_Fax; break;
392 case 0x26: Data->SMSC->Format = SMS_FORMAT_Pager;break;
393 case 0x32: Data->SMSC->Format = SMS_FORMAT_Email;break;
394 }
395 Data->SMSC->Validity.Format = SMS_Validity_RelativeFormat;
396 Data->SMSC->Validity.Relative= msg.Buffer[8];
397
398 i=33;
399 while (msg.Buffer[i]!=0) {i++;}
400 i=i-33;
401 if (i>GSM_MAX_SMSC_NAME_LENGTH) {
402 smprintf(s, "Too long name\n");
403 return ERR_UNKNOWNRESPONSE;
404 }
405 EncodeUnicode(Data->SMSC->Name,msg.Buffer+33,i);
406 smprintf(s, "Name \"%s\"\n", DecodeUnicodeString(Data->SMSC->Name));
407
408 GSM_UnpackSemiOctetNumber(Data->SMSC->DefaultNumber,msg.Buffer+9,true);
409 smprintf(s, "Default number \"%s\"\n", DecodeUnicodeString(Data->SMSC->DefaultNumber));
410
411 GSM_UnpackSemiOctetNumber(Data->SMSC->Number,msg.Buffer+21,false);
412 smprintf(s, "Number \"%s\"\n", DecodeUnicodeString(Data->SMSC->Number));
413
414 return ERR_NONE;
415 case 0x35:
416 smprintf(s, "Getting SMSC failed\n");
417 return ERR_INVALIDLOCATION;
418 }
419 return ERR_UNKNOWNRESPONSE;
420}
421
422GSM_Error DCT3_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
423{
424 unsigned char req[] = {N6110_FRAME_HEADER, 0x33, 0x64,
425 0x00}; /* Location */
426
427 if (smsc->Location==0x00) return ERR_INVALIDLOCATION;
428
429 req[5]=smsc->Location;
430
431 s->Phone.Data.SMSC=smsc;
432 smprintf(s, "Getting SMSC\n");
433 return GSM_WaitFor (s, req, 6, 0x02, 4, ID_GetSMSC);
434}
435
436GSM_Error DCT3_ReplyGetNetworkInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
437{
438 int count;
439 GSM_Phone_Data*Data = &s->Phone.Data;
440#ifdef DEBUG
441 GSM_NetworkInfo NetInfo;
442 char name[100];
443
444 smprintf(s, "Network info received\n");
445 smprintf(s, " Status : ");
446 switch (msg.Buffer[8]) {
447 case 0x01: smprintf(s, "home network"); break;
448 case 0x02: smprintf(s, "roaming network"); break;
449 case 0x03: smprintf(s, "requesting network"); break;
450 case 0x04: smprintf(s, "not registered in the network");break;
451 default : smprintf(s, "unknown");
452 }
453 smprintf(s, "\n");
454 smprintf(s, "Network selection : %s\n", msg.Buffer[9]==1?"manual":"automatic");
455 if (msg.Buffer[8]<0x03) {
456 sprintf(NetInfo.CID, "%02x%02x", msg.Buffer[10], msg.Buffer[11]);
457 smprintf(s, "CID : %s\n", NetInfo.CID);
458
459 sprintf(NetInfo.LAC, "%02x%02x", msg.Buffer[12], msg.Buffer[13]);
460 smprintf(s, "LAC : %s\n", NetInfo.LAC);
461
462 smprintf(s, "Network code : %s\n", NetInfo.NetworkCode);
463 NOKIA_DecodeNetworkCode(msg.Buffer+14,NetInfo.NetworkCode);
464 smprintf(s, "Network name for Gammu : %s ",
465 DecodeUnicodeString(GSM_GetNetworkName(NetInfo.NetworkCode)));
466 smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetInfo.NetworkCode)));
467
468 if (msg.Length>18) {
469 if (msg.Buffer[18]==0x00) {
470 /* In 6210 name is in "normal" Unicode */
471 memcpy(name,msg.Buffer+18,msg.Buffer[17]*2);
472 name[msg.Buffer[17]*2]=0x00;
473 name[msg.Buffer[17]*2+1]=0x00;
474 smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
475 } else {
476 /* In 9210 first 0x00 is cut from Unicode string */
477 name[0] = 0;
478 memcpy(name+1,msg.Buffer+18,msg.Buffer[17]*2);
479 name[msg.Buffer[17]*2+1]=0x00;
480 name[msg.Buffer[17]*2+2]=0x00;
481 smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
482 }
483 }
484 }
485#endif
486 if (Data->RequestID==ID_GetNetworkInfo) {
487 Data->NetworkInfo->NetworkName[0] = 0x00;
488 Data->NetworkInfo->NetworkName[1] = 0x00;
489 Data->NetworkInfo->State = 0;
490 switch (msg.Buffer[8]) {
491 case 0x01: Data->NetworkInfo->State = GSM_HomeNetwork; break;
492 case 0x02: Data->NetworkInfo->State = GSM_RoamingNetwork;break;
493 case 0x03: Data->NetworkInfo->State = GSM_RequestingNetwork;break;
494 case 0x04: Data->NetworkInfo->State = GSM_NoNetwork; break;
495 }
496 if (Data->NetworkInfo->State == GSM_HomeNetwork || Data->NetworkInfo->State == GSM_RoamingNetwork) {
497 if (msg.Buffer[18]==0x00) {
498 /* In 6210 name is in "normal" Unicode */
499 memcpy(Data->NetworkInfo->NetworkName,msg.Buffer+18,msg.Buffer[17]*2);
500 Data->NetworkInfo->NetworkName[msg.Buffer[17]*2] = 0x00;
501 Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+1] = 0x00;
502 } else {
503 /* In 9210 first 0x00 is cut from Unicode string */
504 Data->NetworkInfo->NetworkName[0] = 0;
505 memcpy(Data->NetworkInfo->NetworkName+1,msg.Buffer+18,msg.Buffer[17]*2);
506 Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+1]=0x00;
507 Data->NetworkInfo->NetworkName[msg.Buffer[17]*2+2]=0x00;
508 }
509 NOKIA_DecodeNetworkCode(msg.Buffer+14,Data->NetworkInfo->NetworkCode);
510 sprintf(Data->NetworkInfo->CID, "%02x%02x", msg.Buffer[10], msg.Buffer[11]);
511 sprintf(Data->NetworkInfo->LAC, "%02x%02x", msg.Buffer[12], msg.Buffer[13]);
512 }
513 }
514 /* 6210/6250/7110 */
515 if (Data->RequestID==ID_GetBitmap) {
516 if (msg.Buffer[4]==0x02) {
517 smprintf(s, "Operator logo available\n");
518 count = 7;
519 /* skip network info */
520 count += msg.Buffer[count];
521 count ++;
522 Data->Bitmap->BitmapWidth= msg.Buffer[count++];
523 Data->Bitmap->BitmapHeight= msg.Buffer[count++];
524 count+=4;
525 PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo,msg.Buffer+count,Data->Bitmap);
526 NOKIA_DecodeNetworkCode(msg.Buffer+14,Data->Bitmap->NetworkCode);
527 } else {
528 Data->Bitmap->BitmapWidth= 78;
529 Data->Bitmap->BitmapHeight= 21;
530 GSM_ClearBitmap(Data->Bitmap);
531 strcpy(Data->Bitmap->NetworkCode,"000 00");
532 }
533 }
534 return ERR_NONE;
535}
536
537GSM_Error DCT3_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
538{
539 unsigned char req[] = {N6110_FRAME_HEADER, 0x70};
540
541 s->Phone.Data.NetworkInfo=netinfo;
542 smprintf(s, "Getting network info\n");
543 return GSM_WaitFor (s, req, 4, 0x0a, 4, ID_GetNetworkInfo);
544}
545
546GSM_Error DCT3_ReplyDialCommand(GSM_Protocol_Message msg, GSM_StateMachine *s)
547{
548 smprintf(s, "Answer for call commands\n");
549 return ERR_NONE;
550}
551
552GSM_Error DCT3_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
553{
554 unsigned inti = 0;
555 GSM_Errorerror;
556 unsigned char req[100] = {0x00, 0x01, 0x7c,
557 0x01}; /* call command */
558
559 if (ShowNumber != GSM_CALL_DefaultNumberPresence) return ERR_NOTSUPPORTED;
560
561 error=DCT3_EnableSecurity (s, 0x01);
562 if (error!=ERR_NONE) return error;
563
564 for (i=0; i < strlen(number); i++) req[4+i]=number[i];
565 req[4+i+1]=0;
566
567 smprintf(s, "Making voice call\n");
568 return GSM_WaitFor (s, req, 4+strlen(number)+1, 0x40, 4, ID_DialVoice);
569}
570
571static GSM_Error DCT3_CancelAllCalls(GSM_StateMachine *s)
572{
573 GSM_Errorerror;
574 unsigned char req[] = {0x00, 0x01, 0x7c,
575 0x03}; /* call command */
576
577 error=DCT3_EnableSecurity (s, 0x01);
578 if (error!=ERR_NONE) return error;
579
580 smprintf(s, "Canceling calls\n");
581 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_CancelCall);
582}
583
584GSM_Error DCT3_CancelCall(GSM_StateMachine *s, int ID, bool all)
585{
586 if (!all) return DCT3DCT4_CancelCall(s,ID);
587 return DCT3_CancelAllCalls(s);
588}
589
590GSM_Error DCT3_AnswerAllCalls(GSM_StateMachine *s)
591{
592 GSM_Errorerror;
593 unsigned char req[] = {0x00, 0x01, 0x7c,
594 0x02}; /* call command */
595
596 error=DCT3_EnableSecurity (s, 0x01);
597 if (error!=ERR_NONE) return error;
598
599 smprintf(s, "Answering calls\n");
600 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_AnswerCall);
601}
602
603GSM_Error DCT3_Reset(GSM_StateMachine *s, bool hard)
604{
605 GSM_Error error;
606
607 if (hard) {
608 error=DCT3_EnableSecurity(s, 0x04);
609 } else {
610 error=DCT3_EnableSecurity(s, 0x03);
611 }
612 if (error == ERR_NONE) {
613 s->Phone.Data.EnableIncomingSMS = false;
614 s->Phone.Data.EnableIncomingCB = false;
615 }
616 return error;
617}
618
619GSM_Error DCT3_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
620{
621 return DCT3DCT4_ReplyGetWAPBookmark (msg,s,false);
622}
623
624GSM_Error DCT3_SetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
625{
626 GSM_Error error;
627 int count = 4, location;
628 unsigned char req[600] = {N6110_FRAME_HEADER, 0x09};
629
630 /* We have to enable WAP frames in phone */
631 error=DCT3DCT4_EnableWAPFunctions(s);
632 if (error!=ERR_NONE) return error;
633
634 location = bookmark->Location - 1;
635 if (bookmark->Location == 0) location = 0xffff;
636 req[count++] = (location & 0xff00) >> 8;
637 req[count++] = location & 0x00ff;
638
639 count += NOKIA_SetUnicodeString(s, req+count, bookmark->Title, false);
640 count += NOKIA_SetUnicodeString(s, req+count, bookmark->Address, false);
641
642 /* unknown */
643 req[count++] = 0x01; req[count++] = 0x80; req[count++] = 0x00;
644 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
645 req[count++] = 0x00; req[count++] = 0x00; req[count++] = 0x00;
646
647 smprintf(s, "Setting WAP bookmark\n");
648 error = GSM_WaitFor (s, req, count, 0x3f, 4, ID_SetWAPBookmark);
649 if (error != ERR_NONE) {
650 if (error == ERR_INSIDEPHONEMENU || error == ERR_EMPTY || error == ERR_FULL) {
651 DCT3DCT4_DisableConnectionFunctions(s);
652 }
653 return error;
654 }
655
656 return DCT3DCT4_DisableConnectionFunctions(s);
657}
658
659GSM_Error DCT3_ReplyGetWAPSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
660{
661 int tmp,Number;
662 // int tmp2;
663 GSM_Phone_Data *Data = &s->Phone.Data;
664#ifdef GSM_ENABLE_NOKIA6110
665 GSM_Phone_N6110Data *Priv6110 = &s->Phone.Data.Priv.N6110;
666#endif
667#ifdef GSM_ENABLE_NOKIA7110
668 GSM_Phone_N7110Data *Priv7110 = &s->Phone.Data.Priv.N7110;
669#endif
670
671 switch(msg.Buffer[3]) {
672 case 0x16:
673 smprintf(s, "WAP settings part 1 received OK\n");
674
675 tmp = 4;
676
677 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].Title,false);
678 smprintf(s, "Title: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].Title));
679
680 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].HomePage,false);
681 smprintf(s, "Homepage: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].HomePage));
682#ifdef DEBUG
683 smprintf(s, "Connection type: ");
684 switch (msg.Buffer[tmp]) {
685 case 0x00: smprintf(s, "temporary\n"); break;
686 case 0x01: smprintf(s, "continuous\n"); break;
687 default: smprintf(s, "unknown\n");
688 }
689 smprintf(s, "Connection security: ");
690 switch (msg.Buffer[tmp+13]) {
691 case 0x00: smprintf(s, "off\n");break;
692 case 0x01: smprintf(s, "on\n"); break;
693 default: smprintf(s, "unknown\n");
694 }
695#endif
696 Data->WAPSettings->Settings[0].IsContinuous = false;
697 if (msg.Buffer[tmp] == 0x01) Data->WAPSettings->Settings[0].IsContinuous = true;
698 Data->WAPSettings->Settings[0].IsSecurity = false;
699 if (msg.Buffer[tmp+13] == 0x01) Data->WAPSettings->Settings[0].IsSecurity = true;
700
701 /* I'm not sure here. Experimental values from 6210 5.56 */
702 // tmp2 = DecodeUnicodeLength(Data->WAPSettings->Settings[0].Title);
703 // if (tmp2 != 0) tmp2 --;
704 // tmp2 += tmp;
705 if (!(UnicodeLength(Data->WAPSettings->Settings[0].Title)) % 2) tmp++;
706 if (UnicodeLength(Data->WAPSettings->Settings[0].HomePage)!=0) tmp++;
707
708 smprintf(s, "ID for writing %i\n",msg.Buffer[tmp+5]);
709
710 smprintf(s, "Current set location in phone %i\n",msg.Buffer[tmp+6]);
711
712 smprintf(s, "1 location %i\n",msg.Buffer[tmp+8]);
713 smprintf(s, "2 location %i\n",msg.Buffer[tmp+9]);
714 smprintf(s, "3 location %i\n",msg.Buffer[tmp+10]);
715 smprintf(s, "4 location %i\n",msg.Buffer[tmp+11]);
716#ifdef GSM_ENABLE_NOKIA7110
717 if (strstr(N7110Phone.models, Data->ModelInfo->model) != NULL) {
718 Priv7110->WAPLocations.ID = msg.Buffer[tmp+5];
719 Priv7110->WAPLocations.CurrentLocation= msg.Buffer[tmp+6];
720 Priv7110->WAPLocations.Locations[0] = msg.Buffer[tmp+8];
721 Priv7110->WAPLocations.Locations[1] = msg.Buffer[tmp+9];
722 Priv7110->WAPLocations.Locations[2] = msg.Buffer[tmp+10];
723 Priv7110->WAPLocations.Locations[3] = msg.Buffer[tmp+11];
724
725 // Priv7110->WAPLocations.CurrentLocation= msg.Buffer[tmp2+1];
726 // Priv7110->WAPLocations.Locations[0] = msg.Buffer[tmp2+3];
727 // Priv7110->WAPLocations.Locations[1] = msg.Buffer[tmp2+4];
728 // Priv7110->WAPLocations.Locations[2] = msg.Buffer[tmp2+5];
729 // Priv7110->WAPLocations.Locations[3] = msg.Buffer[tmp2+6];
730 }
731#endif
732#ifdef GSM_ENABLE_NOKIA6110
733 if (strstr(N6110Phone.models, Data->ModelInfo->model) != NULL) {
734 Priv6110->WAPLocations.ID = msg.Buffer[tmp+5];
735 Priv6110->WAPLocations.CurrentLocation= msg.Buffer[tmp+6];
736 Priv6110->WAPLocations.Locations[0] = msg.Buffer[tmp+8];
737 Priv6110->WAPLocations.Locations[1] = msg.Buffer[tmp+9];
738 Priv6110->WAPLocations.Locations[2] = msg.Buffer[tmp+10];
739 Priv6110->WAPLocations.Locations[3] = msg.Buffer[tmp+11];
740 }
741#endif
742 return ERR_NONE;
743 case 0x17:
744 smprintf(s, "WAP settings part 1 receiving error\n");
745 switch (msg.Buffer[4]) {
746 case 0x01:
747 smprintf(s, "Security error. Inside WAP settings menu\n");
748 return ERR_INSIDEPHONEMENU;
749 case 0x02:
750 smprintf(s, "Invalid or empty\n");
751 return ERR_INVALIDLOCATION;
752 default:
753 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
754 return ERR_UNKNOWNRESPONSE;
755 }
756 break;
757 case 0x1c:
758 smprintf(s, "WAP settings part 2 received OK\n");
759 Number = Data->WAPSettings->Number;
760 switch (msg.Buffer[5]) {
761 case 0x00:
762 Data->WAPSettings->Settings[Number].Bearer = WAPSETTINGS_BEARER_SMS;
763 smprintf(s, "Settings for SMS bearer:\n");
764 tmp = 6;
765
766 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].Service,false);
767 smprintf(s, "Service number: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Service));
768
769 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].Server,false);
770 smprintf(s, "Server number: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Server));
771 break;
772 case 0x01:
773 Data->WAPSettings->Settings[Number].Bearer = WAPSETTINGS_BEARER_DATA;
774 smprintf(s, "Settings for data bearer:\n");
775 Data->WAPSettings->Settings[Number].ManualLogin = false;
776 tmp = 10;
777
778 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].IPAddress,false);
779 smprintf(s, "IP address: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].IPAddress));
780
781 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].DialUp,false);
782 smprintf(s, "Dial-up number: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].DialUp));
783
784 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].User,false);
785 smprintf(s, "User name: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].User));
786
787 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].Password,false);
788 smprintf(s, "Password: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Password));
789#ifdef DEBUG
790 smprintf(s, "Authentication type: ");
791 switch (msg.Buffer[6]) {
792 case 0x00: smprintf(s, "normal\n"); break;
793 case 0x01: smprintf(s, "secure\n"); break;
794 default: smprintf(s, "unknown\n"); break;
795 }
796 smprintf(s, "Data call type: ");
797 switch (msg.Buffer[7]) {
798 case 0x00: smprintf(s, "analogue\n"); break;
799 case 0x01: smprintf(s, "ISDN\n"); break;
800 default: smprintf(s, "unknown\n"); break;
801 }
802 smprintf(s, "Data call speed: ");
803 switch (msg.Buffer[9]) {
804 case 0x01: smprintf(s, "9600\n"); break;
805 case 0x02: smprintf(s, "14400\n"); break;
806 default: smprintf(s, "unknown\n"); break;
807 }
808#endif
809 Data->WAPSettings->Settings[Number].IsNormalAuthentication=true;
810 if (msg.Buffer[6]==0x01) Data->WAPSettings->Settings[Number].IsNormalAuthentication=false;
811 Data->WAPSettings->Settings[Number].IsISDNCall=false;
812 if (msg.Buffer[7]==0x01) Data->WAPSettings->Settings[Number].IsISDNCall=true;
813 Data->WAPSettings->Settings[Number].Speed = WAPSETTINGS_SPEED_9600;
814 if (msg.Buffer[9]==0x02) Data->WAPSettings->Settings[Number].Speed = WAPSETTINGS_SPEED_14400;
815 break;
816 case 0x02:
817 Data->WAPSettings->Settings[Number].Bearer=WAPSETTINGS_BEARER_USSD;
818 smprintf(s, "Settings for USSD bearer:\n");
819 tmp = 7;
820 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].Service,false);
821#ifdef DEBUG
822 if (msg.Buffer[6]==0x01)
823 smprintf(s, "Service number: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Service));
824 else
825 smprintf(s, "IP address: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Service));
826#endif
827 Data->WAPSettings->Settings[Number].IsIP=true;
828 if (msg.Buffer[6]==0x01) Data->WAPSettings->Settings[Number].IsIP=false;
829 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[Number].Code,false);
830 smprintf(s, "Service code: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[Number].Code));
831 }
832 Data->WAPSettings->Number++;
833 return ERR_NONE;
834 case 0x1d:
835 smprintf(s, "Incorrect WAP settings location\n");
836 return ERR_NONE;
837 }
838 return ERR_UNKNOWNRESPONSE;
839}
840
841GSM_Error DCT3_GetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
842{
843#ifdef GSM_ENABLE_NOKIA6110
844 GSM_Phone_N6110Data *Priv6110 = &s->Phone.Data.Priv.N6110;
845#endif
846#ifdef GSM_ENABLE_NOKIA7110
847 GSM_Phone_N7110Data *Priv7110 = &s->Phone.Data.Priv.N7110;
848#endif
849 GSM_Error error;
850 int i;
851 unsigned char req[] = {N6110_FRAME_HEADER,0x15,
852 0x00}; /* Location */
853 unsigned char req2[] = {N6110_FRAME_HEADER,0x1b,
854 0x00}; /* Location */
855
856 /* We have to enable WAP frames in phone */
857 error=DCT3DCT4_EnableWAPFunctions(s);
858 if (error!=ERR_NONE) return error;
859
860 s->Phone.Data.WAPSettings = settings;
861 settings->Number = 0;
862 settings->ReadOnly = false;
863
864 req[4] = settings->Location-1;
865 smprintf(s, "Getting WAP settings part 1\n");
866 error = GSM_WaitFor (s, req, 5, 0x3f, 4, ID_GetConnectSet);
867 if (error != ERR_NONE) return error;
868
869#ifdef GSM_ENABLE_NOKIA7110
870 if (strstr(N7110Phone.models, s->Phone.Data.ModelInfo->model) != NULL) {
871 for (i=0;i<4;i++) {
872 req2[4] = Priv7110->WAPLocations.Locations[i];
873 smprintf(s, "Getting WAP settings part 2\n");
874 error=GSM_WaitFor (s, req2, 5, 0x3f, 4, ID_GetConnectSet);
875 if (error != ERR_NONE) return error;
876 if (Priv7110->WAPLocations.Locations[i] == Priv7110->WAPLocations.CurrentLocation) {
877 settings->ActiveBearer = settings->Settings[settings->Number-1].Bearer;
878 }
879 }
880 }
881#endif
882#ifdef GSM_ENABLE_NOKIA6110
883 if (strstr(N6110Phone.models, s->Phone.Data.ModelInfo->model) != NULL) {
884 for (i=0;i<4;i++) {
885 req2[4] = Priv6110->WAPLocations.Locations[i];
886 smprintf(s, "Getting WAP settings part 2\n");
887 error=GSM_WaitFor (s, req2, 5, 0x3f, 4, ID_GetConnectSet);
888 if (error != ERR_NONE) return error;
889 if (Priv6110->WAPLocations.Locations[i] == Priv6110->WAPLocations.CurrentLocation) {
890 settings->ActiveBearer = settings->Settings[settings->Number-1].Bearer;
891 }
892 }
893 }
894#endif
895 if (error == ERR_NONE) {
896 for (i=1;i<3;i++) {
897 CopyUnicodeString(settings->Settings[i].Title,settings->Settings[0].Title);
898 CopyUnicodeString(settings->Settings[i].HomePage,settings->Settings[0].HomePage);
899 settings->Settings[i].IsContinuous = settings->Settings[0].IsContinuous;
900 settings->Settings[i].IsSecurity = settings->Settings[0].IsSecurity;
901
902 settings->Settings[i].IsContinuous = settings->Settings[0].IsContinuous;
903 settings->Settings[i].IsSecurity = settings->Settings[0].IsSecurity;
904 }
905 error = DCT3DCT4_GetActiveConnectSet(s);
906 }
907 if (error != ERR_NONE) return error;
908
909 settings->Proxy[0] = 0x00;
910 settings->Proxy[1] = 0x00;
911 settings->ProxyPort = 8080;
912
913 settings->Proxy2[0] = 0x00;
914 settings->Proxy2[1] = 0x00;
915 settings->Proxy2Port = 8080;
916
917 return DCT3DCT4_DisableConnectionFunctions(s);
918}
919
920GSM_Error DCT3_ReplySetWAPSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
921{
922 switch(msg.Buffer[3]) {
923 case 0x19:
924 smprintf(s, "WAP settings part 1 set OK\n");
925 return ERR_NONE;
926 case 0x1a:
927 smprintf(s, "WAP settings part 1 setting error\n");
928 switch (msg.Buffer[4]) {
929 case 0x01:
930 smprintf(s, "Security error. Inside WAP settings menu\n");
931 return ERR_INSIDEPHONEMENU;
932 case 0x02:
933 smprintf(s, "Incorrect data\n");
934 return ERR_UNKNOWN;
935 default:
936 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
937 return ERR_UNKNOWNRESPONSE;
938 }
939 case 0x1F:
940 smprintf(s, "WAP settings part 2 set OK\n");
941 return ERR_NONE;
942 }
943 return ERR_UNKNOWNRESPONSE;
944}
945
946GSM_Error DCT3_SetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
947{
948#ifdef GSM_ENABLE_NOKIA6110
949 GSM_Phone_N6110Data *Priv6110 = &s->Phone.Data.Priv.N6110;
950#endif
951#ifdef GSM_ENABLE_NOKIA7110
952 GSM_Phone_N7110Data *Priv7110 = &s->Phone.Data.Priv.N7110;
953#endif
954 GSM_Error error;
955 GSM_MultiWAPSettingssettings2;
956 int i,pos,phone1=-1,phone2=-1,phone3=-1;
957 int ID=0,locations[4],loc1=-1,loc2=-1,loc3=-1;
958 unsigned char req[] = {N6110_FRAME_HEADER,0x15,
959 0x00};/* Location */
960 unsigned char req2[] = {N6110_FRAME_HEADER,0x1b,
961 0x00};/* Location */
962 unsigned char SetReq[200] = {N7110_FRAME_HEADER, 0x18,
963 0x00}; /* Location */
964 unsigned char SetReq2[200] = {N7110_FRAME_HEADER, 0x1e,
965 0x00}; /* Location */
966
967 /* We have to enable WAP frames in phone */
968 error=DCT3DCT4_EnableWAPFunctions(s);
969 if (error!=ERR_NONE) return error;
970
971 s->Phone.Data.WAPSettings = &settings2;
972 settings2.Number = 0;
973
974 req[4] = settings->Location-1;
975 smprintf(s, "Getting WAP settings part 1\n");
976 error = GSM_WaitFor (s, req, 6, 0x3f, 4, ID_GetConnectSet);
977 if (error != ERR_NONE) return error;
978
979#ifdef GSM_ENABLE_NOKIA6110
980 if (strstr(N6110Phone.models, s->Phone.Data.ModelInfo->model) != NULL) {
981 for (i=0;i<4;i++) locations[i] = Priv6110->WAPLocations.Locations[i];
982 ID = Priv6110->WAPLocations.ID;
983 }
984#endif
985#ifdef GSM_ENABLE_NOKIA7110
986 if (strstr(N7110Phone.models, s->Phone.Data.ModelInfo->model) != NULL) {
987 for (i=0;i<4;i++) locations[i] = Priv7110->WAPLocations.Locations[i];
988 ID = Priv7110->WAPLocations.ID;
989 }
990#endif
991
992 /* Now we get info about supported types by phone and their locations */
993 for (i=0;i<4;i++) {
994 settings2.Number = 0;
995 settings2.Settings[0].Bearer = 0;
996 req2[4] = locations[i];
997 smprintf(s, "Getting WAP settings part 2\n");
998 error=GSM_WaitFor (s, req2, 6, 0x3f, 4, ID_GetConnectSet);
999 if (error != ERR_NONE) return error;
1000 switch (settings2.Settings[0].Bearer) {
1001 case WAPSETTINGS_BEARER_DATA: phone1 = locations[i]; break;
1002 case WAPSETTINGS_BEARER_SMS : phone2 = locations[i]; break;
1003 case WAPSETTINGS_BEARER_USSD: phone3 = locations[i]; break;
1004 default : break;
1005 }
1006 if (error != ERR_NONE) return error;
1007 }
1008
1009 /* We have some phone locations and some data to set. We try to
1010 * find info about locations in phone used to write concrete bearers
1011 */
1012 for (i=0;i<settings->Number;i++) {
1013 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) {
1014 if (phone1 != -1) loc1=i;
1015 }
1016 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_SMS) {
1017 if (phone2 != -1) loc2=i;
1018 }
1019 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_USSD) {
1020 if (phone3 != -1) loc3=i;
1021 }
1022 }
1023
1024 pos = 5;
1025 memset(SetReq + pos, 0, 200 - pos);
1026 SetReq[4] = settings->Location - 1;
1027 if (loc1 != -1) {
1028 /* Name */
1029 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc1].Title, false);
1030 /* HomePage */
1031 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc1].HomePage, false);
1032 if (settings->Settings[loc1].IsContinuous) SetReq[pos] = 0x01;
1033 pos++;
1034 SetReq[pos++] = ID;
1035
1036 SetReq[pos] = phone1; /* bearer */
1037 switch (settings->ActiveBearer) {
1038 case WAPSETTINGS_BEARER_DATA:
1039 if (loc1 != -1) SetReq[pos] = phone1;
1040 break;
1041 case WAPSETTINGS_BEARER_SMS:
1042 if (loc2 != -1) SetReq[pos] = phone2;
1043 break;
1044 case WAPSETTINGS_BEARER_USSD:
1045 if (loc3 != -1) SetReq[pos] = phone3;
1046 break;
1047 default: break;
1048 }
1049 pos++;
1050
1051 if (settings->Settings[loc1].IsSecurity) SetReq[pos] = 0x01;
1052 pos++;
1053 } else if (loc2 != -1) {
1054 /* Name */
1055 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc2].Title, false);
1056 /* HomePage */
1057 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc2].HomePage, false);
1058 if (settings->Settings[loc2].IsContinuous) SetReq[pos] = 0x01;
1059 pos++;
1060 SetReq[pos++] = ID;
1061
1062 SetReq[pos] = phone2; /* bearer */
1063 switch (settings->ActiveBearer) {
1064 case WAPSETTINGS_BEARER_DATA:
1065 if (loc1 != -1) SetReq[pos] = phone1;
1066 break;
1067 case WAPSETTINGS_BEARER_SMS:
1068 if (loc2 != -1) SetReq[pos] = phone2;
1069 break;
1070 case WAPSETTINGS_BEARER_USSD:
1071 if (loc3 != -1) SetReq[pos] = phone3;
1072 break;
1073 default: break;
1074 }
1075 pos++;
1076
1077 if (settings->Settings[loc2].IsSecurity) SetReq[pos] = 0x01;
1078 pos++;
1079 } else if (loc3 != -1) {
1080 /* Name */
1081 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc3].Title, false);
1082 /* HomePage */
1083 pos += NOKIA_SetUnicodeString(s, SetReq + pos, settings->Settings[loc3].HomePage, false);
1084 if (settings->Settings[loc3].IsContinuous) SetReq[pos] = 0x01;
1085 pos++;
1086 SetReq[pos++] = ID;
1087
1088 SetReq[pos] = phone3; /* bearer */
1089 switch (settings->ActiveBearer) {
1090 case WAPSETTINGS_BEARER_DATA:
1091 if (loc1 != -1) SetReq[pos] = phone1;
1092 break;
1093 case WAPSETTINGS_BEARER_SMS:
1094 if (loc2 != -1) SetReq[pos] = phone2;
1095 break;
1096 case WAPSETTINGS_BEARER_USSD:
1097 if (loc3 != -1) SetReq[pos] = phone3;
1098 break;
1099 default: break;
1100 }
1101 pos++;
1102
1103 if (settings->Settings[loc3].IsSecurity) SetReq[pos] = 0x01;
1104 pos++;
1105 } else {
1106 return ERR_UNKNOWN;/* We have to have write something known */
1107 }
1108 memcpy(SetReq + pos, "\x01\x80\x00\x00\x00\x00\x00\x00\x00", 9);
1109 pos += 9;
1110
1111 smprintf(s, "Writing WAP settings part 1\n");
1112 error=GSM_WaitFor (s, SetReq, pos, 0x3f, 4, ID_SetConnectSet);
1113 if (error != ERR_NONE) return error;
1114
1115 /* Data */
1116 if (phone1 != -1) {
1117 pos = 4;
1118 memset(SetReq2 + pos, 0, 200 - pos);
1119 SetReq2[pos++] = phone1;
1120 SetReq2[pos++] = 0x02;
1121 SetReq2[pos++] = 0x01; /* GSMdata */
1122 if (loc1 != -1) {
1123 if (!settings->Settings[loc1].IsNormalAuthentication) SetReq2[pos] = 0x01;
1124 }
1125 pos++;
1126 if (loc1 != -1) {
1127 if (settings->Settings[loc1].IsISDNCall) SetReq2[pos] = 0x01;
1128 }
1129 pos++;
1130 if (loc1 != -1) {
1131 switch (settings->Settings[loc1].Speed) {
1132 case WAPSETTINGS_SPEED_9600 : SetReq2[pos++] = 0x01; break;
1133 case WAPSETTINGS_SPEED_14400 : SetReq2[pos++] = 0x02; break;
1134 default : SetReq2[pos++] = 0x02; break;
1135 }
1136 switch (settings->Settings[loc1].Speed) {
1137 case WAPSETTINGS_SPEED_9600 : SetReq2[pos++] = 0x01; break;
1138 case WAPSETTINGS_SPEED_14400 : SetReq2[pos++] = 0x02; break;
1139 default : SetReq2[pos++] = 0x02; break;
1140 }
1141 } else pos+=2;
1142 if (loc1 != -1) {
1143 /* IP */
1144 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].IPAddress, false);
1145 /* Number */
1146 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].DialUp, false);
1147 /* Username */
1148 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].User, false);
1149 /* Password */
1150 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc1].Password, false);
1151 } else pos+=5;
1152 memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
1153 pos += 8;
1154 smprintf(s, "Writing WAP settings part 2 (Data bearer)\n");
1155 error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
1156 if (error != ERR_NONE) return error;
1157 }
1158 /* SMS */
1159 if (phone2 != -1) {
1160 pos = 4;
1161 memset(SetReq2 + pos, 0, 200 - pos);
1162 SetReq2[pos++] = phone2;
1163 SetReq2[pos++] = 0x02;
1164 SetReq2[pos++] = 0x00; /* SMS */
1165 if (loc2 != -1) {
1166 /* Service number */
1167 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc2].Service, false);
1168 /* Server number */
1169 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc2].Server, false);
1170 } else pos += 2;
1171 memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
1172 pos += 8;
1173 smprintf(s, "Writing WAP settings part 2 (SMS bearer)\n");
1174 error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
1175 if (error != ERR_NONE) return error;
1176 }
1177 /* USSD */
1178 if (phone3 != -1) {
1179 pos = 4;
1180 memset(SetReq2 + pos, 0, 200 - pos);
1181 SetReq2[pos++] = phone3;
1182 SetReq2[pos++] = 0x02;
1183 SetReq2[pos++] = 0x02; /* USSD */
1184 if (loc3 != -1) {
1185 if (!settings->Settings[loc3].IsIP) SetReq2[pos] = 0x01;
1186 }
1187 pos++;
1188 if (loc3 != -1) {
1189 /* Service number or IP address */
1190 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc3].Service, false);
1191 /* Code number */
1192 pos += NOKIA_SetUnicodeString(s, SetReq2 + pos, settings->Settings[loc3].Code, false);
1193 } else pos+=2;
1194 memcpy(SetReq2 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
1195 pos += 8;
1196 smprintf(s, "Writing WAP settings part 2 (USSD bearer)\n");
1197 error=GSM_WaitFor (s, SetReq2, pos, 0x3f, 4, ID_SetConnectSet);
1198 if (error != ERR_NONE) return error;
1199 }
1200 error = DCT3DCT4_SetActiveConnectSet(s, settings);
1201 if (error != ERR_NONE) return error;
1202
1203 return DCT3DCT4_DisableConnectionFunctions(s);
1204}
1205
1206GSM_Error DCT3_ReplySendSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
1207{
1208 switch (msg.Buffer[3]) {
1209 case 0x02:
1210 smprintf(s, "SMS sent OK\n");
1211 if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,0,0);
1212 return ERR_NONE;
1213 case 0x03:
1214 smprintf(s, "Error %i\n",msg.Buffer[6]);
1215 if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,msg.Buffer[6],0);
1216 return ERR_NONE;
1217 }
1218 return ERR_UNKNOWNRESPONSE;
1219}
1220
1221GSM_Error DCT3_SendSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
1222{
1223 int length;
1224 GSM_Error error;
1225 unsigned char req[256] = {N6110_FRAME_HEADER, 0x01, 0x02, 0x00};
1226
1227 error=PHONE_EncodeSMSFrame(s,sms,req+6,PHONE_SMSSubmit,&length, true);
1228 if (error != ERR_NONE) return error;
1229
1230 smprintf(s, "Sending sms\n");
1231 return s->Protocol.Functions->WriteMessage(s, req, 6+length, 0x02);
1232}
1233
1234GSM_Error DCT3_ReplyNetmonitor(GSM_Protocol_Message msg, GSM_StateMachine *s)
1235{
1236 switch (msg.Buffer[3]) {
1237 case 0x00:
1238 smprintf(s, "Netmonitor correctly set\n");
1239 break;
1240 default:
1241 smprintf(s, "Menu %i\n",msg.Buffer[3]);
1242 smprintf(s, "%s\n",msg.Buffer+4);
1243 strcpy(s->Phone.Data.Netmonitor,msg.Buffer+4);
1244 break;
1245 }
1246 return ERR_NONE;
1247}
1248
1249GSM_Error DCT3_Netmonitor(GSM_StateMachine *s, int testnumber, char *value)
1250{
1251 GSM_Error error;
1252 unsigned char req[] = {0x00, 0x01, 0x7e,
1253 0x00}; /* Test number */
1254
1255 value[0] = 0;
1256
1257 error=DCT3_EnableSecurity (s, 0x01);
1258 if (error != ERR_NONE) return error;
1259
1260 req[3] = testnumber;
1261
1262 smprintf(s, "Getting netmonitor test\n");
1263 s->Phone.Data.Netmonitor = value;
1264 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_Netmonitor);
1265}
1266
1267GSM_Error DCT3_GetManufactureMonth(GSM_StateMachine *s, char *value)
1268{
1269 GSM_Error error;
1270
1271 error=DCT3_EnableSecurity (s, 0x01);
1272 if (error != ERR_NONE) return error;
1273 return NOKIA_GetPhoneString(s,"\x00\x01\xCC\x02",4,0x40,value,ID_GetManufactureMonth,5);
1274}
1275
1276GSM_Error DCT3_GetProductCode(GSM_StateMachine *s, char *value)
1277{
1278 GSM_Error error;
1279
1280 if (strlen(s->Phone.Data.ProductCodeCache)!=0) {
1281 strcpy(value,s->Phone.Data.ProductCodeCache);
1282 return ERR_NONE;
1283 }
1284
1285 error=DCT3_EnableSecurity (s, 0x01);
1286 if (error != ERR_NONE) return error;
1287 return NOKIA_GetPhoneString(s,"\x00\x01\xCA\x01",4,0x40,value,ID_GetProductCode,5);
1288}
1289
1290GSM_Error DCT3_GetOriginalIMEI(GSM_StateMachine *s, char *value)
1291{
1292 GSM_Error error;
1293
1294 error=DCT3_EnableSecurity (s, 0x01);
1295 if (error != ERR_NONE) return error;
1296 return NOKIA_GetPhoneString(s,"\x00\x01\xCC\x01",4,0x40,value,ID_GetOriginalIMEI,5);
1297}
1298
1299GSM_Error DCT3_GetHardware(GSM_StateMachine *s, char *value)
1300{
1301 GSM_Error error;
1302
1303 if (strlen(s->Phone.Data.HardwareCache)!=0) {
1304 strcpy(value,s->Phone.Data.HardwareCache);
1305 return ERR_NONE;
1306 }
1307
1308 error=DCT3_EnableSecurity (s, 0x01);
1309 if (error != ERR_NONE) return error;
1310 return NOKIA_GetPhoneString(s,"\x00\x01\xC8\x05",4,0x40,value,ID_GetHardware,5);
1311}
1312
1313GSM_Error DCT3_GetPPM(GSM_StateMachine *s, char *value)
1314{
1315 GSM_Error error;
1316
1317 error=DCT3_EnableSecurity (s, 0x01);
1318 if (error != ERR_NONE) return error;
1319 return NOKIA_GetPhoneString(s,"\x00\x01\xC8\x12",4,0x40,value,ID_GetPPM,5);
1320}
1321
1322GSM_Error DCT3_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
1323{
1324 unsigned char req[] = {N6110_FRAME_HEADER, 0x36, 0x64};
1325
1326 s->Phone.Data.SMSStatus=status;
1327 smprintf(s, "Getting SMS status\n");
1328 return GSM_WaitFor (s, req, 5, 0x14, 2, ID_GetSMSStatus);
1329
1330 /* 6210 family doesn't show in frame with SMS status info
1331 * about Templates. We get separately info about this SMS folder.
1332 */
1333}
1334
1335GSM_Error DCT3_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
1336{
1337 switch(msg.Buffer[3]) {
1338 case 0x0b:
1339 smprintf(s, "SMS deleted\n");
1340 return ERR_NONE;
1341 case 0x0c:
1342 smprintf(s, "Error deleting SMS\n");
1343 switch (msg.Buffer[4]) {
1344 case 0x00:
1345 /* Not tested on 6210 */
1346 smprintf(s, "Unknown meaning, SMS seems to be deleted\n");
1347 return ERR_NONE;
1348 case 0x02:
1349 /* Not tested on 6210 */
1350 smprintf(s, "Invalid location\n");
1351 return ERR_INVALIDLOCATION;
1352 case 0x06:
1353 /* Not tested on 6210 */
1354 smprintf(s, "Phone is OFF\n");
1355 return ERR_PHONEOFF;
1356 default:
1357 smprintf(s, "Unknown error: %02x\n",msg.Buffer[4]);
1358 return ERR_UNKNOWNRESPONSE;
1359 }
1360 }
1361 return ERR_UNKNOWNRESPONSE;
1362}
1363
1364GSM_Error N71_92_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
1365{
1366 GSM_Phone_Data *Data = &s->Phone.Data;
1367
1368 smprintf(s, "Network level received: %i\n",msg.Buffer[4]);
1369 Data->SignalQuality->SignalStrength = -1;
1370 Data->SignalQuality->SignalPercent = ((int)msg.Buffer[4]);
1371 Data->SignalQuality->BitErrorRate = -1;
1372 return ERR_NONE;
1373}
1374
1375GSM_Error N71_92_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
1376{
1377 unsigned char req[] = {N6110_FRAME_HEADER, 0x81};
1378
1379 s->Phone.Data.SignalQuality = sig;
1380 smprintf(s, "Getting network level\n");
1381 return GSM_WaitFor (s, req, 4, 0x0a, 4, ID_GetSignalQuality);
1382}
1383
1384GSM_Error N71_92_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
1385{
1386 GSM_Phone_Data *Data = &s->Phone.Data;
1387
1388 smprintf(s, "Battery level received: %i\n",msg.Buffer[5]);
1389 Data->BatteryCharge->BatteryPercent = ((int)msg.Buffer[5]);
1390 Data->BatteryCharge->ChargeState = 0;
1391 return ERR_NONE;
1392}
1393
1394GSM_Error N71_92_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
1395{
1396 unsigned char req[] = {N6110_FRAME_HEADER, 0x02};
1397
1398 s->Phone.Data.BatteryCharge = bat;
1399 smprintf(s, "Getting battery level\n");
1400 return GSM_WaitFor (s, req, 4, 0x17, 4, ID_GetBatteryCharge);
1401}
1402
1403GSM_Error N71_92_ReplyPhoneSetting(GSM_Protocol_Message msg, GSM_StateMachine *s)
1404{
1405 GSM_Phone_Bitmap_TypesBmpType;
1406 GSM_Phone_Data *Data = &s->Phone.Data;
1407
1408 switch (msg.Buffer[4]) {
1409 case 0x02:
1410 if (Data->RequestID == ID_GetBitmap || Data->RequestID == ID_EachFrame) {
1411 smprintf(s, "Welcome note text received\n");
1412 CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
1413 smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
1414 return ERR_NONE;
1415 }
1416 if (Data->RequestID == ID_SetBitmap || Data->RequestID == ID_EachFrame) {
1417 smprintf(s, "Startup text set\n");
1418 return ERR_NONE;
1419 }
1420 case 0x15:
1421 if (Data->RequestID == ID_GetBitmap || Data->RequestID == ID_EachFrame) {
1422 smprintf(s, "Startup logo received\n");
1423 BmpType=GSM_Nokia7110StartupLogo;
1424 if (msg.Buffer[17]==0x60) BmpType=GSM_Nokia6210StartupLogo;
1425 if (msg.Buffer[17]==0xc0) BmpType=GSM_NokiaStartupLogo;
1426 PHONE_DecodeBitmap(BmpType, msg.Buffer+22, Data->Bitmap);
1427 return ERR_NONE;
1428 }
1429 if (Data->RequestID == ID_SetBitmap || Data->RequestID == ID_EachFrame) {
1430 smprintf(s, "Startup logo set\n");
1431 return ERR_NONE;
1432 }
1433 case 0x17:
1434 if (Data->RequestID == ID_GetBitmap || Data->RequestID == ID_EachFrame) {
1435 smprintf(s, "Dealer note text received\n");
1436 CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
1437 smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
1438 return ERR_NONE;
1439 }
1440 if (Data->RequestID == ID_SetBitmap || Data->RequestID == ID_EachFrame) {
1441 smprintf(s, "Dealer text set\n");
1442 return ERR_NONE;
1443 }
1444 }
1445 return ERR_UNKNOWNRESPONSE;
1446}
1447
1448GSM_Error N71_92_GetPhoneSetting(GSM_StateMachine *s, int Request, int Setting)
1449{
1450 unsigned char req[] = {N7110_FRAME_HEADER, 0xee,
1451 0x1c}; /* Setting */
1452
1453 req[4]=Setting;
1454 return GSM_WaitFor (s, req, 5, 0x7a, 4, Request);
1455}
1456
1457GSM_Error N71_92_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
1458{
1459 return DCT3_GetDateTime(s, date_time, 0x19);
1460}
1461
1462GSM_Error N71_92_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
1463{
1464 return DCT3_SetDateTime(s, date_time, 0x19);
1465}
1466
1467GSM_Error DCT3_DecodeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *SMS, unsigned char *buffer)
1468{
1469 switch (buffer[12] & 0x03) {
1470 case 0x00:
1471 smprintf(s, "SMS type - deliver\n");
1472 SMS->PDU = SMS_Deliver;
1473 return GSM_DecodeSMSFrame(SMS,buffer,PHONE_SMSDeliver);
1474 case 0x01:
1475 smprintf(s, "SMS type - submit\n");
1476 SMS->PDU = SMS_Submit;
1477 return GSM_DecodeSMSFrame(SMS,buffer,PHONE_SMSSubmit);
1478 case 0x02:
1479 smprintf(s, "SMS type - delivery report\n");
1480 SMS->PDU = SMS_Status_Report;
1481 return GSM_DecodeSMSFrame(SMS,buffer,PHONE_SMSStatusReport);
1482 }
1483 return ERR_UNKNOWN;
1484}
1485
1486GSM_Error N61_91_ReplySetOpLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1487{
1488 switch (msg.Buffer[3]) {
1489 case 0x31:
1490 smprintf(s, "Operator logo set OK\n");
1491 return ERR_NONE;
1492 case 0x32:
1493 smprintf(s, "Error setting operator logo\n");
1494 switch (msg.Buffer[4]) {
1495 case 0x7d:
1496 smprintf(s, "Too high location ?\n");
1497 return ERR_INVALIDLOCATION;
1498 default:
1499 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1500 }
1501 }
1502 return ERR_UNKNOWNRESPONSE;
1503}
1504
1505GSM_Error N61_71_ReplyResetPhoneSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
1506{
1507 smprintf(s, "Phone settings cleaned OK\n");
1508 return ERR_NONE;
1509}
1510
1511GSM_Error N61_71_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type)
1512{
1513 GSM_Errorerror;
1514 unsigned char req[] = {0x00, 0x01, 0x65,
1515 0x01}; /* Reset type */
1516
1517 switch (Type) {
1518 case GSM_RESET_PHONESETTINGS : req[3] = 0x01; break;
1519 case GSM_RESET_DEVICE : req[3] = 0x02; break;
1520 case GSM_RESET_USERINTERFACE : req[3] = 0x08; break;
1521 case GSM_RESET_USERINTERFACE_PHONESETTINGS: req[3] = 0x38; break;
1522 case GSM_RESET_FULLFACTORY : req[3] = 0xff; break;
1523 }
1524
1525 error=DCT3_EnableSecurity (s, 0x01);
1526 if (error != ERR_NONE) return error;
1527
1528 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_ResetPhoneSettings);
1529}
1530
1531#endif
1532
1533/* How should editor hadle tabs in this file? Add editor commands here.
1534 * vim: noexpandtab sw=8 ts=8 sts=8:
1535 */
diff --git a/gammu/emb/common/phone/nokia/dct3/dct3func.h b/gammu/emb/common/phone/nokia/dct3/dct3func.h
new file mode 100644
index 0000000..66b67ec
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/dct3func.h
@@ -0,0 +1,78 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef phone_nokia_dct3_h
4#define phone_nokia_dct3_h
5
6 GSM_Error DCT3_ReplyPressKey (GSM_Protocol_Message msg, GSM_StateMachine *s);
7 GSM_Error DCT3_ReplyPlayTone (GSM_Protocol_Message msg, GSM_StateMachine *s);
8 GSM_Error DCT3_ReplyEnableSecurity(GSM_Protocol_Message msg, GSM_StateMachine *s);
9 GSM_Error DCT3_ReplyGetIMEI (GSM_Protocol_Message msg, GSM_StateMachine *s);
10 GSM_Error DCT3_ReplyGetSMSC (GSM_Protocol_Message msg, GSM_StateMachine *s);
11 GSM_Error DCT3_ReplySIMLogin (GSM_Protocol_Message msg, GSM_StateMachine *s);
12 GSM_Error DCT3_ReplySIMLogout (GSM_Protocol_Message msg, GSM_StateMachine *s);
13 GSM_Error DCT3_ReplyGetDateTime (GSM_Protocol_Message msg, GSM_StateMachine *s);
14 GSM_Error DCT3_ReplyGetAlarm (GSM_Protocol_Message msg, GSM_StateMachine *s);
15 GSM_Error DCT3_ReplySetDateTime (GSM_Protocol_Message msg, GSM_StateMachine *s);
16 GSM_Error DCT3_ReplySetAlarm (GSM_Protocol_Message msg, GSM_StateMachine *s);
17 GSM_Error DCT3_ReplyDialCommand (GSM_Protocol_Message msg, GSM_StateMachine *s);
18 GSM_Error DCT3_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s);
19 GSM_Error DCT3_ReplyGetNetworkInfo(GSM_Protocol_Message msg, GSM_StateMachine *s);
20 GSM_Error DCT3_ReplySendSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s);
21 GSM_Error DCT3_ReplySetSMSC (GSM_Protocol_Message msg, GSM_StateMachine *s);
22 GSM_Error DCT3_ReplyGetWAPSettings(GSM_Protocol_Message msg, GSM_StateMachine *s);
23 GSM_Error DCT3_ReplySetWAPSettings(GSM_Protocol_Message msg, GSM_StateMachine *s);
24 GSM_Error DCT3_ReplyNetmonitor (GSM_Protocol_Message msg, GSM_StateMachine *s);
25 GSM_Error DCT3_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s);
26 GSM_Error N71_92_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s);
27 GSM_Error N71_92_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s);
28 GSM_Error N71_92_ReplyPhoneSetting(GSM_Protocol_Message msg, GSM_StateMachine *s);
29GSM_Error N61_71_ReplyResetPhoneSettings(GSM_Protocol_Message msg, GSM_StateMachine *s);
30 GSM_Error N61_91_ReplySetOpLogo (GSM_Protocol_Message msg, GSM_StateMachine *s);
31#ifdef GSM_ENABLE_CELLBROADCAST
32 GSM_Error DCT3_ReplySetIncomingCB(GSM_Protocol_Message msg, GSM_StateMachine *s);
33 GSM_Error DCT3_ReplyIncomingCB (GSM_Protocol_Message msg, GSM_StateMachine *s);
34#endif
35
36 GSM_Error DCT3_DeleteWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
37 GSM_Error DCT3_GetWAPBookmark (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
38 GSM_Error DCT3_PressKey (GSM_StateMachine *s, GSM_KeyCode Key, bool Press);
39 GSM_Error DCT3_PlayTone (GSM_StateMachine *s, int Herz, unsigned char Volume, bool start);
40 GSM_Error DCT3_EnableSecurity (GSM_StateMachine *s, unsigned char status);
41 GSM_Error DCT3_GetIMEI (GSM_StateMachine *s);
42 GSM_Error DCT3_GetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc );
43 GSM_Error DCT3_GetNetworkInfo (GSM_StateMachine *s, GSM_NetworkInfo *netinfo);
44 GSM_Error DCT3_DialVoice (GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber);
45 GSM_Error DCT3_Reset (GSM_StateMachine *s, bool hard );
46 GSM_Error DCT3_CancelCall (GSM_StateMachine *s, int ID, bool all);
47 GSM_Error DCT3_AnswerAllCalls (GSM_StateMachine *s);
48 GSM_Error DCT3_SendSMSMessage (GSM_StateMachine *s, GSM_SMSMessage *sms );
49 GSM_Error DCT3_GetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm,unsigned char msgtype);
50 GSM_Error DCT3_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype);
51 GSM_Error DCT3_SetAlarm (GSM_StateMachine *s, GSM_Alarm *alarm, unsigned char msgtype);
52 GSM_Error DCT3_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time, unsigned char msgtype);
53 GSM_Error DCT3_SetIncomingCB (GSM_StateMachine *s, bool enable);
54 GSM_Error DCT3_GetSMSStatus (GSM_StateMachine *s, GSM_SMSMemoryStatus *status);
55 GSM_Error DCT3_SetSMSC (GSM_StateMachine *s, GSM_SMSC *smsc );
56 GSM_Error DCT3_GetWAPSettings (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
57 GSM_Error DCT3_SetWAPSettings (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
58 GSM_Error DCT3_SetWAPBookmark (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
59 GSM_Error DCT3_Netmonitor (GSM_StateMachine *s, int testnumber, char *value);
60 GSM_Error DCT3_GetManufactureMonth (GSM_StateMachine *s, char *value);
61 GSM_Error DCT3_GetProductCode (GSM_StateMachine *s, char *value);
62 GSM_Error DCT3_GetOriginalIMEI (GSM_StateMachine *s, char *value);
63 GSM_Error DCT3_GetHardware (GSM_StateMachine *s, char *value);
64 GSM_Error DCT3_GetPPM (GSM_StateMachine *s, char *value);
65 GSM_Error N61_71_ResetPhoneSettings(GSM_StateMachine *s, GSM_ResetSettingsType Type);
66 GSM_Error N71_92_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat);
67 GSM_Error N71_92_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig);
68 GSM_Error N71_92_GetPhoneSetting(GSM_StateMachine *s, int Request, int Setting);
69 GSM_Error N71_92_GetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
70 GSM_Error N71_92_SetDateTime (GSM_StateMachine *s, GSM_DateTime *date_time);
71
72 GSM_Error DCT3_DecodeSMSFrame (GSM_StateMachine *s, GSM_SMSMessage *SMS, unsigned char *buffer);
73
74#endif
75
76/* How should editor hadle tabs in this file? Add editor commands here.
77 * vim: noexpandtab sw=8 ts=8 sts=8:
78 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n6110.c b/gammu/emb/common/phone/nokia/dct3/n6110.c
new file mode 100644
index 0000000..263d12b
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n6110.c
@@ -0,0 +1,2884 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Markus Plail and Gnokii */
3/* Authentication function (c) 1999 or earlier by Pavel Janik */
4/* 5210 calendar IDs by Frederick Ros */
5
6#include "../../../gsmstate.h"
7
8#ifdef GSM_ENABLE_NOKIA6110
9
10#include <string.h>
11
12#include "../../../../cfg/config.h"
13#include "../../../misc/coding/coding.h"
14#include "../../../service/sms/gsmsms.h"
15#include "../../../gsmcomon.h"
16#include "../../pfunc.h"
17#include "../nfunc.h"
18#include "n6110.h"
19#include "dct3func.h"
20
21static unsigned char N6110_MEMORY_TYPES[] = {
22 MEM_ME, 0x02,
23 MEM_SM, 0x03,
24 MEM_ON, 0x05,
25 MEM_DC, 0x07,
26 MEM_RC, 0x08,
27 MEM_MC, 0x09,
28 MEM_VM, 0x0b,
29 0x00, 0x00
30};
31
32static GSM_Error N6110_ReplyGetPhoneLanguage(GSM_Protocol_Message msg, GSM_StateMachine *s)
33{
34 N6110_Language lang = N6110_Auto;
35
36 if (msg.Buffer[3] == 0x15) return ERR_NONE;
37
38 smprintf(s, "Phone language is %02x\n",msg.Buffer[6]);
39 switch (msg.Buffer[6]) {
40 case 0x21: lang = N6110_Europe; break; //Polish
41 }
42 s->Phone.Data.Priv.N6110.PhoneLanguage = lang;
43 return ERR_NONE;
44}
45
46static GSM_Error N6110_GetPhoneLanguage(GSM_StateMachine *s)
47{
48 unsigned char feat_req[] = {N6110_FRAME_HEADER, 0x13, 0x01,
49 0x00, /* Profile location */
50 0x00}; /* Feature number */
51
52 s->Phone.Data.Priv.N6110.PhoneLanguage = N6110_Auto;
53
54 feat_req[5] = 0;
55 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
56 feat_req[6] = 0x1E;
57 } else {
58 feat_req[6] = 0x21;
59 }
60 smprintf(s, "Getting profile feature\n");
61 return GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetLanguage);
62}
63
64struct N6110_Lang_Char {
65 N6110_Language Lang;
66 unsigned char Phone;
67 unsigned char Unicode1;
68 unsigned char Unicode2;
69};
70
71static struct N6110_Lang_Char N6110_Lang_Table[] = {
72{N6110_Europe,0x13,0x01,0x04},//Latin capital letter a with ogonek
73{N6110_Europe,0x14,0x01,0x05},//Latin small letter a with ogonek
74{N6110_Europe,0x15,0x01,0x06},//Latin capital letter c with acute
75{N6110_Europe,0x17,0x01,0x07},//Latin small letter c with acute
76{N6110_Europe,0x1D,0x01,0x18},//Latin capital letter e with ogonek
77{N6110_Europe,0x1E,0x01,0x19},//Latin small letter e with ogonek
78{N6110_Europe,0x83,0x00,0xD3},//Latin capital letter o with acute
79{N6110_Europe,0x8E,0x01,0x41},//Latin capital letter l with stroke
80{N6110_Europe,0x90,0x01,0x42},//Latin small letter l with stroke
81{N6110_Europe,0x92,0x01,0x43},//Latin capital letter n with acute
82{N6110_Europe,0x93,0x01,0x44},//Latin small letter n with acute
83{N6110_Europe,0x9A,0x00,0xF3},//Latin small letter o with acute
84{N6110_Europe,0xB2,0x20,0xAC},//euro
85{N6110_Europe,0xB5,0x01,0x5A},//Latin capital letter s with acute
86{N6110_Europe,0xB6,0x01,0x5B},//Latin small letter s with acute
87{N6110_Europe,0xE7,0x01,0x79},//Latin capital letter z with acute
88{N6110_Europe,0xEE,0x01,0x7A},//Latin small letter z with acute
89{N6110_Europe,0xF4,0x01,0x7C},//Latin small letter z with dot above
90{N6110_Europe,0xF0,0x01,0x7B},//Latin capital letter z with dot above
91{0,0,0,0}
92};
93
94static void N6110_EncodeUnicode(GSM_StateMachine *s, unsigned char *dest, const unsigned char *src, int len)
95{
96 int i_len = 0, o_len, i;
97 wchar_t wc;
98 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
99 bool found;
100
101 for (o_len = 0; i_len < len; o_len++) {
102 found = false;
103 if (Priv->PhoneLanguage != N6110_Auto) {
104 i = 0;
105 while(1) {
106 if (N6110_Lang_Table[i].Lang == 0) break;
107 if (N6110_Lang_Table[i].Lang == Priv->PhoneLanguage &&
108 N6110_Lang_Table[i].Phone == src[i_len]) {
109 dest[o_len*2] = N6110_Lang_Table[i].Unicode1;
110 dest[(o_len*2)+1] = N6110_Lang_Table[i].Unicode2;
111 i_len++;
112 found = true;
113 break;
114 }
115 i++;
116 }
117 }
118 if (!found) {
119 i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
120 dest[o_len*2] = (wc >> 8) & 0xff;
121 dest[(o_len*2)+1] = wc & 0xff;
122 }
123 }
124 dest[o_len*2] = 0;
125 dest[(o_len*2)+1] = 0;
126}
127
128#ifndef ENABLE_LGPL
129
130/* This function provides Nokia authentication protocol.
131 * Nokia authentication protocol is used in the communication between Nokia
132 * mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software,
133 * commercially sold by Nokia Corp.
134 * The authentication scheme is based on the token send by the phone to the
135 * software. The software does it's magic (see the function
136 * N6110_GetNokiaAuthentication) and returns the result back to the phone.
137 * If the result is correct the phone responds with the message "Accessory
138 * connected!" displayed on the LCD. Otherwise it will display "Accessory not
139 * supported" and some functions will not be available for use (?).
140 * The specification of the protocol is not publicly available, no comment.
141 */
142static void N6110_GetNokiaAuthentication(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse)
143{
144 int i, j, CRC=0;
145 unsigned char Temp[16]; /* This is our temporary working area. */
146
147 /* Here we put FAC (Final Assembly Code) and serial number into our area. */
148 Temp[0] = Imei[6]; Temp[1] = Imei[7];
149 Temp[2] = Imei[8]; Temp[3] = Imei[9];
150 Temp[4] = Imei[10]; Temp[5] = Imei[11];
151 Temp[6] = Imei[12]; Temp[7] = Imei[13];
152
153 /* And now the TAC (Type Approval Code). */
154 Temp[8] = Imei[2]; Temp[9] = Imei[3];
155 Temp[10] = Imei[4]; Temp[11] = Imei[5];
156
157 /* And now we pack magic bytes from the phone. */
158 Temp[12] = MagicBytes[0]; Temp[13] = MagicBytes[1];
159 Temp[14] = MagicBytes[2]; Temp[15] = MagicBytes[3];
160
161 for (i=0; i<=11; i++) if (Temp[i + 1]& 1) Temp[i]<<=1;
162 switch (Temp[15] & 0x03) {
163 case 1:
164 case 2: j = Temp[13] & 0x07;
165 for (i=0; i<=3; i++) Temp[i+j] ^= Temp[i+12];
166 break;
167 default: j = Temp[14] & 0x07;
168 for (i=0; i<=3; i++) Temp[i + j] |= Temp[i + 12];
169 }
170 for (i=0; i<=15; i++) CRC ^= Temp[i];
171 for (i=0; i<=15; i++) {
172 switch (Temp[15 - i] & 0x06) {
173 case 0: j = Temp[i] | CRC; break;
174 case 2:
175 case 4: j = Temp[i] ^ CRC; break;
176 case 6: j = Temp[i] & CRC; break;
177 }
178 if (j == CRC) j = 0x2c;
179 if (Temp[i] == 0) j = 0;
180 MagicResponse[i] = j;
181 }
182}
183
184static GSM_Error N6110_ReplyGetMagicBytes(GSM_Protocol_Message msg, GSM_StateMachine *s)
185{
186 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
187 GSM_Phone_Data *Data = &s->Phone.Data;
188
189 sprintf(Data->IMEI, "%s", msg.Buffer+9);
190 sprintf(Data->HardwareCache, "%s", msg.Buffer+39);
191 sprintf(Data->ProductCodeCache, "%s", msg.Buffer+31);
192
193 smprintf(s, "Message: Mobile phone identification received:\n");
194 smprintf(s, "IMEI : %s\n", msg.Buffer+9);
195 smprintf(s, "Model : %s\n", msg.Buffer+25);
196 smprintf(s, "Production Code : %s\n", msg.Buffer+31);
197 smprintf(s, "HW : %s\n", msg.Buffer+39);
198 smprintf(s, "Firmware : %s\n", msg.Buffer+44);
199
200 /* These bytes are probably the source of the "Accessory not connected"
201 * messages on the phone when trying to emulate NCDS... I hope....
202 * UPDATE: of course, now we have the authentication algorithm.
203 */
204 smprintf(s, " Magic bytes : %02x %02x %02x %02x\n", msg.Buffer[50], msg.Buffer[51], msg.Buffer[52], msg.Buffer[53]);
205
206 Priv->MagicBytes[0]=msg.Buffer[50];
207 Priv->MagicBytes[1]=msg.Buffer[51];
208 Priv->MagicBytes[2]=msg.Buffer[52];
209 Priv->MagicBytes[3]=msg.Buffer[53];
210
211 return ERR_NONE;
212}
213
214static GSM_Error N6110_MakeAuthentication(GSM_StateMachine *s)
215{
216 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
217 GSM_Error error;
218 unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10};
219 unsigned char magic_connect[] = {
220 N6110_FRAME_HEADER, 0x12,
221 /* The real magic goes here ... These bytes are filled in
222 * with the function N6110_GetNokiaAuthentication. */
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 /* NOKIA&GNOKII Accessory */
226 'N', 'O', 'K', 'I', 'A', '&', 'N', 'O', 'K', 'I', 'A',
227 'a', 'c', 'c', 'e', 's', 's', 'o', 'r', 'y',
228 0x00, 0x00, 0x00, 0x00};
229
230 smprintf(s, "Getting magic bytes for authentication\n");
231 error=GSM_WaitFor (s, connect4, 4, 0x64, 4, ID_MakeAuthentication);
232 if (error!=ERR_NONE) return error;
233
234 N6110_GetNokiaAuthentication(s->Phone.Data.IMEI, Priv->MagicBytes, magic_connect+4);
235 smprintf(s, "Sending authentication bytes\n");
236 return s->Protocol.Functions->WriteMessage(s, magic_connect, 45, 0x64);
237}
238
239#endif
240
241static GSM_Error N6110_ShowStartInfo(GSM_StateMachine *s, bool enable)
242{
243#ifdef ENABLE_LGPL
244 return ERR_NONE;
245#else
246 GSM_Error error=ERR_NONE;
247
248 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_MAGICBYTES)) {
249 if (s->ConnectionType == GCT_FBUS2 ||
250 s->ConnectionType == GCT_FBUS2IRDA) {
251 error=N6110_MakeAuthentication(s);
252 }
253 }
254 return error;
255#endif
256}
257
258static GSM_Error N6110_Initialise (GSM_StateMachine *s)
259{
260#ifdef DEBUG
261 DCT3_SetIncomingCB(s,true);
262#endif
263 N6110_GetPhoneLanguage(s);
264 return ERR_NONE;
265}
266
267static GSM_Error N6110_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
268{
269 return DCT3_GetDateTime(s, date_time, 0x11);
270}
271
272static GSM_Error N6110_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
273{
274 return DCT3_GetAlarm(s, alarm, 0x11);
275}
276
277static GSM_Error N6110_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
278{
279 return DCT3_SetDateTime(s, date_time, 0x11);
280}
281
282static GSM_Error N6110_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
283{
284 return DCT3_SetAlarm(s, alarm, 0x11);
285}
286
287static GSM_Error N6110_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
288{
289 int count;
290 GSM_Phone_Data *Data = &s->Phone.Data;
291
292 smprintf(s, "Phonebook entry received\n");
293 switch (msg.Buffer[3]) {
294 case 0x02:
295 Data->Memory->EntriesNum = 0;
296 count=5;
297 /* If name is not empty */
298 if (msg.Buffer[count]!=0x00) {
299 if (msg.Buffer[count]>GSM_PHONEBOOK_TEXT_LENGTH) {
300 smprintf(s, "Too long text\n");
301 return ERR_UNKNOWNRESPONSE;
302 }
303 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Text_Name;
304 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
305 if (Data->Memory->MemoryType==MEM_DC ||
306 Data->Memory->MemoryType==MEM_RC ||
307 Data->Memory->MemoryType==MEM_MC ||
308 Data->Memory->MemoryType==MEM_ME) {
309 N6110_EncodeUnicode(s,Data->Memory->Entries[Data->Memory->EntriesNum].Text,
310 msg.Buffer+count+1,msg.Buffer[count]);
311 } else {
312 EncodeUnicode(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
313 msg.Buffer+count+1,msg.Buffer[count]);
314 }
315 } else {
316 memcpy(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
317 msg.Buffer+count+1,msg.Buffer[count]);
318 Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]]=0x00;
319 Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]+1]=0x00;
320 }
321 smprintf(s, "Name \"%s\"\n",
322 DecodeUnicodeString(Data->Memory->Entries[Data->Memory->EntriesNum].Text));
323 Data->Memory->EntriesNum++;
324 }
325 count=count+msg.Buffer[count]+1;
326
327 /* If number is empty */
328 if (msg.Buffer[count]==0x00) return ERR_EMPTY;
329
330 if (msg.Buffer[count]>GSM_PHONEBOOK_TEXT_LENGTH) {
331 smprintf(s, "Too long text\n");
332 return ERR_UNKNOWNRESPONSE;
333 }
334 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType = PBK_Number_General;
335 Data->Memory->Entries[Data->Memory->EntriesNum].VoiceTag = 0;
336 Data->Memory->Entries[Data->Memory->EntriesNum].SMSList[0] = 0;
337 EncodeUnicode(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
338 msg.Buffer+count+1,msg.Buffer[count]);
339 smprintf(s, "Number \"%s\"\n",
340 DecodeUnicodeString(Data->Memory->Entries[Data->Memory->EntriesNum].Text));
341 Data->Memory->EntriesNum++;
342 count=count+msg.Buffer[count]+1;
343
344 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALLER)) {
345 if (msg.Buffer[count]<5) {
346 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Caller_Group;
347 smprintf(s, "Caller group \"%i\"\n",msg.Buffer[count]);
348 Data->Memory->Entries[Data->Memory->EntriesNum].Number=msg.Buffer[count]+1;
349 Data->Memory->EntriesNum++;
350 }
351 }
352 count++;
353
354 if (Data->Memory->MemoryType==MEM_DC ||
355 Data->Memory->MemoryType==MEM_RC ||
356 Data->Memory->MemoryType==MEM_MC) {
357 NOKIA_DecodeDateTime(s, msg.Buffer+count+1,&Data->Memory->Entries[Data->Memory->EntriesNum].Date);
358 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Date;
359
360 /* These values are set, when date and time unavailable in phone.
361 * Values from 3310 - in other can be different */
362 if (Data->Memory->Entries[2].Date.Day !=20 ||
363 Data->Memory->Entries[2].Date.Month !=1 ||
364 Data->Memory->Entries[2].Date.Year !=2118||
365 Data->Memory->Entries[2].Date.Hour !=3 ||
366 Data->Memory->Entries[2].Date.Minute!=14 ||
367 Data->Memory->Entries[2].Date.Second!=7)
368 Data->Memory->EntriesNum++;
369 }
370
371 return ERR_NONE;
372 default:
373 switch (msg.Buffer[4]) {
374 case 0x6f:
375 smprintf(s, "Phone is OFF\n");
376 return ERR_PHONEOFF;
377 case 0x74:
378 /* TODO: check if not too high */
379 smprintf(s, "ERROR: Empty ????\n");
380 Data->Memory->EntriesNum = 0;
381 return ERR_EMPTY;
382 case 0x7d:
383 smprintf(s, "ERROR: Invalid memory type\n");
384 return ERR_NOTSUPPORTED;
385 case 0x8d:
386 smprintf(s, "ERROR: no PIN\n");
387 return ERR_SECURITYERROR;
388 default:
389 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
390 }
391 }
392 return ERR_UNKNOWNRESPONSE;
393}
394
395static GSM_Error N6110_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
396{
397 unsigned char req[] = {N6110_FRAME_HEADER, 0x01,
398 0x00, /* memory type */
399 0x00, /* location */
400 0x00};
401
402 req[4] = NOKIA_GetMemoryType(s, entry->MemoryType,N6110_MEMORY_TYPES);
403 if (req[4]==0xff) return ERR_NOTSUPPORTED;
404
405 req[5] = entry->Location;
406 if (entry->MemoryType==MEM_DC || entry->MemoryType==MEM_RC || entry->MemoryType==MEM_MC) req[5]--;
407
408 s->Phone.Data.Memory=entry;
409 smprintf(s, "Getting phonebook entry\n");
410 return GSM_WaitFor (s, req, 7, 0x03, 4, ID_GetMemory);
411}
412
413static GSM_Error N6110_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
414{
415 GSM_Phone_Data *Data = &s->Phone.Data;
416
417 smprintf(s, "Memory status received\n");
418 switch (msg.Buffer[3]) {
419 case 0x08:
420 smprintf(s, "Memory type: %i\n",msg.Buffer[4]);
421
422 smprintf(s, "Free : %i\n",msg.Buffer[5]);
423 Data->MemoryStatus->MemoryFree=msg.Buffer[5];
424
425 smprintf(s, "Used : %i\n",msg.Buffer[6]);
426 Data->MemoryStatus->MemoryUsed=msg.Buffer[6];
427
428 return ERR_NONE;
429 break;
430 case 0x09:
431 switch (msg.Buffer[4]) {
432 case 0x6f:
433 smprintf(s, "Phone is probably powered off.\n");
434 return ERR_TIMEOUT;
435 case 0x7d:
436 smprintf(s, "Memory type not supported by phone model.\n");
437 return ERR_NOTSUPPORTED;
438 case 0x8d:
439 smprintf(s, "Waiting for security code.\n");
440 return ERR_SECURITYERROR;
441 default:
442 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
443 }
444 default:
445 return ERR_UNKNOWNRESPONSE;
446 }
447}
448
449static GSM_Error N6110_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
450{
451 unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
452 0x00}; /* memory type */
453
454 req[4] = NOKIA_GetMemoryType(s, Status->MemoryType,N6110_MEMORY_TYPES);
455 if (req[4]==0xff) return ERR_NOTSUPPORTED;
456
457 s->Phone.Data.MemoryStatus=Status;
458 smprintf(s, "Getting memory status\n");
459 return GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetMemoryStatus);
460}
461
462static GSM_Error N6110_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
463{
464 GSM_Phone_Data *Data = &s->Phone.Data;
465
466 smprintf(s, "SMS status received\n");
467 switch (msg.Buffer[3]) {
468 case 0x37:
469 smprintf(s, "SIM size : %i\n",msg.Buffer[7]);
470 smprintf(s, "Used in SIM : %i\n",msg.Buffer[10]);
471 smprintf(s, "Unread in SIM : %i\n",msg.Buffer[11]);
472 Data->SMSStatus->SIMUsed = msg.Buffer[10];
473 Data->SMSStatus->SIMUnRead = msg.Buffer[11];
474 Data->SMSStatus->SIMSize = msg.Buffer[7];
475 Data->SMSStatus->PhoneUsed = 0;
476 Data->SMSStatus->PhoneUnRead = 0;
477 Data->SMSStatus->PhoneSize = 0;
478 Data->SMSStatus->TemplatesUsed = 0;
479 return ERR_NONE;
480 case 0x38:
481 smprintf(s, "Error. No PIN ?\n");
482 return ERR_SECURITYERROR;
483 }
484 return ERR_UNKNOWNRESPONSE;
485}
486
487static GSM_Error N6110_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
488{
489 GSM_Phone_Data *Data = &s->Phone.Data;
490
491 smprintf(s, "SMS Message received\n");
492 switch(msg.Buffer[3]) {
493 case 0x08:
494 Data->GetSMSMessage->Number = 1;
495 Data->GetSMSMessage->SMS[0].Name[0] = 0;
496 Data->GetSMSMessage->SMS[0].Name[1] = 0;
497 Data->GetSMSMessage->SMS[0].Memory = MEM_SM;
498 NOKIA_DecodeSMSState(s, msg.Buffer[4], &Data->GetSMSMessage->SMS[0]);
499 switch (msg.Buffer[7]) {
500 case 0x00: case 0x01: /* Report or SMS_Deliver */
501 Data->GetSMSMessage->SMS[0].Folder = 0x01;
502 Data->GetSMSMessage->SMS[0].InboxFolder = true;
503 break;
504 case 0x02: /* SMS_Submit */
505 Data->GetSMSMessage->SMS[0].Folder = 0x02;
506 Data->GetSMSMessage->SMS[0].InboxFolder = false;
507 break;
508 default:
509 return ERR_UNKNOWNRESPONSE;
510 }
511 DCT3_DecodeSMSFrame(s, &Data->GetSMSMessage->SMS[0],msg.Buffer+8);
512 return ERR_NONE;
513 case 0x09:
514 switch (msg.Buffer[4]) {
515 case 0x00:
516 smprintf(s, "Unknown. Probably phone too busy\n");
517 return ERR_UNKNOWN;
518 case 0x02:
519 smprintf(s, "Too high location ?\n");
520 return ERR_INVALIDLOCATION;
521 case 0x06:
522 smprintf(s, "Phone is OFF\n");
523 return ERR_PHONEOFF;
524 case 0x07:
525 smprintf(s, "Empty\n");
526 return ERR_EMPTY;
527 case 0x0c:
528 smprintf(s, "Access error. No PIN ?\n");
529 return ERR_SECURITYERROR;
530 default:
531 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
532 }
533 }
534 return ERR_UNKNOWNRESPONSE;
535}
536
537static GSM_Error N6110_GetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
538{
539 unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x02,
540 0x00, /* Location */
541 0x01, 0x64};
542
543 if (sms->SMS[0].Folder!=0x00) return ERR_NOTSUPPORTED;
544
545 req[5] = sms->SMS[0].Location;
546
547 s->Phone.Data.GetSMSMessage=sms;
548 smprintf(s, "Getting sms\n");
549 return GSM_WaitFor (s, req, 8, 0x02, 4, ID_GetSMSMessage);
550}
551
552static GSM_Error N6110_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
553{
554 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
555 GSM_Error error;
556
557 if (start) {
558 error=s->Phone.Functions->GetSMSStatus(s,&Priv->LastSMSStatus);
559 if (error!=ERR_NONE) return error;
560 Priv->LastSMSRead=0;
561 sms->SMS[0].Location=0;
562 }
563 while (true) {
564 sms->SMS[0].Location++;
565 if (Priv->LastSMSRead>=(Priv->LastSMSStatus.SIMUsed+Priv->LastSMSStatus.PhoneUsed+Priv->LastSMSStatus.TemplatesUsed)) return ERR_EMPTY;
566 error=s->Phone.Functions->GetSMS(s, sms);
567 if (error==ERR_NONE) {
568 Priv->LastSMSRead++;
569 break;
570 }
571 if (error != ERR_EMPTY) return error;
572 }
573 return error;
574}
575
576static GSM_Error N6110_ReplyGetStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
577{
578 GSM_Phone_Data *Data = &s->Phone.Data;
579
580#ifdef DEBUG
581 smprintf(s, "Phone status received :\n");
582 smprintf(s, "Mode : ");
583 switch (msg.Buffer[4]) {
584 case 0x01: smprintf(s, "registered within the network\n"); break;
585 case 0x02: smprintf(s, "call in progress\n"); break; /* ringing or already answered call */
586 case 0x03: smprintf(s, "waiting for security code\n"); break;
587 case 0x04: smprintf(s, "powered off\n"); break;
588 default : smprintf(s, "unknown\n");
589 }
590 smprintf(s, "Power source : ");
591 switch (msg.Buffer[7]) {
592 case 0x01: smprintf(s, "AC/DC\n"); break;
593 case 0x02: smprintf(s, "battery\n"); break;
594 default : smprintf(s, "unknown\n");
595 }
596 smprintf(s, "Battery Level : %d\n", msg.Buffer[8]);
597 smprintf(s, "Signal strength : %d\n", msg.Buffer[5]);
598#endif
599
600 switch (Data->RequestID) {
601 case ID_GetBatteryCharge:
602 Data->BatteryCharge->BatteryPercent = ((int)msg.Buffer[8])*25;
603 switch (msg.Buffer[7]) {
604 case 0x01: Data->BatteryCharge->ChargeState = GSM_BatteryConnected; break;
605 case 0x02: Data->BatteryCharge->ChargeState = GSM_BatteryPowered; break;
606 default : Data->BatteryCharge->ChargeState = 0;
607 }
608 return ERR_NONE;
609 case ID_GetSignalQuality:
610 Data->SignalQuality->SignalPercent = ((int)msg.Buffer[5])*25;
611 return ERR_NONE;
612 default:
613 return ERR_UNKNOWNRESPONSE;
614 }
615}
616
617static GSM_Error N6110_GetStatus(GSM_StateMachine *s, int ID)
618{
619 unsigned char req[] = {N6110_FRAME_HEADER, 0x01};
620
621 return GSM_WaitFor (s, req, 4, 0x04, 4, ID);
622}
623
624static GSM_Error N6110_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
625{
626 char value[100];
627 GSM_Error error;
628
629 sig->BitErrorRate = -1;
630 sig->SignalStrength = -1; /* TODO for netmon */
631
632 smprintf(s, "Getting network level\n");
633 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_POWER_BATT)) {
634 error = DCT3_Netmonitor(s, 1, value);
635 if (error!=ERR_NONE) return error;
636 sig->SignalPercent = 100;
637 if (value[4]!='-') {
638 if (value[5]=='9' && value[6]>'4') sig->SignalPercent = 25;
639 if (value[5]=='9' && value[6]<'5') sig->SignalPercent = 50;
640 if (value[5]=='8' && value[6]>'4') sig->SignalPercent = 75;
641 } else sig->SignalPercent = 0;
642 return ERR_NONE;
643 } else {
644 s->Phone.Data.SignalQuality = sig;
645 return N6110_GetStatus(s, ID_GetSignalQuality);
646 }
647}
648
649static GSM_Error N6110_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
650{
651 char value[100];
652 GSM_Error error;
653
654 smprintf(s, "Getting battery level\n");
655 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_POWER_BATT)) {
656 error = DCT3_Netmonitor(s, 23, value);
657 if (error!=ERR_NONE) return error;
658 bat->BatteryPercent = 100;
659 bat->ChargeState = 0;
660 if (value[29]=='7') bat->BatteryPercent = 75;
661 if (value[29]=='5') bat->BatteryPercent = 50;
662 if (value[29]=='2') bat->BatteryPercent = 25;
663 return ERR_NONE;
664 } else {
665 s->Phone.Data.BatteryCharge = bat;
666 return N6110_GetStatus(s, ID_GetBatteryCharge);
667 }
668}
669
670static GSM_Error N6110_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
671{
672 GSM_Phone_Data *Data = &s->Phone.Data;
673
674 smprintf(s, "SMS message saving status\n");
675 switch (msg.Buffer[3]) {
676 case 0x05:
677 smprintf(s, "Saved at location %i\n",msg.Buffer[5]);
678 Data->SaveSMSMessage->Location=msg.Buffer[5];
679 return ERR_NONE;
680 case 0x06:
681 switch (msg.Buffer[4]) {
682 case 0x02:
683 smprintf(s, "All locations busy\n");
684 return ERR_FULL;
685 case 0x03:
686 smprintf(s, "Too high ?\n");
687 return ERR_INVALIDLOCATION;
688 default:
689 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
690 }
691 }
692 return ERR_UNKNOWNRESPONSE;
693}
694
695static GSM_Error N6110_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
696{
697 int length;
698 GSM_Error error;
699 unsigned char req[256] = {N6110_FRAME_HEADER, 0x04,
700 0x00, /* SMS status */
701 0x02,
702 0x00, /* SMS location */
703 0x02}; /* SMS type */
704
705 req[6] = sms->Location;
706 if (sms->Folder==1) { /* Inbox */
707 req[4] = 1; /* SMS status - GSM_Read */
708 req[7] = 0x00; /* SMS type */
709 sms->PDU = SMS_Deliver;
710 error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSDeliver,&length,true);
711 } else { /* Outbox */
712 req[4] = 5; /* SMS status - GSM_Sent */
713 req[7] = 0x02; /* SMS type */
714 sms->PDU = SMS_Submit;
715 error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSSubmit,&length,true);
716 }
717 if (error != ERR_NONE) return error;
718
719 /* SMS State - GSM_Read -> GSM_Unread and GSM_Sent -> GSM_UnSent */
720 if (sms->State == SMS_UnSent || sms->State == SMS_UnRead) req[4] |= 0x02;
721
722 s->Phone.Data.SaveSMSMessage=sms;
723 smprintf(s, "Saving sms\n");
724 return GSM_WaitFor (s, req, 8+length, 0x14, 4, ID_SaveSMSMessage);
725}
726
727static GSM_Error N6110_SetSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
728{
729 if (sms->Location == 0) return ERR_INVALIDLOCATION;
730 return N6110_PrivSetSMSMessage(s, sms);
731}
732
733static GSM_Error N6110_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
734{
735 sms->Location = 0;
736 return N6110_PrivSetSMSMessage(s, sms);
737}
738
739static GSM_Error N6110_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
740{
741 switch (msg.Buffer[3]) {
742 case 0x37:
743 smprintf(s, "Ringtone set OK\n");
744 return ERR_NONE;
745 break;
746 case 0x38:
747 smprintf(s, "Error setting ringtone\n");
748 switch (msg.Buffer[4]) {
749 case 0x7d:
750 smprintf(s, "Too high location ?\n");
751 return ERR_INVALIDLOCATION;
752 default:
753 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
754 }
755 }
756 return ERR_UNKNOWNRESPONSE;
757}
758
759static GSM_Error N6110_ReplySetBinRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
760{
761 switch (msg.Buffer[4]) {
762 case 0x00:
763 smprintf(s, "Set at location %i\n",msg.Buffer[3]+1);
764 return ERR_NONE;
765 default:
766 smprintf(s, "Invalid location. Too high ?\n");
767 return ERR_INVALIDLOCATION;
768 }
769}
770
771static GSM_Error N6110_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
772{
773 GSM_NetworkInfo NetInfo;
774 GSM_Error error;
775 int size=200,current=8;
776 GSM_UDHHeader UDHHeader;
777 unsigned char req[1000] = {N6110_FRAME_HEADER, 0x36,
778 0x00, /* Location */
779 0x00,0x78};
780 unsigned char reqBin[1000] = {0x00,0x01,0xa0,0x00,0x00,0x0c,0x01,0x2c};
781
782 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NORING)) return ERR_NOTSUPPORTED;
783 if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
784
785 switch (Ringtone->Format) {
786 case RING_NOTETONE:
787 if (Ringtone->Location==255) {
788 /* Only 6110, 6130 and 6150 support it */
789 if (strcmp(s->Phone.Data.Model,"NSE-3") == 0 || strcmp(s->Phone.Data.Model,"NSK-3") == 0 ||
790 strcmp(s->Phone.Data.Model,"NSM-1") == 0) {
791 req[0] = 0x0c;
792 req[1] = 0x01;
793 UDHHeader.Type = UDH_NokiaRingtone;
794 GSM_EncodeUDHHeader(&UDHHeader);
795 /* We copy UDH now */
796 memcpy(req+2,UDHHeader.Text,UDHHeader.Length);
797 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+2+UDHHeader.Length, &size);
798 error = s->Protocol.Functions->WriteMessage(s, req, 2+UDHHeader.Length+size, 0x12);
799 if (error!=ERR_NONE) return error;
800 my_sleep(1000);
801 /* We have to make something (not important, what) now */
802 /* no answer from phone*/
803 return DCT3_GetNetworkInfo(s,&NetInfo);
804 } else {
805 return ERR_NOTSUPPORTED;
806 }
807 }
808 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+7, &size);
809 req[4] = Ringtone->Location - 1;
810 smprintf(s, "Setting ringtone\n");
811 return GSM_WaitFor (s, req, 7 + size, 0x05, 4, ID_SetRingtone);
812 case RING_NOKIABINARY:
813 error=DCT3_EnableSecurity (s, 0x01);
814 if (error!=ERR_NONE) return error;
815 memcpy(reqBin+current,DecodeUnicodeString(Ringtone->Name),UnicodeLength(Ringtone->Name));
816 current += UnicodeLength(Ringtone->Name);
817 reqBin[current++] = 0x00;
818 reqBin[current++] = 0x00;
819 reqBin[current++] = 0x00;/*xxx*/
820 memcpy(reqBin+current,Ringtone->NokiaBinary.Frame,Ringtone->NokiaBinary.Length);
821 current=current+Ringtone->NokiaBinary.Length;
822 reqBin[3]=Ringtone->Location-1;
823 if (!strcmp(s->Phone.Data.ModelInfo->model,"3210")) reqBin[5]=0x10;
824 smprintf(s, "Setting binary ringtone\n");
825 return GSM_WaitFor (s, reqBin, current, 0x40, 4, ID_SetRingtone);
826 case RING_MIDI:
827 return ERR_NOTSUPPORTED;
828 }
829 return ERR_NOTSUPPORTED;
830}
831
832static GSM_Error N6110_ReplyGetOpLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
833{
834 int count=5;
835 GSM_Phone_Data *Data = &s->Phone.Data;
836
837 smprintf(s, "Operator logo received\n");
838 NOKIA_DecodeNetworkCode(msg.Buffer+count,Data->Bitmap->NetworkCode);
839 count = count + 3;
840 smprintf(s, "Network code : %s\n", Data->Bitmap->NetworkCode);
841 smprintf(s, "Network name for Gammu : %s ",
842 DecodeUnicodeString(GSM_GetNetworkName(Data->Bitmap->NetworkCode)));
843 smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(Data->Bitmap->NetworkCode)));
844
845 count = count + 3; /* We ignore size */
846 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
847 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
848 count++;
849 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo,msg.Buffer+count,Data->Bitmap);
850 return ERR_NONE;
851}
852
853static GSM_Error N6110_ReplyGetStartup(GSM_Protocol_Message msg, GSM_StateMachine *s)
854{
855 int i, count = 5;
856 GSM_Phone_Data *Data = &s->Phone.Data;
857
858 smprintf(s, "Startup logo & notes received\n");
859 for (i=0;i<msg.Buffer[4];i++) {
860 switch (msg.Buffer[count++]) {
861 case 0x01:
862 smprintf(s, "Startup logo\n");
863 if (Data->Bitmap->Type == GSM_StartupLogo) {
864 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
865 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
866 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, msg.Buffer + count, Data->Bitmap);
867 } else {
868 count = count + 2;
869 }
870 count = count + PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0);
871 break;
872 case 0x02:
873 smprintf(s, "Welcome note\n");
874 if (Data->Bitmap->Type == GSM_WelcomeNote_Text) {
875 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
876 smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
877 }
878 count = count + msg.Buffer[count] + 1;
879 break;
880 case 0x03:
881 smprintf(s, "Dealer welcome note\n");
882 if (Data->Bitmap->Type == GSM_DealerNote_Text) {
883 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
884 smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
885 }
886 count = count + msg.Buffer[count] + 1;
887 break;
888 default:
889 smprintf(s, "Unknown block\n");
890 return ERR_UNKNOWNRESPONSE;
891 break;
892 }
893 }
894 return ERR_NONE;
895}
896
897static GSM_Error N6110_ReplyGetCallerLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
898{
899 int count;
900 GSM_Phone_Data *Data = &s->Phone.Data;
901
902 switch (msg.Buffer[3]) {
903 case 0x11:
904 smprintf(s, "Caller group info received\n");
905 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+6,msg.Buffer[5]);
906 smprintf(s, "Name : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
907 Data->Bitmap->DefaultName = false;
908 if (msg.Buffer[5] == 0x00) Data->Bitmap->DefaultName = true;
909 count = msg.Buffer[5] + 6;
910 Data->Bitmap->RingtoneID = msg.Buffer[count++];
911 Data->Bitmap->DefaultRingtone = false;
912 Data->Bitmap->FileSystemRingtone = false;
913 if (Data->Bitmap->RingtoneID == 16) Data->Bitmap->DefaultRingtone = true;
914 smprintf(s, "Ringtone ID: %02x\n",Data->Bitmap->RingtoneID);
915 Data->Bitmap->BitmapEnabled=(msg.Buffer[count++]==1);
916#ifdef DEBUG
917 smprintf(s, "Caller group logo ");
918 if (Data->Bitmap->BitmapEnabled) {
919 smprintf(s, "enabled\n");
920 } else {
921 smprintf(s, "disabled\n");
922 }
923#endif
924 count = count + 3; /* We ignore size */
925 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
926 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
927 count++;
928 PHONE_DecodeBitmap(GSM_NokiaCallerLogo,msg.Buffer+count,Data->Bitmap);
929 Data->Bitmap->DefaultBitmap = false;
930 return ERR_NONE;
931 case 0x12:
932 smprintf(s, "Error getting caller group info\n");
933 return ERR_INVALIDLOCATION;
934 }
935 return ERR_UNKNOWNRESPONSE;
936}
937
938static GSM_Error N6110_ReplyGetSetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
939{
940 int count = 5, i;
941 GSM_Phone_Data *Data = &s->Phone.Data;
942
943 switch (msg.Buffer[3]) {
944 case 0x02:
945 smprintf(s, "Picture Image received\n");
946 if (msg.Buffer[count]!=0) {
947 GSM_UnpackSemiOctetNumber(Data->Bitmap->Sender, msg.Buffer + 5, true);
948 /* Convert number of semioctets to number of chars */
949 i = msg.Buffer[5];
950 if (i % 2) i++;
951 i=i / 2 + 1;
952 count = count + i + 1;
953 } else {
954 Data->Bitmap->Sender[0] = 0x00;
955 Data->Bitmap->Sender[1] = 0x00;
956 count+=2;
957 }
958 smprintf(s, "Sender : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Sender));
959 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPICTUREUNI) ||
960 (!strcmp(Data->Model,"NHM-5") && Data->VerNum < 5.79)) {
961 count++;
962 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count+1,msg.Buffer[count]);
963 count += UnicodeLength(Data->Bitmap->Text) + 1;
964 } else {
965 if (!strcmp(Data->Model,"NHM-5")) {
966 i = msg.Buffer[count] * 256 + msg.Buffer[count+1];
967 } else {
968 /* 3410 4.26 */
969 i = msg.Buffer[count] * 256 + msg.Buffer[count+1] - 2;
970 count += 2;
971 }
972 memcpy(Data->Bitmap->Text,msg.Buffer+count+2,i);
973 Data->Bitmap->Text[i] = 0;
974 Data->Bitmap->Text[i+1] = 0;
975 count += i + 2;
976 }
977 smprintf(s, "Text : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
978 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
979 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
980 PHONE_DecodeBitmap(GSM_NokiaPictureImage, msg.Buffer + count + 2, Data->Bitmap);
981#ifdef DEBUG
982 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,Data->Bitmap);
983#endif
984 return ERR_NONE;
985 break;
986 case 0x04:
987 smprintf(s, "Picture Image set OK\n");
988 return ERR_NONE;
989 case 0x05:
990 smprintf(s, "Can't set Picture Image - invalid location ?\n");
991 return ERR_INVALIDLOCATION;
992 break;
993 case 0x06:
994 smprintf(s, "Can't get Picture Image - invalid location ?\n");
995 return ERR_INVALIDLOCATION;
996 break;
997 }
998 return ERR_UNKNOWNRESPONSE;
999}
1000
1001static GSM_Error N6110_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
1002{
1003 GSM_Error error;
1004 unsigned char req[10] = {N6110_FRAME_HEADER};
1005
1006 s->Phone.Data.Bitmap=Bitmap;
1007 switch (Bitmap->Type) {
1008 case GSM_StartupLogo:
1009 case GSM_WelcomeNote_Text:
1010 case GSM_DealerNote_Text:
1011 if (Bitmap->Type == GSM_StartupLogo && IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTUP)) return ERR_NOTSUPPORTED;
1012 req[3] = 0x16;
1013 return GSM_WaitFor (s, req, 4, 0x05, 4, ID_GetBitmap);
1014 case GSM_CallerGroupLogo:
1015 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLER)) return ERR_NOTSUPPORTED;
1016 req[3] = 0x10;
1017 req[4] = Bitmap->Location - 1;
1018 error = GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetBitmap);
1019 if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s,Bitmap);
1020 return error;
1021 case GSM_OperatorLogo:
1022 req[3] = 0x33;
1023 req[4] = 0x01;
1024 return GSM_WaitFor (s, req, 5, 0x05, 4, ID_GetBitmap);
1025 case GSM_PictureImage:
1026 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOPICTURE)) return ERR_NOTSUPPORTED;
1027 req[3] = 0x01;
1028 req[4] = Bitmap->Location - 1;
1029 return GSM_WaitFor (s, req, 5, 0x47, 4, ID_GetBitmap);
1030 default:
1031 break;
1032 }
1033 return ERR_NOTSUPPORTED;
1034}
1035
1036static GSM_Error N6110_ReplySetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1037{
1038 switch (msg.Buffer[3]) {
1039 case 0x11:
1040 smprintf(s, "Feature of profile set\n");
1041 return ERR_NONE;
1042 case 0x12:
1043 smprintf(s, "Error setting profile feature\n");
1044 return ERR_NOTSUPPORTED;
1045 }
1046 return ERR_UNKNOWNRESPONSE;
1047}
1048
1049static GSM_Error N6110_SetProfileFeature(GSM_StateMachine *s, unsigned char profile, unsigned char feature, unsigned char value)
1050{
1051 unsigned char req[] = {N6110_FRAME_HEADER, 0x10, 0x01,
1052 0x00, /* Profile */
1053 0x00, /* Feature */
1054 0x00}; /* Value */
1055
1056 req[5]=profile;
1057 req[6]=feature;
1058 req[7]=value;
1059 smprintf(s, "Setting profile feature\n");
1060 return GSM_WaitFor (s, req, 8, 0x05, 4, ID_SetProfile);
1061}
1062
1063static GSM_Error N6110_ReplySetStartup(GSM_Protocol_Message msg, GSM_StateMachine *s)
1064{
1065 smprintf(s, "Startup logo set OK\n");
1066 return ERR_NONE;
1067}
1068
1069static GSM_Error N6110_ReplySetCallerLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1070{
1071 switch (msg.Buffer[3]) {
1072 case 0x14:
1073 smprintf(s, "Caller group set OK\n");
1074 return ERR_NONE;
1075 case 0x15:
1076 smprintf(s, "Error setting caller group\n");
1077 return ERR_INVALIDLOCATION;
1078 }
1079 return ERR_UNKNOWNRESPONSE;
1080}
1081
1082static GSM_Error N6110_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
1083{
1084 unsigned char reqPreview[1000] = {0x0c,0x01};
1085 unsigned char req[600] = {N6110_FRAME_HEADER};
1086 GSM_UDH UDHType = UDH_NokiaOperatorLogo;
1087 int count = 0, textlen, Width, Height;
1088 GSM_UDHHeader UDHHeader;
1089 GSM_NetworkInfo NetInfo;
1090 GSM_Error error;
1091
1092 switch (Bitmap->Type) {
1093 case GSM_CallerGroupLogo:
1094 case GSM_OperatorLogo:
1095 if (Bitmap->Location == 255) {
1096 /* Only 6110, 6130 and 6150 support it */
1097 if (strcmp(s->Phone.Data.Model,"NSE-3") == 0 || strcmp(s->Phone.Data.Model,"NSK-3") == 0 ||
1098 strcmp(s->Phone.Data.Model,"NSM-1") == 0) {
1099 if (Bitmap->Type==GSM_CallerGroupLogo) UDHType = UDH_NokiaCallerLogo;
1100 UDHHeader.Type = UDHType;
1101 GSM_EncodeUDHHeader(&UDHHeader);
1102 /* We copy UDH now */
1103 memcpy(reqPreview+2,UDHHeader.Text,UDHHeader.Length);
1104 count = count + UDHHeader.Length;
1105 if (Bitmap->Type == GSM_OperatorLogo) {
1106 NOKIA_EncodeNetworkCode(reqPreview+count,Bitmap->NetworkCode);
1107 count = count + 3;
1108 } else {
1109 if (Bitmap->DefaultBitmap) {
1110 Bitmap->BitmapWidth = 72;
1111 Bitmap->BitmapHeight = 14;
1112 GSM_ClearBitmap(Bitmap);
1113 }
1114 }
1115 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo,Bitmap,reqPreview, &count);
1116 reqPreview[count]=0x00;
1117 error = s->Protocol.Functions->WriteMessage(s, reqPreview, count + 1, 0x12);
1118 if (error!=ERR_NONE) return error;
1119 my_sleep(1000);
1120 /* We have to make something (not important, what) now */
1121 /* no answer from phone*/
1122 return DCT3_GetNetworkInfo(s,&NetInfo);
1123 } else {
1124 smprintf(s, "%s\n",s->Phone.Data.Model);
1125 return ERR_NOTSUPPORTED;
1126 }
1127 }
1128 break;
1129 default:
1130 break;
1131 }
1132
1133 count = 3;
1134
1135 switch (Bitmap->Type) {
1136 case GSM_StartupLogo:
1137 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTUP)) return ERR_NOTSUPPORTED;
1138 if (Bitmap->Location != 1) {
1139 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTANI)) return ERR_NOTSUPPORTED;
1140 }
1141 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTANI)) {
1142 if (!strcmp(s->Phone.Data.ModelInfo->model,"3210")) {
1143 error = N6110_SetProfileFeature(s,0,0x2e,((unsigned char)(Bitmap->Location-1)));
1144 } else {
1145 error = N6110_SetProfileFeature(s,0,0x29,((unsigned char)(Bitmap->Location-1)));
1146 }
1147 if (error == ERR_NOTSUPPORTED) error = ERR_SECURITYERROR;
1148 if (error != ERR_NONE) return error;
1149 if (Bitmap->Location != 1) return ERR_NONE;
1150 }
1151 req[count++] = 0x18;
1152 req[count++] = 0x01; /* One block */
1153 req[count++] = 0x01;
1154 PHONE_GetBitmapWidthHeight(GSM_NokiaStartupLogo, &Width, &Height);
1155 req[count++] = Height;
1156 req[count++] = Width;
1157 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, req + count, Bitmap);
1158 count = count + PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0);
1159 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1160 case GSM_WelcomeNote_Text:
1161 case GSM_DealerNote_Text:
1162 req[count++] = 0x18;
1163 req[count++] = 0x01; /* One block */
1164 if (Bitmap->Type == GSM_WelcomeNote_Text) {
1165 req[count++] = 0x02;
1166 } else {
1167 req[count++] = 0x03;
1168 }
1169 textlen = UnicodeLength(Bitmap->Text);
1170 req[count++] = textlen;
1171 memcpy(req + count,DecodeUnicodeString(Bitmap->Text),textlen);
1172 count += textlen;
1173 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1174 case GSM_CallerGroupLogo:
1175 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLER)) return ERR_NOTSUPPORTED;
1176 req[count++] = 0x13;
1177 req[count++] = Bitmap->Location - 1;
1178 if (Bitmap->DefaultName) {
1179 req[count++] = 0;
1180 } else {
1181 textlen = UnicodeLength(Bitmap->Text);
1182 req[count++] = textlen;
1183 memcpy(req+count,DecodeUnicodeString(Bitmap->Text),textlen);
1184 count += textlen;
1185 }
1186 if (Bitmap->DefaultRingtone) {
1187 req[count++] = 16;
1188 } else {
1189 req[count++] = Bitmap->RingtoneID;
1190 }
1191 /* Value here is number of phone menu connected
1192 * with caller logo in Nokia 61x0: 0x00 = Off, 0x01 = On,
1193 * 0x02 = View Graphics, 0x03 = Send Graphics,
1194 * 0x04 = Send via IR. For higher menu option connected with
1195 * caller logo is not displayed
1196 */
1197 if (Bitmap->DefaultBitmap) {
1198 Bitmap->BitmapWidth = 72;
1199 Bitmap->BitmapHeight = 14;
1200 GSM_ClearBitmap(Bitmap);
1201 req[count++] = 0;
1202 } else {
1203 if (Bitmap->BitmapEnabled) req[count++] = 0x01; else req[count++] = 0x00;
1204 }
1205 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) / 256;
1206 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) % 256;
1207 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, Bitmap, req, &count);
1208 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetBitmap);
1209 case GSM_OperatorLogo:
1210 req[count++] = 0x30;
1211 req[count++] = 0x01;
1212 NOKIA_EncodeNetworkCode(req+count, Bitmap->NetworkCode);
1213 count = count + 3;
1214 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaOperatorLogo,0,0) + 4) / 256;
1215 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaOperatorLogo,0,0) + 4) % 256;
1216 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, Bitmap, req, &count);
1217 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1218 case GSM_PictureImage:
1219 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOPICTURE)) return ERR_NOTSUPPORTED;
1220 req[count++] = 0x03;
1221 req[count++] = Bitmap->Location - 1;
1222 if (Bitmap->Sender[0]!=0 || Bitmap->Sender[1]!=0) {
1223 req[count]=GSM_PackSemiOctetNumber(Bitmap->Sender, req+count+1,true);
1224 /* Convert number of semioctets to number of chars and add count */
1225 textlen = req[count];
1226 if (textlen % 2) textlen++;
1227 count += textlen / 2 + 1;
1228 count++;
1229 } else {
1230 req[count++] = 0x00;
1231 req[count++] = 0x00;
1232 }
1233 req[count++] = 0x00;
1234 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPICTUREUNI) ||
1235 (!strcmp(s->Phone.Data.Model,"NHM-5") && s->Phone.Data.VerNum < 5.79)) {
1236 textlen = UnicodeLength(Bitmap->Text);
1237 req[count++] = textlen;
1238 memcpy(req+count,DecodeUnicodeString(Bitmap->Text),textlen);
1239 count += textlen;
1240 } else {
1241 textlen = UnicodeLength(Bitmap->Text)*2;
1242 if (!strcmp(s->Phone.Data.Model,"NHM-5")) {
1243 req[count++] = textlen;
1244 } else {
1245 /* 3410 4.26 */
1246 req[count++] = textlen+2;
1247 req[count++] = 0x00;
1248 req[count++] = 0x1e;
1249 }
1250 memcpy(req+count,Bitmap->Text,textlen);
1251 count += textlen;
1252 }
1253 NOKIA_CopyBitmap(GSM_NokiaPictureImage, Bitmap, req, &count);
1254 return GSM_WaitFor (s, req, count, 0x47, 4, ID_SetBitmap);
1255 default:
1256 break;
1257 }
1258 return ERR_NOTSUPPORTED;
1259}
1260
1261static GSM_Error N6110_ReplyCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1262{
1263 GSM_Phone_Data *Data = &s->Phone.Data;
1264 int tmp, count;
1265 GSM_Call call;
1266
1267 call.CallIDAvailable = true;
1268 call.Status = 0;
1269 smprintf(s, "Call info, ");
1270 switch (msg.Buffer[3]) {
1271 case 0x02:
1272 smprintf(s, "Call established, waiting for answer\n");
1273 call.Status = GSM_CALL_CallEstablished;
1274 break;
1275 case 0x03:
1276 smprintf(s, "Call started\n");
1277 /* no phone number in frame */
1278 call.Status = GSM_CALL_CallStart;
1279 break;
1280 case 0x04:
1281 smprintf(s, "Remote end hang up\n");
1282 smprintf(s, "CC : %i\n",msg.Buffer[6]);
1283 call.Status = GSM_CALL_CallRemoteEnd;
1284 call.StatusCode = msg.Buffer[6];
1285 break;
1286 case 0x05:
1287 smprintf(s, "Incoming call\n");
1288 smprintf(s, "Number : \"");
1289 count=msg.Buffer[6];
1290 for (tmp=0; tmp <count; tmp++) smprintf(s, "%c", msg.Buffer[7+tmp]);
1291 smprintf(s, "\"\nName : \"");
1292 for (tmp=0; tmp<msg.Buffer[7+count]; tmp++) smprintf(s, "%c", msg.Buffer[8+count+tmp]);
1293 smprintf(s, "\"\n");
1294
1295 call.Status = GSM_CALL_IncomingCall;
1296 EncodeUnicode(call.PhoneNumber, msg.Buffer+7, msg.Buffer[6]);
1297 break;
1298 case 0x07:
1299 smprintf(s, "Call answer initiated\n");
1300 break;
1301 case 0x09:
1302 smprintf(s, "Call released\n");
1303 call.Status = GSM_CALL_CallLocalEnd;
1304 break;
1305 case 0x0a:
1306 smprintf(s, "Call is being released\n");
1307 break;
1308 case 0x23:
1309 smprintf(s, "Call held\n");
1310 call.Status = GSM_CALL_CallHeld;
1311 break;
1312 case 0x25:
1313 smprintf(s, "Call resumed\n");
1314 call.Status = GSM_CALL_CallResumed;
1315 break;
1316 case 0x27:
1317 smprintf(s, "Call switched\n");
1318 /* incorrect call id in frame - 6150 5.22 */
1319 call.CallIDAvailable = false;
1320 call.Status = GSM_CALL_CallSwitched;
1321 break;
1322 case 0x29:
1323 smprintf(s, "Joining call to the conference (conference)\n");
1324 break;
1325 case 0x2A:
1326 smprintf(s, "Removing call from the conference (split)\n");
1327 break;
1328 }
1329 if (call.CallIDAvailable) smprintf(s, "Call ID : %d\n",msg.Buffer[4]);
1330 if (Data->EnableIncomingCall && s->User.IncomingCall!=NULL && call.Status != 0) {
1331 if (call.CallIDAvailable) call.CallID = msg.Buffer[4];
1332 s->User.IncomingCall(s->CurrentConfig->Device, call);
1333 }
1334 if (s->Phone.Data.RequestID == ID_CancelCall) {
1335 if (msg.Buffer[3] == 0x09) {
1336 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1337 /* when we canceled call and see frame about other
1338 * call releasing, we don't give ERR_NONE for "our"
1339 * call release command
1340 */
1341 return ERR_NEEDANOTHERANSWER;
1342 }
1343 }
1344 if (s->Phone.Data.RequestID == ID_AnswerCall) {
1345 if (msg.Buffer[3] == 0x07) {
1346 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1347 return ERR_NEEDANOTHERANSWER;
1348 }
1349 }
1350 if (s->Phone.Data.RequestID == ID_UnholdCall) {
1351 if (msg.Buffer[3] == 0x25) {
1352 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1353 return ERR_NEEDANOTHERANSWER;
1354 }
1355 }
1356 if (s->Phone.Data.RequestID == ID_HoldCall) {
1357 if (msg.Buffer[3] == 0x23) {
1358 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1359 return ERR_NEEDANOTHERANSWER;
1360 }
1361 }
1362 if (s->Phone.Data.RequestID == ID_ConferenceCall) {
1363 if (msg.Buffer[3] == 0x29) {
1364 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1365 return ERR_NEEDANOTHERANSWER;
1366 }
1367 }
1368 if (s->Phone.Data.RequestID == ID_SplitCall) {
1369 if (msg.Buffer[3] == 0x2B) {
1370 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1371 return ERR_NEEDANOTHERANSWER;
1372 }
1373 }
1374 return ERR_NONE;
1375}
1376
1377static GSM_Error N6110_DeleteSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
1378{
1379 unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02,
1380 0x00}; /* Location */
1381
1382 if (sms->Folder!=0x00) return ERR_NOTSUPPORTED;
1383
1384 req[5]=sms->Location;
1385
1386 smprintf(s, "Deleting sms\n");
1387 return GSM_WaitFor (s, req, 6, 0x14, 4, ID_DeleteSMSMessage);
1388}
1389
1390static GSM_Error N6110_ReplySetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
1391{
1392 smprintf(s, "Reply for writing memory\n");
1393 switch (msg.Buffer[3]) {
1394 case 0x05:
1395 smprintf(s, "Done OK\n");
1396 return ERR_NONE;
1397 case 0x06:
1398 smprintf(s, "Error\n");
1399 switch (msg.Buffer[4]) {
1400 case 0x7d:
1401 smprintf(s, "Too high location ?\n");
1402 return ERR_INVALIDLOCATION;
1403 case 0x90:
1404 smprintf(s, "Too long name...or other error\n");
1405 return ERR_NOTSUPPORTED;
1406 default:
1407 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1408 }
1409 }
1410 return ERR_UNKNOWNRESPONSE;
1411}
1412
1413static GSM_Error N6110_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1414{
1415 int current, Group, Name, Number;
1416 unsigned char req[128] = {N6110_FRAME_HEADER, 0x04,
1417 0x00, /* memory type */
1418 0x00}; /* location */
1419
1420 if (entry->Location == 0) return ERR_NOTSUPPORTED;
1421
1422 GSM_PhonebookFindDefaultNameNumberGroup(entry, &Name, &Number, &Group);
1423
1424 req[4] = NOKIA_GetMemoryType(s, entry->MemoryType,N6110_MEMORY_TYPES);
1425 req[5] = entry->Location;
1426
1427 current = 7;
1428
1429 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
1430 if (Name != -1) {
1431 req[6] = UnicodeLength(entry->Entries[Name].Text);
1432 memcpy(req+current,DecodeUnicodeString(entry->Entries[Name].Text),UnicodeLength(entry->Entries[Name].Text));
1433 current += UnicodeLength(entry->Entries[Name].Text);
1434 } else req[6] = 0;
1435 } else {
1436 if (Name != -1) {
1437 req[6] = UnicodeLength(entry->Entries[Name].Text)*2+2;
1438 memcpy(req+current,entry->Entries[Name].Text,UnicodeLength(entry->Entries[Name].Text)*2);
1439 current += UnicodeLength(entry->Entries[Name].Text)*2;
1440 } else req[6] = 0;
1441 req[current++]=0x00;
1442 req[current++]=0x00;
1443 }
1444
1445 if (Number != -1) {
1446 req[current++]=UnicodeLength(entry->Entries[Number].Text);
1447 memcpy(req+current,DecodeUnicodeString(entry->Entries[Number].Text),UnicodeLength(entry->Entries[Number].Text));
1448 current += UnicodeLength(entry->Entries[Number].Text);
1449 } else req[current++] = 0;
1450
1451 /* This allow to save 14 characters name into SIM memory, when
1452 * no caller group is selected. */
1453 if (Group == -1) {
1454 req[current++] = 0xff;
1455 } else {
1456 req[current++] = entry->Entries[Group].Number-1;
1457 }
1458
1459 smprintf(s, "Writing phonebook entry\n");
1460 return GSM_WaitFor (s, req, current, 0x03, 4, ID_SetMemory);
1461}
1462
1463static GSM_Error N6110_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1464{
1465 GSM_MemoryEntry dwa;
1466
1467 dwa.Location = entry->Location;
1468 dwa.MemoryType = entry->MemoryType;
1469 dwa.EntriesNum = 0;
1470
1471 return N6110_SetMemory(s, &dwa);
1472}
1473
1474static GSM_Error N6110_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
1475{
1476 GSM_Phone_Data *Data = &s->Phone.Data;
1477 char buffer[2000];
1478 GSM_Error error;
1479 int i,end,start;
1480
1481 smprintf(s, "Ringtone received\n");
1482 switch (msg.Buffer[4]) {
1483 case 0x00:
1484 switch (Data->Ringtone->Format) {
1485 case RING_NOTETONE:
1486 memcpy(buffer,msg.Buffer,msg.Length);
1487 i=7;
1488 if (buffer[9]==0x4a && buffer[10]==0x3a) i=8;
1489 buffer[i]=0x02;
1490 error=GSM_DecodeNokiaRTTLRingtone(Data->Ringtone, buffer+i, msg.Length-i);
1491 if (error!=ERR_NONE) return ERR_EMPTY;
1492 return ERR_NONE;
1493 case RING_NOKIABINARY:
1494 i=8;
1495 while (msg.Buffer[i]!=0) {
1496 i++;
1497 if (i>msg.Length) return ERR_EMPTY;
1498 }
1499 EncodeUnicode(Data->Ringtone->Name,msg.Buffer+8,i-8);
1500 smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
1501 /* Looking for start && end */
1502 end=0;start=0;i=0;
1503 while (true) {
1504 if (start!=0) {
1505 if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
1506 end=i+2; break;
1507 }
1508 if (msg.Buffer[i]==0x0e && msg.Buffer[i+1]==0x0b) {
1509 end=i+2; break;
1510 }
1511 } else {
1512 if (msg.Buffer[i]==0x02 && msg.Buffer[i+1]==0xfc && msg.Buffer[i+2]==0x09) {
1513 start = i;
1514 }
1515 }
1516 i++;
1517 if (i==msg.Length-3) return ERR_EMPTY;
1518 }
1519 /* Copying frame */
1520 memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+start,end-start);
1521 Data->Ringtone->NokiaBinary.Length=end-start;
1522#ifdef DEBUG
1523 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, Data->Ringtone->NokiaBinary.Frame, Data->Ringtone->NokiaBinary.Length);
1524#endif
1525 return ERR_NONE;
1526 case RING_MIDI:
1527 return ERR_NOTSUPPORTED;
1528 }
1529 smprintf(s, "Ringtone format is %i\n",Data->Ringtone->Format);
1530 break;
1531 default:
1532 smprintf(s, "Invalid location. Too high ?\n");
1533 return ERR_INVALIDLOCATION;
1534 }
1535 return ERR_UNKNOWNRESPONSE;
1536}
1537
1538static GSM_Error N6110_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
1539{
1540 GSM_Error error;
1541 unsigned char req[] = {0x00, 0x01, 0x9e,
1542 0x00}; /* location */
1543
1544 if (PhoneRingtone) return ERR_NOTSUPPORTED;
1545 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NORING)) return ERR_NOTSUPPORTED;
1546 if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
1547
1548 if (Ringtone->Format == 0x00) {
1549 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) {
1550 Ringtone->Format = RING_NOTETONE;
1551 } else {
1552 Ringtone->Format = RING_NOKIABINARY;
1553 }
1554 }
1555
1556 switch (Ringtone->Format) {
1557 case RING_NOTETONE:
1558 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
1559 break;
1560 case RING_NOKIABINARY:
1561 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
1562 break;
1563 case RING_MIDI:
1564 return ERR_NOTSUPPORTED;
1565 }
1566
1567 error=DCT3_EnableSecurity (s, 0x01);
1568 if (error!=ERR_NONE) return error;
1569
1570 req[3]=Ringtone->Location-1;
1571 s->Phone.Data.Ringtone=Ringtone;
1572 smprintf(s, "Getting (binary) ringtone\n");
1573 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_GetRingtone);
1574}
1575
1576static GSM_Error N6110_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1577{
1578 *s->Phone.Data.SecurityStatus = msg.Buffer[4];
1579
1580#ifdef DEBUG
1581 smprintf(s, "Security code status\n");
1582 switch(msg.Buffer[4]) {
1583 case SEC_SecurityCode: smprintf(s, "waiting for Security Code.\n"); break;
1584 case SEC_Pin : smprintf(s, "waiting for PIN.\n"); break;
1585 case SEC_Pin2 : smprintf(s, "waiting for PIN2.\n"); break;
1586 case SEC_Puk : smprintf(s, "waiting for PUK.\n"); break;
1587 case SEC_Puk2 : smprintf(s, "waiting for PUK2.\n"); break;
1588 case SEC_None : smprintf(s, "nothing to enter.\n"); break;
1589 default : smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1590 return ERR_UNKNOWNRESPONSE;
1591 }
1592#endif
1593 return ERR_NONE;
1594}
1595
1596static GSM_Error N6110_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
1597{
1598 unsigned char req[4] = {N6110_FRAME_HEADER, 0x07};
1599
1600 s->Phone.Data.SecurityStatus=Status;
1601 smprintf(s, "Getting security code status\n");
1602 return GSM_WaitFor (s, req, 4, 0x08, 2, ID_GetSecurityStatus);
1603}
1604
1605static GSM_Error N6110_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
1606{
1607 switch (msg.Buffer[3]) {
1608 case 0x0b:
1609 smprintf(s, "Security code OK\n");
1610 return ERR_NONE;
1611 case 0x0c:
1612 switch (msg.Buffer[4]) {
1613 case 0x88:
1614 smprintf(s, "Wrong code\n");
1615 return ERR_SECURITYERROR;
1616 case 0x8b:
1617 smprintf(s, "Not required\n");
1618 return ERR_NONE;
1619 default:
1620 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1621 }
1622 }
1623 return ERR_UNKNOWNRESPONSE;
1624}
1625
1626static GSM_Error N6110_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
1627{
1628 int len = 0;
1629 unsigned char req[15] = {N6110_FRAME_HEADER, 0x0a,
1630 0x00}; /* Type of code to enter */
1631
1632 req[4]=Code.Type;
1633
1634 len = strlen(Code.Code);
1635 memcpy(req+5,Code.Code,len);
1636 req[5+len]=0x00;
1637 req[6+len]=0x00;
1638
1639 smprintf(s, "Entering security code\n");
1640 return GSM_WaitFor (s, req, 7+len, 0x08, 4, ID_EnterSecurityCode);
1641}
1642
1643static GSM_Error N6110_ReplyGetSpeedDial(GSM_Protocol_Message msg, GSM_StateMachine *s)
1644{
1645 GSM_Phone_Data *Data = &s->Phone.Data;
1646
1647 switch (msg.Buffer[3]) {
1648 case 0x17:
1649 smprintf(s, "Speed dial received\n");
1650 switch (msg.Buffer[4]) {
1651 case 0x02:
1652 Data->SpeedDial->MemoryType = MEM_ME;
1653 smprintf(s, "ME ");
1654 break;
1655 case 0x03:
1656 Data->SpeedDial->MemoryType = MEM_SM;
1657 smprintf(s, "SIM ");
1658 break;
1659 default:
1660 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1661 return ERR_UNKNOWNRESPONSE;
1662 }
1663 Data->SpeedDial->MemoryLocation = msg.Buffer[5];
1664 if (msg.Buffer[5] == 0x00) Data->SpeedDial->MemoryLocation = Data->SpeedDial->Location;
1665 Data->SpeedDial->MemoryNumberID = 2;
1666 smprintf(s, "location %i\n",Data->SpeedDial->MemoryLocation);
1667 return ERR_NONE;
1668 case 0x18:
1669 smprintf(s, "Error getting speed dial. Invalid location\n");
1670 return ERR_INVALIDLOCATION;
1671 }
1672 return ERR_UNKNOWNRESPONSE;
1673}
1674
1675static GSM_Error N6110_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
1676{
1677 unsigned char req[] = {N6110_FRAME_HEADER, 0x16,
1678 0x01}; /* location */
1679
1680 req[4] = SpeedDial->Location;
1681
1682 s->Phone.Data.SpeedDial=SpeedDial;
1683 smprintf(s, "Getting speed dial\n");
1684 return GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetSpeedDial);
1685}
1686
1687static GSM_Error N6110_ReplySendDTMF(GSM_Protocol_Message msg, GSM_StateMachine *s)
1688{
1689 switch (msg.Buffer[3]) {
1690 case 0x40:
1691 smprintf(s, "During sending DTMF\n");
1692 return ERR_NONE;
1693 case 0x51:
1694 smprintf(s, "DTMF sent OK\n");
1695 return ERR_NONE;
1696 }
1697 return ERR_UNKNOWNRESPONSE;
1698}
1699
1700static GSM_Error N6110_ReplyGetDisplayStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1701{
1702 int i;
1703 GSM_Phone_Data *Data = &s->Phone.Data;
1704
1705 smprintf(s, "Display status received\n");
1706 if (Data->RequestID == ID_GetDisplayStatus) Data->DisplayFeatures->Number=0;
1707 for (i=0;i<msg.Buffer[4];i++) {
1708 if (msg.Buffer[2*i+6] == 0x02) {
1709#ifdef DEBUG
1710 switch (msg.Buffer[2*i+5]) {
1711 case 0x01: smprintf(s, "Call in progress\n"); break;
1712 case 0x02: smprintf(s, "Unknown\n"); break;
1713 case 0x03: smprintf(s, "Unread SMS\n"); break;
1714 case 0x04: smprintf(s, "Voice call\n"); break;
1715 case 0x05: smprintf(s, "Fax call active\n"); break;
1716 case 0x06: smprintf(s, "Data call active\n"); break;
1717 case 0x07: smprintf(s, "Keyboard lock\n"); break;
1718 case 0x08: smprintf(s, "SMS storage full\n"); break;
1719 }
1720#endif
1721 if (Data->RequestID == ID_GetDisplayStatus) {
1722 switch (msg.Buffer[2*i+5]) {
1723 case 0x01: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_CallActive;
1724 break;
1725 case 0x03: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_UnreadSMS;
1726 break;
1727 case 0x04: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_VoiceCall;
1728 break;
1729 case 0x05: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_FaxCall;
1730 break;
1731 case 0x06: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_DataCall;
1732 break;
1733 case 0x07: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_KeypadLocked;
1734 break;
1735 case 0x08: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_SMSMemoryFull;
1736 break;
1737 }
1738 if (msg.Buffer[2*i+5]!=0x02) Data->DisplayFeatures->Number++;
1739 }
1740 }
1741 }
1742 return ERR_NONE;
1743}
1744
1745static GSM_Error N6110_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
1746{
1747 unsigned char req[] = {N6110_FRAME_HEADER, 0x51};
1748
1749 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_DISPSTATUS)) return ERR_NOTSUPPORTED;
1750
1751 s->Phone.Data.DisplayFeatures = features;
1752 smprintf(s, "Getting display status\n");
1753 return GSM_WaitFor (s, req, 4, 0x0d, 4, ID_GetDisplayStatus);
1754}
1755
1756static GSM_Profile_PhoneTableValue Profile6110[] = {
1757 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x00},
1758 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x01},
1759 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x02},
1760 {Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0xff},
1761 {Profile_Lights, PROFILE_LIGHTS_OFF, 0x01,0x00},
1762 {Profile_Lights, PROFILE_LIGHTS_AUTO, 0x01,0x01},
1763 {Profile_CallAlert, PROFILE_CALLALERT_RINGING, 0x02,0x01},
1764 {Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE, 0x02,0x02},
1765 {Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x02,0x04},
1766 {Profile_CallAlert, PROFILE_CALLALERT_RINGONCE, 0x02,0x05},
1767 {Profile_CallAlert, PROFILE_CALLALERT_ASCENDING, 0x02,0x06},
1768 {Profile_CallAlert, PROFILE_CALLALERT_CALLERGROUPS,0x02,0x07},
1769 /* Ringtone ID */
1770 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x04,0x06},
1771 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x04,0x07},
1772 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x04,0x08},
1773 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x04,0x09},
1774 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x04,0x0a},
1775 {Profile_MessageTone, PROFILE_MESSAGE_NOTONE, 0x05,0x00},
1776 {Profile_MessageTone, PROFILE_MESSAGE_STANDARD, 0x05,0x01},
1777 {Profile_MessageTone, PROFILE_MESSAGE_SPECIAL, 0x05,0x02},
1778 {Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE, 0x05,0x03},
1779 {Profile_MessageTone, PROFILE_MESSAGE_ASCENDING, 0x05,0x04},
1780 {Profile_Vibration, PROFILE_VIBRATION_OFF, 0x06,0x00},
1781 {Profile_Vibration, PROFILE_VIBRATION_ON, 0x06,0x01},
1782 {Profile_WarningTone, PROFILE_WARNING_OFF, 0x07,0xff},
1783 {Profile_WarningTone, PROFILE_WARNING_ON, 0x07,0x04},
1784 /* Caller groups */
1785 {Profile_AutoAnswer, PROFILE_AUTOANSWER_OFF, 0x09,0x00},
1786 {Profile_AutoAnswer, PROFILE_AUTOANSWER_ON, 0x09,0x01},
1787 {0x00, 0x00, 0x00,0x00}
1788};
1789
1790static GSM_Profile_PhoneTableValue Profile3310[] = {
1791 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x00},
1792 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x01},
1793 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x02},
1794 {Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0xff},
1795 {Profile_CallAlert, PROFILE_CALLALERT_RINGING, 0x01,0x01},
1796 {Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE, 0x01,0x02},
1797 {Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x01,0x04},
1798 {Profile_CallAlert, PROFILE_CALLALERT_RINGONCE, 0x01,0x05},
1799 {Profile_CallAlert, PROFILE_CALLALERT_ASCENDING, 0x01,0x06},
1800 /* Ringtone ID */
1801 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x03,0x06},
1802 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x03,0x07},
1803 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x03,0x08},
1804 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x03,0x09},
1805 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x03,0x0a},
1806 {Profile_MessageTone, PROFILE_MESSAGE_NOTONE, 0x04,0x00},
1807 {Profile_MessageTone, PROFILE_MESSAGE_STANDARD, 0x04,0x01},
1808 {Profile_MessageTone, PROFILE_MESSAGE_SPECIAL, 0x04,0x02},
1809 {Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE, 0x04,0x03},
1810 {Profile_MessageTone, PROFILE_MESSAGE_ASCENDING, 0x04,0x04},
1811 {Profile_MessageTone, PROFILE_MESSAGE_PERSONAL, 0x04,0x05},
1812 {Profile_Vibration, PROFILE_VIBRATION_OFF, 0x05,0x00},
1813 {Profile_Vibration, PROFILE_VIBRATION_ON, 0x05,0x01},
1814 {Profile_Vibration, PROFILE_VIBRATION_FIRST, 0x05,0x02},
1815 {Profile_WarningTone, PROFILE_WARNING_OFF, 0x06,0xff},
1816 {Profile_WarningTone, PROFILE_WARNING_ON, 0x06,0x04},
1817 {Profile_ScreenSaver, PROFILE_SAVER_OFF, 0x07,0x00},
1818 {Profile_ScreenSaver, PROFILE_SAVER_ON, 0x07,0x01},
1819 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_5SEC, 0x08,0x00},
1820 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_20SEC, 0x08,0x01},
1821 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_1MIN, 0x08,0x02},
1822 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_2MIN, 0x08,0x03},
1823 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_5MIN, 0x08,0x04},
1824 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_10MIN, 0x08,0x05},
1825 {0x00, 0x00, 0x00,0x00}
1826};
1827
1828static GSM_Error N6110_ReplyGetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1829{
1830 GSM_Phone_Data *Data = &s->Phone.Data;
1831
1832 switch (msg.Buffer[3]) {
1833 case 0x14:
1834 smprintf(s, "Profile feature %02x with value %02x\n",msg.Buffer[6],msg.Buffer[8]);
1835 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1836 switch (msg.Buffer[6]) {
1837 case 0x02:
1838 smprintf(s, "Ringtone ID\n");
1839 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_RingtoneID;
1840 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8];
1841 Data->Profile->FeaturesNumber++;
1842 break;
1843 case 0x09 :
1844 smprintf(s, "screen saver number\n");
1845 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_ScreenSaverNumber;
1846 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8] + 1;
1847 Data->Profile->FeaturesNumber++;
1848 break;
1849 case 0x24:
1850 smprintf(s, "selected profile\n");
1851 if (msg.Buffer[8] + 1 == Data->Profile->Location) Data->Profile->Active = true;
1852 break;
1853 default:
1854 NOKIA_FindFeatureValue(s, Profile3310,msg.Buffer[6],msg.Buffer[8],Data,false);
1855 }
1856 return ERR_NONE;
1857 }
1858 switch (msg.Buffer[6]) {
1859 case 0x01: /* Lights */
1860 if (Data->Profile->CarKitProfile) {
1861 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1862 }
1863 break;
1864 case 0x03:
1865 smprintf(s, "Ringtone ID\n");
1866 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_RingtoneID;
1867 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8];
1868 Data->Profile->FeaturesNumber++;
1869 break;
1870 case 0x08: /* Caller groups */
1871 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1872 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,true);
1873 }
1874 break;
1875 case 0x09: /* Autoanswer */
1876 if (Data->Profile->CarKitProfile || Data->Profile->HeadSetProfile) {
1877 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1878 }
1879 break;
1880 case 0x2A:
1881 smprintf(s, "selected profile\n");
1882 if (msg.Buffer[8] + 1 == Data->Profile->Location) Data->Profile->Active = true;
1883 break;
1884 default:
1885 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1886 }
1887 return ERR_NONE;
1888 case 0x15:
1889 smprintf(s, "Invalid profile location\n");
1890 return ERR_INVALIDLOCATION;
1891 case 0x1b:
1892 Data->Profile->Name[0] = 0;
1893 Data->Profile->Name[1] = 0;
1894 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1895 EncodeUnicode(Data->Profile->Name,msg.Buffer+10,msg.Buffer[9]);
1896 } else {
1897 if (msg.Length > 0x0A) {
1898 CopyUnicodeString(Data->Profile->Name,msg.Buffer+10);
1899 }
1900 }
1901 smprintf(s, "Profile name: \"%s\"\n",Data->Profile->Name);
1902 Data->Profile->DefaultName = false;
1903 if (msg.Buffer[9]==0x00) Data->Profile->DefaultName = true;
1904 return ERR_NONE;
1905 }
1906 return ERR_UNKNOWNRESPONSE;
1907}
1908
1909static GSM_Error N6110_GetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1910{
1911 GSM_Error error;
1912 int i,j;
1913 unsigned char name_req[] = {N6110_FRAME_HEADER, 0x1a, 0x00};
1914 unsigned char feat_req[] = {N6110_FRAME_HEADER, 0x13, 0x01,
1915 0x00, /* Profile location */
1916 0x00}; /* Feature number */
1917
1918 s->Phone.Data.Profile=Profile;
1919
1920 smprintf(s, "Getting profile name\n");
1921 error = GSM_WaitFor (s, name_req, 5, 0x05, 4, ID_GetProfile);
1922 if (error!=ERR_NONE) return error;
1923 if (Profile->DefaultName) {
1924 NOKIA_GetDefaultProfileName(s, Profile);
1925 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1926 switch(Profile->Location) {
1927 case 1: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Personal"),strlen(GetMsg(s->msg,"Personal")));
1928 break;
1929 case 2: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Car"),strlen(GetMsg(s->msg,"Car")));
1930 break;
1931 case 3: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Headset"),strlen(GetMsg(s->msg,"Headset")));
1932 break;
1933 }
1934 }
1935 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1936 switch(Profile->Location) {
1937 case 1: EncodeUnicode(Profile->Name,GetMsg(s->msg,"General"),strlen(GetMsg(s->msg,"General")));
1938 break;
1939 case 2: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Silent"),strlen(GetMsg(s->msg,"Silent")));
1940 break;
1941 case 3: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Discreet"),strlen(GetMsg(s->msg,"Discreet")));
1942 break;
1943 case 4: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Loud"),strlen(GetMsg(s->msg,"Loud")));
1944 break;
1945 case 5: EncodeUnicode(Profile->Name,GetMsg(s->msg,"My style"),strlen(GetMsg(s->msg,"My style")));
1946 break;
1947 case 6: Profile->Name[0] = 0; Profile->Name[1] = 0;
1948 break;
1949 }
1950 }
1951 }
1952
1953 Profile->FeaturesNumber = 0;
1954
1955 Profile->CarKitProfile = false;
1956 Profile->HeadSetProfile = false;
1957 if (Profile->Location == 6) Profile->CarKitProfile = true;
1958 if (Profile->Location == 7) Profile->HeadSetProfile = true;
1959 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1960 if (Profile->Location == 2) Profile->CarKitProfile = true;
1961 if (Profile->Location == 3) Profile->HeadSetProfile = true;
1962 }
1963 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1964 Profile->HeadSetProfile = false; //fixme
1965 Profile->CarKitProfile = false;
1966 }
1967
1968 for (i = 0x00; i <= 0x09; i++) {
1969 feat_req[5] = Profile->Location - 1;
1970 feat_req[6] = i;
1971 smprintf(s, "Getting profile feature\n");
1972 error = GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetProfile);
1973 if (error!=ERR_NONE) return error;
1974 }
1975
1976 for (i=0;i<Profile->FeaturesNumber;i++) {
1977 if (Profile->FeatureID[i] == Profile_CallAlert &&
1978 Profile->FeatureValue[i] != PROFILE_CALLALERT_CALLERGROUPS) {
1979 for (j=0;j<5;j++) Profile->CallerGroups[j] = true;
1980 }
1981 }
1982
1983 Profile->Active = false;
1984 feat_req[5] = 0;
1985 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1986 feat_req[6] = 0x24;
1987 } else {
1988 feat_req[6] = 0x2A;
1989 }
1990 smprintf(s, "Getting profile feature\n");
1991 error = GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetProfile);
1992
1993 return error;
1994}
1995
1996static GSM_Error N6110_SetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1997{
1998 int i;
1999 bool found;
2000 unsigned char ID,Value;
2001 GSM_Error error;
2002 GSM_Profile_PhoneTableValue *ProfilePhone = Profile6110;
2003
2004 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) ProfilePhone = Profile3310;
2005
2006 for (i=0;i<Profile->FeaturesNumber;i++) {
2007 found = false;
2008 if (ProfilePhone == Profile3310) {
2009 switch (Profile->FeatureID[i]) {
2010 case Profile_RingtoneID:
2011 ID = 0x02;
2012 Value = Profile->FeatureValue[i];
2013 found = true;
2014 break;
2015 case Profile_ScreenSaverNumber:
2016 ID = 0x09;
2017 Value = Profile->FeatureValue[i];
2018 found = true;
2019 break;
2020 default:
2021 found=NOKIA_FindPhoneFeatureValue(
2022 s,
2023 ProfilePhone,
2024 Profile->FeatureID[i],Profile->FeatureValue[i],
2025 &ID,&Value);
2026 }
2027 }
2028 if (ProfilePhone == Profile6110) {
2029 switch (Profile->FeatureID[i]) {
2030 case Profile_RingtoneID:
2031 ID = 0x03;
2032 Value = Profile->FeatureValue[i];
2033 found = true;
2034 break;
2035 default:
2036 found=NOKIA_FindPhoneFeatureValue(
2037 s,
2038 ProfilePhone,
2039 Profile->FeatureID[i],Profile->FeatureValue[i],
2040 &ID,&Value);
2041 }
2042 }
2043 if (found) {
2044 error=N6110_SetProfileFeature (s,((unsigned char)(Profile->Location-1)),ID,Value);
2045 if (error!=ERR_NONE) return error;
2046 }
2047 }
2048 return ERR_NONE;
2049}
2050
2051static GSM_Error N6110_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
2052{
2053 GSM_Phone_Data *Data = &s->Phone.Data;
2054 GSM_SMSMessage sms;
2055
2056#ifdef DEBUG
2057 smprintf(s, "SMS message received\n");
2058 sms.State = SMS_UnRead;
2059 sms.InboxFolder = true;
2060 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+7);
2061#endif
2062 if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
2063 sms.State = SMS_UnRead;
2064 sms.InboxFolder = true;
2065 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+7);
2066
2067 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
2068 }
2069 return ERR_NONE;
2070}
2071
2072static GSM_Error N6110_ReplyAddCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2073{
2074 smprintf(s, "Writting calendar note: ");
2075 switch (msg.Buffer[4]) {
2076 case 0x01:
2077 smprintf(s, "OK\n");
2078 return ERR_NONE;
2079 case 0x73:
2080 case 0x7d:
2081 smprintf(s, "error\n");
2082 return ERR_UNKNOWN;
2083 case 0x81:
2084 smprintf(s,"during editing notes in phone menu\n");
2085 return ERR_INSIDEPHONEMENU;
2086 default:
2087 smprintf(s, "unknown ERROR %i\n",msg.Buffer[4]);
2088 }
2089 return ERR_UNKNOWNRESPONSE;
2090}
2091
2092static GSM_Error N6110_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2093{
2094 bool Reminder3310 = false;
2095 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, i, current;
2096 unsigned char mychar1,mychar2;
2097 unsigned char req[200] = {N6110_FRAME_HEADER, 0x64, 0x01, 0x10,
2098 0x00, /* Length of the rest of the frame */
2099 0x00, /* Calendar note type */
2100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2101 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x01};
2102
2103 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2104
2105 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
2106
2107 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52)) {
2108 switch(Note->Type) {
2109 case GSM_CAL_REMINDER: req[7]=0x01; break;
2110 case GSM_CAL_CALL : req[7]=0x02; break;
2111 case GSM_CAL_MEETING : req[7]=0x03; break;
2112 case GSM_CAL_BIRTHDAY: req[7]=0x04; break;
2113 case GSM_CAL_T_ATHL : req[7]=0x05; break;
2114 case GSM_CAL_T_BALL : req[7]=0x06; break;
2115 case GSM_CAL_T_CYCL : req[7]=0x07; break;
2116 case GSM_CAL_T_BUDO : req[7]=0x08; break;
2117 case GSM_CAL_T_DANC : req[7]=0x09; break;
2118 case GSM_CAL_T_EXTR : req[7]=0x0a; break;
2119 case GSM_CAL_T_FOOT : req[7]=0x0b; break;
2120 case GSM_CAL_T_GOLF : req[7]=0x0c; break;
2121 case GSM_CAL_T_GYM : req[7]=0x0d; break;
2122 case GSM_CAL_T_HORS : req[7]=0x0e; break;
2123 case GSM_CAL_T_HOCK : req[7]=0x0f; break;
2124 case GSM_CAL_T_RACE : req[7]=0x10; break;
2125 case GSM_CAL_T_RUGB : req[7]=0x11; break;
2126 case GSM_CAL_T_SAIL : req[7]=0x12; break;
2127 case GSM_CAL_T_STRE : req[7]=0x13; break;
2128 case GSM_CAL_T_SWIM : req[7]=0x14; break;
2129 case GSM_CAL_T_TENN : req[7]=0x15; break;
2130 case GSM_CAL_T_TRAV : req[7]=0x16; break;
2131 case GSM_CAL_T_WINT : req[7]=0x17; break;
2132 default : req[7]=0x01; break;
2133 }
2134 } else {
2135 switch(Note->Type) {
2136 case GSM_CAL_CALL : req[7]=0x02; break;
2137 case GSM_CAL_MEETING : req[7]=0x03; break;
2138 case GSM_CAL_BIRTHDAY: req[7]=0x04; break;
2139 case GSM_CAL_REMINDER:
2140 default : req[7]=0x01; break;
2141 }
2142 }
2143
2144 if (Time == -1) return ERR_UNKNOWN;
2145 NOKIA_EncodeDateTime(s, req+8, &Note->Entries[Time].Date);
2146 req[14] = Note->Entries[Time].Date.Second;
2147
2148 if (Alarm != -1) {
2149 NOKIA_EncodeDateTime(s, req+15, &Note->Entries[Alarm].Date);
2150 req[21] = Note->Entries[Alarm].Date.Second;
2151 }
2152
2153 current = 23;
2154
2155 if (Text != -1) {
2156 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52) ||
2157 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL82)) {
2158 req[22] = UnicodeLength(Note->Entries[Text].Text)*2;
2159 memcpy(req+current,Note->Entries[Text].Text,UnicodeLength(Note->Entries[Text].Text)*2);
2160 current += UnicodeLength(Note->Entries[Text].Text)*2;
2161 } else {
2162 req[22] = UnicodeLength(Note->Entries[Text].Text);
2163 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL33)) {
2164 Reminder3310 = true;
2165 if (!strcmp(s->Phone.Data.ModelInfo->model,"3310") && s->Phone.Data.VerNum<5.11) {
2166 if (Note->Type!=GSM_CAL_REMINDER) Reminder3310 = false;
2167 }
2168 if (!strcmp(s->Phone.Data.ModelInfo->model,"3330") && s->Phone.Data.VerNum<=4.50) {
2169 if (Note->Type!=GSM_CAL_REMINDER) Reminder3310 = false;
2170 }
2171 if (Reminder3310) {
2172 req[22]++; /* one additional char */
2173 req[current++] = 0x01; /* we use now subset 1 */
2174 for (i=0;i<((int)UnicodeLength(Note->Entries[Text].Text));i++) {
2175 /* Euro char */
2176 if (Note->Entries[Text].Text[i*2]==0x20 && Note->Entries[Text].Text[i*2+1]==0xAC) {
2177 req[current++] = 0xe2;
2178 req[current++] = 0x82;
2179 req[current++] = 0xac;
2180 req[23] = 0x03; /* use subset 3 */
2181 req[22]+=2; /* two additional chars */
2182 } else if (EncodeWithUTF8Alphabet(Note->Entries[Text].Text[i*2],Note->Entries[Text].Text[i*2+1],&mychar1,&mychar2)) {
2183 req[current++] = mychar1;
2184 req[current++] = mychar2;
2185 req[23] = 0x03; /* use subset 3 */
2186 req[22]++; /* one additional char */
2187 } else {
2188 current+=DecodeWithUnicodeAlphabet(((wchar_t)(Note->Entries[Text].Text[i*2]*256+Note->Entries[Text].Text[i*2+1])),req+current);
2189 }
2190 }
2191 }
2192 }
2193 if (!Reminder3310) {
2194 memcpy(req+current,DecodeUnicodeString(Note->Entries[Text].Text),UnicodeLength(Note->Entries[Text].Text));
2195 current += UnicodeLength(Note->Entries[Text].Text);
2196 }
2197 }
2198 } else req[22] = 0x00;
2199
2200 if (Note->Type == GSM_CAL_CALL) {
2201 if (Phone != -1) {
2202 req[current++] = UnicodeLength(Note->Entries[Phone].Text);
2203 memcpy(req+current,DecodeUnicodeString(Note->Entries[Phone].Text),UnicodeLength(Note->Entries[Phone].Text));
2204 current += UnicodeLength(Note->Entries[Phone].Text);
2205 } else req[current++] = 0x00;
2206 }
2207
2208 req[6] = current - 8;
2209
2210 smprintf(s, "Writing calendar note\n");
2211 return GSM_WaitFor (s, req, current, 0x13, 4, ID_SetCalendarNote);
2212}
2213
2214static GSM_Error N6110_ReplyDeleteCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2215{
2216 smprintf(s, "Deleting calendar note: ");
2217 switch (msg.Buffer[4]) {
2218 case 0x01:
2219 smprintf(s, "done OK\n");
2220 return ERR_NONE;
2221 case 0x81:
2222 smprintf(s,"during editing notes in phone menu\n");
2223 return ERR_INSIDEPHONEMENU;
2224 case 0x93:
2225 smprintf(s, "Can't be done - too high location ?\n");
2226 return ERR_INVALIDLOCATION;
2227 default:
2228 smprintf(s, "unknown ERROR %i\n",msg.Buffer[4]);
2229 return ERR_UNKNOWNRESPONSE;
2230 }
2231}
2232
2233static GSM_Error N6110_DeleteCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2234{
2235 unsigned char req[] = {N6110_FRAME_HEADER, 0x68,
2236 0x00}; /* Location */
2237
2238 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2239
2240 req[4] = Note->Location;
2241
2242 smprintf(s, "Deleting calendar note\n");
2243 return GSM_WaitFor (s, req, 5, 0x13, 5, ID_DeleteCalendarNote);
2244}
2245
2246/* for example: "Euro_char" text */
2247static void Decode3310Subset3(int j, GSM_Protocol_Message msg, GSM_Phone_Data *Data)
2248{
2249 wchar_t wc;
2250 int len = 0;
2251 int i;
2252 bool charfound;
2253 GSM_CalendarEntry *Entry = Data->Cal;
2254
2255 i = j;
2256 while (i!=msg.Buffer[23]) {
2257 EncodeWithUnicodeAlphabet(msg.Buffer+24+i,&wc);
2258 charfound = false;
2259 if (i!=msg.Buffer[23]-2) {
2260 if (msg.Buffer[24+i] ==0xe2 && msg.Buffer[24+i+1]==0x82 &&
2261 msg.Buffer[24+i+2]==0xac) {
2262 wc = 0x20 * 256 + 0xac;
2263 i+=2;
2264 charfound = true;
2265 }
2266 }
2267 if (i!=msg.Buffer[23]-1 && !charfound) {
2268 if (msg.Buffer[24+i]>=0xc2) {
2269 wc = DecodeWithUTF8Alphabet(msg.Buffer[24+i],msg.Buffer[24+i+1]);
2270 i++;
2271 }
2272 }
2273 Entry->Entries[Entry->EntriesNum].Text[len++] = (wc >> 8) & 0xff;
2274 Entry->Entries[Entry->EntriesNum].Text[len++] = wc & 0xff;
2275 i++;
2276 }
2277 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2278 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2279}
2280
2281/* For example: "a with : above" char */
2282static void Decode3310Subset2(int j, GSM_Protocol_Message msg, GSM_Phone_Data *Data)
2283{
2284 int len = 0;
2285 int i;
2286 GSM_CalendarEntry *Entry = Data->Cal;
2287
2288 i = j;
2289 while (i!=msg.Buffer[23]) {
2290 Entry->Entries[Entry->EntriesNum].Text[len++] = 0x00;
2291 Entry->Entries[Entry->EntriesNum].Text[len++] = msg.Buffer[24+i];
2292 i++;
2293 }
2294 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2295 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2296}
2297
2298static GSM_Error N6110_ReplyGetNextCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2299{
2300 int i = 0;
2301 bool SpecialSubSet = false;
2302 GSM_CalendarEntry *Entry = s->Phone.Data.Cal;
2303
2304 switch (msg.Buffer[4]) {
2305 case 0x01:
2306 smprintf(s, "Calendar note received\n");
2307 switch (msg.Buffer[8]) {
2308 case 0x01: Entry->Type = GSM_CAL_REMINDER; break;
2309 case 0x02: Entry->Type = GSM_CAL_CALL; break;
2310 case 0x03: Entry->Type = GSM_CAL_MEETING; break;
2311 case 0x04: Entry->Type = GSM_CAL_BIRTHDAY; break;
2312 case 0x05: Entry->Type = GSM_CAL_T_ATHL; break;
2313 case 0x06: Entry->Type = GSM_CAL_T_BALL; break;
2314 case 0x07: Entry->Type = GSM_CAL_T_CYCL; break;
2315 case 0x08: Entry->Type = GSM_CAL_T_BUDO; break;
2316 case 0x09: Entry->Type = GSM_CAL_T_DANC; break;
2317 case 0x0a: Entry->Type = GSM_CAL_T_EXTR; break;
2318 case 0x0b: Entry->Type = GSM_CAL_T_FOOT; break;
2319 case 0x0c: Entry->Type = GSM_CAL_T_GOLF; break;
2320 case 0x0d: Entry->Type = GSM_CAL_T_GYM; break;
2321 case 0x0e: Entry->Type = GSM_CAL_T_HORS; break;
2322 case 0x0f: Entry->Type = GSM_CAL_T_HOCK; break;
2323 case 0x10: Entry->Type = GSM_CAL_T_RACE; break;
2324 case 0x11: Entry->Type = GSM_CAL_T_RUGB; break;
2325 case 0x12: Entry->Type = GSM_CAL_T_SAIL; break;
2326 case 0x13: Entry->Type = GSM_CAL_T_STRE; break;
2327 case 0x14: Entry->Type = GSM_CAL_T_SWIM; break;
2328 case 0x15: Entry->Type = GSM_CAL_T_TENN; break;
2329 case 0x16: Entry->Type = GSM_CAL_T_TRAV; break;
2330 case 0x17: Entry->Type = GSM_CAL_T_WINT; break;
2331 default :
2332 smprintf(s, "Unknown note type %i\n",msg.Buffer[8]);
2333 return ERR_UNKNOWNRESPONSE;
2334 }
2335#ifdef DEBUG
2336 switch (msg.Buffer[8]) {
2337 case 0x01: smprintf(s, "Reminder\n"); break;
2338 case 0x02: smprintf(s, "Call\n"); break;
2339 case 0x03: smprintf(s, "Meeting\n"); break;
2340 case 0x04: smprintf(s, "Birthday\n"); break;
2341 }
2342#endif
2343 Entry->EntriesNum = 0;
2344
2345 NOKIA_DecodeDateTime(s, msg.Buffer+9, &Entry->Entries[0].Date);
2346 smprintf(s, "Time : %02i-%02i-%04i %02i:%02i:%02i\n",
2347 Entry->Entries[0].Date.Day,Entry->Entries[0].Date.Month,Entry->Entries[0].Date.Year,
2348 Entry->Entries[0].Date.Hour,Entry->Entries[0].Date.Minute,Entry->Entries[0].Date.Second);
2349 Entry->Entries[0].EntryType = CAL_START_DATETIME;
2350 Entry->EntriesNum++;
2351
2352 NOKIA_DecodeDateTime(s, msg.Buffer+16, &Entry->Entries[1].Date);
2353 if (Entry->Entries[1].Date.Year!=0) {
2354 smprintf(s, "Alarm : %02i-%02i-%04i %02i:%02i:%02i\n",
2355 Entry->Entries[1].Date.Day,Entry->Entries[1].Date.Month,Entry->Entries[1].Date.Year,
2356 Entry->Entries[1].Date.Hour,Entry->Entries[1].Date.Minute,Entry->Entries[1].Date.Second);
2357 Entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
2358 Entry->EntriesNum++;
2359 } else {
2360 smprintf(s, "No alarm\n");
2361 }
2362
2363 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52) ||
2364 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL82)) {
2365 memcpy(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24,msg.Buffer[23]);
2366 Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23] ]=0;
2367 Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23]+1]=0;
2368 } else {
2369 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL33)) {
2370 /* first char is subset for 33xx and reminders */
2371 if (Entry->Type == GSM_CAL_REMINDER) {
2372 i=1;
2373 smprintf(s, "Subset %i in reminder note !\n",msg.Buffer[24]);
2374 }
2375 SpecialSubSet = true;
2376 switch (msg.Buffer[24]) {
2377 case 2 : Decode3310Subset2(i,msg,&s->Phone.Data); break;
2378 case 3 : Decode3310Subset3(i,msg,&s->Phone.Data); break;
2379 default : SpecialSubSet = false; break;
2380 }
2381 }
2382 if (!SpecialSubSet) {
2383 N6110_EncodeUnicode(s,Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+i,msg.Buffer[23]-i);
2384 }
2385 }
2386 smprintf(s, "Text \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
2387 if (msg.Buffer[23] != 0x00) {
2388 Entry->Entries[Entry->EntriesNum].EntryType = CAL_TEXT;
2389 Entry->EntriesNum++;
2390 }
2391
2392 if (Entry->Type == GSM_CAL_CALL) {
2393 EncodeUnicode(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+msg.Buffer[23]+1,msg.Buffer[24+msg.Buffer[23]]);
2394 smprintf(s, "Phone : \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
2395 if (msg.Buffer[24+msg.Buffer[23]] != 0x00) {
2396 Entry->Entries[Entry->EntriesNum].EntryType = CAL_PHONE;
2397 Entry->EntriesNum++;
2398 }
2399 }
2400 return ERR_NONE;
2401 case 0x93:
2402 smprintf(s, "Can't get calendar note - too high location?\n");
2403 return ERR_INVALIDLOCATION;
2404 }
2405 return ERR_UNKNOWNRESPONSE;
2406}
2407
2408static GSM_Error N6110_GetNextCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
2409{
2410 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location;
2411 GSM_Error error;
2412 GSM_DateTime date_time;
2413 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
2414 unsigned char req[] = {N6110_FRAME_HEADER, 0x66,
2415 0x00}; /* Location */
2416
2417 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2418
2419 if (start) {
2420 Priv->LastCalendarPos = 1;
2421 } else {
2422 Priv->LastCalendarPos++;
2423 }
2424
2425 Note->Location = Priv->LastCalendarPos;
2426 req[4] = Priv->LastCalendarPos;
2427
2428 s->Phone.Data.Cal=Note;
2429 smprintf(s, "Getting calendar note\n");
2430 error=GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNote);
2431
2432 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
2433 /* 2090 year is set for example in 3310 */
2434 if (error == ERR_NONE && Note->Entries[Time].Date.Year == 2090) {
2435 error=N6110_GetDateTime(s, &date_time);
2436 if (error == ERR_NONE) Note->Entries[Time].Date.Year = date_time.Year;
2437 }
2438 return error;
2439}
2440
2441GSM_Error N6110_ReplyUSSDInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
2442{
2443 unsigned char buffer[2000],buffer2[4000];
2444 int tmp;
2445
2446 tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, msg.Buffer+8, buffer);
2447 msg.Buffer[tmp] = 0;
2448
2449 smprintf(s, "USSD reply: \"%s\"\n",buffer);
2450
2451 if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
2452 EncodeUnicode(buffer2,buffer,strlen(buffer));
2453 s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
2454 }
2455
2456 return ERR_NONE;
2457}
2458
2459GSM_Error N6110_AnswerCall(GSM_StateMachine *s, int ID, bool all)
2460{
2461 GSM_Error error;
2462 unsigned char req1[] = {N6110_FRAME_HEADER, 0x42, 0x05, 0x01,
2463 0x07, 0xa2, 0x88, 0x81, 0x21, 0x15, 0x63, 0xa8,
2464 0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15,
2465 0x63, 0x80};
2466
2467 if (!all) {
2468 smprintf(s, "Answering call part 1\n");
2469 error = GSM_WaitFor (s, req1, 24, 0x01, 5, ID_AnswerCall);
2470 if (error != ERR_NONE) return error;
2471 return DCT3DCT4_AnswerCall(s,ID);
2472 }
2473
2474 return DCT3_AnswerAllCalls(s);
2475}
2476
2477static GSM_Error N6110_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
2478{
2479 unsigned int pos = 4;
2480 unsigned char req[100] = {N6110_FRAME_HEADER,0x01,
2481 0x0c}; /* Length of number */
2482
2483 if (ShowNumber == GSM_CALL_DefaultNumberPresence) return DCT3_DialVoice(s,number,ShowNumber);
2484
2485 req[pos++] = strlen(number);
2486 memcpy(req+pos,number,strlen(number));
2487 pos += strlen(number);
2488 req[pos++] = 0x05; /* call type: voice - 0x05, data - 0x01 */
2489 req[pos++] = 0x01;
2490 req[pos++] = 0x01;
2491 req[pos++] = 0x05;
2492 req[pos++] = 0x81;
2493 switch (ShowNumber) {
2494 case GSM_CALL_HideNumber:
2495 req[pos++] = 0x02;
2496 break;
2497 case GSM_CALL_ShowNumber:
2498 req[pos++] = 0x03;
2499 break;
2500 case GSM_CALL_DefaultNumberPresence:
2501 req[pos++] = 0x01;
2502 break;
2503 }
2504 req[pos++] = 0x00;
2505 req[pos++] = 0x00;
2506
2507 smprintf(s, "Making voice call\n");
2508 return GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
2509}
2510
2511GSM_Error N6110_UnholdCall(GSM_StateMachine *s, int ID)
2512{
2513 unsigned char req[] = {N6110_FRAME_HEADER, 0x24, 0x00, 0x02};
2514
2515 req[4] = (unsigned char)ID;
2516 s->Phone.Data.CallID = ID;
2517
2518 smprintf(s, "Unholding call\n");
2519 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_UnholdCall);
2520}
2521
2522GSM_Error N6110_HoldCall(GSM_StateMachine *s, int ID)
2523{
2524 unsigned char req[] = {N6110_FRAME_HEADER, 0x22, 0x00, 0x00};
2525
2526 req[4] = (unsigned char)ID;
2527 s->Phone.Data.CallID = ID;
2528
2529 smprintf(s, "Unholding call\n");
2530 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_HoldCall);
2531}
2532
2533/* Joining selected call to current (and making conference) */
2534GSM_Error N6110_ConferenceCall(GSM_StateMachine *s, int ID)
2535{
2536 unsigned char req[] = {N6110_FRAME_HEADER, 0x28, 0x00, 0x01};
2537
2538 req[4] = (unsigned char)ID;
2539 s->Phone.Data.CallID = ID;
2540
2541 smprintf(s, "Conference call\n");
2542 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_ConferenceCall);
2543}
2544
2545/* Removing selected call from conference and making private call with it
2546 * (conference call is on hold) */
2547GSM_Error N6110_SplitCall(GSM_StateMachine *s, int ID)
2548{
2549 unsigned char req[] = {N6110_FRAME_HEADER, 0x2A, 0x00, 0x01};
2550
2551 req[4] = (unsigned char)ID;
2552 s->Phone.Data.CallID = ID;
2553
2554 smprintf(s, "Split call\n");
2555 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_SplitCall);
2556}
2557
2558/* This probably need more investigation */
2559GSM_Error N6110_SwitchCall(GSM_StateMachine *s, int ID, bool next)
2560{
2561// unsigned char req[] = {N6110_FRAME_HEADER, 0x20}; calls info
2562 unsigned char req[] = {N6110_FRAME_HEADER, 0x26, 0x00};
2563
2564 s->Phone.Data.CallID = ID;
2565
2566 if (next) {
2567 smprintf(s, "Switch call\n");
2568 return GSM_WaitFor (s, req, 4, 0x01, 4, ID_SwitchCall);
2569 } else {
2570 req[4] = (unsigned char)ID;
2571
2572 smprintf(s, "Switch call\n");
2573 return GSM_WaitFor (s, req, 5, 0x01, 4, ID_SwitchCall);
2574 }
2575}
2576
2577/* This probably need more investigation */
2578GSM_Error N6110_TransferCall(GSM_StateMachine *s, int ID, bool next)
2579{
2580 unsigned char req[] = {N6110_FRAME_HEADER, 0x2C, 0x00};
2581
2582 s->Phone.Data.CallID = ID;
2583
2584 if (next) {
2585 smprintf(s, "Transfer call\n");
2586 return GSM_WaitFor (s, req, 4, 0x01, 4, ID_TransferCall);
2587 } else {
2588 req[4] = (unsigned char)ID;
2589
2590 smprintf(s, "Transfer call\n");
2591 return GSM_WaitFor (s, req, 5, 0x01, 4, ID_TransferCall);
2592 }
2593}
2594
2595static GSM_Reply_Function N6110ReplyFunctions[] = {
2596 {N6110_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
2597 {N6110_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
2598 {N6110_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
2599 {N6110_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
2600 {N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
2601 {N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
2602 {N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
2603 {N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
2604 {N6110_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
2605 {N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_HoldCall },
2606 {N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_IncomingFrame },
2607 {N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_UnholdCall },
2608 {N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_IncomingFrame },
2609 {N6110_ReplyCallInfo, "\x01",0x03,0x27,ID_IncomingFrame },
2610 {N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_ConferenceCall },
2611 {N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_IncomingFrame },
2612 {N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_SplitCall },
2613 {N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_IncomingFrame },
2614 {N6110_ReplySendDTMF, "\x01",0x03,0x40,ID_SendDTMF },
2615 {NoneReply, "\x01",0x03,0x40,ID_DialVoice },
2616 {NoneReply, "\x01",0x03,0x40,ID_IncomingFrame },
2617 {NoneReply, "\x01",0x03,0x43,ID_AnswerCall },
2618 {N6110_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
2619
2620 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
2621 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
2622 {N6110_ReplyIncomingSMS, "\x02",0x03,0x10,ID_IncomingFrame },
2623#ifdef GSM_ENABLE_CELLBROADCAST
2624 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
2625 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
2626 {DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
2627#endif
2628 {DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
2629 {DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
2630 {DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
2631
2632 {N6110_ReplyGetMemory, "\x03",0x03,0x02,ID_GetMemory },
2633 {N6110_ReplyGetMemory, "\x03",0x03,0x03,ID_GetMemory },
2634 {N6110_ReplySetMemory, "\x03",0x03,0x05,ID_SetMemory },
2635 {N6110_ReplySetMemory, "\x03",0x03,0x06,ID_SetMemory },
2636 {N6110_ReplyGetMemoryStatus, "\x03",0x03,0x08,ID_GetMemoryStatus },
2637 {N6110_ReplyGetMemoryStatus, "\x03",0x03,0x09,ID_GetMemoryStatus },
2638 {N6110_ReplyGetCallerLogo, "\x03",0x03,0x11,ID_GetBitmap },
2639 {N6110_ReplyGetCallerLogo, "\x03",0x03,0x12,ID_GetBitmap },
2640 {N6110_ReplySetCallerLogo, "\x03",0x03,0x14,ID_SetBitmap },
2641 {N6110_ReplySetCallerLogo, "\x03",0x03,0x15,ID_SetBitmap },
2642 {N6110_ReplyGetSpeedDial, "\x03",0x03,0x17,ID_GetSpeedDial },
2643 {N6110_ReplyGetSpeedDial, "\x03",0x03,0x18,ID_GetSpeedDial },
2644 /* 0x1A, 0x1B - reply set speed dial */
2645
2646 {N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetSignalQuality },
2647 {N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetBatteryCharge },
2648
2649 {N6110_ReplySetProfileFeature, "\x05",0x03,0x11,ID_SetProfile },
2650 {N6110_ReplySetProfileFeature, "\x05",0x03,0x12,ID_SetProfile },
2651 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x14,ID_GetProfile },
2652 {N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x14,ID_GetLanguage },
2653 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x15,ID_GetProfile },
2654 {N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x15,ID_GetLanguage },
2655 {N6110_ReplyGetStartup, "\x05",0x03,0x17,ID_GetBitmap },
2656 {N6110_ReplySetStartup, "\x05",0x03,0x19,ID_SetBitmap },
2657 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x1b,ID_GetProfile },
2658 {N61_91_ReplySetOpLogo, "\x05",0x03,0x31,ID_SetBitmap },
2659 {N61_91_ReplySetOpLogo, "\x05",0x03,0x32,ID_SetBitmap },
2660 {N6110_ReplyGetOpLogo, "\x05",0x03,0x34,ID_GetBitmap },
2661 {N6110_ReplySetRingtone, "\x05",0x03,0x37,ID_SetRingtone },
2662 {N6110_ReplySetRingtone, "\x05",0x03,0x38,ID_SetRingtone },
2663
2664 {DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x02,ID_Divert },
2665 {DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x03,ID_Divert },
2666 {N6110_ReplyUSSDInfo, "\x06",0x03,0x05,ID_IncomingFrame },
2667 {NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },//incoming call divert info
2668
2669 {N6110_ReplyGetSecurityStatus, "\x08",0x03,0x08,ID_GetSecurityStatus },
2670 {N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0b,ID_EnterSecurityCode },
2671 {N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0c,ID_EnterSecurityCode },
2672
2673 {DCT3_ReplySIMLogin, "\x09",0x03,0x80,ID_IncomingFrame },
2674 {DCT3_ReplySIMLogout, "\x09",0x03,0x81,ID_IncomingFrame },
2675
2676 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
2677 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
2678
2679 {N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_GetDisplayStatus },
2680 {N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_IncomingFrame },
2681
2682 {DCT3_ReplySetDateTime, "\x11",0x03,0x61,ID_SetDateTime },
2683 {DCT3_ReplyGetDateTime, "\x11",0x03,0x63,ID_GetDateTime },
2684 {DCT3_ReplySetAlarm, "\x11",0x03,0x6C,ID_SetAlarm },
2685 {DCT3_ReplyGetAlarm, "\x11",0x03,0x6E,ID_GetAlarm },
2686
2687 {N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_SetCalendarNote },
2688 {N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_IncomingFrame },
2689 {N6110_ReplyGetNextCalendar, "\x13",0x03,0x67,ID_GetCalendarNote },
2690 {N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_DeleteCalendarNote },
2691 {N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_IncomingFrame },
2692
2693 {N6110_ReplySaveSMSMessage, "\x14",0x03,0x05,ID_SaveSMSMessage },
2694 {N6110_ReplySaveSMSMessage, "\x14",0x03,0x06,ID_SaveSMSMessage },
2695 {N6110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetSMSMessage },
2696 {N6110_ReplyGetSMSMessage, "\x14",0x03,0x09,ID_GetSMSMessage },
2697 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0B,ID_DeleteSMSMessage },
2698 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0C,ID_DeleteSMSMessage },
2699 {N6110_ReplyGetSMSStatus, "\x14",0x03,0x37,ID_GetSMSStatus },
2700 {N6110_ReplyGetSMSStatus, "\x14",0x03,0x38,ID_GetSMSStatus },
2701
2702 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
2703 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
2704 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
2705 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
2706 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
2707 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
2708 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
2709 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
2710 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
2711 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
2712 {DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
2713 {DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
2714 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x16,ID_GetConnectSet },
2715 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x17,ID_GetConnectSet },
2716 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x19,ID_SetConnectSet },
2717 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1A,ID_SetConnectSet },
2718 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1C,ID_GetConnectSet },
2719 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1D,ID_GetConnectSet },
2720 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1F,ID_SetConnectSet },
2721
2722 {DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
2723 {N61_71_ReplyResetPhoneSettings, "\x40",0x02,0x65,ID_ResetPhoneSettings },
2724 {DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
2725 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
2726 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
2727 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
2728 {DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
2729 {DCT3_ReplyPlayTone, "\x40",0x02,0x8F,ID_PlayTone },
2730 {N6110_ReplyGetRingtone, "\x40",0x02,0x9E,ID_GetRingtone },
2731 {N6110_ReplySetBinRingtone, "\x40",0x02,0xA0,ID_SetRingtone },
2732 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
2733 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
2734 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
2735 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth},
2736 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
2737
2738 {N6110_ReplyGetSetPicture, "\x47",0x03,0x02,ID_GetBitmap },
2739 {N6110_ReplyGetSetPicture, "\x47",0x03,0x04,ID_SetBitmap },
2740 {N6110_ReplyGetSetPicture, "\x47",0x03,0x05,ID_SetBitmap },
2741 {N6110_ReplyGetSetPicture, "\x47",0x03,0x06,ID_GetBitmap },
2742
2743#ifndef ENABLE_LGPL
2744 {N6110_ReplyGetMagicBytes, "\x64",0x00,0x00,ID_MakeAuthentication },
2745#endif
2746
2747 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
2748 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
2749 {DCT3_ReplyPressKey, "\xD2",0x02,0x46,ID_PressKey },
2750 {DCT3_ReplyPressKey, "\xD2",0x02,0x47,ID_PressKey },
2751
2752 {NULL, "\x00",0x00,0x00,ID_None }
2753};
2754
2755GSM_Phone_Functions N6110Phone = {
2756 "2100|3210|3310|3330|3390|3410|3610|5110|5110i|5130|5190|5210|5510|6110|6130|6150|6190|8210|8250|8290|8850|8855|8890",
2757 N6110ReplyFunctions,
2758 N6110_Initialise,
2759 PHONE_Terminate,
2760 GSM_DispatchMessage,
2761 N6110_ShowStartInfo,
2762 NOKIA_GetManufacturer,
2763 DCT3DCT4_GetModel,
2764 DCT3DCT4_GetFirmware,
2765 DCT3_GetIMEI,
2766 DCT3_GetOriginalIMEI,
2767 DCT3_GetManufactureMonth,
2768 DCT3_GetProductCode,
2769 DCT3_GetHardware,
2770 DCT3_GetPPM,
2771 NOTSUPPORTED, /* GetSIMIMSI */
2772 N6110_GetDateTime,
2773 N6110_SetDateTime,
2774 N6110_GetAlarm,
2775 N6110_SetAlarm,
2776 NOTSUPPORTED, /* GetLocale */
2777 NOTSUPPORTED, /* SetLocale */
2778 DCT3_PressKey,
2779 DCT3_Reset,
2780 N61_71_ResetPhoneSettings,
2781 N6110_EnterSecurityCode,
2782 N6110_GetSecurityStatus,
2783 N6110_GetDisplayStatus,
2784 NOTIMPLEMENTED, /* SetAutoNetworkLogin */
2785 N6110_GetBatteryCharge,
2786 N6110_GetSignalQuality,
2787 DCT3_GetNetworkInfo,
2788 NOTSUPPORTED, /* GetCategory */
2789 NOTSUPPORTED, /* AddCategory */
2790 NOTSUPPORTED, /* GetCategoryStatus */
2791 N6110_GetMemoryStatus,
2792 N6110_GetMemory,
2793 NOTIMPLEMENTED, /* GetNextMemory */
2794 N6110_SetMemory,
2795 NOTIMPLEMENTED, /* AddMemory */
2796 N6110_DeleteMemory,
2797 NOTIMPLEMENTED, /* DeleteAllMemory */
2798 N6110_GetSpeedDial,
2799 NOTIMPLEMENTED, /* SetSpeedDial */
2800 DCT3_GetSMSC,
2801 DCT3_SetSMSC,
2802 DCT3_GetSMSStatus,
2803 N6110_GetSMSMessage,
2804 N6110_GetNextSMSMessage,
2805 N6110_SetSMS,
2806 N6110_AddSMS,
2807 N6110_DeleteSMSMessage,
2808 DCT3_SendSMSMessage,
2809 NOTSUPPORTED, /* SendSavedSMS */
2810 NOKIA_SetIncomingSMS,
2811 DCT3_SetIncomingCB,
2812 PHONE_GetSMSFolders,
2813 NOTSUPPORTED, /* AddSMSFolder */
2814 NOTSUPPORTED, /* DeleteSMSFolder */
2815 N6110_DialVoice,
2816 N6110_AnswerCall,
2817 DCT3_CancelCall,
2818 N6110_HoldCall,
2819 N6110_UnholdCall,
2820 N6110_ConferenceCall,
2821 N6110_SplitCall,
2822 N6110_TransferCall,
2823 N6110_SwitchCall,
2824 DCT3DCT4_GetCallDivert,
2825 DCT3DCT4_SetCallDivert,
2826 DCT3DCT4_CancelAllDiverts,
2827 NOKIA_SetIncomingCall,
2828 NOKIA_SetIncomingUSSD,
2829 DCT3DCT4_SendDTMF,
2830 N6110_GetRingtone,
2831 N6110_SetRingtone,
2832 NOTSUPPORTED, /* GetRingtonesInfo */
2833 NOTSUPPORTED, /* DeleteUserRingtones */
2834 DCT3_PlayTone,
2835 DCT3_GetWAPBookmark,
2836 DCT3_SetWAPBookmark,
2837 DCT3_DeleteWAPBookmark,
2838 DCT3_GetWAPSettings,
2839 DCT3_SetWAPSettings,
2840 NOTSUPPORTED, /* GetMMSSettings */
2841 NOTSUPPORTED, /* SetMMSSettings */
2842 NOTSUPPORTED, /* GetSyncMLSettings*/
2843 NOTSUPPORTED, /* SetSyncMLSettings*/
2844 NOTSUPPORTED, /* GetChatSettings */
2845 NOTSUPPORTED, /* SetChatSettings */
2846 N6110_GetBitmap,
2847 N6110_SetBitmap,
2848 NOTSUPPORTED, /* GetToDoStatus */
2849 NOTSUPPORTED, /* GetToDo */
2850 NOTSUPPORTED, /* GetNextToDo */
2851 NOTSUPPORTED, /* SetToDo */
2852 NOTSUPPORTED, /* AddToDo */
2853 NOTSUPPORTED, /* DeleteToDo */
2854 NOTSUPPORTED, /* DeleteAllToDo */
2855 NOTIMPLEMENTED, /* GetCalendarStatus */
2856 NOTIMPLEMENTED, /* GetCalendar */
2857 N6110_GetNextCalendarNote,
2858 NOTIMPLEMENTED, /* SetCalendar */
2859 N6110_AddCalendarNote,
2860 N6110_DeleteCalendarNote,
2861 NOTIMPLEMENTED, /* DeleteAllCalendar */
2862 NOTSUPPORTED, /* GetCalendarSettings */
2863 NOTSUPPORTED, /* SetCalendarSettings */
2864 NOTSUPPORTED, /* GetNote */
2865 N6110_GetProfile,
2866 N6110_SetProfile,
2867 NOTSUPPORTED, /* GetFMStation */
2868 NOTSUPPORTED, /* SetFMStation */
2869 NOTSUPPORTED, /* ClearFMStations */
2870 NOTSUPPORTED, /* GetNextFileFolder */
2871 NOTSUPPORTED, /* GetFilePart */
2872 NOTSUPPORTED, /* AddFile */
2873 NOTSUPPORTED, /* GetFileSystemStatus */
2874 NOTSUPPORTED, /* DeleteFile */
2875 NOTSUPPORTED, /* AddFolder */
2876 NOTSUPPORTED, /* GetGPRSAccessPoint */
2877 NOTSUPPORTED /* SetGPRSAccessPoint */
2878};
2879
2880#endif
2881
2882/* How should editor hadle tabs in this file? Add editor commands here.
2883 * vim: noexpandtab sw=8 ts=8 sts=8:
2884 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n6110.h b/gammu/emb/common/phone/nokia/dct3/n6110.h
new file mode 100644
index 0000000..d243766
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n6110.h
@@ -0,0 +1,45 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef n6110_h
4#define n6110_h
5
6#include "../../../config.h"
7#include "../../../service/sms/gsmsms.h"
8#include "dct3comm.h"
9
10typedef struct {
11#ifndef ENABLE_LGPL
12 unsigned char MagicBytes[4];
13#endif
14 int LastCalendarPos;
15 DCT3_WAPSettings_LocationsWAPLocations;
16
17 GSM_SMSMemoryStatus LastSMSStatus;
18 int LastSMSRead;
19
20 int PhoneLanguage;
21} GSM_Phone_N6110Data;
22
23typedef enum {
24 N6110_Auto = 1,
25 N6110_Europe
26} N6110_Language;
27
28#ifndef GSM_USED_MBUS2
29# define GSM_USED_MBUS2
30#endif
31#ifndef GSM_USED_FBUS2
32# define GSM_USED_FBUS2
33#endif
34#ifndef GSM_USED_FBUS2IRDA
35# define GSM_USED_FBUS2IRDA
36#endif
37#ifndef GSM_USED_IRDAPHONET
38# define GSM_USED_IRDAPHONET
39#endif
40
41#endif
42
43/* How should editor hadle tabs in this file? Add editor commands here.
44 * vim: noexpandtab sw=8 ts=8 sts=8:
45 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n7110.c b/gammu/emb/common/phone/nokia/dct3/n7110.c
new file mode 100644
index 0000000..5a02c9c
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n7110.c
@@ -0,0 +1,1724 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Markus Plail and Gnokii */
3
4#include "../../../gsmstate.h"
5
6#ifdef GSM_ENABLE_NOKIA7110
7
8#include <string.h>
9#include <time.h>
10
11#include "../../../misc/coding/coding.h"
12#include "../../../gsmcomon.h"
13#include "../../../service/gsmlogo.h"
14#include "../../pfunc.h"
15#include "../nfunc.h"
16#include "../nfuncold.h"
17#include "n7110.h"
18#include "dct3func.h"
19
20static GSM_Error N7110_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
21{
22 return DCT3_GetAlarm(s, alarm, 0x19);
23}
24
25static GSM_Error N7110_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
26{
27 return DCT3_SetAlarm(s, alarm, 0x19);
28}
29
30static GSM_Error N7110_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
31{
32 GSM_Phone_Data *Data = &s->Phone.Data;
33
34 smprintf(s, "Phonebook entry received\n");
35 switch (msg.Buffer[6]) {
36 case 0x0f:
37 return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
38 default:
39 return N71_65_DecodePhonebook(s, Data->Memory,Data->Bitmap,Data->SpeedDial,msg.Buffer+18,msg.Length-18,false);
40 }
41 return ERR_UNKNOWN;
42}
43
44static GSM_Error N7110_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
45{
46 unsigned char req[] = {N7110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
47 0x02, /* memory type */
48 0x05,
49 0x00, 0x00,/* location */
50 0x00, 0x00};
51
52 req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
53 if (req[9]==0xff) return ERR_NOTSUPPORTED;
54
55 if (entry->Location==0x00) return ERR_INVALIDLOCATION;
56
57 req[10] = entry->Location / 256;
58 req[11] = entry->Location % 256;
59
60 s->Phone.Data.Memory=entry;
61 smprintf(s, "Getting phonebook entry\n");
62 return GSM_WaitFor (s, req, 14, 0x03, 4, ID_GetMemory);
63}
64
65static GSM_Error N7110_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
66{
67 GSM_Phone_Data *Data = &s->Phone.Data;
68
69 smprintf(s, "Memory status received\n");
70 /* Quess ;-)) */
71 if (msg.Buffer[10]==0x10) {
72 Data->MemoryStatus->MemoryFree = msg.Buffer[14]*256 + msg.Buffer[15];
73 } else {
74 Data->MemoryStatus->MemoryFree = msg.Buffer[18];
75 }
76 smprintf(s, " Size : %i\n",Data->MemoryStatus->MemoryFree);
77 Data->MemoryStatus->MemoryUsed = msg.Buffer[16]*256 + msg.Buffer[17];
78 smprintf(s, " Used : %i\n",Data->MemoryStatus->MemoryUsed);
79 Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
80 smprintf(s, " Free : %i\n",Data->MemoryStatus->MemoryFree);
81 return ERR_NONE;
82}
83
84static GSM_Error N7110_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
85{
86 unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
87 0x05}; /* Memory type */
88
89 req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
90 if (req[5]==0xff) return ERR_NOTSUPPORTED;
91
92 s->Phone.Data.MemoryStatus=Status;
93 smprintf(s, "Getting memory status\n");
94 return GSM_WaitFor (s, req, 6, 0x03, 4, ID_GetMemoryStatus);
95}
96
97static void N7110_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
98{
99 int ifolderid;
100
101 /* simulate flat SMS memory */
102 if (sms->Folder==0x00) {
103 ifolderid = sms->Location / PHONE_MAXSMSINFOLDER;
104 *folderid = (ifolderid + 1) * 0x08;
105 *location = sms->Location - ifolderid * PHONE_MAXSMSINFOLDER;
106 } else {
107 *folderid = sms->Folder * 0x08;
108 *location = sms->Location;
109 }
110 smprintf(s, "SMS folder %i & location %i -> 7110 folder %i & location %i\n",
111 sms->Folder,sms->Location,*folderid,*location);
112}
113
114static void N7110_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
115{
116 sms->Folder= 0;
117 sms->Location= (folderid / 0x08 - 1) * PHONE_MAXSMSINFOLDER + location;
118 smprintf(s, "7110 folder %i & location %i -> SMS folder %i & location %i\n",
119 folderid,location,sms->Folder,sms->Location);
120}
121
122static GSM_Error N7110_ReplyGetSMSFolders(GSM_Protocol_Message msg, GSM_StateMachine *s)
123{
124 int j,current=5;
125 unsigned char buffer[200];
126 GSM_Phone_Data*Data = &s->Phone.Data;
127
128 switch (msg.Buffer[3]) {
129 case 0x7B:
130 smprintf(s, "Names for SMS folders received\n");
131 Data->SMSFolders->Number=msg.Buffer[4];
132 for (j=0;j<msg.Buffer[4];j++) {
133 smprintf(s, "Folder index: %02x",msg.Buffer[current]);
134 current++;
135 smprintf(s, ", folder name: \"");
136 CopyUnicodeString(buffer,msg.Buffer+current);
137 if ((UnicodeLength(buffer))>GSM_MAX_SMS_FOLDER_NAME_LEN) {
138 smprintf(s, "Too long text\n");
139 return ERR_UNKNOWNRESPONSE;
140 }
141 CopyUnicodeString(Data->SMSFolders->Folder[j].Name,buffer);
142 smprintf(s, "%s\"\n",DecodeUnicodeString(buffer));
143 current=current+2+UnicodeLength(buffer)*2;
144 Data->SMSFolders->Folder[j].InboxFolder = false;
145 if (j==0) Data->SMSFolders->Folder[j].InboxFolder = true;
146 Data->SMSFolders->Folder[j].Memory = MEM_ME;
147 if (j==0 || j==1) Data->SMSFolders->Folder[j].InboxFolder = MEM_MT;
148 }
149 return ERR_NONE;
150 case 0x7C:
151 smprintf(s, "Security error ? No PIN ?\n");
152 return ERR_SECURITYERROR;
153 case 0xCA:
154 smprintf(s, "Wait a moment. Phone is during power on and busy now\n");
155 return ERR_SECURITYERROR;
156 }
157 return ERR_UNKNOWNRESPONSE;
158}
159
160static GSM_Error N7110_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
161{
162 unsigned char req[] = {N6110_FRAME_HEADER, 0x7A, 0x00, 0x00};
163
164 s->Phone.Data.SMSFolders=folders;
165 smprintf(s, "Getting SMS folders\n");
166 return GSM_WaitFor (s, req, 6, 0x14, 4, ID_GetSMSFolders);
167}
168
169static GSM_Error N7110_ReplyGetSMSFolderStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
170{
171 int i;
172 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
173
174 smprintf(s, "SMS folder status received\n");
175 Priv->LastSMSFolder.Number=msg.Buffer[4]*256+msg.Buffer[5];
176 smprintf(s, "Number of Entries: %i\n",Priv->LastSMSFolder.Number);
177 smprintf(s, "Locations: ");
178 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
179 Priv->LastSMSFolder.Location[i]=msg.Buffer[6+(i*2)]*256+msg.Buffer[(i*2)+7];
180 if (Priv->LastSMSFolder.Location[i] > PHONE_MAXSMSINFOLDER) {
181 smprintf(s, "Increase PHONE_MAXSMSINFOLDER\n");
182 return ERR_UNKNOWNRESPONSE;
183 }
184 smprintf(s, "%i ",Priv->LastSMSFolder.Location[i]);
185 }
186 smprintf(s, "\n");
187 NOKIA_SortSMSFolderStatus(s, &Priv->LastSMSFolder);
188 return ERR_NONE;
189}
190
191static GSM_Error N7110_PrivGetSMSFolderStatus(GSM_StateMachine *s, int folderid)
192{
193 unsigned char req[] = {N7110_FRAME_HEADER, 0x6b,
194 0x08, /* folderID */
195 0x0F, 0x01};
196
197 req[4] = folderid;
198
199 smprintf(s, "Getting SMS folder status\n");
200 return GSM_WaitFor (s, req, 7, 0x14, 4, ID_GetSMSFolderStatus);
201}
202
203static GSM_Error N7110_GetSMSFolderStatus(GSM_StateMachine *s, int folderid)
204{
205 GSM_Error error;
206 int i;
207 GSM_NOKIASMSFolderfolder;
208
209 error = N7110_PrivGetSMSFolderStatus(s,folderid);
210 /* 0x08 contais read Inbox, 0xf8 unread Inbox.
211 * we want all msg from Inbox, so read both 0x08 and 0xf8 */
212 if (folderid==0x08 && error==ERR_NONE) {
213 folder=s->Phone.Data.Priv.N7110.LastSMSFolder;
214 error = N7110_PrivGetSMSFolderStatus(s,0xf8);
215 if (error==ERR_NONE) {
216 for (i=0;i<folder.Number;i++) {
217 s->Phone.Data.Priv.N7110.LastSMSFolder.Location[s->Phone.Data.Priv.N7110.LastSMSFolder.Number++]=folder.Location[i];
218 }
219 }
220 }
221 return error;
222}
223
224static GSM_SMSMessageLayout N7110_SMSTemplate = {
225 36 /* SMS Text */, 17 /* Phone number*/,
226 255 /* SMSC Number */, 15 /* TPDCS */,
227 255 /* SendingDateTime */, 255 /* SMSCDateTime*/,
228 255 /* TPStatus */, 16 /* TPUDL */,
229 255 /* TPVP */, 12 /* firstbyte*/,
230 13 /* TPMR */, 255 /* TPPID?? */};
231
232static GSM_Error N7110_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
233{
234 int i;
235 int Width, Height;
236 unsigned char output[500], output2[500];
237 GSM_Phone_Data *Data = &s->Phone.Data;
238
239 switch(msg.Buffer[3]) {
240 case 0x08:
241 switch (msg.Buffer[8]) {
242 case 0x00:
243 case 0x01:
244 smprintf(s, "SMS message\n");
245 if (Data->RequestID == ID_GetSMSMessage) {
246 Data->GetSMSMessage->Number=1;
247 NOKIA_DecodeSMSState(s, msg.Buffer[4], &Data->GetSMSMessage->SMS[0]);
248 DCT3_DecodeSMSFrame(s, &Data->GetSMSMessage->SMS[0],msg.Buffer+9);
249 return ERR_NONE;
250 }
251 case 0x02:
252 smprintf(s, "SMS template\n");
253 if (Data->RequestID == ID_GetSMSMessage) {
254 Data->GetSMSMessage->Number=1;
255 NOKIA_DecodeSMSState(s, msg.Buffer[4], &Data->GetSMSMessage->SMS[0]);
256 Data->GetSMSMessage->SMS[0].PDU=SMS_Submit;
257 GSM_DecodeSMSFrame(&Data->GetSMSMessage->SMS[0],msg.Buffer+9,N7110_SMSTemplate);
258 return ERR_NONE;
259 }
260 case 0x07:
261 smprintf(s, "Picture Image\n");
262 switch (Data->RequestID) {
263 case ID_GetBitmap:
264 PHONE_GetBitmapWidthHeight(GSM_NokiaPictureImage, &Width, &Height);
265 Data->Bitmap->BitmapWidth= Width;
266 Data->Bitmap->BitmapHeight= Height;
267 PHONE_DecodeBitmap(GSM_NokiaPictureImage, msg.Buffer + 51, Data->Bitmap);
268 GSM_UnpackSemiOctetNumber(Data->Bitmap->Sender,msg.Buffer+22,true);
269#ifdef DEBUG
270 GSM_UnpackSemiOctetNumber(output,msg.Buffer+9,true);
271 smprintf(s, "SMSC : %s\n",DecodeUnicodeString(output));
272#endif
273 Data->Bitmap->Text[0] = 0;
274 Data->Bitmap->Text[1] = 0;
275 if (msg.Length!=304) {
276 GSM_UnpackEightBitsToSeven(0, msg.Length-304, msg.Length-304, msg.Buffer+52+PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0),output);
277 DecodeDefault(Data->Bitmap->Text, output, msg.Length - 304, true, NULL);
278 }
279 return ERR_NONE;
280 case ID_GetSMSMessage:
281 Data->GetSMSMessage->Number = 0;
282 i = 0;
283 output[i++] = 0x30; /* Smart Messaging 3.0 */
284 output[i++] = SM30_OTA;
285 output[i++] = 0x01; /* Length */
286 output[i++] = 0x00; /* Length */
287 output[i++] = 0x00;
288 PHONE_GetBitmapWidthHeight(GSM_NokiaPictureImage, &Width, &Height);
289 output[i++] = Width;
290 output[i++] = Height;
291 output[i++] = 0x01;
292 memcpy(output+i,msg.Buffer+51,PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0));
293 i = i + PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0);
294 if (msg.Length!=304) {
295 output[i++] = SM30_UNICODETEXT;
296 output[i++] = 0;
297 output[i++] = 0; /* Length - later changed */
298 GSM_UnpackEightBitsToSeven(0, msg.Length-304, msg.Length-304, msg.Buffer+52+PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0),output2);
299 DecodeDefault(output+i, output2, msg.Length - 304, true, NULL);
300 output[i - 1] = UnicodeLength(output+i) * 2;
301 i = i + output[i-1];
302 }
303 GSM_MakeMultiPartSMS(Data->GetSMSMessage,output,i,UDH_NokiaProfileLong,SMS_Coding_8bit,1,0);
304 for (i=0;i<3;i++) {
305 Data->GetSMSMessage->SMS[i].Number[0]=0;
306 Data->GetSMSMessage->SMS[i].Number[1]=0;
307 }
308 return ERR_NONE;
309 default:
310 smprintf(s, "Unknown SMS type: %i\n",msg.Buffer[8]);
311 return ERR_UNKNOWNRESPONSE;
312 }
313 default:
314 smprintf(s, "Unknown SMS type: %i\n",msg.Buffer[8]);
315 }
316 break;
317 case 0x09:
318 switch (msg.Buffer[4]) {
319 case 0x02:
320 smprintf(s, "Too high location ?\n");
321 return ERR_INVALIDLOCATION;
322 case 0x07:
323 smprintf(s, "Empty\n");
324 return ERR_EMPTY;
325 default:
326 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
327 }
328 case 0x6F:
329 smprintf(s, "SMS message info received\n");
330 if (msg.Length == 43) {
331 Data->GetSMSMessage->SMS[0].Name[0] = 0;
332 Data->GetSMSMessage->SMS[0].Name[1] = 0;
333 } else {
334 CopyUnicodeString(Data->GetSMSMessage->SMS[0].Name,msg.Buffer+43);
335 }
336 smprintf(s, "Name: \"%s\"\n",DecodeUnicodeString(Data->GetSMSMessage->SMS[0].Name));
337 return ERR_NONE;
338 }
339 return ERR_UNKNOWNRESPONSE;
340}
341
342static GSM_Error N7110_PrivGetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
343{
344 GSM_Error error;
345 unsigned char folderid;
346 int location;
347 int i;
348 unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
349 0x08, /* folder ID */
350 0x00, 0x05, /* location */
351 0x01, 0x65, 0x01};
352 unsigned char NameReq[] = {N6110_FRAME_HEADER, 0x6E,
353 0x08, /* folder ID */
354 0x00, 0x05}; /* location */
355
356 N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
357
358 req[4]=folderid;
359 req[5]=location / 256;
360 req[6]=location;
361
362 s->Phone.Data.GetSMSMessage=sms;
363 smprintf(s, "Getting sms\n");
364 error=GSM_WaitFor (s, req, 10, 0x14, 4, ID_GetSMSMessage);
365 if (error==ERR_NONE) {
366 NameReq[4] = folderid;
367 NameReq[5] = location / 256;
368 NameReq[6] = location;
369 smprintf(s, "Getting sms info\n");
370 error=GSM_WaitFor (s, NameReq, 7, 0x14, 4, ID_GetSMSMessage);
371 if (error != ERR_NONE) return error;
372 for (i=0;i<sms->Number;i++) {
373 N7110_SetSMSLocation(s, &sms->SMS[i], folderid, location);
374 sms->SMS[i].Folder = folderid/0x08;
375 sms->SMS[i].InboxFolder = true;
376 if (folderid/0x08 != 0x01) sms->SMS[i].InboxFolder = false;
377 CopyUnicodeString(sms->SMS[i].Name,sms->SMS[0].Name);
378 sms->SMS[i].Memory = MEM_ME;
379 if (folderid/0x08 == 0x01 || folderid/0x08 == 0x02) {
380 sms->SMS[i].Memory = MEM_MT;
381 if (folderid/0x08 == 0x01) { /* Inbox */
382 if (sms->SMS[i].State == SMS_Sent) sms->SMS[i].Memory = MEM_ME;
383 if (sms->SMS[i].State == SMS_UnSent) sms->SMS[i].Memory = MEM_ME;
384 if (sms->SMS[i].State == SMS_Read) sms->SMS[i].Memory = MEM_SM;
385 if (sms->SMS[i].State == SMS_UnRead) sms->SMS[i].Memory = MEM_SM;
386 }
387 if (folderid/0x08 == 0x02) { /* Outbox */
388 if (sms->SMS[i].State == SMS_Sent) sms->SMS[i].Memory = MEM_SM;
389 if (sms->SMS[i].State == SMS_UnSent) sms->SMS[i].Memory = MEM_SM;
390 if (sms->SMS[i].State == SMS_Read) sms->SMS[i].Memory = MEM_ME;
391 if (sms->SMS[i].State == SMS_UnRead) sms->SMS[i].Memory = MEM_ME;
392 }
393 }
394 }
395 }
396 return error;
397}
398
399static GSM_Error N7110_GetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
400{
401 GSM_Error error;
402 unsigned char folderid;
403 int location;
404 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
405 int i;
406 bool found = false;
407
408 N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
409 error=N7110_GetSMSFolderStatus(s, folderid);
410 if (error!=ERR_NONE) return error;
411 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
412 if (Priv->LastSMSFolder.Location[i]==location) {
413 found = true;
414 break;
415 }
416 }
417 if (!found) return ERR_EMPTY;
418 return N7110_PrivGetSMSMessage(s,sms);
419}
420
421static GSM_Error N7110_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
422{
423 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
424 unsigned char folderid;
425 int location;
426 GSM_Error error;
427 int i;
428 bool findnextfolder = false;
429
430 if (start) {
431 folderid=0x00;
432 findnextfolder=true;
433 error=N7110_GetSMSFolders(s,&Priv->LastSMSFolders);
434 if (error!=ERR_NONE) return error;
435 } else {
436 N7110_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
437 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
438 if (Priv->LastSMSFolder.Location[i]==location) break;
439 }
440 /* Is this last location in this folder ? */
441 if (i==Priv->LastSMSFolder.Number-1) {
442 findnextfolder=true;
443 } else {
444 location=Priv->LastSMSFolder.Location[i+1];
445 }
446 }
447 if (findnextfolder) {
448 Priv->LastSMSFolder.Number=0;
449 while (Priv->LastSMSFolder.Number==0) {
450 folderid=folderid+0x08;
451 /* Too high folder number */
452 if ((folderid/0x08)>Priv->LastSMSFolders.Number) return ERR_EMPTY;
453 /* Get next folder status */
454 error=N7110_GetSMSFolderStatus(s, folderid);
455 if (error!=ERR_NONE) return error;
456 /* First location from this folder */
457 location=Priv->LastSMSFolder.Location[0];
458 }
459 }
460 N7110_SetSMSLocation(s, &sms->SMS[0], folderid, location);
461
462 return N7110_PrivGetSMSMessage(s, sms);
463}
464
465static int N7110_ReturnBinaryRingtoneLocation(char *model)
466{
467 if (strcmp(model,"NSE-5") == 0) return 0x72; /* first 0x72 - 7110 */
468 if (strcmp(model,"NPE-3") == 0) return 0x89; /* first 0x89 - 6210 */
469 if (strcmp(model,"NHM-3") == 0) return 0x89; /* quess for 6250 */
470 return 0;
471}
472
473static GSM_Error N7110_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
474{
475 int tmp,i;
476 GSM_Phone_Data *Data = &s->Phone.Data;
477
478 smprintf(s, "Ringtone received\n");
479 switch (msg.Buffer[3]) {
480 case 0x23:
481 tmp=0;i=4;
482 while (msg.Buffer[i]!=0 || msg.Buffer[i+1]!=0) {
483 tmp++;
484 i=i+2;
485 if (i>msg.Length) return ERR_EMPTY;
486 }
487 memcpy(Data->Ringtone->Name,msg.Buffer+6,tmp*2);
488 smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
489 /* Looking for end */
490 i=37;
491 while (true) {
492 if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
493 i=i+2; break;
494 }
495 if (msg.Buffer[i]==0x0e && msg.Buffer[i+1]==0x0b) {
496 i=i+2; break;
497 }
498 i++;
499 if (i==msg.Length) return ERR_EMPTY;
500 }
501 /* Copying frame */
502 memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+37,i-37);
503 Data->Ringtone->NokiaBinary.Length=i-37;
504 return ERR_NONE;
505 case 0x24:
506 smprintf(s, "Invalid location. Too high ?\n");
507 return ERR_INVALIDLOCATION;
508 }
509 return ERR_UNKNOWNRESPONSE;
510}
511
512static GSM_Error N7110_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
513{
514 unsigned char req[] = {N7110_FRAME_HEADER, 0x22, 0x00, 0x00};
515
516 if (PhoneRingtone) return ERR_NOTSUPPORTED;
517 if (Ringtone->Format == 0x00) Ringtone->Format = RING_NOKIABINARY;
518
519 switch (Ringtone->Format) {
520 case RING_NOTETONE:
521 /* In the future get binary and convert */
522 return ERR_NOTSUPPORTED;
523 case RING_NOKIABINARY:
524 req[5]=N7110_ReturnBinaryRingtoneLocation(s->Phone.Data.Model)+Ringtone->Location;
525 s->Phone.Data.Ringtone=Ringtone;
526 smprintf(s, "Getting binary ringtone\n");
527 return GSM_WaitFor (s, req, 6, 0x1f, 4, ID_GetRingtone);
528 case RING_MIDI:
529 return ERR_NOTSUPPORTED;
530 }
531 return ERR_NOTSUPPORTED;
532}
533
534static GSM_Error N7110_ReplyGetPictureImageInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
535{
536 int i;
537 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
538
539 smprintf(s, "Received info for Picture Images\n");
540 smprintf(s, "Number : %i\n",msg.Buffer[4]*256+msg.Buffer[5]);
541 smprintf(s, "Locations :");
542 Priv->LastPictureImageFolder.Number=msg.Buffer[4]*256+msg.Buffer[5];
543 for (i=0;i<Priv->LastPictureImageFolder.Number;i++) {
544 Priv->LastPictureImageFolder.Location[i]=msg.Buffer[6+i*2]*256+msg.Buffer[7+i*2];
545 smprintf(s, " %i",Priv->LastPictureImageFolder.Location[i]);
546 }
547 smprintf(s, "\n");
548 return ERR_NONE;
549}
550
551static GSM_Error N7110_GetPictureImageLocation(GSM_StateMachine *s, GSM_Bitmap *Bitmap, unsigned char *folder, int *location)
552{
553 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
554 GSM_SMSFolders folders;
555 GSM_Error error;
556 int i, j = 0, count = 0;
557 unsigned char req[] = {N6110_FRAME_HEADER, 0x96,
558 0x00, /* Folder ID */
559 0x0f, 0x07};
560
561 error=N7110_GetSMSFolders (s, &folders);
562 if (error!=ERR_NONE) return error;
563
564 for (i=0;i<folders.Number;i++) {
565 req[4] = (i+1) * 0x08;/* SMS folder ID */
566 error = GSM_WaitFor (s, req, 7, 0x14, 4, ID_GetBitmap);
567 if (error!=ERR_NONE) return error;
568 for (j=0;j<Priv->LastPictureImageFolder.Number;j++) {
569 count++;
570 if (count==Bitmap->Location) break;
571 }
572 if (count==Bitmap->Location) break;
573 }
574 if (count!=Bitmap->Location) return ERR_INVALIDLOCATION;
575 *folder = (i+1) * 0x08;/* SMS Folder ID */
576 *location= Priv->LastPictureImageFolder.Location[j];
577 return ERR_NONE;
578}
579
580static GSM_Error N7110_GetPictureImage(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
581{
582 unsigned char folder;
583 int location;
584 GSM_Error error;
585 unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
586 0x00, /* Folder ID */
587 0x00, 0x00, /* Location */
588 0x00, 0x64};
589
590 error = N7110_GetPictureImageLocation(s, Bitmap, &folder, &location);
591 switch (error) {
592 case ERR_NONE:
593 req[4] = folder;
594 req[5] = location / 256;
595 req[6] = location % 256;
596 return GSM_WaitFor (s, req, 9, 0x14, 4, ID_GetBitmap);
597 default:
598 return error;
599 }
600}
601
602static GSM_Error N7110_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
603{
604 GSM_MemoryEntry pbk;
605 GSM_Error error;
606 unsigned char OpReq[] = {N6110_FRAME_HEADER, 0x70};
607
608 s->Phone.Data.Bitmap=Bitmap;
609 switch (Bitmap->Type) {
610 case GSM_StartupLogo:
611 smprintf(s, "Getting startup logo\n");
612 return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x15);
613 case GSM_WelcomeNote_Text:
614 smprintf(s, "Getting welcome note\n");
615 return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x02);
616 case GSM_DealerNote_Text:
617 smprintf(s, "Getting dealer note\n");
618 return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x17);
619 case GSM_CallerGroupLogo:
620 pbk.MemoryType = MEM7110_CG;
621 pbk.Location = Bitmap->Location;
622 smprintf(s, "Getting caller group logo\n");
623 error=N7110_GetMemory(s,&pbk);
624 if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s,Bitmap);
625 return error;
626 case GSM_OperatorLogo:
627 smprintf(s, "Getting operator logo\n");
628 /* This is like DCT3_GetNetworkInfo */
629 return GSM_WaitFor (s, OpReq, 4, 0x0a, 4, ID_GetBitmap);
630 case GSM_PictureImage:
631 /* 7110 doesn't support it */
632 if (strcmp(s->Phone.Data.Model,"NSE-5") == 0) return ERR_NOTSUPPORTED;
633 return N7110_GetPictureImage(s, Bitmap);
634 default:
635 break;
636 }
637 return ERR_NOTSUPPORTED;
638}
639
640static GSM_Error N7110_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
641{
642 GSM_Ringtonedest;
643 GSM_Errorerror;
644 GSM_NetworkInfoNetInfo;
645 int size=200;
646 unsigned charreq[1000] = {0x7C, 0x01, 0x00, 0x0D, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00}; /*Length*/
649 unsigned charreq2[4000] = {N7110_FRAME_HEADER, 0x1F, 0x00,
650 0x87, /* Location */
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
656
657 switch (Ringtone->Format) {
658 case RING_NOTETONE:
659 if (Ringtone->Location==255) {
660 /* 7110 doesn't support it */
661 if (strcmp(s->Phone.Data.Model,"NSE-5") == 0) return ERR_NOTSUPPORTED;
662 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+11, &size);
663 req[10] = size;
664 error = s->Protocol.Functions->WriteMessage(s, req, size+11, 0x00);
665 if (error!=ERR_NONE) return error;
666 my_sleep(1000);
667 /* We have to make something (not important, what) now */
668 /* no answer from phone*/
669 return DCT3_GetNetworkInfo(s,&NetInfo);
670 }
671 GSM_RingtoneConvert(&dest, Ringtone, RING_NOKIABINARY);
672 break;
673 case RING_NOKIABINARY:
674 memcpy(&dest,Ringtone,sizeof(GSM_Ringtone));
675 break;
676 default:
677 return ERR_NOTSUPPORTED;
678 }
679 req2[5]=N7110_ReturnBinaryRingtoneLocation(s->Phone.Data.Model)+Ringtone->Location;
680 CopyUnicodeString(req2+6,Ringtone->Name);
681 memcpy(req2+37,dest.NokiaBinary.Frame,dest.NokiaBinary.Length);
682 error = s->Protocol.Functions->WriteMessage(s, req2, 37+dest.NokiaBinary.Length, 0x1F);
683 if (error!=ERR_NONE) return error;
684 my_sleep(1000);
685 /* We have to make something (not important, what) now */
686 /* no answer from phone*/
687 return DCT3_GetNetworkInfo(s,&NetInfo);
688}
689
690static GSM_Error N7110_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
691{
692 GSM_Phone_Data *Data = &s->Phone.Data;
693
694 switch (msg.Buffer[3]) {
695 case 0x05:
696 smprintf(s, "SMS message saving status\n");
697 smprintf(s, "Saved in folder %i at location %i\n",msg.Buffer[4], msg.Buffer[5]*256+msg.Buffer[6]);
698 if (msg.Buffer[4] == 0xf8) {
699 N7110_SetSMSLocation(s, Data->SaveSMSMessage,0x08,msg.Buffer[5]*256+msg.Buffer[6]);
700 Data->SaveSMSMessage->Folder = 0x01;
701 } else {
702 N7110_SetSMSLocation(s, Data->SaveSMSMessage,msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
703 Data->SaveSMSMessage->Folder = msg.Buffer[4] / 0x08;
704 }
705 return ERR_NONE;
706 case 0x06:
707 smprintf(s, "SMS message saving status\n");
708 switch (msg.Buffer[4]) {
709 case 0x03:
710 smprintf(s, "Too high location ?\n");
711 return ERR_INVALIDLOCATION;
712 default:
713 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
714 }
715 break;
716 case 0x84:
717 smprintf(s, "Name for SMS changed OK to \"%s\"\n",DecodeUnicodeString(msg.Buffer+7));
718 smprintf(s, "Saved in folder %i at location %i\n",msg.Buffer[4], msg.Buffer[5]*256+msg.Buffer[6]);
719 if (msg.Buffer[4] == 0xf8) {
720 N7110_SetSMSLocation(s, Data->SaveSMSMessage,0x08,msg.Buffer[5]*256+msg.Buffer[6]);
721 Data->SaveSMSMessage->Folder = 0x01;
722 } else {
723 N7110_SetSMSLocation(s, Data->SaveSMSMessage,msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
724 Data->SaveSMSMessage->Folder = msg.Buffer[4] / 0x08;
725 }
726 return ERR_NONE;
727 }
728 return ERR_UNKNOWNRESPONSE;
729}
730
731static GSM_Error N7110_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
732{
733 int length, location;
734 unsigned char folderid, folder;
735 GSM_Error error;
736 unsigned char req[256] = {N6110_FRAME_HEADER, 0x04,
737 0x03, /* sms status */
738 0x10, /* folder */
739 0x00,0x00, /* location */
740 0x00};
741 unsigned char NameReq[200] = {N6110_FRAME_HEADER, 0x83};
742
743 switch (sms->State) {
744 case SMS_Read: req[4] = 0x01; break;
745 case SMS_UnRead: req[4] = 0x03; break;
746 case SMS_Sent: req[4] = 0x05; break;
747 case SMS_UnSent: req[4] = 0x07; break;
748 }
749
750 N7110_GetSMSLocation(s, sms, &folderid, &location);
751 req[5] = folderid;
752 req[6] = location / 256;
753 req[7] = location;
754
755 /* Outbox */
756 if (folderid == 0x10 && (sms->State == SMS_Sent || sms->State == SMS_UnSent)) {
757 /* We will use SIM Outbox */
758 sms->PDU = SMS_Submit;
759 }
760 /* Inbox */
761 if (folderid == 0x08 && sms->State == SMS_UnRead) {
762 /* We will use SIM Inbox */
763 req[5] = 0xf8;
764 }
765
766 switch (sms->PDU) {
767 case SMS_Deliver:
768 error = PHONE_EncodeSMSFrame(s,sms,req+9,PHONE_SMSDeliver,&length,true);
769 break;
770 case SMS_Submit:
771 smprintf(s, "Saving SMS template\n");
772 error = PHONE_EncodeSMSFrame(s,sms,req+9,N7110_SMSTemplate,&length,true);
773 req[8] = 0x02;/* SMS Template info */
774 break;
775 default:
776 return ERR_UNKNOWN;
777 }
778 if (error != ERR_NONE) return error;
779
780 s->Phone.Data.SaveSMSMessage=sms;
781 smprintf(s, "Saving sms\n");
782 error=GSM_WaitFor (s, req, 9+length, 0x14, 4, ID_SaveSMSMessage);
783 if (error == ERR_NONE && UnicodeLength(sms->Name)!=0) {
784 folder = sms->Folder;
785 sms->Folder = 0;
786 N7110_GetSMSLocation(s, sms, &folderid, &location);
787 length = 4;
788 NameReq[length++] = folderid;
789 NameReq[length++] = location / 256;
790 NameReq[length++] = location;
791 CopyUnicodeString(NameReq+length, sms->Name);
792 length = length+UnicodeLength(sms->Name)*2;
793 NameReq[length++] = 0;
794 NameReq[length++] = 0;
795 error=GSM_WaitFor (s, NameReq, length, 0x14, 4, ID_SaveSMSMessage);
796 sms->Folder = folder;
797 }
798 return error;
799}
800
801static GSM_Error N7110_SetSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
802{
803 int location;
804 unsigned char folderid;
805
806 N7110_GetSMSLocation(s, sms, &folderid, &location);
807 if (location == 0) return ERR_INVALIDLOCATION;
808 return N7110_PrivSetSMSMessage(s, sms);
809}
810
811static GSM_Error N7110_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
812{
813 int location;
814 unsigned char folderid;
815
816 N7110_GetSMSLocation(s, sms, &folderid, &location);
817 location = 0;
818 N7110_SetSMSLocation(s, sms, folderid, location);
819 return N7110_PrivSetSMSMessage(s, sms);
820}
821
822static GSM_Error N7110_ReplyClearOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
823{
824 smprintf(s, "Clearing operator logo.....\n");
825 return ERR_NONE;
826}
827
828static GSM_Error N7110_ReplySetOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
829{
830 smprintf(s, "Setting operator logo.....\n");
831 return ERR_NONE;
832}
833
834static GSM_Error N7110_SetCallerLogo(GSM_StateMachine *s, GSM_Bitmap *bitmap)
835{
836 int block=0, i, Width, Height;
837 unsigned int count = 18;
838 char string[500];
839 unsigned char req[500] = {N6110_FRAME_HEADER, 0x0b, 0x00,
840 0x01, 0x01, 0x00, 0x00, 0x0c,
841 0x00, 0x10, /* memory type */
842 0x00, 0x00, /* location */
843 0x00, 0x00, 0x00};
844
845 req[13] = bitmap->Location;
846
847 /* Enabling/disabling logo */
848 if (bitmap->DefaultBitmap) {
849 string[0] = 0; //disabling
850 } else {
851 string[0] = bitmap->BitmapEnabled?1:0;
852 }
853 string[1] = 0;
854 count += N71_65_PackPBKBlock(s, N7110_PBK_LOGOON, 2, block++, string, req + count);
855
856 /* Ringtone */
857 if (!bitmap->DefaultRingtone) {
858 string[0] = bitmap->RingtoneID;
859 string[1] = 0;
860 count += N71_65_PackPBKBlock(s, N7110_PBK_RINGTONE_ID, 2, block++, string, req + count);
861 }
862
863 /* Number of group */
864 string[0] = bitmap->Location;
865 string[1] = 0;
866 count += N71_65_PackPBKBlock(s, N7110_PBK_GROUP, 2, block++, string, req + count);
867
868 /* Name */
869 if (!bitmap->DefaultName) {
870 i = UnicodeLength(bitmap->Text) * 2;
871 string[0] = i + 2;
872 memcpy(string + 1, bitmap->Text, i);
873 string[i + 1] = 0;
874 count += N71_65_PackPBKBlock(s, N7110_PBK_NAME, i + 2, block++, string, req + count);
875 }
876
877 /* Logo */
878 if (bitmap->DefaultBitmap) {
879 bitmap->BitmapWidth = 72;
880 bitmap->BitmapHeight = 14;
881 GSM_ClearBitmap(bitmap);
882 }
883 PHONE_GetBitmapWidthHeight(GSM_NokiaCallerLogo, &Width, &Height);
884 string[0] = Width;
885 string[1] = Height;
886 string[2] = 0;
887 string[3] = 0;
888 string[4] = PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0);
889 PHONE_EncodeBitmap(GSM_NokiaCallerLogo, string + 5, bitmap);
890 count += N71_65_PackPBKBlock(s, N7110_PBK_GROUPLOGO, PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 5, block++, string, req + count);
891
892 req[17] = block;
893
894 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetBitmap);
895}
896
897static GSM_Error N7110_ReplySetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
898{
899 smprintf(s, "Picture Image written OK, folder %i, location %i\n",msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
900 return ERR_NONE;
901}
902
903static GSM_Error N7110_SetPictureImage(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
904{
905 unsigned char folder;
906 GSM_Error error;
907 int location, i, count, Width, Height;
908 GSM_Phone_Bitmap_TypesType = GSM_NokiaPictureImage;
909 unsigned char req[500] = {N6110_FRAME_HEADER, 0x50, 0x07,
910 0x00, /* location*/
911 0x00, 0x00, /* index*/
912 0x07};
913
914 error=N7110_GetPictureImageLocation(s, Bitmap, &folder, &location);
915 switch (error) {
916 case ERR_NONE:
917 req[5] = folder;
918 req[6] = location / 256;
919 req[7] = location % 256;
920 break;
921 case ERR_INVALIDLOCATION:
922 req[5] = 0x21;/* Save in Templates folder */
923 req[6] = 0;
924 req[7] = 0;
925 break;
926 default:
927 return error;
928 }
929
930 /* Cleaning */
931 for (i=0;i<36;i++) req[i+9]=0;
932
933 count=8;
934 if (UnicodeLength(Bitmap->Text)==0) {
935 count+=2 ;req[count]=0x0c;
936 count+=2 ;req[count]=0x0d;
937 count+=2 ;req[count]=0x0e;
938 count+=2 ;req[count]=0x0f;
939 count+=2 ;req[count]=0x10;
940 count+=2 ;req[count]=0x11;
941 count+=23;req[count]=0x02;
942 count++ ;
943 } else {
944 count+=2 ;req[count]=0x54;
945 count++ ;req[count]=0xd4;
946 count++ ;req[count]=0x0d;
947 count+=2 ;req[count]=0x0e;
948 count+=2 ;req[count]=0x0f;
949 count+=2 ;req[count]=0x10;
950 count+=2 ;req[count]=0x11;
951 count+=21;req[count]=0x01;
952 count+=3 ;
953 }
954 req[count] = 0x01;
955 count+=2;
956 req[count++] = 0x01;
957 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
958 req[count++] = Width;
959 req[count++] = Height;
960 req[count++] = PHONE_GetBitmapSize(Type,0,0) / 256;
961 req[count++] = PHONE_GetBitmapSize(Type,0,0) % 256;
962 PHONE_EncodeBitmap(Type, req + count, Bitmap);
963 count += PHONE_GetBitmapSize(Type,0,0);
964 if (UnicodeLength(Bitmap->Text)!=0) {
965 req[count] = UnicodeLength(Bitmap->Text);
966 GSM_PackSevenBitsToEight(0, Bitmap->Text, req+count+1,strlen(Bitmap->Text));
967 count = count + req[count];
968 } else {
969 req[count++]=0x00;
970 }
971 req[count++]=0x00;
972 smprintf(s, "Setting Picture Image\n");
973 return GSM_WaitFor (s, req, count, 0x14, 4, ID_SetBitmap);
974}
975
976static GSM_Error N7110_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
977{
978 GSM_Error error;
979 GSM_Phone_Bitmap_TypesType;
980 int Width, Height, i;
981 unsigned char reqStartup[1000] = {N7110_FRAME_HEADER, 0xec,
982 0x15, /* Startup Logo setting */
983 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
984 0x00, /* Bitmap height */
985 0xc0, 0x03, 0x00,
986 0x00, /* Bitmap width */
987 0xc0, 0x04, 0x03, 0x00};
988 unsigned char reqOp[1000] = {N7110_FRAME_HEADER, 0xa3, 0x01,
989 0x00, /* logo disabled */
990 0x00, 0xf0, 0x00,/* network code (000 00) */
991 0x00 ,0x04,
992 0x08, /* length of rest */
993 0x00, 0x00, /* Bitmap width / height */
994 0x00,
995 0x00, /* Bitmap size */
996 0x00, 0x00};
997 unsigned char reqClrOp[] = {0x00, 0x01, 0x00, 0xaf, 0x00};
998 unsigned char reqStartupText[500] = {N7110_FRAME_HEADER, 0xec,
999 0x02}; /* Startup Text setting */
1000
1001 switch (Bitmap->Type) {
1002 case GSM_StartupLogo:
1003 if (Bitmap->Location!=1) return ERR_NOTSUPPORTED;
1004 Type=GSM_Nokia6210StartupLogo;
1005 if (strcmp(s->Phone.Data.Model,"NSE-5") == 0) Type=GSM_Nokia7110StartupLogo;
1006 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
1007 reqStartup[12] = Height;
1008 reqStartup[16] = Width;
1009 PHONE_EncodeBitmap(Type, reqStartup + 21, Bitmap);
1010 smprintf(s, "Setting startup logo\n");
1011 return GSM_WaitFor (s, reqStartup, 21+PHONE_GetBitmapSize(Type,0,0), 0x7A, 4, ID_SetBitmap);
1012 case GSM_WelcomeNote_Text:
1013 CopyUnicodeString(reqStartupText + 5, Bitmap->Text);
1014 i = 6 + UnicodeLength(Bitmap->Text) * 2;
1015 reqStartupText[i++] = 0;
1016 reqStartupText[i++] = 0;
1017 return GSM_WaitFor (s, reqStartupText, i, 0x7A, 4, ID_SetBitmap);
1018 case GSM_DealerNote_Text:
1019 reqStartupText[4] = 0x17;
1020 CopyUnicodeString(reqStartupText + 5, Bitmap->Text);
1021 i = 6 + UnicodeLength(Bitmap->Text) * 2;
1022 reqStartupText[i++] = 0;
1023 reqStartupText[i++] = 0;
1024 return GSM_WaitFor (s, reqStartupText, i, 0x7A, 4, ID_SetBitmap);
1025 case GSM_OperatorLogo:
1026 /* We want to set operator logo, not clear */
1027 if (strcmp(Bitmap->NetworkCode,"000 00")) {
1028 reqOp[5] = 0x01;/* Logo enabled */
1029 NOKIA_EncodeNetworkCode(reqOp+6, Bitmap->NetworkCode);
1030 Type = GSM_Nokia7110OperatorLogo;
1031 reqOp[11] = 8 + PHONE_GetBitmapSize(Type,0,0);
1032 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
1033 reqOp[12]=Width;
1034 reqOp[13]=Height;
1035 reqOp[15]=PHONE_GetBitmapSize(Type,0,0);
1036 PHONE_EncodeBitmap(Type, reqOp + 18, Bitmap);
1037 smprintf(s, "Setting operator logo\n");
1038 return GSM_WaitFor (s, reqOp, 18+PHONE_GetBitmapSize(Type,0,0), 0x0A, 4, ID_SetBitmap);
1039 } else {
1040 smprintf(s, "Clearing operator logo\n");
1041 for (i=0;i<5;i++) {
1042 reqClrOp[4]=i;
1043 error=GSM_WaitFor (s, reqClrOp, 5, 0x0A, 4, ID_SetBitmap);
1044 if (error!=ERR_NONE) return error;
1045 }
1046 return GSM_WaitFor (s, reqOp, 18, 0x0A, 4, ID_SetBitmap);
1047 }
1048 case GSM_CallerGroupLogo:
1049 return N7110_SetCallerLogo(s,Bitmap);
1050 case GSM_PictureImage:
1051 return N7110_SetPictureImage(s,Bitmap);
1052 default:
1053 break;
1054 }
1055 return ERR_NOTSUPPORTED;
1056}
1057
1058static GSM_Error N7110_ReplyDeleteMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
1059{
1060 smprintf(s, "Phonebook entry deleted\n");
1061 return ERR_NONE;
1062}
1063
1064static GSM_Error N7110_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1065{
1066 unsigned char req[] = {N7110_FRAME_HEADER, 0x0f, 0x00, 0x01,
1067 0x04, 0x00, 0x00, 0x0c, 0x01, 0xff,
1068 0x00, 0x01, /* location*/
1069 0x05, /* memory type*/
1070 0x00, 0x00, 0x00};
1071
1072 req[12] = entry->Location / 256;
1073 req[13] = entry->Location % 256;
1074
1075 req[14] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
1076 if (req[14]==0xff) return ERR_NOTSUPPORTED;
1077
1078 smprintf(s, "Deleting phonebook entry\n");
1079 return GSM_WaitFor (s, req, 18, 0x03, 4, ID_SetMemory);
1080}
1081
1082static GSM_Error N7110_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1083{
1084 int count = 18, blocks;
1085 unsigned char req[500] = {N7110_FRAME_HEADER, 0x0b, 0x00,
1086 0x01, 0x01, 0x00, 0x00, 0x0c,
1087 0x00, 0x00, /* memory type*/
1088 0x00, 0x00, /* location*/
1089 0x00, 0x00, 0x00};
1090
1091 if (entry->Location == 0) return ERR_NOTSUPPORTED;
1092
1093 req[11] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
1094 if (req[11]==0xff) return ERR_NOTSUPPORTED;
1095
1096 req[12] = entry->Location >> 8;
1097 req[13] = entry->Location & 0xff;
1098
1099 count = count + N71_65_EncodePhonebookFrame(s, req+18, *entry, &blocks, false, IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_VOICETAGS));
1100 req[17] = blocks;
1101
1102 smprintf(s, "Writing phonebook entry\n");
1103 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetMemory);
1104}
1105
1106static GSM_Error N7110_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
1107{
1108 unsigned char folderid;
1109 int location;
1110 unsigned char req[] = {N7110_FRAME_HEADER, 0x0a,
1111 0x00, /* folder */
1112 0x00, 0x00, /* location */
1113 0x01};
1114
1115 N7110_GetSMSLocation(s, sms, &folderid, &location);
1116 req[4] = folderid;
1117 req[5] = location / 256;
1118 req[6] = location;
1119
1120 smprintf(s, "Deleting sms\n");
1121 return GSM_WaitFor (s, req, 8, 0x14, 4, ID_DeleteSMSMessage);
1122}
1123
1124static GSM_Error N7110_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1125{
1126 GSM_Phone_Data *Data = &s->Phone.Data;
1127
1128 smprintf(s, "SMS status received\n");
1129 switch (msg.Buffer[3]) {
1130 case 0x37:
1131 smprintf(s, "SIM size : %i\n",msg.Buffer[8]*256+msg.Buffer[9]);
1132 smprintf(s, "Used in phone memory : %i\n",msg.Buffer[10]*256+msg.Buffer[11]);
1133 smprintf(s, "Unread in phone memory : %i\n",msg.Buffer[12]*256+msg.Buffer[13]);
1134 smprintf(s, "Used in SIM : %i\n",msg.Buffer[14]*256+msg.Buffer[15]);
1135 smprintf(s, "Unread in SIM : %i\n",msg.Buffer[16]*256+msg.Buffer[17]);
1136 Data->SMSStatus->SIMSize= msg.Buffer[8]*256+msg.Buffer[9];
1137 Data->SMSStatus->PhoneUsed= msg.Buffer[10]*256+msg.Buffer[11];
1138 Data->SMSStatus->PhoneUnRead = msg.Buffer[12]*256+msg.Buffer[13];
1139 Data->SMSStatus->PhoneSize= 150;
1140 Data->SMSStatus->SIMUsed = msg.Buffer[14]*256+msg.Buffer[15];
1141 Data->SMSStatus->SIMUnRead = msg.Buffer[16]*256+msg.Buffer[17];
1142 return ERR_NONE;
1143 case 0x38:
1144 smprintf(s, "Error. No PIN ?\n");
1145 return ERR_SECURITYERROR;
1146 }
1147 return ERR_UNKNOWNRESPONSE;
1148}
1149
1150static GSM_Error N7110_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
1151{
1152 GSM_Error error;
1153 GSM_Phone_N7110Data*Priv = &s->Phone.Data.Priv.N7110;
1154
1155 error = DCT3_GetSMSStatus(s,status);
1156 if (error != ERR_NONE) return error;
1157
1158 /* 6210 family doesn't show in frame with SMS status info
1159 * about Templates. We get separately info about this SMS folder.
1160 */
1161 error = N7110_GetSMSFolderStatus(s, 0x20);
1162 if (error != ERR_NONE) return error;
1163 status->TemplatesUsed = Priv->LastSMSFolder.Number;
1164
1165 return ERR_NONE;
1166}
1167
1168static GSM_Error N7110_ReplyGetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1169{
1170 GSM_Phone_Data *Data = &s->Phone.Data;
1171
1172 switch (msg.Buffer[3]) {
1173 case 0x02:
1174 smprintf(s, "Profile feature %02x with value %02x\n",msg.Buffer[6],msg.Buffer[10]);
1175 switch (msg.Buffer[6]) {
1176 case 0x03:
1177 smprintf(s, "Ringtone ID\n");
1178 Data->Profile->FeatureID[Data->Profile->FeaturesNumber] = Profile_RingtoneID;
1179 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = msg.Buffer[10];
1180 Data->Profile->FeaturesNumber++;
1181 break;
1182 case 0x08:/* Caller groups */
1183 NOKIA_FindFeatureValue(s, Profile71_65,msg.Buffer[6],msg.Buffer[10],Data,true);
1184 break;
1185 case 0x09:/* Autoanswer */
1186 if (Data->Profile->CarKitProfile || Data->Profile->HeadSetProfile) {
1187 NOKIA_FindFeatureValue(s, Profile71_65,msg.Buffer[6],msg.Buffer[10],Data,false);
1188 }
1189 break;
1190 case 0xff :
1191 CopyUnicodeString(Data->Profile->Name, msg.Buffer+10);
1192 smprintf(s, "profile Name: \"%s\"\n", DecodeUnicodeString(Data->Profile->Name));
1193 Data->Profile->DefaultName = false;
1194 break;
1195 default:
1196 NOKIA_FindFeatureValue(s, Profile71_65,msg.Buffer[6],msg.Buffer[10],Data,false);
1197 }
1198 return ERR_NONE;
1199 }
1200 return ERR_UNKNOWNRESPONSE;
1201}
1202
1203static GSM_Error N7110_GetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1204{
1205 GSM_Error error;
1206 int i;
1207 unsigned char Features[12] = {0x00,0x02,0x03,0x04,0x05,0x06,
1208 0x07,0x08,0x09,0xff,
1209 0x0a,0x22};
1210 unsigned char req[] = {N6110_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01,
1211 0x00, /* Profile Location*/
1212 0xff}; /* Feature number*/
1213
1214 if (Profile->Location > 7) return ERR_INVALIDLOCATION;
1215
1216 Profile->CarKitProfile = false;
1217 Profile->HeadSetProfile = false;
1218 if (Profile->Location == 6) Profile->CarKitProfile = true;
1219 if (Profile->Location == 7) Profile->HeadSetProfile = true;
1220
1221 Profile->FeaturesNumber = 0;
1222
1223 s->Phone.Data.Profile=Profile;
1224 for (i = 0; i < 10; i++) {
1225 req[7] = Profile->Location;
1226 req[8] = Features[i];
1227 smprintf(s, "Getting profile feature\n");
1228 error = GSM_WaitFor (s, req, 9, 0x39, 4, ID_GetProfile);
1229 if (error!=ERR_NONE) return error;
1230 }
1231 NOKIA_GetDefaultProfileName(s, Profile);
1232 Profile->Active = false;
1233 return error;
1234}
1235
1236static GSM_Error N7110_ReplySetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1237{
1238 smprintf(s, "Profile feature set\n");
1239 return ERR_NONE;
1240}
1241
1242static GSM_Error N7110_SetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1243{
1244 int i;
1245 bool found;
1246 GSM_Errorerror;
1247 unsigned charID,Value;
1248 unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x01, 0x01, 0x03,
1249 0x02, /* feature number*/
1250 0x01, /* Profile Location */
1251 0x01,
1252 0xff}; /* Value */
1253
1254 for (i=0;i<Profile->FeaturesNumber;i++) {
1255 found = false;
1256 switch (Profile->FeatureID[i]) {
1257 case Profile_RingtoneID:
1258 ID = 0x03;
1259 Value = Profile->FeatureValue[i];
1260 found = true;
1261 break;
1262 default:
1263 found=NOKIA_FindPhoneFeatureValue(
1264 s,
1265 Profile71_65,
1266 Profile->FeatureID[i],Profile->FeatureValue[i],
1267 &ID,&Value);
1268 }
1269 if (found) {
1270 req[7] = ID;
1271 req[8] = Profile->Location;
1272 req[10] = Value;
1273 smprintf(s, "Setting profile feature\n");
1274 error = GSM_WaitFor (s, req, 11, 0x39, 4, ID_SetProfile);
1275 if (error!=ERR_NONE) return error;
1276 }
1277 }
1278 return ERR_NONE;
1279}
1280
1281static GSM_Error N7110_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
1282{
1283 GSM_MemoryEntry pbk;
1284 GSM_Error error;
1285
1286 pbk.MemoryType = MEM7110_SP;
1287 pbk.Location = SpeedDial->Location;
1288 SpeedDial->MemoryLocation = 0;
1289 s->Phone.Data.SpeedDial = SpeedDial;
1290
1291 smprintf(s, "Getting speed dial\n");
1292 error=N7110_GetMemory(s,&pbk);
1293 switch (error) {
1294 case ERR_NOTSUPPORTED:
1295 smprintf(s, "No speed dials set in phone\n");
1296 return ERR_EMPTY;
1297 case ERR_NONE:
1298 if (SpeedDial->MemoryLocation == 0) {
1299 smprintf(s, "Speed dial not assigned or error in firmware\n");
1300 return ERR_EMPTY;
1301 }
1302 return ERR_NONE;
1303 default:
1304 return error;
1305 }
1306}
1307
1308static GSM_Error N7110_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
1309{
1310 GSM_SMSMessage sms;
1311 GSM_Phone_Data *Data = &s->Phone.Data;
1312
1313#ifdef DEBUG
1314 smprintf(s, "SMS message received\n");
1315 sms.State = SMS_UnRead;
1316 sms.InboxFolder = true;
1317 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+8);
1318#endif
1319 if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
1320 sms.State = SMS_UnRead;
1321 sms.InboxFolder = true;
1322 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+8);
1323
1324 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
1325 }
1326 return ERR_NONE;
1327}
1328
1329static GSM_Error N7110_Initialise (GSM_StateMachine *s)
1330{
1331#ifdef DEBUG
1332 DCT3_SetIncomingCB(s,true);
1333#endif
1334#ifdef GSM_ENABLE_N71_92INCOMINGINFO
1335 /* Enables various things like incoming SMS, call info, etc. */
1336 return N71_65_EnableFunctions (s, "\x01\x02\x06\x0A\x14\x17", 6);
1337#endif
1338 return ERR_NONE;
1339}
1340
1341static GSM_Error N7110_ReplyGetCalendarInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1342{
1343 /* Old method 1 for accessing calendar */
1344 return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N7110.LastCalendar);
1345}
1346
1347#ifdef DEBUG
1348static GSM_Error N7110_ReplyGetCalendarNotePos(GSM_Protocol_Message msg, GSM_StateMachine *s)
1349{
1350 /* Old method 1 for accessing calendar */
1351 return N71_65_ReplyGetCalendarNotePos1(msg, s, &s->Phone.Data.Priv.N7110.FirstCalendarPos);
1352}
1353#endif
1354
1355static GSM_Error N7110_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
1356{
1357 return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N7110.LastCalendar,&s->Phone.Data.Priv.N7110.LastCalendarYear,&s->Phone.Data.Priv.N7110.LastCalendarPos);
1358 //return N71_65_GetNextCalendar2(s,Note,start,&s->Phone.Data.Priv.N7110.LastCalendarYear,&s->Phone.Data.Priv.N7110.LastCalendarPos);
1359}
1360
1361static GSM_Error N7110_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
1362{
1363 GSM_Error error;
1364
1365 /* Method 1 */
1366 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N7110.LastCalendar);
1367 if (error!=ERR_NONE) return error;
1368 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
1369 return ERR_NONE;
1370
1371 /* Method 2 */
1372 // return GE_NOTSUPPORTED;
1373}
1374
1375static GSM_Error N7110_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
1376{
1377 //return N71_65_AddCalendar1(s, Note, NULL);
1378 return N71_65_AddCalendar2(s,Note);
1379}
1380
1381static GSM_Error N7110_ReplyGetNetworkInfoError(GSM_Protocol_Message msg, GSM_StateMachine *s)
1382{
1383 smprintf(s, "Probably means no PIN\n");
1384 return ERR_SECURITYERROR;
1385}
1386
1387static GSM_Error N7110_SetIncomingCall(GSM_StateMachine *s, bool enable)
1388{
1389#ifndef GSM_ENABLE_N71_92INCOMINGINFO
1390 return ERR_SOURCENOTAVAILABLE;
1391#endif
1392 return NOKIA_SetIncomingCall(s,enable);
1393}
1394
1395static GSM_Error N7110_SetIncomingUSSD(GSM_StateMachine *s, bool enable)
1396{
1397#ifndef GSM_ENABLE_N71_92INCOMINGINFO
1398 return ERR_SOURCENOTAVAILABLE;
1399#endif
1400 return NOKIA_SetIncomingUSSD(s,enable);
1401}
1402
1403static GSM_Error N7110_SetIncomingSMS(GSM_StateMachine *s, bool enable)
1404{
1405#ifndef GSM_ENABLE_N71_92INCOMINGINFO
1406 return ERR_SOURCENOTAVAILABLE;
1407#endif
1408 return NOKIA_SetIncomingSMS(s,enable);
1409}
1410
1411GSM_Error N7110_AnswerCall(GSM_StateMachine *s, int ID, bool all)
1412{
1413 if (!all) return DCT3DCT4_AnswerCall(s,ID);
1414 return DCT3_AnswerAllCalls(s);
1415}
1416
1417GSM_Error N7110_SetCallDivert(GSM_StateMachine *s, GSM_MultiCallDivert *divert)
1418{
1419 GSM_Errorerror;
1420 int i;
1421
1422 /* No answer from phone side */
1423 i = s->ReplyNum;
1424 s->ReplyNum = 1;
1425 error = DCT3DCT4_SetCallDivert(s,divert);
1426 s->ReplyNum = i;
1427 return error;
1428}
1429
1430GSM_Error N7110_CancelAllDiverts(GSM_StateMachine *s)
1431{
1432 GSM_Errorerror;
1433 int i;
1434
1435 /* No answer from phone side */
1436 i = s->ReplyNum;
1437 s->ReplyNum = 1;
1438 error = DCT3DCT4_CancelAllDiverts(s);
1439 s->ReplyNum = i;
1440 return error;
1441}
1442
1443static GSM_Reply_Function N7110ReplyFunctions[] = {
1444 {N71_65_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
1445 {N71_65_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
1446 {N71_65_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
1447 {N71_65_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
1448 {N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
1449 {N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
1450 {N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
1451 {N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
1452 {N71_65_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
1453 {N71_65_ReplyCallInfo, "\x01",0x03,0x0B,ID_IncomingFrame },
1454 {N71_65_ReplyCallInfo, "\x01",0x03,0x0C,ID_IncomingFrame },
1455 {N71_65_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
1456 {N71_65_ReplyCallInfo, "\x01",0x03,0x53,ID_IncomingFrame },
1457 {N71_65_ReplySendDTMF, "\x01",0x03,0x59,ID_SendDTMF },
1458 {N71_65_ReplySendDTMF, "\x01",0x03,0x5E,ID_SendDTMF },
1459
1460 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
1461 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
1462 {N7110_ReplyIncomingSMS, "\x02",0x03,0x10,ID_IncomingFrame },
1463#ifdef GSM_ENABLE_CELLBROADCAST
1464 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
1465 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
1466 {DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
1467#endif
1468 {DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
1469 {DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
1470 {DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
1471#ifdef GSM_ENABLE_CELLBROADCAST
1472 {DCT3_ReplySetIncomingCB, "\x02",0x03,0xCA,ID_SetIncomingCB },
1473#endif
1474
1475 {N7110_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
1476 {N7110_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
1477 {N7110_ReplyDeleteMemory, "\x03",0x03,0x10,ID_SetMemory },
1478 {N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetBitmap },
1479 {N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetMemory },
1480
1481 {N71_65_ReplyUSSDInfo, "\x06",0x03,0x03,ID_IncomingFrame },
1482 {NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },
1483
1484 {DCT3_ReplySIMLogin, "\x09",0x03,0x80,ID_IncomingFrame },
1485 {DCT3_ReplySIMLogout, "\x09",0x03,0x81,ID_IncomingFrame },
1486
1487 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
1488 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetBitmap },
1489 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
1490 {N7110_ReplyGetNetworkInfoError, "\x0A",0x03,0x72,ID_GetNetworkInfo },
1491 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x73,ID_IncomingFrame },
1492 {N71_92_ReplyGetSignalQuality, "\x0A",0x03,0x82,ID_GetSignalQuality },
1493 {N7110_ReplySetOperatorLogo, "\x0A",0x03,0xA4,ID_SetBitmap },
1494 {N7110_ReplyClearOperatorLogo, "\x0A",0x03,0xB0,ID_SetBitmap },
1495 {NoneReply, "\x0A",0x03,0xB5,ID_IncomingFrame },
1496
1497#ifdef DEBUG
1498 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x02,ID_SetCalendarNote },/*method 1*/
1499 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x04,ID_SetCalendarNote },/*method 1*/
1500 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x06,ID_SetCalendarNote },/*method 1*/
1501 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x08,ID_SetCalendarNote },/*method 1*/
1502#endif
1503 {N71_65_ReplyDelCalendar, "\x13",0x03,0x0C,ID_DeleteCalendarNote },
1504 {N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
1505#ifdef DEBUG
1506 {N7110_ReplyGetCalendarNotePos, "\x13",0x03,0x32,ID_GetCalendarNotePos },/*method 1*/
1507#endif
1508 {N7110_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
1509#ifdef DEBUG
1510 {N71_65_ReplyGetNextCalendar2, "\x13",0x03,0x3F,ID_GetCalendarNote },/*method 2*/
1511#endif
1512 {N71_65_ReplyAddCalendar2, "\x13",0x03,0x41,ID_SetCalendarNote },/*method 2*/
1513
1514 {N7110_ReplySaveSMSMessage, "\x14",0x03,0x05,ID_SaveSMSMessage },
1515 {N7110_ReplySaveSMSMessage, "\x14",0x03,0x06,ID_SaveSMSMessage },
1516 {N7110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetSMSMessage },
1517 {N7110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetBitmap },
1518 {N7110_ReplyGetSMSMessage, "\x14",0x03,0x09,ID_GetSMSMessage },
1519 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0B,ID_DeleteSMSMessage },
1520 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0C,ID_DeleteSMSMessage },
1521 {N7110_ReplyGetSMSStatus, "\x14",0x03,0x37,ID_GetSMSStatus },
1522 {N7110_ReplyGetSMSStatus, "\x14",0x03,0x38,ID_GetSMSStatus },
1523 {N7110_ReplySetPicture, "\x14",0x03,0x51,ID_SetBitmap },
1524 {N7110_ReplyGetSMSFolderStatus, "\x14",0x03,0x6C,ID_GetSMSFolderStatus },
1525 {N7110_ReplyGetSMSMessage, "\x14",0x03,0x6F,ID_GetSMSMessage },
1526 {N7110_ReplyGetSMSFolders, "\x14",0x03,0x7B,ID_GetSMSFolders },
1527 {N7110_ReplyGetSMSFolders, "\x14",0x03,0x7C,ID_GetSMSFolders },
1528 {N7110_ReplySaveSMSMessage, "\x14",0x03,0x84,ID_SaveSMSMessage },
1529 {N7110_ReplyGetPictureImageInfo, "\x14",0x03,0x97,ID_GetBitmap },
1530 {N7110_ReplyGetSMSFolders, "\x14",0x03,0xCA,ID_GetSMSFolders },
1531
1532 {N71_92_ReplyGetBatteryCharge, "\x17",0x03,0x03,ID_GetBatteryCharge },
1533
1534 {DCT3_ReplySetDateTime, "\x19",0x03,0x61,ID_SetDateTime },
1535 {DCT3_ReplyGetDateTime, "\x19",0x03,0x63,ID_GetDateTime },
1536 {DCT3_ReplySetAlarm, "\x19",0x03,0x6C,ID_SetAlarm },
1537 {DCT3_ReplyGetAlarm, "\x19",0x03,0x6E,ID_GetAlarm },
1538
1539 {N7110_ReplyGetRingtone, "\x1f",0x03,0x23,ID_GetRingtone },
1540 {N7110_ReplyGetRingtone, "\x1f",0x03,0x24,ID_GetRingtone },
1541
1542 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
1543 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
1544 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
1545 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
1546 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
1547 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
1548 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
1549 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
1550 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
1551 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
1552 {DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
1553 {DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
1554 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x16,ID_GetConnectSet },
1555 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x17,ID_GetConnectSet },
1556 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x19,ID_SetConnectSet },
1557 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1A,ID_SetConnectSet },
1558 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1C,ID_GetConnectSet },
1559 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1D,ID_GetConnectSet },
1560 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1F,ID_SetConnectSet },
1561
1562 {N7110_ReplyGetProfileFeature, "\x39",0x03,0x02,ID_GetProfile },
1563 {N7110_ReplySetProfileFeature, "\x39",0x03,0x04,ID_SetProfile },
1564
1565 {DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
1566 {N61_71_ReplyResetPhoneSettings, "\x40",0x02,0x65,ID_ResetPhoneSettings },
1567 {DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
1568 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
1569 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
1570 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
1571 {DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
1572 {DCT3_ReplyPlayTone, "\x40",0x02,0x8F,ID_PlayTone },
1573 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
1574 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
1575 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
1576 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth },
1577 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
1578 {NoneReply, "\x40",0x02,0xFF,ID_IncomingFrame },
1579
1580 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_GetBitmap },
1581 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_SetBitmap },
1582 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_GetBitmap },
1583 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_SetBitmap },
1584 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x17,ID_GetBitmap },
1585 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x17,ID_SetBitmap },
1586
1587 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
1588 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
1589 {DCT3_ReplyPressKey, "\xD2",0x02,0x46,ID_PressKey },
1590 {DCT3_ReplyPressKey, "\xD2",0x02,0x47,ID_PressKey },
1591
1592 {NULL, "\x00",0x00,0x00,ID_None }
1593};
1594
1595GSM_Phone_Functions N7110Phone = {
1596 "6210|6250|7110|7190",
1597 N7110ReplyFunctions,
1598 N7110_Initialise,
1599 PHONE_Terminate,
1600 GSM_DispatchMessage,
1601 NOTSUPPORTED, /* ShowStartInfo */
1602 NOKIA_GetManufacturer,
1603 DCT3DCT4_GetModel,
1604 DCT3DCT4_GetFirmware,
1605 DCT3_GetIMEI,
1606 DCT3_GetOriginalIMEI,
1607 DCT3_GetManufactureMonth,
1608 DCT3_GetProductCode,
1609 DCT3_GetHardware,
1610 DCT3_GetPPM,
1611 NOTSUPPORTED, /* GetSIMIMSI */
1612 N71_92_GetDateTime,
1613 N71_92_SetDateTime,
1614 N7110_GetAlarm,
1615 N7110_SetAlarm,
1616 NOTSUPPORTED, /* GetLocale */
1617 NOTSUPPORTED, /* SetLocale */
1618 DCT3_PressKey,
1619 DCT3_Reset,
1620 N61_71_ResetPhoneSettings,
1621 NOTSUPPORTED, /* EnterSecurityCode*/
1622 NOTSUPPORTED, /* GetSecurityStatus*/
1623 NOTSUPPORTED, /* GetDisplayStatus*/
1624 NOTIMPLEMENTED, /* SetAutoNetworkLogin*/
1625 N71_92_GetBatteryCharge,
1626 N71_92_GetSignalQuality,
1627 DCT3_GetNetworkInfo,
1628 NOTSUPPORTED, /* GetCategory */
1629 NOTSUPPORTED, /* AddCategory */
1630 NOTSUPPORTED, /* GetCategoryStatus */
1631 N7110_GetMemoryStatus,
1632 N7110_GetMemory,
1633 NOTIMPLEMENTED, /* GetNextMemory */
1634 N7110_SetMemory,
1635 NOTIMPLEMENTED, /* AddMemory */
1636 N7110_DeleteMemory,
1637 NOTIMPLEMENTED, /* DeleteAllMemory */
1638 N7110_GetSpeedDial,
1639 NOTIMPLEMENTED, /* SetSpeedDial */
1640 DCT3_GetSMSC,
1641 DCT3_SetSMSC,
1642 N7110_GetSMSStatus,
1643 N7110_GetSMSMessage,
1644 N7110_GetNextSMSMessage,
1645 N7110_SetSMS,
1646 N7110_AddSMS,
1647 N7110_DeleteSMS,
1648 DCT3_SendSMSMessage,
1649 NOTSUPPORTED, /* SendSavedSMS */
1650 N7110_SetIncomingSMS,
1651 DCT3_SetIncomingCB,
1652 N7110_GetSMSFolders,
1653 NOTIMPLEMENTED, /* AddSMSFolder */
1654 NOTIMPLEMENTED, /* DeleteSMSFolder */
1655 DCT3_DialVoice,
1656 N7110_AnswerCall,
1657 DCT3_CancelCall,
1658 NOTIMPLEMENTED, /* HoldCall */
1659 NOTIMPLEMENTED, /* UnholdCall */
1660 NOTIMPLEMENTED, /* ConferenceCall */
1661 NOTIMPLEMENTED, /* SplitCall */
1662 NOTIMPLEMENTED, /* TransferCall */
1663 NOTIMPLEMENTED, /* SwitchCall */
1664 NOTSUPPORTED, /* GetCallDivert */
1665 N7110_SetCallDivert,
1666 N7110_CancelAllDiverts,
1667 N7110_SetIncomingCall,
1668 N7110_SetIncomingUSSD,
1669 DCT3DCT4_SendDTMF,
1670 N7110_GetRingtone,
1671 N7110_SetRingtone,
1672 NOTSUPPORTED, /* GetRingtonesInfo*/
1673 NOTSUPPORTED, /* DeleteUserRingtones*/
1674 DCT3_PlayTone,
1675 DCT3_GetWAPBookmark,
1676 DCT3_SetWAPBookmark,
1677 DCT3_DeleteWAPBookmark,
1678 DCT3_GetWAPSettings,
1679 DCT3_SetWAPSettings,
1680 NOTSUPPORTED, /* GetMMSSettings */
1681 NOTSUPPORTED, /* SetMMSSettings */
1682 NOTSUPPORTED, /* GetSyncMLSettings*/
1683 NOTSUPPORTED, /* SetSyncMLSettings*/
1684 NOTSUPPORTED, /* GetChatSettings */
1685 NOTSUPPORTED, /* SetChatSettings */
1686 N7110_GetBitmap,
1687 N7110_SetBitmap,
1688 NOTSUPPORTED, /* GetToDoStatus */
1689 NOTSUPPORTED, /* GetToDo */
1690 NOTSUPPORTED, /* GetNextToDo */
1691 NOTSUPPORTED, /* SetToDo */
1692 NOTSUPPORTED, /* AddToDo */
1693 NOTSUPPORTED, /* DeleteToDo */
1694 NOTSUPPORTED, /* DeleteAllToDo */
1695 N7110_GetCalendarStatus,
1696 NOTIMPLEMENTED, /* GetCalendar */
1697 N7110_GetNextCalendar,
1698 NOTIMPLEMENTED, /* SetCalendar */
1699 N7110_AddCalendar,
1700 N71_65_DelCalendar,
1701 NOTIMPLEMENTED, /* DeleteAllCalendar*/
1702 NOTSUPPORTED, /* GetCalendarSettings*/
1703 NOTSUPPORTED, /* SetCalendarSettings*/
1704 NOTSUPPORTED, /* GetNote */
1705 N7110_GetProfile,
1706 N7110_SetProfile,
1707 NOTSUPPORTED, /* GetFMStation */
1708 NOTSUPPORTED, /* SetFMStation */
1709 NOTSUPPORTED, /* ClearFMStations */
1710 NOTSUPPORTED, /* GetNextFileFolder*/
1711 NOTSUPPORTED, /* GetFilePart */
1712 NOTSUPPORTED, /* AddFile */
1713 NOTSUPPORTED, /* GetFileSystemStatus*/
1714 NOTSUPPORTED, /* DeleteFile */
1715 NOTSUPPORTED, /* AddFolder */
1716 NOTSUPPORTED, /* GetGPRSAccessPoint*/
1717 NOTSUPPORTED /* SetGPRSAccessPoint*/
1718};
1719
1720#endif
1721
1722/* How should editor hadle tabs in this file? Add editor commands here.
1723 * vim: noexpandtab sw=8 ts=8 sts=8:
1724 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n7110.h b/gammu/emb/common/phone/nokia/dct3/n7110.h
new file mode 100644
index 0000000..a7934c2
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n7110.h
@@ -0,0 +1,45 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef n7110_h
4#define n7110_h
5
6#include "../ncommon.h"
7#include "dct3comm.h"
8
9typedef struct {
10 int LastCalendarYear;
11 int LastCalendarPos;
12 GSM_NOKIACalToDoLocationsLastCalendar;
13 int FirstCalendarPos;
14
15 GSM_NOKIASMSFolder LastSMSFolder;
16 GSM_SMSFolders LastSMSFolders;
17 GSM_NOKIASMSFolder LastPictureImageFolder;
18
19 DCT3_WAPSettings_LocationsWAPLocations;
20} GSM_Phone_N7110Data;
21
22#ifndef GSM_USED_MBUS2
23# define GSM_USED_MBUS2
24#endif
25#ifndef GSM_USED_FBUS2
26# define GSM_USED_FBUS2
27#endif
28#ifndef GSM_USED_FBUS2DLR3
29# define GSM_USED_FBUS2DLR3
30#endif
31#ifndef GSM_USED_FBUS2BLUE
32# define GSM_USED_FBUS2BLUE
33#endif
34#ifndef GSM_USED_IRDAPHONET
35# define GSM_USED_IRDAPHONET
36#endif
37#ifndef GSM_USED_BLUEFBUS2
38# define GSM_USED_BLUEFBUS2
39#endif
40
41#endif
42
43/* How should editor hadle tabs in this file? Add editor commands here.
44 * vim: noexpandtab sw=8 ts=8 sts=8:
45 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n9210.c b/gammu/emb/common/phone/nokia/dct3/n9210.c
new file mode 100644
index 0000000..e82d530
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n9210.c
@@ -0,0 +1,396 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include "../../../gsmstate.h"
4
5#ifdef GSM_ENABLE_NOKIA9210
6
7#include <string.h>
8#include <time.h>
9
10#include "../../../misc/coding/coding.h"
11#include "../../../gsmcomon.h"
12#include "../../../service/gsmlogo.h"
13#include "../../pfunc.h"
14#include "../nfunc.h"
15#include "n9210.h"
16#include "dct3func.h"
17
18static GSM_Error N9210_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
19{
20 unsigned char OpReq[] = {N6110_FRAME_HEADER, 0x70};
21
22 s->Phone.Data.Bitmap=Bitmap;
23 switch (Bitmap->Type) {
24 case GSM_OperatorLogo:
25 smprintf(s, "Getting operator logo\n");
26 /* This is like DCT3_GetNetworkInfo */
27 return GSM_WaitFor (s, OpReq, 4, 0x0a, 4, ID_GetBitmap);
28 case GSM_StartupLogo:
29 smprintf(s, "Getting startup logo\n");
30 return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x15);
31 case GSM_WelcomeNote_Text:
32 smprintf(s, "Getting welcome note\n");
33 return N71_92_GetPhoneSetting(s, ID_GetBitmap, 0x02);
34 default:
35 break;
36 }
37 return ERR_NOTSUPPORTED;
38}
39
40static GSM_Error N9210_ReplySetOpLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
41{
42 smprintf(s, "Operator logo clear/set\n");
43 return ERR_NONE;
44}
45
46static GSM_Error N9210_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
47{
48 GSM_Error error;
49 GSM_Phone_Bitmap_TypesType;
50 int Width, Height, i,count=3;
51 unsigned char req[600] = { N7110_FRAME_HEADER };
52 unsigned char reqStartup[1000] = {
53 N6110_FRAME_HEADER, 0xec,
54 0x15, /* Startup Logo setting */
55 0x04, 0x00, 0x00, 0x00, 0x30, 0x00,
56 0x02, 0xc0, 0x54, 0x00, 0x03, 0xc0,
57 0xf8, 0xf8, 0x01, 0x04};
58 unsigned char reqStartupText[500] = {
59 N7110_FRAME_HEADER, 0xec,
60 0x02}; /* Startup Text setting */
61 unsigned char reqClrOp[] = {
62 N7110_FRAME_HEADER, 0xAF,
63 0x02}; /* Number of logo = 0 - 0x04 */
64
65 switch (Bitmap->Type) {
66 case GSM_StartupLogo:
67 if (Bitmap->Location!=1) return ERR_NOTSUPPORTED;
68 Type=GSM_NokiaStartupLogo;
69 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
70 PHONE_EncodeBitmap(Type, reqStartup + 21, Bitmap);
71 smprintf(s, "Setting startup logo\n");
72 return GSM_WaitFor (s, reqStartup, 21+PHONE_GetBitmapSize(Type,0,0), 0x7A, 4, ID_SetBitmap);
73 case GSM_WelcomeNote_Text:
74 /* Nokia bug: Unicode text is moved one char to left */
75 CopyUnicodeString(reqStartupText + 4, Bitmap->Text);
76 reqStartupText[4] = 0x02;
77 i = 5 + UnicodeLength(Bitmap->Text) * 2;
78 reqStartupText[i++] = 0;
79 reqStartupText[i++] = 0;
80 return GSM_WaitFor (s, reqStartupText, i, 0x7A, 4, ID_SetBitmap);
81 case GSM_OperatorLogo:
82 /* First part for clearing logo */
83 if (!strcmp(Bitmap->NetworkCode,"000 00")) {
84 for (i=0;i<5;i++) {
85 reqClrOp[4] = i;
86 error=GSM_WaitFor (s, reqClrOp, 5, 0x0A, 4, ID_SetBitmap);
87 if (error != ERR_NONE) return error;
88 }
89 }
90 Type=GSM_NokiaOperatorLogo;
91 req[count++] = 0xA3;
92 req[count++] = 0x01;
93 req[count++] = 0x00; /* Logo removed */
94 NOKIA_EncodeNetworkCode(req+count, "000 00");
95 count = count + 3;
96 req[count++] = 0x00;
97 req[count++] = 0x04;
98 req[count++] = 0x08; /* Length of rest + 2 */
99 memcpy(req+count, "\x00\x00\x00\x00\x00\x00", 6);
100 count += 6;
101 error=GSM_WaitFor (s, req, count, 0x0A, 4, ID_SetBitmap);
102 if (error != ERR_NONE) return error;
103 /* We wanted only clear - now exit */
104 if (!strcmp(Bitmap->NetworkCode,"000 00")) return error;
105
106 /* Now setting logo */
107 count=3;
108 req[count++] = 0xA3;
109 req[count++] = 0x01;
110 req[count++] = 0x01; /* Logo set */
111 NOKIA_EncodeNetworkCode(req+count, Bitmap->NetworkCode);
112 count = count + 3;
113 req[count++] = 0x00;
114 req[count++] = 0x04;
115 req[count++] = PHONE_GetBitmapSize(Type,0,0)+8;
116 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
117 req[count++] = Width;
118 req[count++] = Height;
119 req[count++] = PHONE_GetBitmapSize(Type,0,0);
120 req[count++] = 0x00;
121 req[count++] = 0x00;
122 req[count++] = 0x00;
123 PHONE_EncodeBitmap(Type, req+count, Bitmap);
124 return GSM_WaitFor (s, req, count+PHONE_GetBitmapSize(Type,0,0), 0x0A, 4, ID_SetBitmap);
125 default:
126 break;
127 }
128 return ERR_NOTSUPPORTED;
129}
130
131static GSM_Error N9210_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
132{
133 GSM_SMSMessage sms;
134 GSM_Phone_Data *Data = &s->Phone.Data;
135
136#ifdef DEBUG
137 smprintf(s, "SMS message received\n");
138 sms.State = SMS_UnRead;
139 sms.InboxFolder = true;
140 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+5);
141#endif
142 if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
143 sms.State = SMS_UnRead;
144 sms.InboxFolder = true;
145 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+5);
146
147 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
148 }
149 return ERR_NONE;
150}
151
152#ifdef GSM_ENABLE_N71_92INCOMINGINFO
153static GSM_Error N9210_ReplySetIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
154{
155 switch (msg.Buffer[3]) {
156 case 0x0e:
157 s->Phone.Data.EnableIncomingSMS = true;
158 smprintf(s, "Incoming SMS enabled\n");
159 return ERR_NONE;
160 case 0x0f:
161 smprintf(s, "Error enabling incoming SMS\n");
162 switch (msg.Buffer[4]) {
163 case 0x0c:
164 smprintf(s, "No PIN ?\n");
165 return ERR_SECURITYERROR;
166 default:
167 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
168 }
169 }
170 return ERR_UNKNOWNRESPONSE;
171}
172#endif
173
174static GSM_Error N9210_SetIncomingSMS(GSM_StateMachine *s, bool enable)
175{
176#ifdef GSM_ENABLE_N71_92INCOMINGINFO
177 unsigned char req[] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
178
179 if (enable!=s->Phone.Data.EnableIncomingSMS) {
180 if (enable) {
181 smprintf(s, "Enabling incoming SMS\n");
182 return GSM_WaitFor (s, req, 7, 0x02, 4, ID_SetIncomingSMS);
183 } else {
184 s->Phone.Data.EnableIncomingSMS = false;
185 smprintf(s, "Disabling incoming SMS\n");
186 }
187 }
188 return ERR_NONE;
189#else
190 return ERR_SOURCENOTAVAILABLE;
191#endif
192}
193
194static GSM_Error N9210_Initialise (GSM_StateMachine *s)
195{
196#ifdef DEBUG
197 DCT3_SetIncomingCB(s,true);
198
199#ifdef GSM_ENABLE_N71_92INCOMINGINFO
200 N9210_SetIncomingSMS(s,true);
201#endif
202
203#endif
204 return ERR_NONE;
205}
206
207GSM_Error N9210_AnswerCall(GSM_StateMachine *s, int ID, bool all)
208{
209 if (!all) return DCT3DCT4_AnswerCall(s,ID);
210 return DCT3_AnswerAllCalls(s);
211}
212
213static GSM_Reply_Function N9210ReplyFunctions[] = {
214 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame},
215 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame},
216#ifdef GSM_ENABLE_N71_92INCOMINGINFO
217 {N9210_ReplySetIncomingSMS, "\x02",0x03,0x0E,ID_SetIncomingSMS},
218 {N9210_ReplySetIncomingSMS, "\x02",0x03,0x0F,ID_SetIncomingSMS},
219#endif
220 {N9210_ReplyIncomingSMS, "\x02",0x03,0x11,ID_IncomingFrame},
221#ifdef GSM_ENABLE_CELLBROADCAST
222 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB},
223 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB},
224 {DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame},
225#endif
226 {DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
227 {DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
228 {DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
229
230 {N61_91_ReplySetOpLogo, "\x05",0x03,0x31,ID_SetBitmap },
231 {N61_91_ReplySetOpLogo, "\x05",0x03,0x32,ID_SetBitmap },
232
233 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo},
234 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame},
235 {N71_92_ReplyGetSignalQuality, "\x0A",0x03,0x82,ID_GetSignalQuality},
236 {N9210_ReplySetOpLogo, "\x0A",0x03,0xA4,ID_SetBitmap },
237 {N9210_ReplySetOpLogo, "\x0A",0x03,0xB0,ID_SetBitmap },
238
239 {N71_92_ReplyGetBatteryCharge, "\x17",0x03,0x03,ID_GetBatteryCharge},
240
241 {DCT3_ReplySetDateTime, "\x19",0x03,0x61,ID_SetDateTime },
242 {DCT3_ReplyGetDateTime, "\x19",0x03,0x63,ID_GetDateTime },
243
244 {DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity},
245 {DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
246 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
247 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
248 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
249 {DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
250 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
251 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
252 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode},
253 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth},
254 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI},
255
256 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_GetBitmap },
257 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x02,ID_SetBitmap },
258 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_GetBitmap },
259 {N71_92_ReplyPhoneSetting, "\x7a",0x04,0x15,ID_SetBitmap },
260
261 {DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetModel },
262 {DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetFirmware },
263
264 {NULL, "\x00",0x00,0x00,ID_None }
265};
266
267GSM_Phone_Functions N9210Phone = {
268 "9210|9210i",
269 N9210ReplyFunctions,
270 N9210_Initialise,
271 PHONE_Terminate,
272 GSM_DispatchMessage,
273 NOTSUPPORTED, /* ShowStartInfo */
274 NOKIA_GetManufacturer,
275 DCT3DCT4_GetModel,
276 DCT3DCT4_GetFirmware,
277 DCT3_GetIMEI,
278 DCT3_GetOriginalIMEI,
279 DCT3_GetManufactureMonth,
280 DCT3_GetProductCode,
281 DCT3_GetHardware,
282 DCT3_GetPPM,
283 NOTSUPPORTED, /* GetSIMIMSI */
284 N71_92_GetDateTime,
285 N71_92_SetDateTime,
286 NOTIMPLEMENTED, /* GetAlarm */
287 NOTIMPLEMENTED, /* SetAlarm */
288 NOTSUPPORTED, /* GetLocale */
289 NOTSUPPORTED, /* SetLocale */
290 NOTIMPLEMENTED, /* PressKey */
291 NOTIMPLEMENTED, /* Reset */
292 NOTIMPLEMENTED, /* ResetPhoneSettings*/
293 NOTSUPPORTED, /* EnterSecurityCode*/
294 NOTSUPPORTED, /* GetSecurityStatus*/
295 NOTSUPPORTED, /* GetDisplayStatus*/
296 NOTIMPLEMENTED, /* SetAutoNetworkLogin*/
297 N71_92_GetBatteryCharge,
298 N71_92_GetSignalQuality,
299 DCT3_GetNetworkInfo,
300 NOTSUPPORTED, /* GetCategory */
301 NOTSUPPORTED, /* AddCategory */
302 NOTSUPPORTED, /* GetCategoryStatus */
303 NOTIMPLEMENTED, /* GetMemoryStatus */
304 NOTIMPLEMENTED, /* GetMemory */
305 NOTIMPLEMENTED, /* GetNextMemory */
306 NOTIMPLEMENTED, /* SetMemory */
307 NOTIMPLEMENTED, /* AddMemory */
308 NOTIMPLEMENTED, /* DeleteMemory */
309 NOTIMPLEMENTED, /* DeleteAllMemory */
310 NOTIMPLEMENTED, /* GetSpeedDial */
311 NOTIMPLEMENTED, /* SetSpeedDial */
312 DCT3_GetSMSC,
313 DCT3_SetSMSC, /* FIXME: test it */
314 NOTIMPLEMENTED, /* GetSMSStatus */
315 NOTIMPLEMENTED, /* GetSMS */
316 NOTIMPLEMENTED, /* GetNextSMS */
317 NOTIMPLEMENTED, /* SetSMS */
318 NOTIMPLEMENTED, /* AddSMS */
319 NOTIMPLEMENTED, /* DeleteSMS */
320 DCT3_SendSMSMessage,
321 NOTSUPPORTED, /* SendSavedSMS */
322 N9210_SetIncomingSMS,
323 DCT3_SetIncomingCB,
324 NOTIMPLEMENTED, /* GetSMSFolders */
325 NOTSUPPORTED, /* AddSMSFolder */
326 NOTSUPPORTED, /* DeleteSMSFolder */
327 DCT3_DialVoice,
328 N9210_AnswerCall,
329 DCT3_CancelCall,
330 NOTSUPPORTED, /* HoldCall */
331 NOTSUPPORTED, /* UnholdCall */
332 NOTSUPPORTED, /* ConferenceCall */
333 NOTSUPPORTED, /* SplitCall */
334 NOTSUPPORTED, /* TransferCall */
335 NOTSUPPORTED, /* SwitchCall */
336 NOTSUPPORTED, /* GetCallDivert */
337 NOTSUPPORTED, /* SetCallDivert */
338 NOTSUPPORTED, /* CancelAllDiverts*/
339 NOTSUPPORTED, /* SetIncomingCall */
340 NOTIMPLEMENTED, /* SetIncomingUSSD */
341 NOTSUPPORTED, /* SendDTMF */
342 NOTIMPLEMENTED, /* GetRingtone */
343 NOTIMPLEMENTED, /* SetRingtone */
344 NOTSUPPORTED, /* GetRingtonesInfo*/
345 NOTSUPPORTED, /* DeleteUserRingtones*/
346 NOTSUPPORTED, /* PlayTone */
347 NOTIMPLEMENTED, /* GetWAPBookmark */
348 NOTIMPLEMENTED, /* SetWAPBookmark */
349 NOTIMPLEMENTED, /* DeleteWAPBookmark */
350 NOTIMPLEMENTED, /* GetWAPSettings */
351 NOTSUPPORTED, /* SetWAPSettings */
352 NOTSUPPORTED, /* GetMMSSettings */
353 NOTSUPPORTED, /* SetMMSSettings */
354 NOTSUPPORTED, /* GetSyncMLSettings*/
355 NOTSUPPORTED, /* SetSyncMLSettings*/
356 NOTSUPPORTED, /* GetChatSettings */
357 NOTSUPPORTED, /* SetChatSettings */
358 N9210_GetBitmap,
359 N9210_SetBitmap,
360 NOTSUPPORTED, /* GetToDoStatus */
361 NOTSUPPORTED, /* GetToDo */
362 NOTSUPPORTED, /* GetNextToDo */
363 NOTSUPPORTED, /* SetToDo */
364 NOTSUPPORTED, /* AddToDo */
365 NOTSUPPORTED, /* DeleteToDo */
366 NOTSUPPORTED, /* DeleteAllToDo */
367 NOTSUPPORTED, /* GetCalendarStatus*/
368 NOTSUPPORTED, /* GetCalendar */
369 NOTSUPPORTED, /* GetNextCalendar */
370 NOTSUPPORTED, /* SetCalendar */
371 NOTSUPPORTED, /* AddCalendar */
372 NOTSUPPORTED, /* DeleteCalendar */
373 NOTSUPPORTED, /* DeleteAllCalendar*/
374 NOTSUPPORTED, /* GetCalendarSettings*/
375 NOTSUPPORTED, /* SetCalendarSettings*/
376 NOTSUPPORTED, /* GetNote */
377 NOTIMPLEMENTED, /* GetProfile */
378 NOTSUPPORTED, /* SetProfile */
379 NOTSUPPORTED, /* GetFMStation */
380 NOTSUPPORTED, /* SetFMStation */
381 NOTSUPPORTED, /* ClearFMStations */
382 NOTSUPPORTED, /* GetNextFileFolder*/
383 NOTSUPPORTED, /* GetFilePart */
384 NOTSUPPORTED, /* AddFile */
385 NOTSUPPORTED, /* GetFileSystemStatus*/
386 NOTSUPPORTED, /* DeleteFile */
387 NOTSUPPORTED, /* AddFolder */
388 NOTSUPPORTED, /* GetGPRSAccessPoint*/
389 NOTSUPPORTED /* SetGPRSAccessPoint*/
390};
391
392#endif
393
394/* How should editor hadle tabs in this file? Add editor commands here.
395 * vim: noexpandtab sw=8 ts=8 sts=8:
396 */
diff --git a/gammu/emb/common/phone/nokia/dct3/n9210.h b/gammu/emb/common/phone/nokia/dct3/n9210.h
new file mode 100644
index 0000000..8998532
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n9210.h
@@ -0,0 +1,17 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef n9210_h
4#define n9210_h
5
6#ifndef GSM_USED_MBUS2
7# define GSM_USED_MBUS2
8#endif
9#ifndef GSM_USED_FBUS2
10# define GSM_USED_FBUS2
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/phone/nokia/dct4/dct4func.c b/gammu/emb/common/phone/nokia/dct4/dct4func.c
new file mode 100644
index 0000000..9fa931f
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/dct4func.c
@@ -0,0 +1,115 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include "../../../gsmstate.h"
4
5#include <string.h>
6#include <time.h>
7
8#include "../../../gsmcomon.h"
9#include "../../../misc/coding/coding.h"
10#include "../../../service/gsmlogo.h"
11#include "../nfunc.h"
12#include "../nfuncold.h"
13#include "../../pfunc.h"
14#include "dct4func.h"
15
16#ifdef GSM_ENABLE_NOKIA_DCT4
17
18GSM_Error DCT4_ReplyGetPhoneMode(GSM_Protocol_Message msg, GSM_StateMachine *s)
19{
20 s->Phone.Data.PhoneString[0] = msg.Buffer[4];
21 return ERR_NONE;
22}
23
24GSM_Error DCT4_GetPhoneMode(GSM_StateMachine *s)
25{
26 unsigned char req[] = {N6110_FRAME_HEADER, 0x02, 0x00, 0x00};
27
28 smprintf(s,"Getting phone mode\n");
29
30 return GSM_WaitFor (s, req, 6, 0x15, 4, ID_Reset);
31}
32
33GSM_Error DCT4_ReplySetPhoneMode(GSM_Protocol_Message msg, GSM_StateMachine *s)
34{
35 return ERR_NONE;
36}
37
38GSM_Error DCT4_SetPhoneMode(GSM_StateMachine *s, DCT4_PHONE_MODE mode)
39{
40 unsigned char PhoneMode[10];
41 int i;
42 GSM_Error error;
43 unsigned char req[] = {N6110_FRAME_HEADER, 0x01,
44 0x04, /* phone mode */
45 0x00};
46
47 if (s->ConnectionType != GCT_FBUS2) return ERR_OTHERCONNECTIONREQUIRED;
48
49 s->Phone.Data.PhoneString = PhoneMode;
50 req[4] = mode;
51
52 while (1) {
53 smprintf(s,"Going to phone mode %i\n",mode);
54 error = GSM_WaitFor (s, req, 6, 0x15, 4, ID_Reset);
55 if (error != ERR_NONE) return error;
56 for (i=0;i<20;i++) {
57 error=DCT4_GetPhoneMode(s);
58 if (error != ERR_NONE) return error;
59 if (PhoneMode[0] == mode) return ERR_NONE;
60 my_sleep(500);
61 }
62 }
63 return ERR_NONE;
64}
65
66GSM_Error DCT4_ReplyGetIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
67{
68 memcpy(s->Phone.Data.IMEI,msg.Buffer + 10, 16);
69 smprintf(s, "Received IMEI %s\n",s->Phone.Data.IMEI);
70 return ERR_NONE;
71}
72
73GSM_Error DCT4_GetIMEI (GSM_StateMachine *s)
74{
75 unsigned char req[5] = {N6110_FRAME_HEADER, 0x00, 0x41};
76
77 smprintf(s, "Getting IMEI\n");
78 return GSM_WaitFor (s, req, 5, 0x1B, 2, ID_GetIMEI);
79}
80
81GSM_Error DCT4_GetHardware(GSM_StateMachine *s, char *value)
82{
83 return NOKIA_GetPhoneString(s,"\x00\x03\x02\x07\x00\x02",6,0x1b,value,ID_GetHardware,10);
84}
85
86GSM_Error DCT4_GetProductCode(GSM_StateMachine *s, char *value)
87{
88 return NOKIA_GetPhoneString(s,"\x00\x03\x04\x0b\x00\x02",6,0x1b,value,ID_GetProductCode,10);
89}
90
91GSM_Error DCT4_Reset(GSM_StateMachine *s, bool hard)
92{
93 unsigned char req[] = {N6110_FRAME_HEADER, 0x05,
94 0x80, /* 0x80 - reset, 0x00 - off */
95 0x00};
96 //unsigned char TimeReq[] = {N6110_FRAME_HEADER, 0x0E, 0x00, 0x00};
97
98 if (hard) return ERR_NOTSUPPORTED;
99
100 //error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
101 //if (error != ERR_NONE) return error;
102 //error = DCT4_SetPhoneMode(s, DCT4_MODE_NORMAL);
103 //if (error != ERR_NONE) return error;
104
105 s->Phone.Data.EnableIncomingSMS = false;
106 s->Phone.Data.EnableIncomingCB = false;
107
108 return GSM_WaitFor (s, req, 6, 0x15, 2, ID_Reset);
109}
110
111#endif
112
113/* How should editor hadle tabs in this file? Add editor commands here.
114 * vim: noexpandtab sw=8 ts=8 sts=8:
115 */
diff --git a/gammu/emb/common/phone/nokia/dct4/dct4func.h b/gammu/emb/common/phone/nokia/dct4/dct4func.h
new file mode 100644
index 0000000..ad802e8
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/dct4func.h
@@ -0,0 +1,30 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef dct4func_h
4#define dct4func_h
5
6#include "../ncommon.h"
7#include "../../../service/sms/gsmsms.h"
8
9typedef enum {
10 DCT4_MODE_NORMAL = 0x01,
11 DCT4_MODE_TEST = 0x04,
12 DCT4_MODE_LOCAL = 0x05
13} DCT4_PHONE_MODE;
14
15GSM_Error DCT4_ReplyGetPhoneMode (GSM_Protocol_Message msg, GSM_StateMachine *s);
16GSM_Error DCT4_ReplySetPhoneMode (GSM_Protocol_Message msg, GSM_StateMachine *s);
17 GSM_Error DCT4_ReplyGetIMEI (GSM_Protocol_Message msg, GSM_StateMachine *s);
18
19 GSM_Error DCT4_GetPhoneMode (GSM_StateMachine *s);
20 GSM_Error DCT4_SetPhoneMode (GSM_StateMachine *s, DCT4_PHONE_MODE mode);
21 GSM_Error DCT4_GetIMEI (GSM_StateMachine *s);
22 GSM_Error DCT4_GetHardware (GSM_StateMachine *s, char *value);
23 GSM_Error DCT4_GetProductCode (GSM_StateMachine *s, char *value);
24 GSM_Error DCT4_Reset (GSM_StateMachine *s, bool hard);
25
26#endif
27
28/* How should editor hadle tabs in this file? Add editor commands here.
29 * vim: noexpandtab sw=8 ts=8 sts=8:
30 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n3320.c b/gammu/emb/common/phone/nokia/dct4/n3320.c
new file mode 100644
index 0000000..51e6f18
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n3320.c
@@ -0,0 +1,271 @@
1/* (c) 2004 by Marcin Wiacek */
2
3#include "../../../gsmstate.h"
4
5#ifdef GSM_ENABLE_NOKIA3320
6
7#include <string.h>
8#include <time.h>
9
10#include "../../../gsmcomon.h"
11#include "../../../misc/coding/coding.h"
12#include "../../../service/gsmlogo.h"
13#include "../nfunc.h"
14#include "../nfuncold.h"
15#include "../../pfunc.h"
16#include "n3320.h"
17
18static GSM_Error N3320_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
19{
20 smprintf(s, "Phonebook entry received\n");
21 switch (msg.Buffer[6]) {
22 case 0x0f:
23 return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
24 default:
25 return N71_65_DecodePhonebook(s, s->Phone.Data.Memory, s->Phone.Data.Bitmap, s->Phone.Data.SpeedDial, msg.Buffer+22, msg.Length-22,true);
26 }
27 return ERR_UNKNOWN;
28}
29
30static GSM_Error N3320_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
31{
32 unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
33 0xfe, 0x10, /* memory type */
34 0x00, 0x00, 0x00, 0x00,
35 0x00, 0x01, /* location */
36 0x00, 0x00, 0x01};
37
38 req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
39 if (entry->MemoryType == MEM_SM) return ERR_NOTSUPPORTED;
40 if (req[9]==0xff) return ERR_NOTSUPPORTED;
41
42 if (entry->Location==0x00) return ERR_INVALIDLOCATION;
43
44 req[14] = entry->Location / 256;
45 req[15] = entry->Location % 256;
46
47 s->Phone.Data.Memory=entry;
48 smprintf(s, "Getting phonebook entry\n");
49 return GSM_WaitFor (s, req, 19, 0x03, 4, ID_GetMemory);
50}
51
52static GSM_Error N3320_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
53{
54 GSM_Phone_Data *Data = &s->Phone.Data;
55
56 smprintf(s, "Memory status received\n");
57 /* Quess ;-)) */
58 if (msg.Buffer[14]==0x10) {
59 Data->MemoryStatus->MemoryFree = msg.Buffer[18]*256 + msg.Buffer[19];
60 } else {
61 Data->MemoryStatus->MemoryFree = msg.Buffer[17];
62 }
63 smprintf(s, "Size : %i\n",Data->MemoryStatus->MemoryFree);
64 Data->MemoryStatus->MemoryUsed = msg.Buffer[20]*256 + msg.Buffer[21];
65 smprintf(s, "Used : %i\n",Data->MemoryStatus->MemoryUsed);
66 Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
67 smprintf(s, "Free : %i\n",Data->MemoryStatus->MemoryFree);
68 return ERR_NONE;
69}
70
71static GSM_Error N3320_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
72{
73 unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
74 0x00, /* memory type */
75 0x55, 0x55, 0x55, 0x00};
76
77 req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
78 if (Status->MemoryType == MEM_SM) return ERR_NOTSUPPORTED;
79 if (req[5]==0xff) return ERR_NOTSUPPORTED;
80
81 s->Phone.Data.MemoryStatus=Status;
82 smprintf(s, "Getting memory status\n");
83 return GSM_WaitFor (s, req, 10, 0x03, 4, ID_GetMemoryStatus);
84}
85
86static GSM_Error N3320_ReplyGetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
87{
88 smprintf(s, "Date & time received\n");
89 if (msg.Buffer[4]==0x01) {
90 NOKIA_DecodeDateTime(s, msg.Buffer+10, s->Phone.Data.DateTime);
91 return ERR_NONE;
92 }
93 smprintf(s, "Not set in phone\n");
94 return ERR_EMPTY;
95}
96
97static GSM_Error N3320_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
98{
99 unsigned char req[] = {N6110_FRAME_HEADER, 0x0A, 0x00, 0x00};
100
101 s->Phone.Data.DateTime=date_time;
102 smprintf(s, "Getting date & time\n");
103 return GSM_WaitFor (s, req, 6, 0x19, 4, ID_GetDateTime);
104}
105
106static GSM_Error N3320_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
107{
108 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);
109}
110
111static GSM_Error N3320_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
112{
113 GSM_Error error;
114
115 /* Method 1 */
116 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N3320.LastCalendar);
117 if (error!=ERR_NONE) return error;
118 Status->Used = s->Phone.Data.Priv.N3320.LastCalendar.Number;
119 return ERR_NONE;
120}
121
122static GSM_Error N3320_ReplyGetCalendarInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
123{
124 return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N3320.LastCalendar);
125}
126
127static GSM_Reply_Function N3320ReplyFunctions[] = {
128 {N3320_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
129 {N3320_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
130
131 {N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
132 {N3320_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
133
134 {N3320_ReplyGetDateTime, "\x19",0x03,0x0B,ID_GetDateTime },
135
136 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
137 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
138
139 {NULL, "\x00",0x00,0x00,ID_None }
140};
141
142GSM_Phone_Functions N3320Phone = {
143 "3320",
144 N3320ReplyFunctions,
145 NONEFUNCTION, /* Initialise */
146 NONEFUNCTION, /* Terminate */
147 GSM_DispatchMessage,
148 NOTSUPPORTED, /* ShowStartInfo */
149 NOKIA_GetManufacturer,
150 DCT3DCT4_GetModel,
151 DCT3DCT4_GetFirmware,
152 NOTSUPPORTED, /* GetIMEI */
153 NOTSUPPORTED, /* GetOriginalIMEI */
154 NOTSUPPORTED, /* GetManufactureMonth*/
155 NOTSUPPORTED, /* GetProductCode */
156 NOTSUPPORTED, /* GetHardware */
157 NOTSUPPORTED, /* GetPPM */
158 NOTSUPPORTED, /* GetSIMIMSI */
159 N3320_GetDateTime,
160 NOTSUPPORTED, /* SetDateTime */
161 NOTSUPPORTED, /* GetAlarm */
162 NOTSUPPORTED, /* SetAlarm */
163 NOTSUPPORTED, /* GetLocale */
164 NOTSUPPORTED, /* SetLocale */
165 NOTSUPPORTED, /* PressKey */
166 NOTSUPPORTED, /* Reset */
167 NOTSUPPORTED, /* ResetPhoneSettings*/
168 NOTSUPPORTED, /* EnterSecurityCode*/
169 NOTSUPPORTED, /* GetSecurityStatus*/
170 NOTSUPPORTED, /* GetDisplayStatus*/
171 NOTSUPPORTED, /* SetAutoNetworkLogin*/
172 NOTSUPPORTED, /* GetBatteryCharge*/
173 NOTSUPPORTED, /* GetSignalQuality*/
174 NOTSUPPORTED, /* GetNetworkInfo */
175 NOTSUPPORTED, /* GetCategory */
176 NOTSUPPORTED, /* AddCategory */
177 NOTSUPPORTED, /* GetCategoryStatus */
178 N3320_GetMemoryStatus,
179 N3320_GetMemory,
180 NOTSUPPORTED, /* GetNextMemory */
181 NOTSUPPORTED, /* SetMemory */
182 NOTSUPPORTED, /* AddMemory */
183 NOTSUPPORTED, /* DeleteMemory */
184 NOTIMPLEMENTED, /* DeleteAllMemory */
185 NOTSUPPORTED, /* GetSpeedDial */
186 NOTSUPPORTED, /* SetSpeedDial */
187 NOTSUPPORTED, /* GetSMSC */
188 NOTSUPPORTED, /* SetSMSC */
189 NOTSUPPORTED, /* GetSMSStatus */
190 NOTSUPPORTED, /* GetSMS */
191 NOTSUPPORTED, /* GetNextSMS */
192 NOTSUPPORTED, /* SetSMS */
193 NOTSUPPORTED, /* AddSMS */
194 NOTSUPPORTED, /* DeleteSMS */
195 NOTSUPPORTED, /* SendSMS */
196 NOTSUPPORTED, /* SendSavedSMS */
197 NOTSUPPORTED, /* SetIncomingSMS */
198 NOTSUPPORTED, /* SetIncomingCB */
199 NOTSUPPORTED, /* GetSMSFolders */
200 NOTSUPPORTED, /* AddSMSFolder */
201 NOTSUPPORTED, /* DeleteSMSFolder */
202 NOTIMPLEMENTED, /* DialVoice */
203 NOTIMPLEMENTED, /* AnswerCall */
204 NOTIMPLEMENTED, /* CancelCall */
205 NOTIMPLEMENTED, /* HoldCall */
206 NOTIMPLEMENTED, /* UnholdCall */
207 NOTIMPLEMENTED, /* ConferenceCall */
208 NOTIMPLEMENTED, /* SplitCall */
209 NOTIMPLEMENTED, /* TransferCall */
210 NOTIMPLEMENTED, /* SwitchCall */
211 NOTSUPPORTED, /* GetCallDivert */
212 NOTSUPPORTED, /* SetCallDivert */
213 NOTSUPPORTED, /* CancelAllDiverts*/
214 NOTIMPLEMENTED, /* SetIncomingCall */
215 NOTIMPLEMENTED, /* SetIncomingUSSD */
216 NOTSUPPORTED, /* SendDTMF */
217 NOTSUPPORTED, /* GetRingtone */
218 NOTSUPPORTED, /* SetRingtone */
219 NOTSUPPORTED, /* GetRingtonesInfo*/
220 NOTIMPLEMENTED, /* DeleteUserRingtones*/
221 NOTSUPPORTED, /* PlayTone */
222 NOTSUPPORTED, /* GetWAPBookmark */
223 NOTSUPPORTED, /* SetWAPBookmark */
224 NOTSUPPORTED, /* DeleteWAPBookmark */
225 NOTSUPPORTED, /* GetWAPSettings */
226 NOTSUPPORTED, /* SetWAPSettings */
227 NOTSUPPORTED, /* GetMMSSettings */
228 NOTSUPPORTED, /* SetMMSSettings */
229 NOTSUPPORTED, /* GetSyncMLSettings*/
230 NOTSUPPORTED, /* SetSyncMLSettings*/
231 NOTSUPPORTED, /* GetChatSettings */
232 NOTSUPPORTED, /* SetChatSettings */
233 NOTSUPPORTED, /* GetBitmap */
234 NOTSUPPORTED, /* SetBitmap */
235 NOTSUPPORTED, /* GetToDoStatus */
236 NOTSUPPORTED, /* GetToDo */
237 NOTSUPPORTED, /* GetNextToDo */
238 NOTSUPPORTED, /* SetToDo */
239 NOTSUPPORTED, /* AddToDo */
240 NOTSUPPORTED, /* DeleteToDo */
241 NOTSUPPORTED, /* DeleteAllToDo */
242 N3320_GetCalendarStatus,
243 NOTIMPLEMENTED, /* GetCalendar */
244 N3320_GetNextCalendar,
245 NOTIMPLEMENTED, /* SetCalendar */
246 NOTSUPPORTED, /* AddCalendar */
247 NOTSUPPORTED, /* DeleteCalendar */
248 NOTIMPLEMENTED, /* DeleteAllCalendar*/
249 NOTSUPPORTED, /* GetCalendarSettings*/
250 NOTSUPPORTED, /* SetCalendarSettings*/
251 NOTSUPPORTED, /* GetNote */
252 NOTSUPPORTED, /* GetProfile */
253 NOTSUPPORTED, /* SetProfile */
254 NOTSUPPORTED, /* GetFMStation */
255 NOTSUPPORTED, /* SetFMStation */
256 NOTSUPPORTED, /* ClearFMStations */
257 NOTSUPPORTED, /* GetNextFileFolder*/
258 NOTSUPPORTED, /* GetFilePart */
259 NOTIMPLEMENTED, /* AddFilePart */
260 NOTSUPPORTED, /* GetFileSystemStatus*/
261 NOTIMPLEMENTED, /* DeleteFile */
262 NOTIMPLEMENTED, /* AddFolder */
263 NOTSUPPORTED, /* GetGPRSAccessPoint*/
264 NOTSUPPORTED /* SetGPRSAccessPoint*/
265};
266
267#endif
268
269/* How should editor hadle tabs in this file? Add editor commands here.
270 * vim: noexpandtab sw=8 ts=8 sts=8:
271 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n3320.h b/gammu/emb/common/phone/nokia/dct4/n3320.h
new file mode 100644
index 0000000..13825a9
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n3320.h
@@ -0,0 +1,30 @@
1/* (c) 2004 by Marcin Wiacek */
2
3#ifndef n3320_h
4#define n3320_h
5
6#include "../ncommon.h"
7#include "../../../service/sms/gsmsms.h"
8
9#ifndef GSM_USED_MBUS2
10# define GSM_USED_MBUS2
11#endif
12#ifndef GSM_USED_FBUS2
13# define GSM_USED_FBUS2
14#endif
15
16typedef struct {
17 int LastCalendarYear;
18 int LastCalendarPos;
19 GSM_NOKIACalToDoLocationsLastCalendar;
20 int FirstCalendarPos;
21 unsigned char CalendarIcons[10];
22 GSM_CalendarNoteType CalendarIconsTypes[10];
23 int CalendarIconsNum;
24} GSM_Phone_N3320Data;
25
26#endif
27
28/* How should editor hadle tabs in this file? Add editor commands here.
29 * vim: noexpandtab sw=8 ts=8 sts=8:
30 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n3650.c b/gammu/emb/common/phone/nokia/dct4/n3650.c
new file mode 100644
index 0000000..2da55bf
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n3650.c
@@ -0,0 +1,392 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include "../../../gsmstate.h"
4
5#ifdef GSM_ENABLE_NOKIA3650
6
7#include <string.h>
8#include <time.h>
9
10#include "../../../gsmcomon.h"
11#include "../../../misc/coding/coding.h"
12#include "../../../service/gsmlogo.h"
13#include "../nfunc.h"
14#include "../nfuncold.h"
15#include "../../pfunc.h"
16#include "dct4func.h"
17#include "n3650.h"
18
19static GSM_Error N3650_ReplyGetFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
20{
21 int old;
22
23 smprintf(s,"File part received\n");
24 old = s->Phone.Data.File->Used;
25
26 if (msg.Length < 10) {
27 if (old == 0) return ERR_UNKNOWN;
28 return ERR_EMPTY;
29 }
30
31 s->Phone.Data.File->Used += msg.Buffer[10]*256*256*256+
32 msg.Buffer[11]*256*256+
33 msg.Buffer[12]*256+
34 msg.Buffer[13];
35 smprintf(s,"Length: %i\n",
36 msg.Buffer[10]*256*256*256+
37 msg.Buffer[11]*256*256+
38 msg.Buffer[12]*256+
39 msg.Buffer[13]);
40 s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
41 memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+18,s->Phone.Data.File->Used-old);
42 if (s->Phone.Data.File->Used-old < 0x03 * 256 + 0xD4) return ERR_EMPTY;
43 return ERR_NONE;
44}
45
46static GSM_Error N3650_GetFilePart(GSM_StateMachine *s, GSM_File *File)
47{
48 unsigned int len=10,i;
49 GSM_Error error;
50 unsigned char StartReq[500] = {
51 N7110_FRAME_HEADER, 0x0D, 0x10, 0x01, 0x07,
52 0x24, /* len1 */
53 0x12, /* len2 */
54 0x0E, /* len3 */
55 0x00}; /* File name */
56 unsigned char ContinueReq[] = {
57 N7110_FRAME_HEADER, 0x0D, 0x20, 0x01, 0xF0,
58 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00};
59
60 if (File->Used == 0) {
61 sprintf(StartReq+10,"%s",File->ID_FullName);
62 len+=strlen(File->ID_FullName)-1;
63 StartReq[7] = strlen(File->ID_FullName) + 3;
64
65 StartReq[8] = strlen(File->ID_FullName);
66 StartReq[9] = 0;
67 while (File->ID_FullName[StartReq[8]] != '\\') {
68 StartReq[8]--;
69 StartReq[9]++;
70 }
71 for (i=StartReq[8];i<strlen(File->ID_FullName);i++) {
72 StartReq[i+10] = StartReq[i+1+10];
73 }
74 StartReq[9]--;
75
76 EncodeUnicode(File->Name,File->ID_FullName+StartReq[8]+1,StartReq[9]);
77 File->Folder = false;
78
79 error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
80 if (error != ERR_NONE) return error;
81
82 s->Phone.Data.File = File;
83 return GSM_WaitFor (s, StartReq, len, 0x58, 4, ID_GetFile);
84 }
85
86 s->Phone.Data.File = File;
87 error = GSM_WaitFor (s, ContinueReq, 14, 0x58, 4, ID_GetFile);
88
89 //if (error == GE_EMPTY) {
90 // error = DCT4_SetPhoneMode(s, DCT4_MODE_NORMAL);
91 // if (error != ERR_NONE) return error;
92 // return GE_EMPTY;
93 //}
94
95 return error;
96}
97
98static GSM_Error N3650_ReplyGetFolderInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
99{
100 GSM_File *File = s->Phone.Data.FileInfo;
101 GSM_Phone_N3650Data*Priv = &s->Phone.Data.Priv.N3650;
102 int i,pos = 6;
103
104 i = Priv->FilesLocationsUsed-1;
105 while (1) {
106 if (i==Priv->FilesLocationsCurrent-1) break;
107 dbgprintf("Copying %i to %i, max %i, current %i\n",
108 i,i+msg.Buffer[5],
109 Priv->FilesLocationsUsed,Priv->FilesLocationsCurrent);
110 memcpy(Priv->Files[i+msg.Buffer[5]],Priv->Files[i],sizeof(GSM_File));
111 i--;
112 }
113 Priv->FileEntries = msg.Buffer[5];
114 Priv->FilesLocationsUsed += msg.Buffer[5];
115 for (i=0;i<msg.Buffer[5];i++) {
116 Priv->Files[Priv->FilesLocationsCurrent+i]->Folder = true;
117 if (msg.Buffer[pos+2] == 0x01) {
118 Priv->Files[Priv->FilesLocationsCurrent+i]->Folder = false;
119 smprintf(s,"File ");
120 }
121 EncodeUnicode(Priv->Files[Priv->FilesLocationsCurrent+i]->Name,msg.Buffer+pos+9,msg.Buffer[pos+8]);
122 smprintf(s,"%s\n",DecodeUnicodeString(Priv->Files[Priv->FilesLocationsCurrent+i]->Name));
123 Priv->Files[Priv->FilesLocationsCurrent+i]->Level = File->Level+1;
124 sprintf(Priv->Files[Priv->FilesLocationsCurrent+i]->ID_FullName,"%s\\%s",File->ID_FullName,msg.Buffer+pos+9);
125 pos+=msg.Buffer[pos+1];
126 }
127 dbgprintf("\n");
128 return ERR_NONE;
129}
130
131static GSM_Error N3650_GetFolderInfo(GSM_StateMachine *s, GSM_File *File)
132{
133 int len=10;
134 unsigned char req[500] = {
135 N7110_FRAME_HEADER, 0x0B, 0x00, 0x01, 0x07,
136 0x18, /* folder name length + 6 */
137 0x12, /* folder name length */
138 0x00,
139 0x00}; /* folder name */
140
141 sprintf(req+10,File->ID_FullName);
142 len +=strlen(File->ID_FullName);
143 req[7] = strlen(File->ID_FullName) + 6;
144 req[8] = strlen(File->ID_FullName);
145 req[len++] = 0x00;
146 req[len++] = 0x00;
147
148 s->Phone.Data.FileInfo = File;
149 return GSM_WaitFor (s, req, len, 0x58, 4, ID_GetFile);
150}
151
152static GSM_Error N3650_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start)
153{
154 GSM_Error error;
155 GSM_Phone_N3650Data*Priv = &s->Phone.Data.Priv.N3650;
156
157 if (start) {
158 error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
159 if (error != ERR_NONE) return error;
160
161 Priv->Files[0]->Folder = true;
162 Priv->Files[0]->Level = 1;
163 Priv->Files[0]->Name[0] = 0;
164 Priv->Files[0]->Name[1] = 0;
165 Priv->Files[0]->ID_FullName[0]= 'Z';
166 Priv->Files[0]->ID_FullName[1]= ':';
167 Priv->Files[0]->ID_FullName[2]= 0;
168
169 Priv->Files[1]->Folder = true;
170 Priv->Files[1]->Level = 1;
171 Priv->Files[1]->Name[0] = 0;
172 Priv->Files[1]->Name[1] = 0;
173 Priv->Files[1]->ID_FullName[0]= 'E';
174 Priv->Files[1]->ID_FullName[1]= ':';
175 Priv->Files[1]->ID_FullName[2]= 0;
176
177 Priv->Files[2]->Folder = true;
178 Priv->Files[2]->Level = 1;
179 Priv->Files[2]->Name[0] = 0;
180 Priv->Files[2]->Name[1] = 0;
181 Priv->Files[2]->ID_FullName[0]= 'C';
182 Priv->Files[2]->ID_FullName[1]= ':';
183 Priv->Files[2]->ID_FullName[2]= 0;
184
185 Priv->FilesLocationsUsed = 3;
186 Priv->FilesLocationsCurrent = 0;
187 Priv->FileLev = 1;
188 }
189
190 if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) {
191 // error = DCT4_SetPhoneMode(s, DCT4_MODE_NORMAL);
192 // if (error != ERR_NONE) return error;
193
194 return ERR_EMPTY;
195 }
196
197 strcpy(File->ID_FullName,Priv->Files[Priv->FilesLocationsCurrent]->ID_FullName);
198 File->Level= Priv->Files[Priv->FilesLocationsCurrent]->Level;
199 File->Folder= Priv->Files[Priv->FilesLocationsCurrent]->Folder;
200 CopyUnicodeString(File->Name,Priv->Files[Priv->FilesLocationsCurrent]->Name);
201 Priv->FilesLocationsCurrent++;
202
203 if (!File->Folder) return ERR_NONE;
204
205 if (Priv->FilesLocationsCurrent > 1) {
206 if (File->ID_FullName[0]!=Priv->Files[Priv->FilesLocationsCurrent-2]->ID_FullName[0]) {
207 if (File->ID_FullName[0] == 'E') {
208 error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
209 error = DCT4_SetPhoneMode(s, DCT4_MODE_TEST);
210 }
211 if (File->ID_FullName[0] == 'C') {
212 error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
213 error = DCT4_SetPhoneMode(s, DCT4_MODE_LOCAL);
214 }
215 // if (error != ERR_NONE) return error;
216 }
217 }
218
219 File->ReadOnly = false;
220 File->System = false;
221 File->Protected = false;
222 File->Hidden = false;
223
224 return N3650_GetFolderInfo(s, File);
225}
226
227static GSM_Error N3650_Initialise (GSM_StateMachine *s)
228{
229 GSM_Phone_N3650Data *Priv = &s->Phone.Data.Priv.N3650;
230 int i;
231
232 for (i=0;i<10000;i++) {
233 Priv->Files[i] = malloc(sizeof(GSM_File));
234 if (Priv->Files[i] == NULL) return ERR_MOREMEMORY;
235 }
236 return ERR_NONE;
237}
238
239static GSM_Error N3650_Terminate(GSM_StateMachine *s)
240{
241 GSM_Phone_N3650Data *Priv = &s->Phone.Data.Priv.N3650;
242 int i;
243
244 for (i=0;i<10000;i++) free(Priv->Files[i]);
245 return ERR_NONE;
246}
247
248static GSM_Reply_Function N3650ReplyFunctions[] = {
249 {DCT4_ReplySetPhoneMode, "\x15",0x03,0x64,ID_Reset },
250 {DCT4_ReplyGetPhoneMode, "\x15",0x03,0x65,ID_Reset },
251 {NoneReply, "\x15",0x03,0x68,ID_Reset },
252
253 {DCT4_ReplyGetIMEI, "\x1B",0x03,0x01,ID_GetIMEI },
254 {NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x08,ID_GetHardware },
255 {NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x0C,ID_GetProductCode },
256
257 {N3650_ReplyGetFolderInfo, "\x58",0x03,0x0C,ID_GetFile },
258 {N3650_ReplyGetFilePart, "\x58",0x03,0x0E,ID_GetFile },
259
260 {NULL, "\x00",0x00,0x00,ID_None }
261};
262
263GSM_Phone_Functions N3650Phone = {
264 "3650|NGAGE",
265 N3650ReplyFunctions,
266 N3650_Initialise,
267 N3650_Terminate,
268 GSM_DispatchMessage,
269 NOTSUPPORTED, /* ShowStartInfo */
270 NOKIA_GetManufacturer,
271 DCT3DCT4_GetModel,
272 DCT3DCT4_GetFirmware,
273 DCT4_GetIMEI,
274 NOTSUPPORTED, /* GetOriginalIMEI */
275 NOTSUPPORTED, /* GetManufactureMonth*/
276 DCT4_GetProductCode,
277 DCT4_GetHardware,
278 NOTSUPPORTED, /* GetPPM */
279 NOTSUPPORTED, /* GetSIMIMSI */
280 NOTSUPPORTED, /* GetDateTime */
281 NOTSUPPORTED, /* SetDateTime */
282 NOTSUPPORTED, /* GetAlarm */
283 NOTSUPPORTED, /* SetAlarm */
284 NOTSUPPORTED, /* GetLocale */
285 NOTSUPPORTED, /* SetLocale */
286 NOTSUPPORTED, /* PressKey */
287 DCT4_Reset,
288 NOTSUPPORTED, /* ResetPhoneSettings*/
289 NOTSUPPORTED, /* EnterSecurityCode*/
290 NOTSUPPORTED, /* GetSecurityStatus*/
291 NOTSUPPORTED, /* GetDisplayStatus*/
292 NOTSUPPORTED, /* SetAutoNetworkLogin*/
293 NOTSUPPORTED, /* GetBatteryCharge*/
294 NOTSUPPORTED, /* GetSignalQuality*/
295 NOTSUPPORTED, /* GetNetworkInfo */
296 NOTSUPPORTED, /* GetCategory */
297 NOTSUPPORTED, /* AddCategory */
298 NOTSUPPORTED, /* GetCategoryStatus */
299 NOTSUPPORTED, /* GetMemoryStatus */
300 NOTSUPPORTED, /* GetMemory */
301 NOTSUPPORTED, /* GetNextMemory */
302 NOTSUPPORTED, /* SetMemory */
303 NOTSUPPORTED, /* AddMemory */
304 NOTSUPPORTED, /* DeleteMemory */
305 NOTIMPLEMENTED, /* DeleteAllMemory */
306 NOTSUPPORTED, /* GetSpeedDial */
307 NOTSUPPORTED, /* SetSpeedDial */
308 NOTSUPPORTED, /* GetSMSC */
309 NOTSUPPORTED, /* SetSMSC */
310 NOTSUPPORTED, /* GetSMSStatus */
311 NOTSUPPORTED, /* GetSMS */
312 NOTSUPPORTED, /* GetNextSMS */
313 NOTSUPPORTED, /* SetSMS */
314 NOTSUPPORTED, /* AddSMS */
315 NOTSUPPORTED, /* DeleteSMS */
316 NOTSUPPORTED, /* SendSMS */
317 NOTSUPPORTED, /* SendSavedSMS */
318 NOTSUPPORTED, /* SetIncomingSMS */
319 NOTSUPPORTED, /* SetIncomingCB */
320 NOTSUPPORTED, /* GetSMSFolders */
321 NOTSUPPORTED, /* AddSMSFolder */
322 NOTSUPPORTED, /* DeleteSMSFolder */
323 NOTIMPLEMENTED, /* DialVoice */
324 NOTIMPLEMENTED, /* AnswerCall */
325 NOTIMPLEMENTED, /* CancelCall */
326 NOTIMPLEMENTED, /* HoldCall */
327 NOTIMPLEMENTED, /* UnholdCall */
328 NOTIMPLEMENTED, /* ConferenceCall */
329 NOTIMPLEMENTED, /* SplitCall */
330 NOTIMPLEMENTED, /* TransferCall */
331 NOTIMPLEMENTED, /* SwitchCall */
332 NOTSUPPORTED, /* GetCallDivert */
333 NOTSUPPORTED, /* SetCallDivert */
334 NOTSUPPORTED, /* CancelAllDiverts*/
335 NOTIMPLEMENTED, /* SetIncomingCall */
336 NOTIMPLEMENTED, /* SetIncomingUSSD */
337 NOTSUPPORTED, /* SendDTMF */
338 NOTSUPPORTED, /* GetRingtone */
339 NOTSUPPORTED, /* SetRingtone */
340 NOTSUPPORTED, /* GetRingtonesInfo*/
341 NOTIMPLEMENTED, /* DeleteUserRingtones*/
342 NOTSUPPORTED, /* PlayTone */
343 NOTSUPPORTED, /* GetWAPBookmark */
344 NOTSUPPORTED, /* SetWAPBookmark */
345 NOTSUPPORTED, /* DeleteWAPBookmark */
346 NOTSUPPORTED, /* GetWAPSettings */
347 NOTSUPPORTED, /* SetWAPSettings */
348 NOTSUPPORTED, /* GetMMSSettings */
349 NOTSUPPORTED, /* SetMMSSettings */
350 NOTSUPPORTED, /* GetSyncMLSettings*/
351 NOTSUPPORTED, /* SetSyncMLSettings*/
352 NOTSUPPORTED, /* GetChatSettings */
353 NOTSUPPORTED, /* SetChatSettings */
354 NOTSUPPORTED, /* GetBitmap */
355 NOTSUPPORTED, /* SetBitmap */
356 NOTSUPPORTED, /* GetToDoStatus */
357 NOTSUPPORTED, /* GetToDo */
358 NOTSUPPORTED, /* GetNextToDo */
359 NOTSUPPORTED, /* SetToDo */
360 NOTSUPPORTED, /* AddToDo */
361 NOTSUPPORTED, /* DeleteToDo */
362 NOTSUPPORTED, /* DeleteAllToDo */
363 NOTIMPLEMENTED, /* GetCalendarStatus*/
364 NOTIMPLEMENTED, /* GetCalendar */
365 NOTSUPPORTED, /* GetNextCalendar */
366 NOTIMPLEMENTED, /* SetCalendar */
367 NOTSUPPORTED, /* AddCalendar */
368 NOTSUPPORTED, /* DeleteCalendar */
369 NOTIMPLEMENTED, /* DeleteAllCalendar*/
370 NOTSUPPORTED, /* GetCalendarSettings*/
371 NOTSUPPORTED, /* SetCalendarSettings*/
372 NOTSUPPORTED, /* GetNote */
373 NOTSUPPORTED, /* GetProfile */
374 NOTSUPPORTED, /* SetProfile */
375 NOTSUPPORTED, /* GetFMStation */
376 NOTSUPPORTED, /* SetFMStation */
377 NOTSUPPORTED, /* ClearFMStations */
378 N3650_GetNextFileFolder,
379 N3650_GetFilePart,
380 NOTIMPLEMENTED, /* AddFilePart */
381 NOTSUPPORTED, /* GetFileSystemStatus*/
382 NOTIMPLEMENTED, /* DeleteFile */
383 NOTIMPLEMENTED, /* AddFolder */
384 NOTSUPPORTED, /* GetGPRSAccessPoint*/
385 NOTSUPPORTED /* SetGPRSAccessPoint*/
386};
387
388#endif
389
390/* How should editor hadle tabs in this file? Add editor commands here.
391 * vim: noexpandtab sw=8 ts=8 sts=8:
392 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n3650.h b/gammu/emb/common/phone/nokia/dct4/n3650.h
new file mode 100644
index 0000000..7769ba5
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n3650.h
@@ -0,0 +1,30 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef n3650_h
4#define n3650_h
5
6#include "../../../gsmcomon.h"
7#include "../../../gsmstate.h"
8#include "../../../service/gsmmisc.h"
9#include "../../../service/sms/gsmsms.h"
10
11#ifndef GSM_USED_MBUS2
12# define GSM_USED_MBUS2
13#endif
14#ifndef GSM_USED_FBUS2
15# define GSM_USED_FBUS2
16#endif
17
18typedef struct {
19 int FileLev;
20 int FilesLocationsUsed;
21 int FilesLocationsCurrent;
22 GSM_File *Files[10000];
23 int FileEntries;
24} GSM_Phone_N3650Data;
25
26#endif
27
28/* How should editor hadle tabs in this file? Add editor commands here.
29 * vim: noexpandtab sw=8 ts=8 sts=8:
30 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n6510.c b/gammu/emb/common/phone/nokia/dct4/n6510.c
new file mode 100644
index 0000000..67fe492
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n6510.c
@@ -0,0 +1,5782 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* based on some work from Markus Plail, Pawel Kot and Gnokii */
3/* function for making CRC for filesystem (c) 2003 by Michael Schroeder */
4
5#include "../../../gsmstate.h"
6
7#ifdef GSM_ENABLE_NOKIA6510
8
9#include <string.h>
10#include <time.h>
11
12#include "../../../misc/coding/coding.h"
13#include "../../../gsmcomon.h"
14#include "../../../service/gsmlogo.h"
15#include "../nfunc.h"
16#include "../nfuncold.h"
17#include "../../pfunc.h"
18#include "dct4func.h"
19#include "n6510.h"
20
21static GSM_Error N6510_Initialise (GSM_StateMachine *s)
22{
23 s->Phone.Data.Priv.N6510.CalendarIconsNum = 0;
24
25 /* Enables various things like incoming SMS, call info, etc. */
26 return N71_65_EnableFunctions (s, "\x01\x02\x06\x0A\x14\x17\x39", 7);
27}
28
29static GSM_Error N6510_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
30{
31 smprintf(s, "Phonebook entry received\n");
32 switch (msg.Buffer[6]) {
33 case 0x0f:
34 return N71_65_ReplyGetMemoryError(msg.Buffer[10], s);
35 default:
36 return N71_65_DecodePhonebook(s, s->Phone.Data.Memory, s->Phone.Data.Bitmap, s->Phone.Data.SpeedDial, msg.Buffer+22, msg.Length-22,false);
37 }
38 return ERR_UNKNOWN;
39}
40
41static GSM_Error N6510_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
42{
43 unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
44 0xfe, 0x10, /* memory type */
45 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x01, /* location */
47 0x00, 0x00, 0x01};
48
49 req[9] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
50 if (req[9]==0xff) return ERR_NOTSUPPORTED;
51
52 if (entry->Location==0x00) return ERR_INVALIDLOCATION;
53
54 req[14] = entry->Location / 256;
55 req[15] = entry->Location % 256;
56
57 s->Phone.Data.Memory=entry;
58 smprintf(s, "Getting phonebook entry\n");
59 return GSM_WaitFor (s, req, 19, 0x03, 4, ID_GetMemory);
60}
61
62static GSM_Error N6510_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
63{
64 GSM_Phone_Data *Data = &s->Phone.Data;
65
66 smprintf(s, "Memory status received\n");
67 /* Quess ;-)) */
68 if (msg.Buffer[14]==0x10) {
69 Data->MemoryStatus->MemoryFree = msg.Buffer[18]*256 + msg.Buffer[19];
70 } else {
71 Data->MemoryStatus->MemoryFree = msg.Buffer[17];
72 }
73 smprintf(s, "Size : %i\n",Data->MemoryStatus->MemoryFree);
74 Data->MemoryStatus->MemoryUsed = msg.Buffer[20]*256 + msg.Buffer[21];
75 smprintf(s, "Used : %i\n",Data->MemoryStatus->MemoryUsed);
76 Data->MemoryStatus->MemoryFree -= Data->MemoryStatus->MemoryUsed;
77 smprintf(s, "Free : %i\n",Data->MemoryStatus->MemoryFree);
78 return ERR_NONE;
79}
80
81static GSM_Error N6510_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
82{
83 unsigned char req[] = {N6110_FRAME_HEADER, 0x03, 0x02,
84 0x00, /* memory type */
85 0x55, 0x55, 0x55, 0x00};
86
87 req[5] = NOKIA_GetMemoryType(s, Status->MemoryType,N71_65_MEMORY_TYPES);
88 if (req[5]==0xff) return ERR_NOTSUPPORTED;
89
90 s->Phone.Data.MemoryStatus=Status;
91 smprintf(s, "Getting memory status\n");
92 return GSM_WaitFor (s, req, 10, 0x03, 4, ID_GetMemoryStatus);
93}
94
95static GSM_Error N6510_ReplyGetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
96{
97 int i, current, j;
98 GSM_Phone_Data *Data = &s->Phone.Data;
99
100 switch (msg.Buffer[4]) {
101 case 0x00:
102 smprintf(s, "SMSC received\n");
103 break;
104 case 0x02:
105 smprintf(s, "SMSC empty\n");
106 return ERR_INVALIDLOCATION;
107 default:
108 smprintf(s, "Unknown SMSC state: %02x\n",msg.Buffer[4]);
109 return ERR_UNKNOWNRESPONSE;
110 }
111 memset(Data->SMSC,0,sizeof(GSM_SMSC));
112 Data->SMSC->Location = msg.Buffer[8];
113 Data->SMSC->Format = SMS_FORMAT_Text;
114 switch (msg.Buffer[10]) {
115 case 0x00: Data->SMSC->Format = SMS_FORMAT_Text; break;
116 case 0x22: Data->SMSC->Format = SMS_FORMAT_Fax; break;
117 case 0x26: Data->SMSC->Format = SMS_FORMAT_Pager;break;
118 case 0x32: Data->SMSC->Format = SMS_FORMAT_Email;break;
119 }
120 Data->SMSC->Validity.Format= SMS_Validity_RelativeFormat;
121 Data->SMSC->Validity.Relative= msg.Buffer[12];
122 current = 14;
123 for (i=0;i<msg.Buffer[13];i++) {
124 switch (msg.Buffer[current]) {
125 case 0x81:
126 j=current+4;
127 while (msg.Buffer[j]!=0) {j++;}
128 j=j-33;
129 if (j>GSM_MAX_SMSC_NAME_LENGTH) {
130 smprintf(s, "Too long name\n");
131 return ERR_UNKNOWNRESPONSE;
132 }
133 CopyUnicodeString(Data->SMSC->Name,msg.Buffer+current+4);
134 smprintf(s, " Name \"%s\"\n", DecodeUnicodeString(Data->SMSC->Name));
135 break;
136 case 0x82:
137 switch (msg.Buffer[current+2]) {
138 case 0x01:
139 GSM_UnpackSemiOctetNumber(Data->SMSC->DefaultNumber,msg.Buffer+current+4,true);
140 smprintf(s, " Default number \"%s\"\n", DecodeUnicodeString(Data->SMSC->DefaultNumber));
141 break;
142 case 0x02:
143 GSM_UnpackSemiOctetNumber(Data->SMSC->Number,msg.Buffer+current+4,false);
144 smprintf(s, " Number \"%s\"\n", DecodeUnicodeString(Data->SMSC->Number));
145 break;
146 default:
147 smprintf(s, "Unknown SMSC number: %02x\n",msg.Buffer[current+2]);
148 return ERR_UNKNOWNRESPONSE;
149 }
150 break;
151 default:
152 smprintf(s, "Unknown SMSC block: %02x\n",msg.Buffer[current]);
153 return ERR_UNKNOWNRESPONSE;
154 }
155 current = current + msg.Buffer[current+1];
156 }
157 return ERR_NONE;
158}
159
160static GSM_Error N6510_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
161{
162 unsigned char req[] = {N6110_FRAME_HEADER, 0x14,
163 0x01, /* location */
164 0x00};
165
166 if (smsc->Location==0x00) return ERR_INVALIDLOCATION;
167
168 req[4]=smsc->Location;
169
170 s->Phone.Data.SMSC=smsc;
171 smprintf(s, "Getting SMSC\n");
172 return GSM_WaitFor (s, req, 6, 0x02, 4, ID_GetSMSC);
173}
174
175static GSM_Error N6510_ReplySetSMSC(GSM_Protocol_Message msg, GSM_StateMachine *s)
176{
177 switch (msg.Buffer[4]) {
178 case 0x00:
179 smprintf(s, "SMSC set OK\n");
180 return ERR_NONE;
181 case 0x02:
182 smprintf(s, "Invalid SMSC location\n");
183 return ERR_INVALIDLOCATION;
184 default:
185 smprintf(s, "Unknown SMSC state: %02x\n",msg.Buffer[4]);
186 return ERR_UNKNOWNRESPONSE;
187 }
188 return ERR_UNKNOWNRESPONSE;
189}
190
191static GSM_Error N6510_SetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
192{
193 int count = 13,i;
194 unsigned char req[256] = {N6110_FRAME_HEADER,
195 0x12, 0x55, 0x01, 0x0B, 0x34,
196 0x05, /* Location */
197 0x00,
198 0x00, /* Format */
199 0x00,
200 0xFF}; /* Validity*/
201
202 req[8] = smsc->Location;
203 switch (smsc->Format) {
204 case SMS_FORMAT_Text: req[10] = 0x00;break;
205 case SMS_FORMAT_Fax: req[10] = 0x22;break;
206 case SMS_FORMAT_Pager: req[10] = 0x26;break;
207 case SMS_FORMAT_Email: req[10] = 0x32;break;
208 }
209 req[12] = smsc->Validity.Relative;
210
211 /* We have now blocks. Number of blocks = 3 */
212 req[count++] = 0x03;
213
214 /* -------------- SMSC number ----------------- */
215 /* Block type: number */
216 req[count++] = 0x82;
217 /* Offset to next block */
218 req[count++] = 0x1A;
219 /* Type of number: SMSC number */
220 req[count++] = 0x02;
221 req[count] = GSM_PackSemiOctetNumber(smsc->Number, req+count+2, false) + 1;
222 if (req[count]>18) {
223 smprintf(s, "Too long SMSC number in frame\n");
224 return ERR_UNKNOWN;
225 }
226 req[count+1] = req[count] - 1;
227 count += 23;
228
229 /* --------------- Default number ------------- */
230 /* Block type: number */
231 req[count++] = 0x82;
232 /* Offset to next block */
233 req[count++] = 0x14;
234 /* Type of number: default number */
235 req[count++] = 0x01;
236 req[count] = GSM_PackSemiOctetNumber(smsc->DefaultNumber, req+count+2, true) + 1;
237 if (req[count]*2>12) {
238 smprintf(s, "Too long SMSC number in frame\n");
239 return ERR_UNKNOWN;
240 }
241 req[count+1] = req[count] - 1;
242 count += 17;
243
244 /* -------------- SMSC name ------------------- */
245 req[count++] = 0x81;
246 req[count++] = UnicodeLength(smsc->Name)*2 + 2 + 4;
247 req[count++] = UnicodeLength(smsc->Name)*2 + 2;
248 req[count++] = 0x00;
249 /* Can't make CopyUnicodeString(req+count,sms->Name) !!!!
250 * with MSVC6 count is changed then
251 */
252 i = count;
253 CopyUnicodeString(req+i,smsc->Name);
254 count += UnicodeLength(smsc->Name)*2 + 2;
255
256 smprintf(s, "Setting SMSC\n");
257 return GSM_WaitFor (s, req, count, 0x02, 4, ID_SetSMSC);
258}
259
260static GSM_Error N6510_ReplyGetNetworkInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
261{
262 int current = msg.Buffer[7]+7, tmp;
263 GSM_Phone_Data*Data = &s->Phone.Data;
264#ifdef DEBUG
265 char name[100];
266 GSM_NetworkInfo NetInfo;
267
268 smprintf(s, "Network status: ");
269 switch (msg.Buffer[8]) {
270 case 0x00 : smprintf(s, "home network\n"); break;
271 case 0x01 : smprintf(s, "roaming network\n"); break;
272 case 0x04 : smprintf(s, "not logged"); break;
273 case 0x06 : smprintf(s, "SIM card rejected\n"); break;
274 case 0x09 : smprintf(s, "not logged"); break;
275 default : smprintf(s, "unknown %i!\n",msg.Buffer[8]); break;
276 }
277 if (msg.Buffer[8]==0x00 || msg.Buffer[8] == 0x01) {
278 NOKIA_DecodeNetworkCode(msg.Buffer + (current + 7),NetInfo.NetworkCode);
279 smprintf(s, "Network code : %s\n", NetInfo.NetworkCode);
280 smprintf(s, "Network name for Gammu : %s ",
281 DecodeUnicodeString(GSM_GetNetworkName(NetInfo.NetworkCode)));
282 smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(NetInfo.NetworkCode)));
283
284 sprintf(NetInfo.LAC,"%02x%02x", msg.Buffer[current+1], msg.Buffer[current+2]);
285 smprintf(s, "LAC : %s\n", NetInfo.LAC);
286
287 sprintf(NetInfo.CID, "%02x%02x", msg.Buffer[current+5], msg.Buffer[current+6]);
288 smprintf(s, "CID : %s\n", NetInfo.CID);
289
290 tmp = 10;
291 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,name,true);
292 smprintf(s, "Network name for phone : %s\n",DecodeUnicodeString(name));
293 }
294#endif
295 if (Data->RequestID==ID_GetNetworkInfo) {
296 Data->NetworkInfo->NetworkName[0] = 0x00;
297 Data->NetworkInfo->NetworkName[1] = 0x00;
298 Data->NetworkInfo->State = 0;
299 switch (msg.Buffer[8]) {
300 case 0x00: Data->NetworkInfo->State = GSM_HomeNetwork; break;
301 case 0x01: Data->NetworkInfo->State = GSM_RoamingNetwork;break;
302 case 0x04:
303 case 0x06:
304 case 0x09: Data->NetworkInfo->State = GSM_NoNetwork; break;
305 }
306 if (Data->NetworkInfo->State == GSM_HomeNetwork || Data->NetworkInfo->State == GSM_RoamingNetwork) {
307 tmp = 10;
308 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,Data->NetworkInfo->NetworkName,true);
309 sprintf(Data->NetworkInfo->LAC, "%02x%02x", msg.Buffer[current+1], msg.Buffer[current+2]);
310 sprintf(Data->NetworkInfo->CID, "%02x%02x", msg.Buffer[current+5], msg.Buffer[current+6]);
311 NOKIA_DecodeNetworkCode(msg.Buffer + (current+7),Data->NetworkInfo->NetworkCode);
312 }
313 }
314 return ERR_NONE;
315}
316
317static GSM_Error N6510_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
318{
319 unsigned char req[] = {N6110_FRAME_HEADER, 0x00, 0x00};
320
321 s->Phone.Data.NetworkInfo=netinfo;
322 smprintf(s, "Getting network info\n");
323 return GSM_WaitFor (s, req, 5, 0x0a, 4, ID_GetNetworkInfo);
324}
325
326static GSM_Error N6510_EncodeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *req, GSM_SMSMessageLayout *Layout, int *length)
327{
328 int start, count = 0, pos1, pos2, pos3, pos4, pos5;
329 GSM_Error error;
330
331 memset(Layout,255,sizeof(GSM_SMSMessageLayout));
332
333 start = *length;
334
335 req[count++] = 0x01;
336 if (sms->PDU != SMS_Deliver) {
337 req[count++] = 0x02;
338 } else {
339 req[count++] = 0x00;
340 }
341
342 pos1 = count; count++;
343 /* firstbyte set in SMS Layout */
344 Layout->firstbyte = count; count++;
345 if (sms->PDU != SMS_Deliver) {
346 Layout->TPMR = count; count++;
347
348 Layout->TPPID = count; count++;
349
350 /* TP.DCS set in SMS layout */
351 Layout->TPDCS = count; count++;
352 req[count++] = 0x00;
353 } else {
354 Layout->TPPID = count; count++;
355 /* TP.DCS set in SMS layout */
356 Layout->TPDCS = count; count++;
357 Layout->DateTime = count; count += 7;
358 req[count++] = 0x55;
359 req[count++] = 0x55;
360 req[count++] = 0x55;
361 }
362
363 /* We have now blocks. Number of blocks = 3 or 4 */
364 if (sms->PDU != SMS_Deliver) {
365 req[count++] = 0x04;
366 } else {
367 req[count++] = 0x03;
368 }
369
370 /* -------------- Phone number ------------- */
371 /* Block type: number */
372 req[count++] = 0x82;
373 /* Offset to next block */
374 req[count++] = 0x10;
375 /* Type of number: default number */
376 req[count++] = 0x01;
377 pos4 = count; count++;
378 /* now coded Number in SMS Layout */
379 Layout->Number = count; count+= 12;
380
381 /* -------------- SMSC number -------------- */
382 /* Block type: number */
383 req[count++] = 0x82;
384 /* Offset to next block */
385 req[count++] = 0x10;
386 /* Type of number: SMSC number */
387 req[count++] = 0x02;
388 pos5 = count; count++;
389 /* now coded SMSC number in SMS Layout */
390 Layout->SMSCNumber = count; count += 12;
391
392 /* -------------- SMS validity ------------- */
393 if (sms->PDU != SMS_Deliver) {
394 /* Block type: validity */
395 req[count++] = 0x08;
396 req[count++] = 0x04;
397 /* data length */
398 req[count++] = 0x01;
399 Layout->TPVP = count; count++;
400 }
401
402 /* --------------- SMS text ---------------- */
403 /* Block type: SMS text */
404 req[count++] = 0x80;
405 /* this the same as req[11] but starting from req[42] */
406 pos2 = count; count++;
407 pos3 = count; count++;
408 /* FIXME*/
409 Layout->TPUDL = count; count++;
410 /* SMS text and UDH coded in SMS Layout */
411 Layout->Text = count;
412
413 error = PHONE_EncodeSMSFrame(s,sms,req,*Layout,length,false);
414 if (error != ERR_NONE) return error;
415
416 req[pos1] = *length - 1;
417 req[pos2] = *length - Layout->Text + 6;
418 req[pos3] = *length - Layout->Text;
419
420 /* Convert number of semioctets to number of chars */
421 req[pos4] = req[Layout->Number] + 4;
422 if (req[pos4] % 2) req[pos4]++;
423 req[pos4] /= 2;
424
425 req[pos5] = req[Layout->SMSCNumber] + 1;
426
427 if (req[pos4]>12 || req[pos5]>12) {
428 smprintf(s, "Too long phone number in frame\n");
429 return ERR_UNKNOWN;
430 }
431
432 return ERR_NONE;
433}
434
435static GSM_Error N6510_ReplyGetSMSFolders(GSM_Protocol_Message msg, GSM_StateMachine *s)
436{
437 int j, num = 0, pos;
438 GSM_Phone_Data *Data = &s->Phone.Data;
439
440 switch (msg.Buffer[3]) {
441 case 0x13:
442 smprintf(s, "SMS folders names received\n");
443 Data->SMSFolders->Number = msg.Buffer[5]+2;
444 pos = 6;
445 for (j=0;j<msg.Buffer[5];j++) {
446 while (true) {
447 if (msg.Buffer[pos] == msg.Buffer[6] &&
448 msg.Buffer[pos+1] == msg.Buffer[7]) break;
449 if (pos+4 > msg.Length) return ERR_UNKNOWNRESPONSE;
450 pos++;
451 }
452 pos+=4;
453 smprintf(s, "Folder index: %02x",msg.Buffer[pos - 2]);
454 if (msg.Buffer[pos - 1]>GSM_MAX_SMS_FOLDER_NAME_LEN) {
455 smprintf(s, "Too long text\n");
456 return ERR_UNKNOWNRESPONSE;
457 }
458 CopyUnicodeString(Data->SMSFolders->Folder[num].Name,msg.Buffer + pos);
459 smprintf(s, ", folder name: \"%s\"\n",DecodeUnicodeString(Data->SMSFolders->Folder[num].Name));
460 Data->SMSFolders->Folder[num].InboxFolder = false;
461 Data->SMSFolders->Folder[num].Memory = MEM_ME;
462 if (num == 0x01) { /* OUTBOX SIM */
463 Data->SMSFolders->Folder[0].Memory = MEM_SM;
464 Data->SMSFolders->Folder[0].InboxFolder = true;
465
466 Data->SMSFolders->Folder[1].Memory = MEM_SM;
467
468 CopyUnicodeString(Data->SMSFolders->Folder[2].Name,Data->SMSFolders->Folder[0].Name);
469 Data->SMSFolders->Folder[2].Memory = MEM_ME;
470 Data->SMSFolders->Folder[2].InboxFolder = true;
471
472 CopyUnicodeString(Data->SMSFolders->Folder[3].Name,Data->SMSFolders->Folder[1].Name);
473 Data->SMSFolders->Folder[3].Memory = MEM_ME;
474 Data->SMSFolders->Folder[3].InboxFolder = false;
475
476 num+=2;
477 }
478 num++;
479 }
480 return ERR_NONE;
481 }
482 return ERR_UNKNOWNRESPONSE;
483}
484
485static GSM_Error N6510_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
486{
487 unsigned char req[] = {N6110_FRAME_HEADER, 0x12, 0x00, 0x00};
488
489 s->Phone.Data.SMSFolders=folders;
490 smprintf(s, "Getting SMS folders\n");
491 return GSM_WaitFor (s, req, 6, 0x14, 4, ID_GetSMSFolders);
492}
493
494static GSM_Error N6510_ReplyGetSMSFolderStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
495{
496 int i;
497 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
498
499 smprintf(s, "SMS folder status received\n");
500 Priv->LastSMSFolder.Number=msg.Buffer[6]*256+msg.Buffer[7];
501 smprintf(s, "Number of Entries: %i\n",Priv->LastSMSFolder.Number);
502 smprintf(s, "Locations: ");
503 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
504 Priv->LastSMSFolder.Location[i]=msg.Buffer[8+(i*2)]*256+msg.Buffer[(i*2)+9];
505 smprintf(s, "%i ",Priv->LastSMSFolder.Location[i]);
506 }
507 smprintf(s, "\n");
508 NOKIA_SortSMSFolderStatus(s, &Priv->LastSMSFolder);
509 return ERR_NONE;
510}
511
512static GSM_Error N6510_GetSMSFolderStatus(GSM_StateMachine *s, int folderid)
513{
514 unsigned char req[] = {N7110_FRAME_HEADER, 0x0C,
515 0x01, /* 0x01=SIM, 0x02=ME */
516 0x00, /* Folder ID */
517 0x0f, 0x55, 0x55, 0x55};
518
519 switch (folderid) {
520 case 0x01: req[5] = 0x02; break; /* INBOX SIM */
521 case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
522 default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders*/
523 }
524
525 smprintf(s, "Getting SMS folder status\n");
526 return GSM_WaitFor (s, req, 10, 0x14, 4, ID_GetSMSFolderStatus);
527}
528
529static void N6510_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
530{
531 int ifolderid;
532
533 /* simulate flat SMS memory */
534 if (sms->Folder==0x00) {
535 ifolderid = sms->Location / PHONE_MAXSMSINFOLDER;
536 *folderid = ifolderid + 0x01;
537 *location = sms->Location - ifolderid * PHONE_MAXSMSINFOLDER;
538 } else {
539 *folderid = sms->Folder;
540 *location = sms->Location;
541 }
542 smprintf(s, "SMS folder %i & location %i -> 6510 folder %i & location %i\n",
543 sms->Folder,sms->Location,*folderid,*location);
544}
545
546static void N6510_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
547{
548 sms->Folder= 0;
549 sms->Location= (folderid - 0x01) * PHONE_MAXSMSINFOLDER + location;
550 smprintf(s, "6510 folder %i & location %i -> SMS folder %i & location %i\n",
551 folderid,location,sms->Folder,sms->Location);
552}
553
554static GSM_Error N6510_DecodeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *buffer)
555{
556 int i, current, blocks=0, SMSTemplateDateTime = 0;
557 GSM_SMSMessageLayout Layout;
558 GSM_Error error;
559
560 memset(&Layout,255,sizeof(GSM_SMSMessageLayout));
561 Layout.firstbyte = 2;
562 switch (buffer[0]) {
563 case 0x00:
564 smprintf(s, "SMS deliver\n");
565 sms->PDU = SMS_Deliver;
566 Layout.TPPID = 3;
567 Layout.TPDCS = 4;
568 Layout.DateTime = 5;
569 blocks = 15;
570 break;
571 case 0x01:
572 smprintf(s, "Delivery report\n");
573 sms->PDU = SMS_Status_Report;
574 Layout.TPMR= 3;
575 Layout.TPStatus= 4;
576 Layout.DateTime = 5;
577 Layout.SMSCTime = 12;
578 blocks = 19;
579 break;
580 case 0x02:
581 smprintf(s, "SMS template\n");
582 sms->PDU = SMS_Submit;
583 Layout.TPMR= 3;
584 Layout.TPPID = 4;
585 Layout.TPDCS = 5;
586 blocks = 7;
587 break;
588 }
589 current = blocks + 1;
590 for (i=0;i<buffer[blocks];i++) {
591 switch (buffer[current]) {
592 case 0x80:
593 smprintf(s, "SMS text\n");
594 if (buffer[current + 2] > buffer[current + 3]) {
595 Layout.TPUDL = current + 2;
596 } else {
597 Layout.TPUDL = current + 3;
598 }
599 Layout.Text = current + 4;
600 break;
601 case 0x82:
602 switch (buffer[current+2]) {
603 case 0x01:
604 smprintf(s, "Phone number\n");
605 Layout.Number = current + 4;
606 break;
607 case 0x02:
608 smprintf(s, "SMSC number\n");
609 Layout.SMSCNumber = current + 4;
610 break;
611 default:
612 smprintf(s, "Unknown number\n");
613 break;
614 }
615 break;
616 case 0x84:
617 smprintf(s, "Date and time of saving for SMS template\n");
618 SMSTemplateDateTime = current + 2;
619 break;
620 default:
621 smprintf(s, "Unknown block %02x\n",buffer[current]);
622 }
623 current = current + buffer[current + 1];
624 }
625 error=GSM_DecodeSMSFrame(sms,buffer,Layout);
626 if (SMSTemplateDateTime != 0) {
627 sms->PDU = SMS_Deliver;
628 NOKIA_DecodeDateTime(s, buffer+SMSTemplateDateTime, &sms->DateTime);
629 sms->DateTime.Timezone = 0;
630 }
631 return error;
632}
633
634static GSM_Error N6510_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
635{
636 int i;
637 int Width, Height;
638 unsigned char output[500]; //output2[500];
639 GSM_Phone_Data *Data = &s->Phone.Data;
640
641 switch(msg.Buffer[3]) {
642 case 0x03:
643 smprintf(s, "SMS Message received\n");
644 Data->GetSMSMessage->Number=1;
645 NOKIA_DecodeSMSState(s, msg.Buffer[5], &Data->GetSMSMessage->SMS[0]);
646 switch (msg.Buffer[14]) {
647 case 0x00:
648 case 0x01:
649 case 0x02:
650 return N6510_DecodeSMSFrame(s, &Data->GetSMSMessage->SMS[0],msg.Buffer+14);
651 case 0xA0:
652 smprintf(s, "Picture Image\n");
653 Data->GetSMSMessage->Number = 0;
654 i = 0;
655 output[i++] = 0x30; /* Smart Messaging 3.0 */
656 output[i++] = SM30_OTA;
657 output[i++] = 0x01; /* Length */
658 output[i++] = 0x00; /* Length */
659 output[i++] = 0x00;
660 PHONE_GetBitmapWidthHeight(GSM_NokiaPictureImage, &Width, &Height);
661 output[i++] = Width;
662 output[i++] = Height;
663 output[i++] = 0x01;
664 memcpy(output+i,msg.Buffer+30,PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0));
665 i = i + PHONE_GetBitmapSize(GSM_NokiaPictureImage,0,0);
666 // if (msg.Length!=282) {
667 // output[i++] = SM30_UNICODETEXT;
668 // output[i++] = 0;
669 // output[i++] = 0; /* Length - later changed */
670 // GSM_UnpackEightBitsToSeven(0, msg.Length-282, msg.Length-304, msg.Buffer+282,output2);
671 // DecodeDefault(output+i, output2, msg.Length - 282, true);
672 // output[i - 1] = UnicodeLength(output+i) * 2;
673 // i = i + output[i-1];
674 // }
675 GSM_MakeMultiPartSMS(Data->GetSMSMessage,output,i,UDH_NokiaProfileLong,SMS_Coding_8bit,1,0);
676 for (i=0;i<3;i++) {
677 Data->GetSMSMessage->SMS[i].Number[0]=0;
678 Data->GetSMSMessage->SMS[i].Number[1]=0;
679 }
680 if (Data->Bitmap != NULL) {
681 Data->Bitmap->Location= 0;
682 PHONE_GetBitmapWidthHeight(GSM_NokiaPictureImage, &Width, &Height);
683 Data->Bitmap->BitmapWidth= Width;
684 Data->Bitmap->BitmapHeight= Height;
685 PHONE_DecodeBitmap(GSM_NokiaPictureImage, msg.Buffer + 30, Data->Bitmap);
686 Data->Bitmap->Sender[0] = 0x00;
687 Data->Bitmap->Sender[1] = 0x00;
688 Data->Bitmap->Text[0] = 0;
689 Data->Bitmap->Text[1] = 0;
690 }
691 return ERR_NONE;
692 default:
693 smprintf(s, "Unknown SMS type: %i\n",msg.Buffer[8]);
694 }
695 break;
696 case 0x0f:
697 smprintf(s, "SMS message info received\n");
698 CopyUnicodeString(Data->GetSMSMessage->SMS[0].Name,msg.Buffer+52);
699 smprintf(s, "Name: \"%s\"\n",DecodeUnicodeString(Data->GetSMSMessage->SMS[0].Name));
700 return ERR_NONE;
701 }
702 return ERR_UNKNOWNRESPONSE;
703}
704
705static GSM_Error N6510_PrivGetSMSMessageBitmap(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, GSM_Bitmap *bitmap)
706{
707 GSM_Error error;
708 unsigned char folderid,namebuffer[200];
709 int location;
710 int i;
711 unsigned char req[] = {
712 N6110_FRAME_HEADER,
713 0x02, /* msg type: 0x02 for getting sms, 0x0e for sms status */
714 0x01, /* 0x01=SIM, 0x02=ME */
715 0x00, /* FolderID */
716 0x00, 0x02,/* Location */
717 0x01, 0x00};
718
719 N6510_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
720
721 switch (folderid) {
722 case 0x01: req[5] = 0x02; break; /* INBOX SIM */
723 case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
724 default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders*/
725 }
726 req[6]=location / 256;
727 req[7]=location;
728
729 s->Phone.Data.GetSMSMessage = sms;
730 s->Phone.Data.Bitmap = bitmap;
731 smprintf(s, "Getting sms message info\n");
732 req[3] = 0x0e; req[8] = 0x55; req[9] = 0x55;
733 error=GSM_WaitFor (s, req, 10, 0x14, 4, ID_GetSMSMessage);
734 if (error!=ERR_NONE) return error;
735 CopyUnicodeString(namebuffer,sms->SMS[0].Name);
736
737 smprintf(s, "Getting sms\n");
738 req[3] = 0x02; req[8] = 0x01; req[9] = 0x00;
739 error=GSM_WaitFor (s, req, 10, 0x14, 4, ID_GetSMSMessage);
740 if (error==ERR_NONE) {
741 for (i=0;i<sms->Number;i++) {
742 N6510_SetSMSLocation(s, &sms->SMS[i], folderid, location);
743 sms->SMS[i].Folder = folderid;
744 sms->SMS[i].InboxFolder = true;
745 if (folderid != 0x01 && folderid != 0x03) sms->SMS[i].InboxFolder = false;
746 sms->SMS[i].Memory= MEM_ME;
747 if (folderid == 0x01 || folderid == 0x02) sms->SMS[i].Memory = MEM_SM;
748 CopyUnicodeString(sms->SMS[i].Name,namebuffer);
749 }
750 }
751 return error;
752}
753
754static GSM_Error N6510_GetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
755{
756 GSM_Error error;
757 unsigned char folderid;
758 int location;
759 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
760 int i;
761 bool found = false;
762
763 N6510_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
764 error=N6510_GetSMSFolderStatus(s, folderid);
765 if (error!=ERR_NONE) return error;
766 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
767 if (Priv->LastSMSFolder.Location[i]==location) {
768 found = true;
769 break;
770 }
771 }
772 if (!found) return ERR_EMPTY;
773 return N6510_PrivGetSMSMessageBitmap(s,sms,NULL);
774}
775
776static GSM_Error N6510_GetNextSMSMessageBitmap(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start, GSM_Bitmap *bitmap)
777{
778 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
779 unsigned char folderid;
780 int location;
781 GSM_Error error;
782 int i;
783 bool findnextfolder = false;
784
785 if (start) {
786 folderid= 0x00;
787 findnextfolder= true;
788 error=N6510_GetSMSFolders(s,&Priv->LastSMSFolders);
789 if (error!=ERR_NONE) return error;
790 } else {
791 N6510_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
792 for (i=0;i<Priv->LastSMSFolder.Number;i++) {
793 if (Priv->LastSMSFolder.Location[i]==location) break;
794 }
795 /* Is this last location in this folder ? */
796 if (i==Priv->LastSMSFolder.Number-1) {
797 findnextfolder=true;
798 } else {
799 location=Priv->LastSMSFolder.Location[i+1];
800 }
801 }
802 if (findnextfolder) {
803 Priv->LastSMSFolder.Number=0;
804 while (Priv->LastSMSFolder.Number==0) {
805 folderid++;
806 /* Too high folder number */
807 if ((folderid-1)>Priv->LastSMSFolders.Number) return ERR_EMPTY;
808 /* Get next folder status */
809 error=N6510_GetSMSFolderStatus(s, folderid);
810 if (error!=ERR_NONE) return error;
811 /* First location from this folder */
812 location=Priv->LastSMSFolder.Location[0];
813 }
814 }
815 N6510_SetSMSLocation(s, &sms->SMS[0], folderid, location);
816
817 return N6510_PrivGetSMSMessageBitmap(s, sms, bitmap);
818}
819
820static GSM_Error N6510_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
821{
822 return N6510_GetNextSMSMessageBitmap(s, sms, start, NULL);
823}
824
825static GSM_Error N6510_ReplyStartupNoteLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
826{
827 GSM_Phone_Data *Data = &s->Phone.Data;
828
829 if (Data->RequestID == ID_GetBitmap) {
830 switch (msg.Buffer[4]) {
831 case 0x01:
832 smprintf(s, "Welcome note text received\n");
833 CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
834 smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
835 return ERR_NONE;
836 case 0x10:
837 smprintf(s, "Dealer note text received\n");
838 CopyUnicodeString(Data->Bitmap->Text,msg.Buffer+6);
839 smprintf(s, "Text is \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
840 return ERR_NONE;
841 case 0x0f:
842 smprintf(s, "Startup logo received\n");
843 PHONE_DecodeBitmap(GSM_Nokia7110StartupLogo, msg.Buffer + 22, Data->Bitmap);
844 return ERR_NONE;
845 }
846 }
847 if (Data->RequestID == ID_SetBitmap) {
848 switch (msg.Buffer[4]) {
849 case 0x01:
850 case 0x10:
851 case 0x0f:
852 case 0x25:
853 return ERR_NONE;
854 }
855 }
856 return ERR_UNKNOWN;
857}
858
859static GSM_Error N6510_GetPictureImage(GSM_StateMachine *s, GSM_Bitmap *Bitmap, int *location)
860{
861 GSM_MultiSMSMessage sms;
862 int Number;
863 GSM_Bitmap bitmap;
864 GSM_Error error;
865
866 sms.SMS[0].Folder= 0;
867 Number = 0;
868 bitmap.Location = 255;
869 error=N6510_GetNextSMSMessageBitmap(s, &sms, true, &bitmap);
870 while (error == ERR_NONE) {
871 if (bitmap.Location != 255) {
872 Number++;
873 if (Number == Bitmap->Location) {
874 bitmap.Location = Bitmap->Location;
875 memcpy(Bitmap,&bitmap,sizeof(GSM_Bitmap));
876 *location = sms.SMS[0].Location;
877 return ERR_NONE;
878 }
879 }
880 bitmap.Location = 255;
881 sms.SMS[0].Folder = 0;
882 error=N6510_GetNextSMSMessageBitmap(s, &sms, false, &bitmap);
883 }
884 return ERR_INVALIDLOCATION;
885}
886
887static GSM_Error N6510_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
888{
889 unsigned char reqOp[] = {N6110_FRAME_HEADER, 0x23, 0x00, 0x00, 0x55, 0x55, 0x55};
890 unsigned char reqStartup[] = {N6110_FRAME_HEADER, 0x02, 0x0f};
891 unsigned char reqNote[] = {N6110_FRAME_HEADER, 0x02, 0x01, 0x00};
892 GSM_MemoryEntrypbk;
893 GSM_Error error;
894 int Location;
895
896 s->Phone.Data.Bitmap=Bitmap;
897 switch (Bitmap->Type) {
898 case GSM_StartupLogo:
899 Bitmap->BitmapWidth = 96;
900 Bitmap->BitmapHeight = 65;
901 GSM_ClearBitmap(Bitmap);
902 smprintf(s, "Getting startup logo\n");
903 return GSM_WaitFor (s, reqStartup, 5, 0x7A, 4, ID_GetBitmap);
904 case GSM_DealerNote_Text:
905 reqNote[4] = 0x10;
906 smprintf(s, "Getting dealer note\n");
907 return GSM_WaitFor (s, reqNote, 6, 0x7A, 4, ID_GetBitmap);
908 case GSM_WelcomeNote_Text:
909 smprintf(s, "Getting welcome note\n");
910 return GSM_WaitFor (s, reqNote, 6, 0x7A, 4, ID_GetBitmap);
911 case GSM_CallerGroupLogo:
912 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBK35)) return ERR_NOTSUPPORTED;
913 Bitmap->BitmapWidth = 72;
914 Bitmap->BitmapHeight = 14;
915 GSM_ClearBitmap(Bitmap);
916 pbk.MemoryType= MEM7110_CG;
917 pbk.Location= Bitmap->Location;
918 smprintf(s, "Getting caller group logo\n");
919 error=N6510_GetMemory(s,&pbk);
920 if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s, Bitmap);
921 return error;
922 case GSM_OperatorLogo:
923 smprintf(s, "Getting operator logo\n");
924 return GSM_WaitFor (s, reqOp, 9, 0x0A, 4, ID_GetBitmap);
925 case GSM_PictureImage:
926 return N6510_GetPictureImage(s, Bitmap, &Location);
927 default:
928 break;
929 }
930 return ERR_NOTSUPPORTED;
931}
932
933static GSM_Error N6510_ReplyGetIncSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
934{
935 smprintf(s, "Network level changed to: %i\n",msg.Buffer[4]);
936 return ERR_NONE;
937}
938
939static GSM_Error N6510_ReplyGetSignalQuality(GSM_Protocol_Message msg, GSM_StateMachine *s)
940{
941 GSM_Phone_Data *Data = &s->Phone.Data;
942
943 smprintf(s, "Network level received: %i\n",msg.Buffer[8]);
944 Data->SignalQuality->SignalStrength = -1;
945 Data->SignalQuality->SignalPercent = ((int)msg.Buffer[8]);
946 Data->SignalQuality->BitErrorRate = -1;
947 return ERR_NONE;
948}
949
950static GSM_Error N6510_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
951{
952 unsigned char req[] = {N6110_FRAME_HEADER, 0x0B, 0x00, 0x02, 0x00, 0x00, 0x00};
953
954 s->Phone.Data.SignalQuality = sig;
955 smprintf(s, "Getting network level\n");
956 return GSM_WaitFor (s, req, 9, 0x0a, 4, ID_GetSignalQuality);
957}
958
959static GSM_Error N6510_ReplyGetBatteryCharge(GSM_Protocol_Message msg, GSM_StateMachine *s)
960{
961 GSM_Phone_Data *Data = &s->Phone.Data;
962
963 smprintf(s, "Battery level received: %i\n",msg.Buffer[9]*100/7);
964 Data->BatteryCharge->BatteryPercent = ((int)(msg.Buffer[9]*100/7));
965 Data->BatteryCharge->ChargeState = 0;
966 return ERR_NONE;
967}
968
969static GSM_Error N6510_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
970{
971 unsigned char req[] = {N6110_FRAME_HEADER, 0x0A, 0x02, 0x00};
972
973 s->Phone.Data.BatteryCharge = bat;
974 smprintf(s, "Getting battery level\n");
975 return GSM_WaitFor (s, req, 6, 0x17, 4, ID_GetBatteryCharge);
976}
977
978static GSM_Error N6510_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
979{
980 return DCT3DCT4_ReplyGetWAPBookmark (msg, s, true);
981}
982
983static GSM_Error N6510_ReplyGetOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
984{
985 GSM_Phone_Data *Data = &s->Phone.Data;
986
987 smprintf(s, "Operator logo received\n");
988 NOKIA_DecodeNetworkCode(msg.Buffer+12,Data->Bitmap->NetworkCode);
989 smprintf(s, "Network code %s\n",Data->Bitmap->NetworkCode);
990 Data->Bitmap->BitmapWidth= msg.Buffer[20];
991 Data->Bitmap->BitmapHeight= msg.Buffer[21];
992 if (msg.Length == 18) return ERR_EMPTY;
993 PHONE_DecodeBitmap(GSM_Nokia6510OperatorLogo,msg.Buffer+26,Data->Bitmap);
994 return ERR_NONE;
995}
996
997GSM_Error N6510_ReplyDeleteMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
998{
999 smprintf(s, "Phonebook entry deleted\n");
1000 return ERR_NONE;
1001}
1002
1003GSM_Error N6510_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1004{
1005 unsigned char req[] = {N7110_FRAME_HEADER, 0x0f, 0x55, 0x01,
1006 0x04, 0x55, 0x00, 0x10, 0xFF, 0x02,
1007 0x00, 0x01, /* location*/
1008 0x00, 0x00, 0x00, 0x00,
1009 0x05, /* memory type*/
1010 0x55, 0x55, 0x55};
1011
1012 req[12] = entry->Location / 256;
1013 req[13] = entry->Location % 256;
1014
1015 req[18] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
1016 if (req[18]==0xff) return ERR_NOTSUPPORTED;
1017
1018 smprintf(s, "Deleting phonebook entry\n");
1019 return GSM_WaitFor (s, req, 22, 0x03, 4, ID_SetMemory);
1020}
1021
1022static GSM_Error N6510_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1023{
1024 int count = 22, blocks;
1025 unsigned char req[500] = {
1026 N7110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x10,
1027 0x02, 0x00, /* memory type */
1028 0x00, 0x00, /* location */
1029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1030
1031 if (entry->Location == 0) return ERR_NOTSUPPORTED;
1032
1033 req[11] = NOKIA_GetMemoryType(s, entry->MemoryType,N71_65_MEMORY_TYPES);
1034 if (req[11]==0xff) return ERR_NOTSUPPORTED;
1035
1036 req[12] = entry->Location / 256;
1037 req[13] = entry->Location % 256;
1038
1039 count = count + N71_65_EncodePhonebookFrame(s, req+22, *entry, &blocks, true, IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_VOICETAGS));
1040 req[21] = blocks;
1041
1042 smprintf(s, "Writing phonebook entry\n");
1043 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetMemory);
1044}
1045
1046static GSM_Error N6510_ReplySetOperatorLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1047{
1048 smprintf(s, "Operator logo set OK\n");
1049 return ERR_NONE;
1050}
1051
1052static GSM_Error N6510_SetCallerLogo(GSM_StateMachine *s, GSM_Bitmap *bitmap)
1053{
1054 char string[500];
1055 int block=0, i, Width, Height;
1056 unsigned int count = 22;
1057 unsigned char req[500] = {
1058 N6110_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x10,
1059 0xfe, 0x10, /* memory type */
1060 0x00, 0x00, /* location */
1061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1062
1063 req[13] = bitmap->Location;
1064
1065 /* Enabling/disabling logo */
1066 string[0] = bitmap->BitmapEnabled?1:0;
1067 string[1] = 0;
1068 count += N71_65_PackPBKBlock(s, N7110_PBK_LOGOON, 2, block++, string, req + count);
1069
1070 /* Ringtone */
1071 if (!bitmap->DefaultRingtone) {
1072 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBKTONEGAL)) {
1073 } else {
1074 string[0] = 0x00;
1075 string[1] = 0x00;
1076 string[2] = bitmap->RingtoneID;
1077 count += N71_65_PackPBKBlock(s, N7110_PBK_RINGTONE_ID, 3, block++, string, req + count);
1078 count --;
1079 req[count-5] = 8;
1080 }
1081 }
1082
1083 /* Number of group */
1084 string[0] = bitmap->Location;
1085 string[1] = 0;
1086 count += N71_65_PackPBKBlock(s, N7110_PBK_GROUP, 2, block++, string, req + count);
1087
1088 /* Name */
1089 if (!bitmap->DefaultName) {
1090 i = UnicodeLength(bitmap->Text) * 2;
1091 string[0] = i + 2;
1092 memcpy(string + 1, bitmap->Text, i);
1093 string[i + 1] = 0;
1094 count += N71_65_PackPBKBlock(s, N7110_PBK_NAME, i + 2, block++, string, req + count);
1095 }
1096
1097 /* Logo */
1098 if (!bitmap->DefaultBitmap) {
1099 PHONE_GetBitmapWidthHeight(GSM_NokiaCallerLogo, &Width, &Height);
1100 string[0] = Width;
1101 string[1] = Height;
1102 string[2] = 0;
1103 string[3] = 0;
1104 string[4] = PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0);
1105 PHONE_EncodeBitmap(GSM_NokiaCallerLogo, string + 5, bitmap);
1106 count += N71_65_PackPBKBlock(s, N7110_PBK_GROUPLOGO, PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 5, block++, string, req + count);
1107 }
1108
1109 req[21] = block;
1110
1111 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetBitmap);
1112}
1113
1114static GSM_Error N6510_ReplySetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
1115{
1116 //smprintf(s, "Picture Image written OK, folder %i, location %i\n",msg.Buffer[4],msg.Buffer[5]*256+msg.Buffer[6]);
1117 return ERR_NONE;
1118}
1119
1120static GSM_Error N6510_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
1121{
1122 GSM_SMSMessage sms;
1123 GSM_Phone_Bitmap_TypesType;
1124 int Width, Height, i, count;
1125#ifdef DEVELOP
1126 unsigned char folderid;
1127 int location;
1128#endif
1129 GSM_NetworkInfo NetInfo;
1130 GSM_Error error;
1131 unsigned char reqStartup[1000] = {
1132 N7110_FRAME_HEADER, 0x04, 0x0F,
1133 0x00, 0x00, 0x00,
1134 0x04, 0xC0, 0x02, 0x00,
1135 0x41, 0xC0, 0x03, 0x00,
1136 0x60, 0xC0, 0x04};
1137 unsigned char reqColourWallPaper[200] = {
1138 N6110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0xD5,
1139 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
1140 0x00, 0x00, 0x00, 0x01, 0x00,
1141 0x18}; /* Bitmap ID */
1142 unsigned char reqColourStartup[200] = {
1143 N6110_FRAME_HEADER, 0x04, 0x25, 0x00, 0x01, 0x00, 0x18};
1144 unsigned char reqOp[1000] = {
1145 N7110_FRAME_HEADER, 0x25, 0x01,
1146 0x55, 0x00, 0x00, 0x55,
1147 0x01, /* 0x01 - not set, 0x02 - set */
1148 0x0C, 0x08,
1149 0x62, 0xF0, 0x10,/* Network code */
1150 0x03, 0x55, 0x55};
1151 unsigned char reqColourOp[200] = {
1152 N6110_FRAME_HEADER,
1153 0x07, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0xF9, 0x00,
1154 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00,
1155 0x18, /* File ID */
1156 0x00,
1157 0x00, 0x00, 0x00};/* Network code */
1158 unsigned char reqNote[200] = {N6110_FRAME_HEADER, 0x04, 0x01};
1159 unsigned char reqPicture[2000] = {
1160 N6110_FRAME_HEADER, 0x00,
1161 0x02, 0x05, /* SMS folder */
1162 0x00, 0x00, /* location */
1163 0x01, 0x01, 0xa0, 0x02, 0x01, 0x40, 0x00, 0x34,
1164 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1165 0x00, 0x00, 0x55, 0x55, 0x55, 0x03, 0x82, 0x10,
1166 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x10,
1168 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04,
1170 0x00, 0x00, 0xa1, 0x55, 0x01, 0x08, 0x00, 0x00,
1171 0x00, 0x01, 0x48, 0x1c, 0x00, 0xfc, 0x00};
1172
1173 switch (Bitmap->Type) {
1174 case GSM_ColourWallPaper_ID:
1175 reqColourWallPaper[21] = Bitmap->ID;
1176 smprintf(s, "Setting colour wall paper\n");
1177 return GSM_WaitFor (s, reqColourWallPaper, 22, 0x43, 4, ID_SetBitmap);
1178 case GSM_StartupLogo:
1179 Type = GSM_Nokia7110StartupLogo;
1180 switch (Bitmap->Location) {
1181 case 1: PHONE_EncodeBitmap(Type, reqStartup + 22, Bitmap);
1182 break;
1183 case 2: memset(reqStartup+5,0x00,15);
1184 PHONE_ClearBitmap(Type, reqStartup + 22,0,0);
1185 break;
1186 default: return ERR_NOTSUPPORTED;
1187 }
1188 smprintf(s, "Setting startup logo\n");
1189 return GSM_WaitFor (s, reqStartup, 22+PHONE_GetBitmapSize(Type,0,0), 0x7A, 4, ID_SetBitmap);
1190 case GSM_DealerNote_Text:
1191 reqNote[4] = 0x10;
1192 CopyUnicodeString(reqNote + 5, Bitmap->Text);
1193 i = 6 + UnicodeLength(Bitmap->Text) * 2;
1194 reqNote[i++] = 0;
1195 reqNote[i] = 0;
1196 return GSM_WaitFor (s, reqNote, i, 0x7A, 4, ID_SetBitmap);
1197 case GSM_WelcomeNote_Text:
1198 CopyUnicodeString(reqNote + 5, Bitmap->Text);
1199 i = 6 + UnicodeLength(Bitmap->Text) * 2;
1200 reqNote[i++] = 0;
1201 reqNote[i] = 0;
1202 return GSM_WaitFor (s, reqNote, i, 0x7A, 4, ID_SetBitmap);
1203 case GSM_OperatorLogo:
1204 /* We want to set operator logo, not clear */
1205 if (strcmp(Bitmap->NetworkCode,"000 00")) {
1206 memset(reqOp + 19, 0, 281);
1207 NOKIA_EncodeNetworkCode(reqOp+12, Bitmap->NetworkCode);
1208 Type = GSM_Nokia6510OperatorLogo;
1209 reqOp[9] = 0x02;/* Logo enabled */
1210 reqOp[18] = 0x1a;/* FIXME */
1211 reqOp[19] = PHONE_GetBitmapSize(Type,0,0) + 8 + 29 + 2;
1212 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
1213 reqOp[20] = Width;
1214 reqOp[21] = Height;
1215 reqOp[22] = 0x00;
1216 reqOp[23] = PHONE_GetBitmapSize(Type,0,0) + 29;
1217 reqOp[24] = 0x00;
1218 reqOp[25] = PHONE_GetBitmapSize(Type,0,0) + 29;
1219 PHONE_EncodeBitmap(Type, reqOp + 26, Bitmap);
1220 smprintf(s, "Setting operator logo\n");
1221 return GSM_WaitFor (s, reqOp, reqOp[19]+reqOp[11]+10, 0x0A, 4, ID_SetBitmap);
1222 } else {
1223 error=N6510_GetNetworkInfo(s,&NetInfo);
1224 if (error != ERR_NONE) return error;
1225 NOKIA_EncodeNetworkCode(reqOp+12, NetInfo.NetworkCode);
1226 smprintf(s, "Clearing operator logo\n");
1227 return GSM_WaitFor (s, reqOp, 18, 0x0A, 4, ID_SetBitmap);
1228 }
1229 case GSM_ColourOperatorLogo_ID:
1230 /* We want to set operator logo, not clear */
1231 if (strcmp(Bitmap->NetworkCode,"000 00")) {
1232 EncodeBCD(reqColourOp+23, Bitmap->NetworkCode, 6, false);
1233 reqColourOp[21] = Bitmap->ID;
1234 }
1235 smprintf(s, "Setting colour operator logo\n");
1236 return GSM_WaitFor (s, reqColourOp, 26, 0x43, 4, ID_SetBitmap);
1237 case GSM_ColourStartupLogo_ID:
1238 switch (Bitmap->Location) {
1239 case 0: reqColourStartup[6] = 0x00;
1240 reqColourStartup[8] = 0x00;
1241 smprintf(s, "Setting colour startup logo\n");
1242 return GSM_WaitFor (s, reqColourStartup, 9, 0x7A, 4, ID_SetBitmap);
1243 case 1: reqColourStartup[8] = Bitmap->ID;
1244 smprintf(s, "Setting colour startup logo\n");
1245 return GSM_WaitFor (s, reqColourStartup, 9, 0x7A, 4, ID_SetBitmap);
1246 default:return ERR_NOTSUPPORTED;
1247 }
1248 case GSM_CallerGroupLogo:
1249 return N6510_SetCallerLogo(s,Bitmap);
1250 case GSM_PictureImage:
1251 error = N6510_GetPictureImage(s, Bitmap, &sms.Location);
1252 if (error == ERR_NONE) {
1253#ifdef DEVELOP
1254 sms.Folder = 0;
1255 N6510_GetSMSLocation(s, &sms, &folderid, &location);
1256 switch (folderid) {
1257 case 0x01: reqPicture[5] = 0x02; break; /* INBOX SIM */
1258 case 0x02: reqPicture[5] = 0x03; break; /* OUTBOX SIM */
1259 default : reqPicture[5] = folderid - 1; reqPicture[4] = 0x02; break; /* ME folders*/
1260 }
1261 reqPicture[6]=location / 256;
1262 reqPicture[7]=location;
1263#else
1264 return ERR_NOTSUPPORTED;
1265#endif
1266 }
1267 Type = GSM_NokiaPictureImage;
1268 count = 78;
1269 PHONE_EncodeBitmap(Type, reqPicture + count, Bitmap);
1270 count += PHONE_GetBitmapSize(Type,0,0);
1271 smprintf(s, "Setting Picture Image\n");
1272 return GSM_WaitFor (s, reqPicture, count, 0x14, 4, ID_SetBitmap);
1273 default:
1274 break;
1275 }
1276 return ERR_NOTSUPPORTED;
1277}
1278
1279static GSM_Error N6510_ReplyGetRingtoneID(GSM_Protocol_Message msg, GSM_StateMachine *s)
1280{
1281 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1282
1283 smprintf(s, "Ringtone ID received\n");
1284 Priv->RingtoneID = msg.Buffer[15];
1285 return ERR_NONE;
1286}
1287
1288static GSM_Error N6510_ReplySetBinRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
1289{
1290 smprintf(s, "Binary ringtone set\n");
1291 return ERR_NONE;
1292}
1293
1294static GSM_Error N6510_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
1295{
1296 GSM_Error error;
1297 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1298 GSM_NetworkInfo NetInfo;
1299 int size=200, current;
1300 unsigned char GetIDReq[] = {
1301 N7110_FRAME_HEADER, 0x01, 0x00, 0x00,
1302 0x00, 0xFF, 0x06, 0xE1, 0x00,
1303 0xFF, 0x06, 0xE1, 0x01, 0x42};
1304 unsigned char SetPreviewReq[1000] = {
1305 0xAE, /* Ringtone ID */
1306 0x01, 0x00, 0x0D, 0x00,
1307 0x00, 0x00, 0x00, 0x00, 0x00,
1308 0x00}; /*Length*/
1309 unsigned char AddBinaryReq[33000] = {
1310 N7110_FRAME_HEADER, 0x0E, 0x7F, 0xFF, 0xFE};
1311
1312 if (Ringtone->Format == RING_NOTETONE && Ringtone->Location==255)
1313 {
1314 smprintf(s, "Getting ringtone ID\n");
1315 error=GSM_WaitFor (s, GetIDReq, 14, 0xDB, 4, ID_SetRingtone);
1316 if (error != ERR_NONE) return error;
1317 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, SetPreviewReq+11, &size);
1318 SetPreviewReq[0] = Priv->RingtoneID;
1319 SetPreviewReq[10] = size;
1320 smprintf(s, "Setting ringtone\n");
1321 error = s->Protocol.Functions->WriteMessage(s, SetPreviewReq, size+11, 0x00);
1322 if (error!=ERR_NONE) return error;
1323 my_sleep(1000);
1324 /* We have to make something (not important, what) now */
1325 /* no answer from phone*/
1326 return s->Phone.Functions->GetNetworkInfo(s,&NetInfo);
1327 }
1328 if (Ringtone->Format == RING_NOKIABINARY) {
1329 AddBinaryReq[7] = UnicodeLength(Ringtone->Name);
1330 CopyUnicodeString(AddBinaryReq+8,Ringtone->Name);
1331 current = 8 + UnicodeLength(Ringtone->Name)*2;
1332 AddBinaryReq[current++] = Ringtone->NokiaBinary.Length/256 + 1;
1333 AddBinaryReq[current++] = Ringtone->NokiaBinary.Length%256 + 1;
1334 AddBinaryReq[current++] = 0x00;
1335 memcpy(AddBinaryReq+current,Ringtone->NokiaBinary.Frame,Ringtone->NokiaBinary.Length);
1336 current += Ringtone->NokiaBinary.Length;
1337 smprintf(s, "Adding binary ringtone\n");
1338 return GSM_WaitFor (s, AddBinaryReq, current, 0x1F, 4, ID_SetRingtone);
1339 }
1340 if (Ringtone->Format == RING_MIDI) {
1341 AddBinaryReq[7] = UnicodeLength(Ringtone->Name);
1342 CopyUnicodeString(AddBinaryReq+8,Ringtone->Name);
1343 current = 8 + UnicodeLength(Ringtone->Name)*2;
1344 AddBinaryReq[current++] = Ringtone->NokiaBinary.Length/256;
1345 AddBinaryReq[current++] = Ringtone->NokiaBinary.Length%256;
1346 memcpy(AddBinaryReq+current,Ringtone->NokiaBinary.Frame,Ringtone->NokiaBinary.Length);
1347 current += Ringtone->NokiaBinary.Length;
1348 AddBinaryReq[current++] = 0x00;
1349 AddBinaryReq[current++] = 0x00;
1350 smprintf(s, "Adding binary or MIDI ringtone\n");
1351 return GSM_WaitFor (s, AddBinaryReq, current, 0x1F, 4, ID_SetRingtone);
1352 }
1353 return ERR_NOTSUPPORTED;
1354}
1355
1356static GSM_Error N6510_ReplyDeleteRingtones(GSM_Protocol_Message msg, GSM_StateMachine *s)
1357{
1358 smprintf(s, "Ringtones deleted\n");
1359 return ERR_NONE;
1360}
1361
1362static GSM_Error N6510_DeleteUserRingtones(GSM_StateMachine *s)
1363{
1364 unsigned char DelAllRingtoneReq[] = {N7110_FRAME_HEADER, 0x10, 0x7F, 0xFE};
1365
1366 smprintf(s, "Deleting all user ringtones\n");
1367 return GSM_WaitFor (s, DelAllRingtoneReq, 6, 0x1F, 4, ID_SetRingtone);
1368}
1369
1370static GSM_Error N6510_PressKey(GSM_StateMachine *s, GSM_KeyCode Key, bool Press)
1371{
1372#ifdef DEVELOP
1373 unsigned char req[] = {N6110_FRAME_HEADER, 0x11, 0x00, 0x01, 0x00, 0x00,
1374 0x00, /* Event */
1375 0x01}; /* Number of presses */
1376
1377 //req[7] = Key;
1378 if (Press) {
1379 req[8] = NOKIA_PRESSPHONEKEY;
1380 s->Phone.Data.PressKey = true;
1381 smprintf(s, "Pressing key\n");
1382 } else {
1383 req[8] = NOKIA_RELEASEPHONEKEY;
1384 s->Phone.Data.PressKey = false;
1385 smprintf(s, "Releasing key\n");
1386 }
1387 return GSM_WaitFor (s, req, 10, 0x0c, 4, ID_PressKey);
1388#else
1389 return ERR_NOTSUPPORTED;
1390#endif
1391}
1392
1393static GSM_Error N6510_EnableConnectionFunctions(GSM_StateMachine *s, N6510_Connection_Settings Type)
1394{
1395 GSM_Errorerror;
1396 unsigned char req2[] = {N6110_FRAME_HEADER, 0x00, 0x01};
1397 unsigned char req3[] = {N6110_FRAME_HEADER, 0x00, 0x03};
1398 unsigned char req4[] = {N6110_FRAME_HEADER, 0x00, 0x04};
1399
1400 if (Type == N6510_MMS_SETTINGS && IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOMMS)) return ERR_NOTSUPPORTED;
1401
1402 error=DCT3DCT4_DisableConnectionFunctions(s);
1403 if (error!=ERR_NONE) return error;
1404
1405 switch (Type) {
1406 case N6510_WAP_SETTINGS:
1407 return DCT3DCT4_EnableWAPFunctions(s);
1408 case N6510_MMS_SETTINGS:
1409 dbgprintf("Enabling MMS\n");
1410 return GSM_WaitFor (s, req2, 5, 0x3f, 4, ID_EnableConnectFunc);
1411 case N6510_SYNCML_SETTINGS:
1412 dbgprintf("Enabling SyncML\n");
1413 return GSM_WaitFor (s, req3, 5, 0x3f, 5, ID_EnableConnectFunc);
1414 case N6510_CHAT_SETTINGS:
1415 dbgprintf("Enabling Chat\n");
1416 return GSM_WaitFor (s, req4, 5, 0x3f, 5, ID_EnableConnectFunc);
1417 default:
1418 return ERR_UNKNOWN;
1419 }
1420}
1421
1422static GSM_Error N6510_ReplyGetConnectionSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
1423{
1424 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
1425 int tmp,num=0,i;
1426 GSM_Phone_Data *Data = &s->Phone.Data;
1427 unsigned char buff[2000];
1428
1429 switch(msg.Buffer[3]) {
1430 case 0x16:
1431 smprintf(s, "Connection settings received OK\n");
1432
1433 Data->WAPSettings->Number = Priv->BearerNumber;
1434
1435 Data->WAPSettings->Proxy[0] = 0x00;
1436 Data->WAPSettings->Proxy[1] = 0x00;
1437 Data->WAPSettings->ProxyPort = 8080;
1438
1439 Data->WAPSettings->Proxy2[0] = 0x00;
1440 Data->WAPSettings->Proxy2[1] = 0x00;
1441 Data->WAPSettings->Proxy2Port = 8080;
1442
1443 tmp = 4;
1444
1445 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].Title,true);
1446 CopyUnicodeString(Data->WAPSettings->Settings[1].Title,Data->WAPSettings->Settings[0].Title);
1447 smprintf(s, "Title: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].Title));
1448
1449 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].HomePage,true);
1450 CopyUnicodeString(Data->WAPSettings->Settings[1].HomePage,Data->WAPSettings->Settings[0].HomePage);
1451 smprintf(s, "Homepage: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].HomePage));
1452
1453#ifdef DEBUG
1454 smprintf(s, "Connection type: ");
1455 switch (msg.Buffer[tmp]) {
1456 case 0x00: smprintf(s, "temporary\n"); break;
1457 case 0x01: smprintf(s, "continuous\n"); break;
1458 default: smprintf(s, "unknown\n");
1459 }
1460 smprintf(s, "Connection security: ");
1461 switch (msg.Buffer[tmp+1]) {
1462 case 0x00: smprintf(s, "off\n");break;
1463 case 0x01: smprintf(s, "on\n"); break;
1464 default: smprintf(s, "unknown\n");
1465 }
1466 smprintf(s, "Bearer: ");
1467 switch (msg.Buffer[tmp+2]) {
1468 case 0x01: smprintf(s, "GSM data\n");break;
1469 case 0x03: smprintf(s, "GPRS\n");break;
1470 default: smprintf(s, "unknown\n");
1471 }
1472 if (msg.Buffer[tmp+3] == 0x01) smprintf(s, "locked\n");
1473#endif
1474 Data->WAPSettings->Settings[0].IsContinuous = false;
1475 if (msg.Buffer[tmp] == 0x01) Data->WAPSettings->Settings[0].IsContinuous = true;
1476 Data->WAPSettings->Settings[1].IsContinuous = Data->WAPSettings->Settings[0].IsContinuous;
1477
1478 Data->WAPSettings->Settings[0].IsSecurity = false;
1479 if (msg.Buffer[tmp+1] == 0x01) Data->WAPSettings->Settings[0].IsSecurity = true;
1480 Data->WAPSettings->Settings[1].IsSecurity = Data->WAPSettings->Settings[0].IsSecurity;
1481
1482 Data->WAPSettings->ActiveBearer = WAPSETTINGS_BEARER_DATA;
1483 if (msg.Buffer[tmp+2] == 0x03) Data->WAPSettings->ActiveBearer = WAPSETTINGS_BEARER_GPRS;
1484
1485 Data->WAPSettings->ReadOnly = false;
1486 if (msg.Buffer[tmp+3] == 0x01) Data->WAPSettings->ReadOnly = true;
1487
1488 tmp+=3;
1489
1490 if (Priv->BearerNumber == 2) {
1491 /* Here starts settings for data bearer */
1492 Data->WAPSettings->Settings[0].Bearer = WAPSETTINGS_BEARER_DATA;
1493 while ((msg.Buffer[tmp] != 0x01) || (msg.Buffer[tmp + 1] != 0x00)) tmp++;
1494 tmp += 4;
1495
1496#ifdef DEBUG
1497 smprintf(s, "Authentication type: ");
1498 switch (msg.Buffer[tmp]) {
1499 case 0x00: smprintf(s, "normal\n");break;
1500 case 0x01: smprintf(s, "secure\n");break;
1501 default: smprintf(s, "unknown\n");break;
1502 }
1503 smprintf(s, "Data call type: ");
1504 switch (msg.Buffer[tmp+1]) {
1505 case 0x00: smprintf(s, "analogue\n");break;
1506 case 0x01: smprintf(s, "ISDN\n");break;
1507 default: smprintf(s, "unknown\n");break;
1508 }
1509 smprintf(s, "Data call speed: ");
1510 switch (msg.Buffer[tmp+2]) {
1511 case 0x00: smprintf(s, "automatic\n"); break;
1512 case 0x01: smprintf(s, "9600\n");break;
1513 case 0x02: smprintf(s, "14400\n");break;
1514 default: smprintf(s, "unknown\n");break;
1515 }
1516 smprintf(s, "Login Type: ");
1517 switch (msg.Buffer[tmp+4]) {
1518 case 0x00: smprintf(s, "manual\n");break;
1519 case 0x01: smprintf(s, "automatic\n");break;
1520 default: smprintf(s, "unknown\n");break;
1521 }
1522#endif
1523 Data->WAPSettings->Settings[0].IsNormalAuthentication=true;
1524 if (msg.Buffer[tmp]==0x01) Data->WAPSettings->Settings[0].IsNormalAuthentication=false;
1525
1526 Data->WAPSettings->Settings[0].IsISDNCall=false;
1527 if (msg.Buffer[tmp+1]==0x01) Data->WAPSettings->Settings[0].IsISDNCall=true;
1528
1529 switch (msg.Buffer[tmp+2]) {
1530 case 0x00: Data->WAPSettings->Settings[0].Speed=WAPSETTINGS_SPEED_AUTO; break;
1531 case 0x01: Data->WAPSettings->Settings[0].Speed=WAPSETTINGS_SPEED_9600; break;
1532 case 0x02: Data->WAPSettings->Settings[0].Speed=WAPSETTINGS_SPEED_14400; break;
1533 }
1534
1535 Data->WAPSettings->Settings[0].ManualLogin=false;
1536 if (msg.Buffer[tmp+4]==0x00) Data->WAPSettings->Settings[0].ManualLogin = true;
1537
1538 tmp+=5;
1539
1540 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].IPAddress,false);
1541 smprintf(s, "IP address: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].IPAddress));
1542
1543 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].DialUp,true);
1544 smprintf(s, "Dial-up number: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].DialUp));
1545
1546 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].User,true);
1547 smprintf(s, "User name: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].User));
1548
1549 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[0].Password,true);
1550 smprintf(s, "Password: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[0].Password));
1551
1552 num = 1;
1553 } else {
1554 num = 0;
1555 }
1556
1557 /* Here starts settings for gprs bearer */
1558 Data->WAPSettings->Settings[num].Bearer = WAPSETTINGS_BEARER_GPRS;
1559 while (msg.Buffer[tmp] != 0x03) tmp++;
1560 tmp += 4;
1561
1562#ifdef DEBUG
1563 smprintf(s, "Authentication type: ");
1564 switch (msg.Buffer[tmp]) {
1565 case 0x00: smprintf(s, "normal\n");break;
1566 case 0x01: smprintf(s, "secure\n");break;
1567 default: smprintf(s, "unknown\n");break;
1568 }
1569 smprintf(s, "GPRS connection: ");
1570 switch (msg.Buffer[tmp+1]) {
1571 case 0x00: smprintf(s, "ALWAYS online\n"); break;
1572 case 0x01: smprintf(s, "when needed\n"); break;
1573 default: smprintf(s, "unknown\n"); break;
1574 }
1575 smprintf(s, "Login Type: ");
1576 switch (msg.Buffer[tmp+2]) {
1577 case 0x00: smprintf(s, "manual\n");break;
1578 case 0x01: smprintf(s, "automatic\n");break;
1579 default: smprintf(s, "unknown\n");break;
1580 }
1581#endif
1582 Data->WAPSettings->Settings[num].IsNormalAuthentication=true;
1583 if (msg.Buffer[tmp]==0x01) Data->WAPSettings->Settings[num].IsNormalAuthentication=false;
1584
1585 Data->WAPSettings->Settings[num].IsContinuous = true;
1586 if (msg.Buffer[tmp+1] == 0x01) Data->WAPSettings->Settings[num].IsContinuous = false;
1587
1588 Data->WAPSettings->Settings[num].ManualLogin=false;
1589 if (msg.Buffer[tmp+2]==0x00) Data->WAPSettings->Settings[num].ManualLogin = true;
1590
1591 tmp+=3;
1592
1593 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].DialUp,false);
1594 smprintf(s, "Access point: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].DialUp));
1595
1596 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].IPAddress,true);
1597 smprintf(s, "IP address: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].IPAddress));
1598
1599 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].User,true);
1600 smprintf(s, "User name: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].User));
1601
1602 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPSettings->Settings[num].Password,true);
1603 smprintf(s, "Password: \"%s\"\n",DecodeUnicodeString(Data->WAPSettings->Settings[num].Password));
1604
1605 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) {
1606 if (msg.Buffer[tmp] == 0x00 && msg.Buffer[tmp+1] == 0x00) tmp = tmp+2;
1607
1608 memcpy(buff,msg.Buffer+tmp+10,msg.Buffer[tmp+4]);
1609 buff[msg.Buffer[tmp+4]] = 0x00;
1610 smprintf(s, "Proxy 1: \"%s\", port %i\n",buff,msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7]);
1611 EncodeUnicode(Data->WAPSettings->Proxy,buff,strlen(buff));
1612 Data->WAPSettings->ProxyPort = msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7];
1613
1614 memcpy(buff,msg.Buffer+tmp+10+msg.Buffer[tmp+4],msg.Buffer[tmp+5]);
1615 buff[msg.Buffer[tmp+5]] = 0x00;
1616 smprintf(s, "Proxy 2: \"%s\", port %i\n",buff,msg.Buffer[tmp+8]*256+msg.Buffer[tmp+9]);
1617 EncodeUnicode(Data->WAPSettings->Proxy2,buff,strlen(buff));
1618 Data->WAPSettings->Proxy2Port = msg.Buffer[tmp+8]*256+msg.Buffer[tmp+9];
1619
1620 tmp = tmp + msg.Buffer[tmp+3] + 19;
1621
1622 for (i=0;i<4;i++) {
1623#ifdef DEBUG
1624 smprintf(s, "Proxy data %i\n",i+1);
1625 if (msg.Buffer[tmp+2]!=0) memcpy(buff,msg.Buffer+tmp+9,msg.Buffer[tmp+2]*2);
1626 buff[msg.Buffer[tmp+2]*2] =0;
1627 buff[msg.Buffer[tmp+2]*2+1]=0;
1628 smprintf(s, "IP: \"%s\"",DecodeUnicodeString(buff));
1629 smprintf(s, ", port %i\n",msg.Buffer[tmp+3]*256+msg.Buffer[tmp+4]);
1630#endif
1631 tmp = tmp + msg.Buffer[tmp];
1632 }
1633
1634#ifdef DEBUG
1635 smprintf(s, "%02x %02x\n",msg.Buffer[tmp],msg.Buffer[tmp+1]);
1636 smprintf(s, "Port %i\n",msg.Buffer[tmp+3]*256+msg.Buffer[tmp+4]);
1637 tmp = tmp + msg.Buffer[tmp];
1638#endif
1639 }
1640
1641 return ERR_NONE;
1642 case 0x17:
1643 smprintf(s, "Connection settings receiving error\n");
1644 switch (msg.Buffer[4]) {
1645 case 0x01:
1646 smprintf(s, "Security error. Inside phone settings menu\n");
1647 return ERR_INSIDEPHONEMENU;
1648 case 0x02:
1649 smprintf(s, "Invalid or empty\n");
1650 return ERR_INVALIDLOCATION;
1651 default:
1652 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1653 return ERR_UNKNOWNRESPONSE;
1654 }
1655 break;
1656 }
1657 return ERR_UNKNOWNRESPONSE;
1658}
1659
1660static GSM_Error N6510_GetConnectionSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings, N6510_Connection_Settings Type)
1661{
1662 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
1663 GSM_Error error;
1664 unsigned char req[] = {N6110_FRAME_HEADER, 0x15,
1665 0x00}; /* Location */
1666
1667 error = N6510_EnableConnectionFunctions(s, Type);
1668 if (error!=ERR_NONE) return error;
1669
1670 req[4] = settings->Location-1;
1671 s->Phone.Data.WAPSettings = settings;
1672
1673 switch (Type) {
1674 case N6510_MMS_SETTINGS:
1675 smprintf(s, "Getting MMS settings\n");
1676 Priv->BearerNumber = 1;
1677 break;
1678 case N6510_WAP_SETTINGS:
1679 smprintf(s, "Getting WAP settings\n");
1680 Priv->BearerNumber = 2;
1681 break;
1682 case N6510_SYNCML_SETTINGS:
1683 smprintf(s, "Getting SyncML settings\n");
1684 Priv->BearerNumber = 2;
1685 break;
1686 case N6510_CHAT_SETTINGS:
1687 smprintf(s, "Getting Chat settings\n");
1688 Priv->BearerNumber = 1;
1689 break;
1690 }
1691
1692 error=GSM_WaitFor (s, req, 5, 0x3f, 4, ID_GetConnectSet);
1693 if (error != ERR_NONE) {
1694 if (error == ERR_INVALIDLOCATION || error == ERR_INSIDEPHONEMENU) {
1695 DCT3DCT4_DisableConnectionFunctions(s);
1696 }
1697 return error;
1698 }
1699
1700 error=DCT3DCT4_GetActiveConnectSet(s);
1701 if (error != ERR_NONE) return error;
1702
1703 return DCT3DCT4_DisableConnectionFunctions(s);
1704}
1705
1706static GSM_Error N6510_GetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
1707{
1708 return N6510_GetConnectionSettings(s, settings, N6510_WAP_SETTINGS);
1709}
1710
1711static GSM_Error N6510_GetMMSSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
1712{
1713 return N6510_GetConnectionSettings(s, settings, N6510_MMS_SETTINGS);
1714}
1715
1716static GSM_Error N6510_ReplyGetSyncMLSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
1717{
1718 GSM_SyncMLSettings *Sett = s->Phone.Data.SyncMLSettings;
1719
1720 smprintf(s, "SyncML settings received OK\n");
1721 CopyUnicodeString(Sett->User,msg.Buffer+18);
1722 CopyUnicodeString(Sett->Password,msg.Buffer+86);
1723 CopyUnicodeString(Sett->PhonebookDataBase,msg.Buffer+130);
1724 CopyUnicodeString(Sett->CalendarDataBase,msg.Buffer+234);
1725 CopyUnicodeString(Sett->Server,msg.Buffer+338);
1726
1727 Sett->SyncPhonebook = false;
1728 Sett->SyncCalendar = false;
1729 if ((msg.Buffer[598] & 0x02)==0x02) Sett->SyncCalendar = true;
1730 if ((msg.Buffer[598] & 0x01)==0x01) Sett->SyncPhonebook = true;
1731
1732 return ERR_NONE;
1733}
1734
1735static GSM_Error N6510_ReplyGetSyncMLName(GSM_Protocol_Message msg, GSM_StateMachine *s)
1736{
1737 GSM_SyncMLSettings *Sett = s->Phone.Data.SyncMLSettings;
1738
1739 smprintf(s, "SyncML names received OK\n");
1740
1741 CopyUnicodeString(Sett->Name,msg.Buffer+18);
1742
1743 return ERR_NONE;
1744}
1745
1746static GSM_Error N6510_GetSyncMLSettings(GSM_StateMachine *s, GSM_SyncMLSettings *settings)
1747{
1748 GSM_Error error;
1749 // unsigned char NameReq[] = {N6110_FRAME_HEADER, 0x05,
1750 // 0x00, 0x00, 0x00, 0x31, 0x00,
1751 // 0x06, 0x00, 0x00, 0x00, 0xDE, 0x00, 0x00};
1752 // unsigned char GetActive[] = {N6110_FRAME_HEADER, 0x05,
1753 // 0x00, 0x00, 0x00, 0x31, 0x00,
1754 // 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
1755 unsigned char req[] = {N6110_FRAME_HEADER, 0x05,
1756 0x00, 0x00, 0x00, 0x31, 0x00,
1757 0x01, //location
1758 0x00, 0x00, 0x02, 0x46, 0x00, 0x00};
1759
1760 settings->Connection.Location = settings->Location;
1761 error = N6510_GetConnectionSettings(s, &settings->Connection, N6510_SYNCML_SETTINGS);
1762 if (error != ERR_NONE) return error;
1763
1764 settings->Active = settings->Connection.Active;
1765
1766 settings->Name[0] = 0;
1767 settings->Name[1] = 0;
1768 //s->Phone.Data.SyncMLSettings = settings;
1769 //smprintf(s, "Getting SyncML settings name\n");
1770 //error = GSM_WaitFor (s, NameReq, 16, 0x43, 4, ID_GetSyncMLName);
1771 //if (error != ERR_NONE) return error;
1772
1773 req[9] = settings->Location - 1;
1774 smprintf(s, "Getting additional SyncML settings\n");
1775 return GSM_WaitFor (s, req, 16, 0x43, 4, ID_GetSyncMLSettings);
1776}
1777
1778static GSM_Error N6510_ReplyGetChatSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
1779{
1780 GSM_ChatSettings *Sett = s->Phone.Data.ChatSettings;
1781 int i;
1782
1783 Sett->Name[0] = 0;
1784 Sett->Name[1] = 0;
1785 Sett->HomePage[0] = 0;
1786 Sett->HomePage[1] = 0;
1787 Sett->User[0] = 0;
1788 Sett->User[1] = 0;
1789 Sett->Password[0] = 0;
1790 Sett->Password[1] = 0;
1791
1792 switch(msg.Buffer[3]) {
1793 case 0x3B:
1794 smprintf(s, "Chat settings received OK\n");
1795 memcpy(Sett->Name,msg.Buffer+20,msg.Buffer[12]*2);
1796 Sett->Name[msg.Buffer[12]*2] = 0;
1797 Sett->Name[msg.Buffer[12]*2+1] = 0;
1798 memcpy(Sett->HomePage,msg.Buffer+20+msg.Buffer[12]*2,msg.Buffer[15]*2);
1799 Sett->HomePage[msg.Buffer[15]*2] = 0;
1800 Sett->HomePage[msg.Buffer[15]*2+1] = 0;
1801 i = msg.Buffer[12]*2 + msg.Buffer[15]*2 + 29;
1802 memcpy(Sett->User,msg.Buffer+i+3,msg.Buffer[i]*2);
1803 Sett->User[msg.Buffer[i]*2] = 0;
1804 Sett->User[msg.Buffer[i]*2+1] = 0;
1805 memcpy(Sett->Password,msg.Buffer+i+3+msg.Buffer[i]*2,msg.Buffer[i+1]*2);
1806 Sett->Password[msg.Buffer[i+1]*2] = 0;
1807 Sett->Password[msg.Buffer[i+1]*2+1] = 0;
1808 return ERR_NONE;
1809 case 0x3C:
1810 smprintf(s, "Empty chat settings received\n");
1811 return ERR_NONE;
1812 }
1813 return ERR_UNKNOWNRESPONSE;
1814}
1815
1816static GSM_Error N6510_GetChatSettings(GSM_StateMachine *s, GSM_ChatSettings *settings)
1817{
1818 GSM_Error error;
1819 unsigned char req[] = {N6110_FRAME_HEADER, 0x3a,
1820 0x09, // location
1821 0x01, 0x0e};
1822
1823 settings->Connection.Location = settings->Location;
1824 error = N6510_GetConnectionSettings(s, &settings->Connection, N6510_CHAT_SETTINGS);
1825 if (error != ERR_NONE) return error;
1826
1827 settings->Active = settings->Connection.Active;
1828
1829 s->Phone.Data.ChatSettings = settings;
1830 req[4] = settings->Location - 1;
1831 smprintf(s, "Getting additional Chat settings\n");
1832 return GSM_WaitFor (s, req, 7, 0x3f, 4, ID_GetChatSettings);
1833}
1834
1835static GSM_Error N6510_ReplySetConnectionSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
1836{
1837 switch (msg.Buffer[3]) {
1838 case 0x19:
1839 smprintf(s, "Connection settings cleaned\n");
1840 return ERR_NONE;
1841 case 0x1a:
1842 smprintf(s, "Connection settings setting status\n");
1843 switch (msg.Buffer[4]) {
1844 case 0x01:
1845 smprintf(s, "Security error. Inside phone settings menu\n");
1846 return ERR_INSIDEPHONEMENU;
1847 case 0x03:
1848 smprintf(s, "Invalid location\n");
1849 return ERR_INVALIDLOCATION;
1850 case 0x05:
1851 smprintf(s, "Written OK\n");
1852 return ERR_NONE;
1853 default:
1854 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1855 return ERR_UNKNOWNRESPONSE;
1856 }
1857 case 0x28:
1858 case 0x2B:
1859 smprintf(s, "Set OK\n");
1860 return ERR_NONE;
1861 }
1862 return ERR_UNKNOWNRESPONSE;
1863}
1864
1865static GSM_Error N6510_SetConnectionSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings, N6510_Connection_Settings Type)
1866{
1867 GSM_Error error;
1868 int i, pad = 0, length, pos = 5, loc1=-1,loc2=-1,port;
1869 unsigned char*Proxy;
1870 unsigned char req[2000] = {N6110_FRAME_HEADER, 0x18,
1871 0x00}; /* Location */
1872 unsigned char Lock[5] = {N6110_FRAME_HEADER, 0x27,
1873 0x00}; /* Location */
1874 unsigned char UnLock[5] = {N6110_FRAME_HEADER, 0x2A,
1875 0x00}; /* Location */
1876
1877 error = N6510_EnableConnectionFunctions(s, Type);
1878 if (error!=ERR_NONE) return error;
1879
1880 memset(req + pos, 0, 1000 - pos);
1881
1882 req[4] = settings->Location-1;
1883
1884 for (i=0;i<settings->Number;i++) {
1885 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) loc1=i;
1886 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_GPRS) loc2=i;
1887 }
1888
1889 if (loc1 != -1) {
1890 /* Name */
1891 length = UnicodeLength(settings->Settings[loc1].Title);
1892 if (!(length % 2)) pad = 1;
1893 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].Title, false);
1894
1895 /* Home */
1896 length = UnicodeLength(settings->Settings[loc1].HomePage);
1897 if (((length + pad) % 2)) pad = 2; else pad = 0;
1898 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].HomePage, true);
1899
1900 if (settings->Settings[loc1].IsContinuous) req[pos] = 0x01; pos++;
1901 if (settings->Settings[loc1].IsSecurity) req[pos] = 0x01; pos++;
1902 } else if (loc2 != -1) {
1903 /* Name */
1904 length = UnicodeLength(settings->Settings[loc2].Title);
1905 if (!(length % 2)) pad = 1;
1906 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].Title, false);
1907
1908 /* Home */
1909 length = UnicodeLength(settings->Settings[loc2].HomePage);
1910 if (((length + pad) % 2)) pad = 2; else pad = 0;
1911 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].HomePage, true);
1912
1913 if (settings->Settings[loc2].IsContinuous) req[pos] = 0x01; pos++;
1914 if (settings->Settings[loc2].IsSecurity) req[pos] = 0x01; pos++;
1915 } else {
1916 /* Name */
1917 length = 0;
1918 if (!(length % 2)) pad = 1;
1919 pos ++;
1920
1921 /* Home */
1922 length = 0;
1923 if (((length + pad) % 2)) pad = 2; else pad = 0;
1924 pos += 2;
1925
1926 pos += 2;
1927 }
1928
1929 if (Type == N6510_MMS_SETTINGS || Type == N6510_CHAT_SETTINGS) {
1930 req[pos++] = 0x03; //active bearer: GPRS
1931 } else {
1932 if (settings->ActiveBearer == WAPSETTINGS_BEARER_GPRS && loc2 != -1) {
1933 req[pos++] = 0x03; //active bearer: GPRS
1934 } else {
1935 req[pos++] = 0x01; //active bearer: data set
1936 }
1937 }
1938
1939 /* Number of sent bearers */
1940 if (Type == N6510_MMS_SETTINGS || Type == N6510_CHAT_SETTINGS) {
1941 req[pos] = 0x01;
1942 } else {
1943 req[pos] = 0x02;
1944 }
1945 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) req[pos] += 2;
1946 pos++;
1947 pos += pad;
1948
1949 if (Type != N6510_MMS_SETTINGS && Type != N6510_CHAT_SETTINGS) {
1950 /* GSM data block */
1951 memcpy(req + pos, "\x01\x00", 2);pos += 2;
1952
1953 if (loc1 != -1) {
1954 length = UnicodeLength(settings->Settings[loc1].IPAddress)*2+1;
1955 length += UnicodeLength(settings->Settings[loc1].DialUp) *2+2;
1956 length += UnicodeLength(settings->Settings[loc1].User) *2+2;
1957 length += UnicodeLength(settings->Settings[loc1].Password) *2+2;
1958 } else {
1959 length = 1 + 2 + 2 + 2;
1960 }
1961 length += 11;
1962 req[pos++] = length / 256;
1963 req[pos++] = length % 256;
1964
1965 if (loc1 != -1) {
1966 if (!settings->Settings[loc1].IsNormalAuthentication) req[pos]=0x01; pos++;
1967 if (settings->Settings[loc1].IsISDNCall) req[pos]=0x01;pos++;
1968 switch (settings->Settings[loc1].Speed) {
1969 case WAPSETTINGS_SPEED_AUTO : break;
1970 case WAPSETTINGS_SPEED_9600: req[pos]=0x01; break;
1971 case WAPSETTINGS_SPEED_14400: req[pos]=0x02; break;
1972 }
1973 pos++;
1974 req[pos++]=0x01;
1975 if (!settings->Settings[loc1].ManualLogin) req[pos] = 0x01; pos++;
1976
1977 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].IPAddress, false);
1978 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].DialUp, true);
1979 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].User, true);
1980 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc1].Password, true);
1981 } else {
1982 pos += 3;
1983 req[pos++]=0x01;
1984 pos += 8;
1985 }
1986
1987 /* Padding */
1988 pos+=2;
1989 }
1990
1991 /* GPRS block */
1992 memcpy(req + pos, "\x03\x00", 2);pos += 2;
1993
1994 if (loc2 != -1) {
1995 length = UnicodeLength(settings->Settings[loc2].DialUp) *2+1;
1996 length += UnicodeLength(settings->Settings[loc2].IPAddress)*2+2;
1997 length += UnicodeLength(settings->Settings[loc2].User) *2+2;
1998 length += UnicodeLength(settings->Settings[loc2].Password) *2+2;
1999 } else {
2000 length = 7;
2001 }
2002 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) length+=2;
2003 length += 7;
2004 req[pos++] = length / 256;
2005 req[pos++] = length % 256;
2006
2007 if (loc2 != -1) {
2008 if (!settings->Settings[loc2].IsNormalAuthentication) req[pos] = 0x01; pos++;
2009 if (!settings->Settings[loc2].IsContinuous) req[pos] = 0x01; pos++;
2010 if (!settings->Settings[loc2].ManualLogin) req[pos] = 0x01; pos++;
2011
2012 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].DialUp, false);
2013 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].IPAddress, true);
2014 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].User, true);
2015 pos += NOKIA_SetUnicodeString(s, req + pos, settings->Settings[loc2].Password, true);
2016 } else {
2017 pos += 10;
2018 }
2019
2020 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_WAPMMSPROXY)) {
2021 req[pos++] = 0x00;
2022 req[pos++] = 0x00;
2023
2024 /* Proxy block */
2025 req[pos++] = 0x06;
2026 req[pos++] = 0x01;
2027 if (UnicodeLength(settings->Proxy)!=0 ||
2028 UnicodeLength(settings->Proxy2)!=0) {
2029 req[pos++] = (UnicodeLength(settings->Proxy)+UnicodeLength(settings->Proxy2)+13)/256;
2030 req[pos++] = (UnicodeLength(settings->Proxy)+UnicodeLength(settings->Proxy2)+13)%256;
2031 } else {
2032 req[pos++] = (UnicodeLength(settings->Proxy)+UnicodeLength(settings->Proxy2)+12)/256;
2033 req[pos++] = (UnicodeLength(settings->Proxy)+UnicodeLength(settings->Proxy2)+12)%256;
2034 }
2035 req[pos++] = UnicodeLength(settings->Proxy);
2036 req[pos++] = UnicodeLength(settings->Proxy2);
2037 req[pos++] = settings->ProxyPort/256;
2038 req[pos++] = settings->ProxyPort%256;
2039 req[pos++] = settings->Proxy2Port/256;
2040 req[pos++] = settings->Proxy2Port%256;
2041 if (UnicodeLength(settings->Proxy)!=0) {
2042 sprintf(req+pos,"%s",DecodeUnicodeString(settings->Proxy));
2043 pos+=UnicodeLength(settings->Proxy);
2044 }
2045 if (UnicodeLength(settings->Proxy2)!=0) {
2046 sprintf(req+pos,"%s",DecodeUnicodeString(settings->Proxy2));
2047 pos+=UnicodeLength(settings->Proxy2);
2048 }
2049 if (UnicodeLength(settings->Proxy)!=0 ||
2050 UnicodeLength(settings->Proxy2)!=0) {
2051 req[pos++] = 0x00;
2052 }
2053 req[pos++] = 0x00; req[pos++] = 0x00;
2054 req[pos++] = 0x07; //unknown
2055 req[pos++] = 0x00; req[pos++] = 0x00;
2056 req[pos++] = 0x80; //unknown
2057 req[pos++] = 0x01; //unknown
2058 req[pos++] = 0x05; //unknown
2059 req[pos++] = 0x00; req[pos++] = 0x00;
2060
2061 /* Proxy data blocks */
2062 for (i=0;i<4;i++) {
2063 port = 8080;
2064 Proxy = NULL;
2065 if (i==0) {
2066 port = settings->ProxyPort;
2067 Proxy = settings->Proxy;
2068 } else if (i==1) {
2069 port = settings->Proxy2Port;
2070 Proxy = settings->Proxy2;
2071 }
2072 req[pos++] = 0x08; req[pos++] = 0x00;
2073 if (Proxy != NULL && UnicodeLength(Proxy)!=0) {
2074 if (UnicodeLength(Proxy)%2 != 0) {
2075 req[pos++] = (12 + (UnicodeLength(Proxy)+1)*2)/256;
2076 req[pos++] = (12 + (UnicodeLength(Proxy)+1)*2)%256;
2077 } else {
2078 req[pos++] = (12 + UnicodeLength(Proxy)*2)/256;
2079 req[pos++] = (12 + UnicodeLength(Proxy)*2)%256;
2080 }
2081 } else {
2082 req[pos++] = 12/256;
2083 req[pos++] = 12%256;
2084 }
2085 req[pos++] = i+1;
2086 if (Proxy != NULL) {
2087 req[pos++] = UnicodeLength(Proxy);
2088 } else {
2089 req[pos++] = 0;
2090 }
2091 req[pos++] = port/256;
2092 req[pos++] = port%256;
2093 req[pos++] = 0x00;
2094
2095 req[pos++] = 0x00;
2096 req[pos++] = 0x01;
2097
2098 req[pos++] = 0x00;
2099 if (Proxy != NULL && UnicodeLength(Proxy)!=0) {
2100 CopyUnicodeString(req+pos,Proxy);
2101 pos+=UnicodeLength(Proxy)*2;
2102 if (UnicodeLength(Proxy)%2 != 0) {
2103 req[pos++] = 0x00;
2104 req[pos++] = 0x00;
2105 }
2106 }
2107 }
2108
2109 req[pos++] = 0x09; req[pos++] = 0x00; req[pos++] = 0x00;
2110 req[pos++] = 0x0C; req[pos++] = 0x02; req[pos++] = 0x00;
2111 req[pos++] = 0x00; req[pos++] = 0x02; req[pos++] = 0x00;
2112 req[pos++] = 0x00; req[pos++] = 0x00; req[pos++] = 0x00;
2113 } else {
2114 /* end of blocks ? */
2115 memcpy(req + pos, "\x80\x00\x00\x0c", 4);pos += 4;
2116 }
2117
2118 UnLock[4] = settings->Location-1;
2119 smprintf(s, "Making Connection settings read-write\n");
2120 error = GSM_WaitFor (s, UnLock, 5, 0x3f, 4, ID_SetConnectSet);
2121 if (error != ERR_NONE) return error;
2122
2123 switch (Type) {
2124 case N6510_MMS_SETTINGS:
2125 smprintf(s, "Setting MMS settings\n");
2126 break;
2127 case N6510_CHAT_SETTINGS:
2128 smprintf(s, "Setting Chat settings\n");
2129 break;
2130 case N6510_WAP_SETTINGS:
2131 smprintf(s, "Setting WAP settings\n");
2132 break;
2133 case N6510_SYNCML_SETTINGS:
2134 smprintf(s, "Setting SyncML settings\n");
2135 break;
2136 }
2137 error = GSM_WaitFor (s, req, pos, 0x3f, 4, ID_SetConnectSet);
2138 if (error != ERR_NONE) {
2139 if (error == ERR_INSIDEPHONEMENU || error == ERR_INVALIDLOCATION) {
2140 DCT3DCT4_DisableConnectionFunctions(s);
2141 }
2142 return error;
2143 }
2144
2145 if (settings->ReadOnly) {
2146 Lock[4] = settings->Location-1;
2147 smprintf(s, "Making Connection settings readonly\n");
2148 error = GSM_WaitFor (s, Lock, 5, 0x3f, 4, ID_SetConnectSet);
2149 if (error != ERR_NONE) return error;
2150 }
2151
2152 error = DCT3DCT4_SetActiveConnectSet(s, settings);
2153 if (error != ERR_NONE) return error;
2154
2155 return DCT3DCT4_DisableConnectionFunctions(s);
2156}
2157
2158static GSM_Error N6510_SetWAPSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
2159{
2160 return N6510_SetConnectionSettings(s, settings, N6510_WAP_SETTINGS);
2161}
2162
2163static GSM_Error N6510_SetMMSSettings(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
2164{
2165 return N6510_SetConnectionSettings(s, settings, N6510_MMS_SETTINGS);
2166}
2167
2168static GSM_Error N6510_ReplyGetOriginalIMEI(GSM_Protocol_Message msg, GSM_StateMachine *s)
2169{
2170 if (msg.Buffer[7] == 0x00) {
2171 smprintf(s, "No SIM card\n");
2172 return ERR_SECURITYERROR;
2173 } else {
2174 return NOKIA_ReplyGetPhoneString(msg, s);
2175 }
2176}
2177
2178static GSM_Error N6510_GetOriginalIMEI(GSM_StateMachine *s, char *value)
2179{
2180 return NOKIA_GetPhoneString(s,"\x00\x07\x02\x01\x00\x01",6,0x42,value,ID_GetOriginalIMEI,14);
2181}
2182
2183static GSM_Error N6510_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
2184{
2185 GSM_Phone_Data *Data = &s->Phone.Data;
2186
2187 switch (msg.Buffer[3]) {
2188 case 0x09:
2189 switch (msg.Buffer[4]) {
2190 case 0x00:
2191 smprintf(s, "Max. in phone memory : %i\n",msg.Buffer[10]*256+msg.Buffer[11]);
2192 smprintf(s, "Used in phone memory : %i\n",msg.Buffer[12]*256+msg.Buffer[13]);
2193 smprintf(s, "Unread in phone memory : %i\n",msg.Buffer[14]*256+msg.Buffer[15]);
2194 smprintf(s, "Max. in SIM : %i\n",msg.Buffer[22]*256+msg.Buffer[23]);
2195 smprintf(s, "Used in SIM : %i\n",msg.Buffer[24]*256+msg.Buffer[25]);
2196 smprintf(s, "Unread in SIM : %i\n",msg.Buffer[26]*256+msg.Buffer[27]);
2197 Data->SMSStatus->PhoneSize= msg.Buffer[10]*256+msg.Buffer[11];
2198 Data->SMSStatus->PhoneUsed= msg.Buffer[12]*256+msg.Buffer[13];
2199 Data->SMSStatus->PhoneUnRead = msg.Buffer[14]*256+msg.Buffer[15];
2200 Data->SMSStatus->SIMSize= msg.Buffer[22]*256+msg.Buffer[23];
2201 Data->SMSStatus->SIMUsed = msg.Buffer[24]*256+msg.Buffer[25];
2202 Data->SMSStatus->SIMUnRead = msg.Buffer[26]*256+msg.Buffer[27];
2203 return ERR_NONE;
2204 case 0x0f:
2205 smprintf(s, "No PIN\n");
2206 return ERR_SECURITYERROR;
2207 default:
2208 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
2209 return ERR_UNKNOWNRESPONSE;
2210 }
2211 case 0x1a:
2212 smprintf(s, "Wait a moment. Phone is during power on and busy now\n");
2213 return ERR_SECURITYERROR;
2214 }
2215 return ERR_UNKNOWNRESPONSE;
2216}
2217
2218static GSM_Error N6510_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
2219{
2220 GSM_Error error;
2221 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
2222 unsigned char req[] = {N6110_FRAME_HEADER, 0x08, 0x00, 0x00};
2223
2224 s->Phone.Data.SMSStatus=status;
2225 smprintf(s, "Getting SMS status\n");
2226 error = GSM_WaitFor (s, req, 6, 0x14, 2, ID_GetSMSStatus);
2227 if (error != ERR_NONE) return error;
2228
2229 /* DCT4 family doesn't show in frame with SMS status info
2230 * about Templates. We get separately info about this SMS folder.
2231 */
2232 error = N6510_GetSMSFolderStatus(s, 0x06);
2233 if (error != ERR_NONE) return error;
2234 status->TemplatesUsed = Priv->LastSMSFolder.Number;
2235
2236 return error;
2237}
2238
2239static GSM_Error N6510_ReplyDeleteSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
2240{
2241 switch (msg.Buffer[3]) {
2242 case 0x05:
2243 smprintf(s, "SMS deleted OK\n");
2244 return ERR_NONE;
2245 case 0x06:
2246 switch (msg.Buffer[4]) {
2247 case 0x02:
2248 smprintf(s, "Invalid location\n");
2249 return ERR_INVALIDLOCATION;
2250 default:
2251 smprintf(s, "Unknown error: %02x\n",msg.Buffer[4]);
2252 return ERR_UNKNOWNRESPONSE;
2253 }
2254 }
2255 return ERR_UNKNOWNRESPONSE;
2256}
2257
2258static GSM_Error N6510_DeleteSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
2259{
2260 unsigned char folderid;
2261 int location;
2262 unsigned char req[] = {N6110_FRAME_HEADER, 0x04,
2263 0x01, /* 0x01=SM, 0x02=ME */
2264 0x00, /* FolderID */
2265 0x00, 0x02, /* Location */
2266 0x0F, 0x55};
2267
2268 N6510_GetSMSLocation(s, sms, &folderid, &location);
2269
2270 switch (folderid) {
2271 case 0x01: req[5] = 0x02; break; /* INBOX SIM */
2272 case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
2273 default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders*/
2274 }
2275 req[6]=location / 256;
2276 req[7]=location;
2277
2278 smprintf(s, "Deleting sms\n");
2279 return GSM_WaitFor (s, req, 10, 0x14, 4, ID_DeleteSMSMessage);
2280}
2281
2282static GSM_Error N6510_ReplySendSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
2283{
2284 switch (msg.Buffer[8]) {
2285 case 0x00:
2286 smprintf(s, "SMS sent OK, TPMR for sent sms is %02x\n",msg.Buffer[10]);
2287 if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,0,msg.Buffer[10]);
2288 return ERR_NONE;
2289 default:
2290 smprintf(s, "SMS not sent OK, error code probably %i\n",msg.Buffer[8]);
2291 if (s->User.SendSMSStatus!=NULL) s->User.SendSMSStatus(s->CurrentConfig->Device,msg.Buffer[8],msg.Buffer[10]);
2292 return ERR_NONE;
2293 }
2294}
2295
2296static GSM_Error N6510_SendSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
2297{
2298 int length = 11;
2299 GSM_Error error;
2300 GSM_SMSMessageLayout Layout;
2301 unsigned char req [300] = {
2302 N6110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55};
2303
2304 if (sms->PDU == SMS_Deliver) sms->PDU = SMS_Submit;
2305 memset(req+9,0x00,sizeof(req) - 9);
2306 error=N6510_EncodeSMSFrame(s, sms, req + 9, &Layout, &length);
2307 if (error != ERR_NONE) return error;
2308
2309 smprintf(s, "Sending sms\n");
2310 return s->Protocol.Functions->WriteMessage(s, req, length + 9, 0x02);
2311}
2312
2313static GSM_Error N6510_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
2314{
2315 GSM_Phone_Data *Data = &s->Phone.Data;
2316
2317 smprintf(s, "Security Code status received: ");
2318 switch (msg.Buffer[4]) {
2319 case 0x01 : smprintf(s, "waiting for Security Code.\n"); *Data->SecurityStatus = SEC_SecurityCode;break;
2320 case 0x07 :
2321 case 0x02 : smprintf(s, "waiting for PIN.\n"); *Data->SecurityStatus = SEC_Pin; break;
2322 case 0x03 : smprintf(s, "waiting for PUK.\n"); *Data->SecurityStatus = SEC_Puk; break;
2323 case 0x05 : smprintf(s, "PIN ok, SIM ok\n"); *Data->SecurityStatus = SEC_None; break;
2324 case 0x06 : smprintf(s, "No input status\n"); *Data->SecurityStatus = SEC_None; break;
2325 case 0x16 : smprintf(s, "No SIM card\n"); *Data->SecurityStatus = SEC_None; break;
2326 case 0x1A : smprintf(s, "SIM card rejected!\n"); *Data->SecurityStatus = SEC_None; break;
2327 default : smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
2328 return ERR_UNKNOWNRESPONSE;
2329 }
2330 return ERR_NONE;
2331}
2332
2333static GSM_Error N6510_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
2334{
2335 unsigned char req[5] = {N6110_FRAME_HEADER, 0x11, 0x00};
2336
2337 s->Phone.Data.SecurityStatus=Status;
2338 smprintf(s, "Getting security code status\n");
2339 return GSM_WaitFor (s, req, 5, 0x08, 2, ID_GetSecurityStatus);
2340}
2341
2342static GSM_Error N6510_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
2343{
2344 switch (msg.Buffer[3]) {
2345 case 0x08:
2346 smprintf(s, "Security code OK\n");
2347 return ERR_NONE;
2348 case 0x09:
2349 switch (msg.Buffer[4]) {
2350 case 0x06:
2351 smprintf(s, "Wrong PIN\n");
2352 return ERR_SECURITYERROR;
2353 case 0x09:
2354 smprintf(s, "Wrong PUK\n");
2355 return ERR_SECURITYERROR;
2356 default:
2357 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
2358 }
2359 }
2360 return ERR_UNKNOWNRESPONSE;
2361}
2362
2363static GSM_Error N6510_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
2364{
2365 int len = 0;
2366 unsigned char req[15] = {N6110_FRAME_HEADER, 0x07,
2367 0x00};/* Code type */
2368
2369 switch (Code.Type) {
2370 case SEC_Pin: req[4] = 0x02; break;
2371 case SEC_Puk: req[4] = 0x03; break;/* FIXME */
2372 default : return ERR_NOTSUPPORTED;
2373 }
2374
2375 len = strlen(Code.Code);
2376 memcpy(req+5,Code.Code,len);
2377 req[5+len]=0x00;
2378
2379 smprintf(s, "Entering security code\n");
2380 return GSM_WaitFor (s, req, 6+len, 0x08, 4, ID_EnterSecurityCode);
2381}
2382
2383static GSM_Error N6510_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
2384{
2385 unsigned char folder;
2386 GSM_Phone_Data *Data = &s->Phone.Data;
2387
2388 switch (msg.Buffer[3]) {
2389 case 0x01:
2390 switch (msg.Buffer[4]) {
2391 case 0x00:
2392 smprintf(s, "Done OK\n");
2393 smprintf(s, "Folder info: %i %i\n",msg.Buffer[5],msg.Buffer[8]);
2394 switch (msg.Buffer[8]) {
2395 case 0x02 : if (msg.Buffer[5] == 0x02) {
2396 folder = 0x03; /* INBOX ME */
2397 } else {
2398 folder = 0x01; /* INBOX SIM */
2399 }
2400 break;
2401 case 0x03 : if (msg.Buffer[5] == 0x02) {
2402 folder = 0x04; /* OUTBOX ME */
2403 } else {
2404 folder = 0x02; /* OUTBOX SIM */
2405 }
2406 break;
2407 default : folder = msg.Buffer[8] + 1;
2408 }
2409 N6510_SetSMSLocation(s, Data->SaveSMSMessage,folder,msg.Buffer[6]*256+msg.Buffer[7]);
2410 smprintf(s, "Saved in folder %i at location %i\n",folder, msg.Buffer[6]*256+msg.Buffer[7]);
2411 Data->SaveSMSMessage->Folder = folder;
2412 return ERR_NONE;
2413 case 0x02:
2414 printf("Incorrect location\n");
2415 return ERR_INVALIDLOCATION;
2416 case 0x05:
2417 printf("Incorrect folder\n");
2418 return ERR_INVALIDLOCATION;
2419 default:
2420 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
2421 return ERR_UNKNOWNRESPONSE;
2422 }
2423 case 0x17:
2424 smprintf(s, "SMS name changed\n");
2425 return ERR_NONE;
2426 }
2427 return ERR_UNKNOWNRESPONSE;
2428}
2429
2430static GSM_Error N6510_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
2431{
2432 int location, length = 11;
2433 unsigned char folderid, folder;
2434 GSM_SMSMessageLayout Layout;
2435 GSM_Error error;
2436 unsigned char req [300] = {
2437 N6110_FRAME_HEADER, 0x00,
2438 0x01, /* 1 = SIM, 2 = ME */
2439 0x02, /* Folder */
2440 0x00, 0x01, /* Location */
2441 0x01}; /* SMS state */
2442 unsigned char NameReq[200] = {
2443 N6110_FRAME_HEADER, 0x16,
2444 0x01, /* 1 = SIM, 2 = ME */
2445 0x02, /* Folder */
2446 0x00, 0x01}; /* Location */
2447
2448 N6510_GetSMSLocation(s, sms, &folderid, &location);
2449 switch (folderid) {
2450 case 0x01: req[5] = 0x02; break; /* INBOX SIM */
2451 case 0x02: req[5] = 0x03; break; /* OUTBOX SIM */
2452 default : req[5] = folderid - 1; req[4] = 0x02; break; /* ME folders*/
2453 }
2454 req[6]=location / 256;
2455 req[7]=location;
2456
2457 switch (sms->PDU) {
2458 case SMS_Submit:
2459 /* Inbox */
2460 if (folderid == 0x01 || folderid == 0x03) sms->PDU = SMS_Deliver;
2461 break;
2462 case SMS_Deliver:
2463 /* SIM Outbox */
2464 if (folderid == 0x02) sms->PDU = SMS_Submit;
2465 break;
2466 default:
2467 return ERR_UNKNOWN;
2468 }
2469 if (sms->PDU == SMS_Deliver) {
2470 switch (sms->State) {
2471 case SMS_Sent: /* We use GSM_Read, because phone return error */
2472 case SMS_Read: req[8] = 0x01; break;
2473 case SMS_UnSent: /* We use GSM_UnRead, because phone return error */
2474 case SMS_UnRead: req[8] = 0x03; break;
2475 }
2476 } else {
2477 switch (sms->State) {
2478 case SMS_Sent: /* We use GSM_Sent, because phone change folder */
2479 case SMS_Read: req[8] = 0x05; break;
2480 case SMS_UnSent: /* We use GSM_UnSent, because phone change folder */
2481 case SMS_UnRead: req[8] = 0x07; break;
2482 }
2483 }
2484 memset(req+9,0x00,sizeof(req) - 9);
2485 error=N6510_EncodeSMSFrame(s, sms, req + 9, &Layout, &length);
2486 if (error != ERR_NONE) return error;
2487
2488 s->Phone.Data.SaveSMSMessage=sms;
2489 smprintf(s, "Saving sms\n");
2490 error=GSM_WaitFor (s, req, length+9, 0x14, 4, ID_SaveSMSMessage);
2491 if (error == ERR_NONE && UnicodeLength(sms->Name)!=0) {
2492 folder = sms->Folder;
2493 sms->Folder = 0;
2494 N6510_GetSMSLocation(s, sms, &folderid, &location);
2495 switch (folderid) {
2496 case 0x01: NameReq[5] = 0x02; break; /* INBOX SIM */
2497 case 0x02: NameReq[5] = 0x03; break; /* OUTBOX SIM */
2498 default : NameReq[5] = folderid - 1; NameReq[4] = 0x02; break; /* ME folders*/
2499 }
2500 NameReq[6]=location / 256;
2501 NameReq[7]=location;
2502 length = 8;
2503 CopyUnicodeString(NameReq+length, sms->Name);
2504 length = length+UnicodeLength(sms->Name)*2;
2505 NameReq[length++] = 0;
2506 NameReq[length++] = 0;
2507 error=GSM_WaitFor (s, NameReq, length, 0x14, 4, ID_SaveSMSMessage);
2508 sms->Folder = folder;
2509 }
2510 return error;
2511}
2512
2513static GSM_Error N6510_SetSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2514{
2515 int location;
2516 unsigned char folderid;
2517
2518 N6510_GetSMSLocation(s, sms, &folderid, &location);
2519 if (location == 0) return ERR_INVALIDLOCATION;
2520 return N6510_PrivSetSMSMessage(s, sms);
2521}
2522
2523static GSM_Error N6510_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
2524{
2525 int location;
2526 unsigned char folderid;
2527
2528 N6510_GetSMSLocation(s, sms, &folderid, &location);
2529 location = 0;
2530 N6510_SetSMSLocation(s, sms, folderid, location);
2531 return N6510_PrivSetSMSMessage(s, sms);
2532}
2533
2534static GSM_Error N6510_ReplyGetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
2535{
2536 smprintf(s, "Date & time received\n");
2537 if (msg.Buffer[4]==0x01) {
2538 NOKIA_DecodeDateTime(s, msg.Buffer+10, s->Phone.Data.DateTime);
2539 return ERR_NONE;
2540 }
2541 smprintf(s, "Not set in phone\n");
2542 return ERR_EMPTY;
2543}
2544
2545static GSM_Error N6510_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
2546{
2547 unsigned char req[] = {N6110_FRAME_HEADER, 0x0A, 0x00, 0x00};
2548
2549 s->Phone.Data.DateTime=date_time;
2550 smprintf(s, "Getting date & time\n");
2551 return GSM_WaitFor (s, req, 6, 0x19, 4, ID_GetDateTime);
2552}
2553
2554static GSM_Error N6510_ReplySetDateTime(GSM_Protocol_Message msg, GSM_StateMachine *s)
2555{
2556 smprintf(s, "Date & time set\n");
2557 return ERR_NONE;
2558}
2559
2560static GSM_Error N6510_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
2561{
2562 unsigned char req[] = {N6110_FRAME_HEADER,
2563 0x01, 0x00, 0x01, 0x01, 0x0c, 0x01, 0x03,
2564 0x00, 0x00,/* Year */
2565 0x08, 0x01, /* Month & Day */
2566 0x15, 0x1f,/* Hours & Minutes */
2567 0x2b, /* Second ? */
2568 0x00};
2569
2570 NOKIA_EncodeDateTime(s, req+10, date_time);
2571 req[16] = date_time->Second;
2572 smprintf(s, "Setting date & time\n");
2573 return GSM_WaitFor (s, req, 18, 0x19, 4, ID_SetDateTime);
2574}
2575
2576static GSM_Error N6510_ReplyGetManufactureMonth(GSM_Protocol_Message msg, GSM_StateMachine *s)
2577{
2578 if (msg.Buffer[7] == 0x00) {
2579 smprintf(s, "No SIM card\n");
2580 return ERR_SECURITYERROR;
2581 } else {
2582 sprintf(s->Phone.Data.PhoneString,"%02i/%04i",msg.Buffer[13],msg.Buffer[14]*256+msg.Buffer[15]);
2583 return ERR_NONE;
2584 }
2585}
2586
2587static GSM_Error N6510_GetManufactureMonth(GSM_StateMachine *s, char *value)
2588{
2589 unsigned char req[6] = {0x00, 0x05, 0x02, 0x01, 0x00, 0x02};
2590 //unsigned char req[6] = {0x00, 0x03, 0x04, 0x0B, 0x01, 0x00};
2591
2592 s->Phone.Data.PhoneString=value;
2593 smprintf(s, "Getting manufacture month\n");
2594 return GSM_WaitFor (s, req, 6, 0x42, 2, ID_GetManufactureMonth);
2595 //return GSM_WaitFor (s, req, 6, 0x1B, 2, ID_GetManufactureMonth);
2596}
2597
2598static GSM_Error N6510_ReplyGetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
2599{
2600 GSM_Phone_Data *Data = &s->Phone.Data;
2601
2602 switch(msg.Buffer[3]) {
2603 case 0x1A:
2604 smprintf(s, " Alarm: %02d:%02d\n", msg.Buffer[14], msg.Buffer[15]);
2605 Data->Alarm->Repeating = true;
2606 Data->Alarm->Text[0] = 0;
2607 Data->Alarm->Text[1] = 0;
2608 Data->Alarm->DateTime.Hour= msg.Buffer[14];
2609 Data->Alarm->DateTime.Minute= msg.Buffer[15];
2610 Data->Alarm->DateTime.Second= 0;
2611 return ERR_NONE;
2612 case 0x20:
2613 smprintf(s, "Alarm state received\n");
2614 if (msg.Buffer[37] == 0x01) {
2615 smprintf(s, " Not set in phone\n");
2616 return ERR_EMPTY;
2617 }
2618 smprintf(s, "Enabled\n");
2619 return ERR_NONE;
2620 }
2621 return ERR_UNKNOWNRESPONSE;
2622}
2623
2624static GSM_Error N6510_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
2625{
2626 unsigned char StateReq[] = {N6110_FRAME_HEADER, 0x1f, 0x01, 0x00};
2627 unsigned char GetReq [] = {N6110_FRAME_HEADER, 0x19, 0x00, 0x02};
2628 GSM_Errorerror;
2629
2630 if (alarm->Location != 1) return ERR_NOTSUPPORTED;
2631
2632 s->Phone.Data.Alarm=alarm;
2633 smprintf(s, "Getting alarm state\n");
2634 error = GSM_WaitFor (s, StateReq, 6, 0x19, 4, ID_GetAlarm);
2635 if (error != ERR_NONE) return error;
2636
2637 smprintf(s, "Getting alarm\n");
2638 return GSM_WaitFor (s, GetReq, 6, 0x19, 4, ID_GetAlarm);
2639}
2640
2641static GSM_Error N6510_ReplySetAlarm(GSM_Protocol_Message msg, GSM_StateMachine *s)
2642{
2643 smprintf(s, "Alarm set\n");
2644 return ERR_NONE;
2645}
2646
2647static GSM_Error N6510_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
2648{
2649 unsigned char req[] = {N6110_FRAME_HEADER,
2650 0x11, 0x00, 0x01, 0x01, 0x0c, 0x02,
2651 0x01, 0x00, 0x00, 0x00, 0x00,
2652 0x00, 0x00, /* Hours, Minutes */
2653 0x00, 0x00, 0x00 };
2654
2655 if (alarm->Location != 1) return ERR_NOTSUPPORTED;
2656
2657 req[14] = alarm->DateTime.Hour;
2658 req[15] = alarm->DateTime.Minute;
2659
2660 smprintf(s, "Setting alarm\n");
2661 return GSM_WaitFor (s, req, 19, 0x19, 4, ID_SetAlarm);
2662}
2663
2664static GSM_Error N6510_ReplyGetRingtonesInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
2665{
2666 int tmp,i;
2667 GSM_Phone_Data *Data = &s->Phone.Data;
2668
2669 smprintf(s, "Ringtones info received\n");
2670 memset(Data->RingtonesInfo,0,sizeof(GSM_AllRingtonesInfo));
2671 if (msg.Buffer[4] * 256 + msg.Buffer[5] == 0x00) return ERR_EMPTY;
2672 Data->RingtonesInfo->Number = msg.Buffer[4] * 256 + msg.Buffer[5];
2673 tmp = 6;
2674 for (i=0;i<Data->RingtonesInfo->Number;i++) {
2675 Data->RingtonesInfo->Ringtone[i].Group = msg.Buffer[tmp+4];
2676 Data->RingtonesInfo->Ringtone[i].ID = msg.Buffer[tmp+2] * 256 + msg.Buffer[tmp+3];
2677 memcpy(Data->RingtonesInfo->Ringtone[i].Name,msg.Buffer+tmp+8,(msg.Buffer[tmp+6]*256+msg.Buffer[tmp+7])*2);
2678 smprintf(s, "%5i (%5i). \"%s\"\n",
2679 Data->RingtonesInfo->Ringtone[i].ID,
2680 Data->RingtonesInfo->Ringtone[i].Group,
2681 DecodeUnicodeString(Data->RingtonesInfo->Ringtone[i].Name));
2682 tmp = tmp + (msg.Buffer[tmp]*256+msg.Buffer[tmp+1]);
2683 }
2684 return ERR_NONE;
2685}
2686
2687static GSM_Error N6510_PrivGetRingtonesInfo(GSM_StateMachine *s, GSM_AllRingtonesInfo *Info, bool AllRingtones)
2688{
2689 GSM_Errorerror;
2690 unsigned char UserReq[8] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0x02};
2691 // unsigned char All_Req[9] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0xFE, 0x00, 0x7D};
2692 unsigned char All_Req[8] = {N7110_FRAME_HEADER, 0x07, 0x00, 0x00, 0x00, 0x00};
2693
2694 s->Phone.Data.RingtonesInfo=Info;
2695 smprintf(s, "Getting binary ringtones ID\n");
2696 if (AllRingtones) {
2697 // error = GSM_WaitFor (s, All_Req, 9, 0x1f, 4, ID_GetRingtonesInfo);
2698 error = GSM_WaitFor (s, All_Req, 8, 0x1f, 4, ID_GetRingtonesInfo);
2699 if (error == ERR_EMPTY && Info->Number == 0) return ERR_NOTSUPPORTED;
2700 return error;
2701 } else {
2702 error = GSM_WaitFor (s, UserReq, 8, 0x1f, 4, ID_GetRingtonesInfo);
2703 if (error == ERR_EMPTY && Info->Number == 0) return ERR_NOTSUPPORTED;
2704 return error;
2705 }
2706}
2707
2708static GSM_Error N6510_GetRingtonesInfo(GSM_StateMachine *s, GSM_AllRingtonesInfo *Info)
2709{
2710 return N6510_PrivGetRingtonesInfo(s, Info, true);
2711}
2712
2713static GSM_Error N6510_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
2714{
2715 int tmp,i;
2716 GSM_Phone_Data *Data = &s->Phone.Data;
2717
2718 smprintf(s, "Ringtone received\n");
2719 memcpy(Data->Ringtone->Name,msg.Buffer+8,msg.Buffer[7]*2);
2720 Data->Ringtone->Name[msg.Buffer[7]*2]=0;
2721 Data->Ringtone->Name[msg.Buffer[7]*2+1]=0;
2722 smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
2723 if (msg.Buffer[msg.Buffer[7]*2+10] == 'M' &&
2724 msg.Buffer[msg.Buffer[7]*2+11] == 'T' &&
2725 msg.Buffer[msg.Buffer[7]*2+12] == 'h' &&
2726 msg.Buffer[msg.Buffer[7]*2+13] == 'd') {
2727 smprintf(s,"MIDI\n");
2728 tmp = msg.Buffer[7]*2+10;
2729 i = msg.Length - 2; /* ?????? */
2730 Data->Ringtone->Format = RING_MIDI;
2731 } else {
2732 /* Looking for end */
2733 i=8+msg.Buffer[7]*2+3;
2734 tmp = i;
2735 while (true) {
2736 if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
2737 i=i+2; break;
2738 }
2739 i++;
2740 if (i==msg.Length) return ERR_EMPTY;
2741 }
2742 }
2743 /* Copying frame */
2744 memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+tmp,i-tmp);
2745 Data->Ringtone->NokiaBinary.Length=i-tmp;
2746 return ERR_NONE;
2747}
2748
2749static GSM_Error N6510_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
2750{
2751 GSM_AllRingtonesInfo Info;
2752 GSM_Error error;
2753 unsigned char req2[6] = {N7110_FRAME_HEADER, 0x12,
2754 0x00, 0xe7}; /* Location */
2755
2756 if (Ringtone->Format == 0x00) Ringtone->Format = RING_NOKIABINARY;
2757
2758 switch (Ringtone->Format) {
2759 case RING_NOTETONE:
2760 /* In the future get binary and convert */
2761 return ERR_NOTSUPPORTED;
2762 case RING_NOKIABINARY:
2763 s->Phone.Data.Ringtone= Ringtone;
2764 Info.Number = 0;
2765 error=N6510_PrivGetRingtonesInfo(s, &Info, PhoneRingtone);
2766 if (error != ERR_NONE) return error;
2767 if (Ringtone->Location > Info.Number) return ERR_INVALIDLOCATION;
2768 req2[4] = Info.Ringtone[Ringtone->Location-1].ID / 256;
2769 req2[5] = Info.Ringtone[Ringtone->Location-1].ID % 256;
2770 smprintf(s, "Getting binary ringtone\n");
2771 return GSM_WaitFor (s, req2, 6, 0x1f, 4, ID_GetRingtone);
2772 case RING_MIDI:
2773 return ERR_NOTSUPPORTED;
2774 }
2775 return ERR_NOTSUPPORTED;
2776}
2777
2778static GSM_Error N6510_PlayTone(GSM_StateMachine *s, int Herz, unsigned char Volume, bool start)
2779{
2780 GSM_Error error;
2781 unsigned char reqStart[] = {
2782 0x00,0x06,0x01,0x00,0x07,0x00 };
2783 unsigned char reqPlay[] = {
2784 0x00,0x06,0x01,0x14,0x05,0x04,
2785 0x00,0x00,0x00,0x03,0x03,0x08,
2786 0x00,0x00,0x00,0x01,0x00,0x00,
2787 0x03,0x08,0x01,0x00,
2788 0x07,0xd0,/*Frequency */
2789 0x00,0x00,0x03,0x08,0x02,0x00,0x00,
2790 0x05, /*Volume */
2791 0x00,0x00};
2792 unsigned char reqOff[] = {
2793 0x00,0x06,0x01,0x14,0x05,0x05,
2794 0x00,0x00,0x00,0x01,0x03,0x08,
2795 0x05,0x00,0x00,0x08,0x00,0x00};
2796 // unsigned char reqOff2[] = {
2797 // 0x00,0x06,0x01,0x14,0x05,0x04,
2798 // 0x00,0x00,0x00,0x01,0x03,0x08,
2799 // 0x00,0x00,0x00,0x00,0x00,0x00};
2800
2801 if (start) {
2802 smprintf(s, "Enabling sound - part 1\n");
2803 error=GSM_WaitFor (s, reqStart, 6, 0x0b, 4, ID_PlayTone);
2804 if (error!=ERR_NONE) return error;
2805 smprintf(s, "Enabling sound - part 2 (disabling sound command)\n");
2806 error=GSM_WaitFor (s, reqOff, 18, 0x0b, 4, ID_PlayTone);
2807 if (error!=ERR_NONE) return error;
2808 }
2809
2810 /* For Herz==255*255 we have silent */
2811 if (Herz!=255*255) {
2812 reqPlay[23] = Herz%256;
2813 reqPlay[22] = Herz/256;
2814 reqPlay[31] = Volume;
2815 smprintf(s, "Playing sound\n");
2816 return GSM_WaitFor (s, reqPlay, 34, 0x0b, 4, ID_PlayTone);
2817 } else {
2818 reqPlay[23] = 0;
2819 reqPlay[22] = 0;
2820 reqPlay[31] = 0;
2821 smprintf(s, "Playing silent sound\n");
2822 return GSM_WaitFor (s, reqPlay, 34, 0x0b, 4, ID_PlayTone);
2823
2824 // smprintf(s, "Disabling sound - part 1\n");
2825 // error=GSM_WaitFor (s, reqOff, 18, 0x0b, 4, ID_PlayTone);
2826 // if (error!=ERR_NONE) return error;
2827 // smprintf(s, "Disabling sound - part 2\n");
2828 // return GSM_WaitFor (s, reqOff2, 18, 0x0b, 4, ID_PlayTone);
2829 }
2830}
2831
2832static GSM_Error N6510_ReplyGetPPM(GSM_Protocol_Message msg, GSM_StateMachine *s)
2833{
2834 GSM_Phone_Data *Data = &s->Phone.Data;
2835 int pos = 6,len;
2836
2837 smprintf(s, "Received phone info\n");
2838
2839 while(pos < msg.Length) {
2840 if (msg.Buffer[pos] == 0x55 && msg.Buffer[pos+1] == 0x55) {
2841 while(1) {
2842 if (msg.Buffer[pos] != 0x55) break;
2843 pos++;
2844 }
2845 }
2846 len = pos;
2847 while(1) {
2848 if (msg.Buffer[len] == 0x00 && msg.Buffer[len+1] == 0x00) break;
2849 len++;
2850 }
2851 while(1) {
2852 if (msg.Buffer[len] != 0x00) break;
2853 len++;
2854 }
2855 len = len-pos;
2856 smprintf(s, "Block with ID %02x",msg.Buffer[pos]);
2857#ifdef DEBUG
2858 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, msg.Buffer+pos, len);
2859#endif
2860 switch (msg.Buffer[pos]) {
2861 case 0x49:
2862 smprintf(s, "hardware version\n");
2863 break;
2864 case 0x58:
2865 pos += 3;
2866 while (msg.Buffer[pos] != 0x00) pos++;
2867 Data->PhoneString[0] = msg.Buffer[pos - 1];
2868 Data->PhoneString[1] = 0x00;
2869 smprintf(s, "PPM %s\n",Data->PhoneString);
2870 return ERR_NONE;
2871 default:
2872 break;
2873 }
2874 pos += len;
2875 }
2876 return ERR_NOTSUPPORTED;
2877}
2878
2879static GSM_Error N6510_GetPPM(GSM_StateMachine *s,char *value)
2880{
2881 //unsigned char req[6] = {N6110_FRAME_HEADER, 0x07, 0x01, 0xff};
2882 unsigned char req[6] = {N6110_FRAME_HEADER, 0x07, 0x01, 0x00};
2883
2884 s->Phone.Data.PhoneString=value;
2885 smprintf(s, "Getting PPM\n");
2886 return GSM_WaitFor (s, req, 6, 0x1b, 3, ID_GetPPM);
2887}
2888
2889static GSM_Error N6510_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
2890{
2891 GSM_MemoryEntry pbk;
2892 GSM_Error error;
2893
2894 pbk.MemoryType = MEM7110_SP;
2895 pbk.Location = SpeedDial->Location;
2896 SpeedDial->MemoryLocation = 0;
2897 s->Phone.Data.SpeedDial = SpeedDial;
2898
2899 smprintf(s, "Getting speed dial\n");
2900 error=N6510_GetMemory(s,&pbk);
2901 switch (error) {
2902 case ERR_NOTSUPPORTED:
2903 smprintf(s, "No speed dials set in phone\n");
2904 return ERR_EMPTY;
2905 case ERR_NONE:
2906 if (SpeedDial->MemoryLocation == 0) {
2907 smprintf(s, "Speed dial not assigned or error in firmware\n");
2908 return ERR_EMPTY;
2909 }
2910 return ERR_NONE;
2911 default:
2912 return error;
2913 }
2914}
2915
2916static GSM_Error N6510_ReplyGetProfile(GSM_Protocol_Message msg, GSM_StateMachine *s)
2917{
2918 unsigned char *blockstart;
2919 int i,j;
2920 GSM_Phone_Data*Data = &s->Phone.Data;
2921
2922 switch (msg.Buffer[3]) {
2923 case 0x02:
2924 blockstart = msg.Buffer + 7;
2925 for (i = 0; i < 11; i++) {
2926 smprintf(s, "Profile feature %02x ",blockstart[1]);
2927#ifdef DEBUG
2928 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, blockstart, blockstart[0]);
2929#endif
2930
2931 switch (blockstart[1]) {
2932 case 0x03:
2933 smprintf(s, "Ringtone ID\n");
2934 Data->Profile->FeatureID[Data->Profile->FeaturesNumber] = Profile_RingtoneID;
2935 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = blockstart[7];
2936 if (blockstart[7] == 0x00) {
2937 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = blockstart[10];
2938 }
2939 Data->Profile->FeaturesNumber++;
2940 break;
2941 case 0x05:/* SMS tone */
2942 j = Data->Profile->FeaturesNumber;
2943 NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,false);
2944 if (j == Data->Profile->FeaturesNumber) {
2945 Data->Profile->FeatureID[Data->Profile->FeaturesNumber] = Profile_MessageTone;
2946 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = PROFILE_MESSAGE_PERSONAL;
2947 Data->Profile->FeaturesNumber++;
2948 Data->Profile->FeatureID[Data->Profile->FeaturesNumber] = Profile_MessageToneID;
2949 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = blockstart[7];
2950 Data->Profile->FeaturesNumber++;
2951 }
2952 break;
2953 case 0x08:/* Caller groups */
2954 NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,true);
2955 break;
2956 case 0x0c :
2957 CopyUnicodeString(Data->Profile->Name,blockstart + 7);
2958 smprintf(s, "profile Name: \"%s\"\n", DecodeUnicodeString(Data->Profile->Name));
2959 Data->Profile->DefaultName = false;
2960 break;
2961 default:
2962 NOKIA_FindFeatureValue(s, Profile71_65,blockstart[1],blockstart[7],Data,false);
2963 }
2964 blockstart = blockstart + blockstart[0];
2965 }
2966 return ERR_NONE;
2967 case 0x06:
2968 Data->Profile->Active = false;
2969 if (Data->Profile->Location == msg.Buffer[5]) Data->Profile->Active = true;
2970 return ERR_NONE;
2971 }
2972 return ERR_UNKNOWNRESPONSE;
2973}
2974
2975static GSM_Error N6510_GetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
2976{
2977 unsigned char req[150] = {N6110_FRAME_HEADER, 0x01, 0x01, 0x0C, 0x01};
2978 unsigned charreqActive[] = {N6110_FRAME_HEADER, 0x05};
2979 int i, length = 7;
2980 GSM_Errorerror;
2981
2982 /* For now !!! */
2983 if (!strcmp(s->Phone.Data.ModelInfo->model,"3510")) {
2984 if (s->Phone.Data.VerNum>3.37) return ERR_NOTSUPPORTED;
2985 }
2986 if (!strcmp(s->Phone.Data.ModelInfo->model,"6230")) {
2987 return ERR_NOTSUPPORTED;
2988 }
2989
2990 if (Profile->Location>5) return ERR_INVALIDLOCATION;
2991
2992 for (i = 0; i < 0x0a; i++) {
2993 req[length++] = 0x04;
2994 req[length++] = Profile->Location;
2995 req[length++] = i;
2996 req[length++] = 0x01;
2997 }
2998
2999 req[length++] = 0x04;
3000 req[length++] = Profile->Location;
3001 req[length++] = 0x0c;
3002 req[length++] = 0x01;
3003
3004 req[length++] = 0x04;
3005
3006 Profile->CarKitProfile= false;
3007 Profile->HeadSetProfile= false;
3008
3009 Profile->FeaturesNumber = 0;
3010
3011 s->Phone.Data.Profile=Profile;
3012 smprintf(s, "Getting profile\n");
3013 error = GSM_WaitFor (s, req, length, 0x39, 4, ID_GetProfile);
3014 if (error != ERR_NONE) return error;
3015
3016 smprintf(s, "Checking, which profile is active\n");
3017 return GSM_WaitFor (s, reqActive, 4, 0x39, 4, ID_GetProfile);
3018}
3019
3020static GSM_Error N6510_ReplySetProfile(GSM_Protocol_Message msg, GSM_StateMachine *s)
3021{
3022 unsigned char *blockstart;
3023 int i;
3024
3025 smprintf(s, "Response to profile writing received!\n");
3026
3027 blockstart = msg.Buffer + 6;
3028 for (i = 0; i < msg.Buffer[5]; i++) {
3029 switch (blockstart[2]) {
3030 case 0x00: smprintf(s, "keypad tone level"); break;
3031 case 0x02: smprintf(s, "call alert"); break;
3032 case 0x03: smprintf(s, "ringtone"); break;
3033 case 0x04: smprintf(s, "ringtone volume"); break;
3034 case 0x05: smprintf(s, "SMS tone"); break;
3035 case 0x06: smprintf(s, "vibration"); break;
3036 case 0x07: smprintf(s, "warning tone level"); break;
3037 case 0x08: smprintf(s, "caller groups"); break;
3038 case 0x09: smprintf(s, "automatic answer"); break;
3039 case 0x0c: smprintf(s, "name"); break;
3040 default:
3041 smprintf(s, "Unknown block type %02x", blockstart[2]);
3042 break;
3043 }
3044 if (msg.Buffer[4] == 0x00) {
3045 smprintf(s, ": set OK\n");
3046 } else {
3047 smprintf(s, ": setting error %i\n", msg.Buffer[4]);
3048 }
3049 blockstart = blockstart + blockstart[1];
3050 }
3051 return ERR_NONE;
3052}
3053
3054static GSM_Error N6510_SetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
3055{
3056 int i, length = 7, blocks = 0;
3057 bool found;
3058 unsigned charID,Value;
3059 unsigned char req[150] = {N6110_FRAME_HEADER, 0x03, 0x01,
3060 0x06, /* Number of blocks */
3061 0x03};
3062
3063 if (Profile->Location>5) return ERR_INVALIDLOCATION;
3064
3065 for (i=0;i<Profile->FeaturesNumber;i++) {
3066 found = false;
3067 switch (Profile->FeatureID[i]) {
3068 case Profile_RingtoneID:
3069 ID = 0x03;
3070 Value = Profile->FeatureValue[i];
3071 found = true;
3072 break;
3073 default:
3074 found=NOKIA_FindPhoneFeatureValue(
3075 s,
3076 Profile71_65,
3077 Profile->FeatureID[i],Profile->FeatureValue[i],
3078 &ID,&Value);
3079 }
3080 if (found) {
3081 req[length] = 0x09;
3082 req[length + 1] = ID;
3083 req[length + 2] = Profile->Location;
3084 memcpy(req + length + 4, "\x00\x00\x01", 3);
3085 req[length + 8] = 0x03;
3086 req[length + 3] = req[length + 7] = Value;
3087 blocks++;
3088 length += 9;
3089 }
3090 }
3091
3092 smprintf(s, "Setting profile\n");
3093 return GSM_WaitFor (s, req, length, 0x39, 4, ID_SetProfile);
3094}
3095
3096static GSM_Error N6510_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
3097{
3098 GSM_SMSMessage sms;
3099
3100#ifdef DEBUG
3101 smprintf(s, "SMS message received\n");
3102 N6510_DecodeSMSFrame(s, &sms, msg.Buffer+10);
3103#endif
3104
3105 if (s->Phone.Data.EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
3106 sms.State = SMS_UnRead;
3107 sms.InboxFolder = true;
3108
3109 N6510_DecodeSMSFrame(s, &sms, msg.Buffer+10);
3110
3111 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
3112 }
3113 return ERR_NONE;
3114}
3115
3116static GSM_Error N6510_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
3117{
3118 unsigned intpos = 4;
3119 unsigned char req[100] = {N6110_FRAME_HEADER,0x01,
3120 0x0c};/* Number length */
3121
3122 req[pos++] = strlen(number);
3123 EncodeUnicode(req+pos,number,strlen(number));
3124 pos += strlen(number)*2;
3125 req[pos++] = 0x05; /* call type: voice - 0x05, data - 0x01 */
3126 req[pos++] = 0x01;
3127 req[pos++] = 0x05;
3128 req[pos++] = 0x00;
3129 req[pos++] = 0x02;
3130 req[pos++] = 0x00;
3131 req[pos++] = 0x00;
3132 switch (ShowNumber) {
3133 case GSM_CALL_HideNumber:
3134 req[pos++] = 0x02;
3135 break;
3136 case GSM_CALL_ShowNumber:
3137 req[pos++] = 0x03;
3138 break;
3139 case GSM_CALL_DefaultNumberPresence:
3140 req[pos++] = 0x01;
3141 break;
3142 }
3143
3144 smprintf(s, "Making voice call\n");
3145 return GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
3146}
3147
3148/* method 3 */
3149static GSM_Error N6510_ReplyGetCalendarInfo3(GSM_Protocol_Message msg, GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last)
3150{
3151 int i=0,j=0;
3152
3153 while (Last->Location[j] != 0x00) j++;
3154 if (j >= GSM_MAXCALENDARTODONOTES) {
3155 smprintf(s, "Increase GSM_MAXCALENDARTODONOTES\n");
3156 return ERR_UNKNOWN;
3157 }
3158 if (j == 0) {
3159 Last->Number=msg.Buffer[8]*256+msg.Buffer[9];
3160 smprintf(s, "Number of Entries: %i\n",Last->Number);
3161 }
3162 smprintf(s, "Locations: ");
3163 while (14+(i*4) <= msg.Length) {
3164 Last->Location[j++]=msg.Buffer[12+i*4]*256+msg.Buffer[13+i*4];
3165 smprintf(s, "%i ",Last->Location[j-1]);
3166 i++;
3167 }
3168 smprintf(s, "\nNumber of Entries in frame: %i\n",i);
3169 Last->Location[j] = 0;
3170 smprintf(s, "\n");
3171 if (i == 1 && msg.Buffer[12+0*4]*256+msg.Buffer[13+0*4] == 0) return ERR_EMPTY;
3172 if (i == 0) return ERR_EMPTY;
3173 return ERR_NONE;
3174}
3175
3176/* method 3 */
3177static GSM_Error N6510_GetCalendarInfo3(GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last, bool Calendar)
3178{
3179 GSM_Error error;
3180 int i;
3181 unsigned char req[] = {N6110_FRAME_HEADER, 0x9E, 0xFF, 0xFF, 0x00, 0x00,
3182 0x00, 0x00,/* First location */
3183 0x00}; /* 0 = calendar, 1 = ToDo in 6610 style */
3184
3185 Last->Location[0] = 0x00;
3186 Last->Number = 0;
3187
3188 if (Calendar) {
3189 smprintf(s, "Getting locations for calendar method 3\n");
3190 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
3191 } else {
3192 req[10] = 0x01;
3193 smprintf(s, "Getting locations for ToDo method 2\n");
3194 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
3195 }
3196 if (error != ERR_NONE && error != ERR_EMPTY) return error;
3197
3198 while (1) {
3199 i=0;
3200 while (Last->Location[i] != 0x00) i++;
3201 smprintf(s, "i = %i %i\n",i,Last->Number);
3202 if (i == Last->Number) break;
3203 if (i != Last->Number && error == ERR_EMPTY) {
3204 smprintf(s, "Phone doesn't support some notes with this method. Workaround\n");
3205 Last->Number = i;
3206 break;
3207 }
3208 req[8] = Last->Location[i-1] / 256;
3209 req[9] = Last->Location[i-1] % 256;
3210 if (Calendar) {
3211 smprintf(s, "Getting locations for calendar method 3\n");
3212 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
3213 } else {
3214 smprintf(s, "Getting locations for todo method 2\n");
3215 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
3216 }
3217 if (error != ERR_NONE && error != ERR_EMPTY) return error;
3218 }
3219 return ERR_NONE;
3220}
3221
3222/* method 3 */
3223GSM_Error N6510_ReplyGetCalendar3(GSM_Protocol_Message msg, GSM_StateMachine *s)
3224{
3225 GSM_CalendarEntry *entry = s->Phone.Data.Cal;
3226 GSM_DateTime Date;
3227 unsigned long diff;
3228 int i;
3229 bool found = false;
3230 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
3231
3232 smprintf(s, "Calendar note received method 3\n");
3233
3234 smprintf(s,"Note type %02i: ",msg.Buffer[27]);
3235 switch(msg.Buffer[27]) {
3236 case 0x00: smprintf(s,"Reminder\n"); entry->Type = GSM_CAL_REMINDER; break;
3237 case 0x01: smprintf(s,"Meeting\n"); entry->Type = GSM_CAL_MEETING; break;
3238 case 0x02: smprintf(s,"Call\n"); entry->Type = GSM_CAL_CALL; break;
3239 case 0x04: smprintf(s,"Birthday\n"); entry->Type = GSM_CAL_BIRTHDAY; break;
3240 case 0x08: smprintf(s,"Memo\n"); entry->Type = GSM_CAL_MEMO; break;
3241 default : smprintf(s,"unknown\n");
3242 }
3243
3244 smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
3245 msg.Buffer[28]*256+msg.Buffer[29],
3246 msg.Buffer[30],msg.Buffer[31],msg.Buffer[32],
3247 msg.Buffer[33]);
3248 Date.Year = msg.Buffer[28]*256+msg.Buffer[29];
3249 if (entry->Type == GSM_CAL_BIRTHDAY) {
3250 Date.Year = entry->Entries[0].Date.Year;
3251 smprintf(s,"%i\n",Date.Year);
3252 }
3253 Date.Month = msg.Buffer[30];
3254 Date.Day = msg.Buffer[31];
3255 Date.Hour = msg.Buffer[32];
3256 Date.Minute = msg.Buffer[33];
3257 /* Garbage seen with 3510i 3.51 */
3258 if (Date.Month == 0 && Date.Day == 0 && Date.Hour == 0 && Date.Minute == 0) return ERR_EMPTY;
3259 Date.Second= 0;
3260 entry->Entries[0].EntryType = CAL_START_DATETIME;
3261 memcpy(&entry->Entries[0].Date,&Date,sizeof(GSM_DateTime));
3262 entry->EntriesNum++;
3263
3264 if (entry->Type != GSM_CAL_BIRTHDAY) {
3265 smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
3266 msg.Buffer[34]*256+msg.Buffer[35],
3267 msg.Buffer[36],msg.Buffer[37],msg.Buffer[38],
3268 msg.Buffer[39]);
3269 Date.Year = msg.Buffer[34]*256+msg.Buffer[35];
3270 Date.Month = msg.Buffer[36];
3271 Date.Day = msg.Buffer[37];
3272 Date.Hour = msg.Buffer[38];
3273 Date.Minute = msg.Buffer[39];
3274 Date.Second= 0;
3275 entry->Entries[1].EntryType = CAL_END_DATETIME;
3276 memcpy(&entry->Entries[1].Date,&Date,sizeof(GSM_DateTime));
3277 entry->EntriesNum++;
3278 }
3279
3280 smprintf(s, "Note icon: %02x\n",msg.Buffer[21]);
3281 for(i=0;i<Priv->CalendarIconsNum;i++) {
3282 if (Priv->CalendarIconsTypes[i] == entry->Type) {
3283 found = true;
3284 }
3285 }
3286 if (!found) {
3287 Priv->CalendarIconsTypes[Priv->CalendarIconsNum] = entry->Type;
3288 Priv->CalendarIcons[Priv->CalendarIconsNum] = msg.Buffer[21];
3289 Priv->CalendarIconsNum++;
3290 }
3291
3292 if (msg.Buffer[14] == 0xFF && msg.Buffer[15] == 0xFF && msg.Buffer[16] == 0xff && msg.Buffer[17] == 0xff)
3293 {
3294 smprintf(s, "No alarm\n");
3295 } else {
3296 diff = ((unsigned int)msg.Buffer[14]) << 24;
3297 diff += ((unsigned int)msg.Buffer[15]) << 16;
3298 diff += ((unsigned int)msg.Buffer[16]) << 8;
3299 diff += msg.Buffer[17];
3300
3301 memcpy(&entry->Entries[entry->EntriesNum].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
3302 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 60);
3303 smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
3304 entry->Entries[entry->EntriesNum].Date.Day, entry->Entries[entry->EntriesNum].Date.Month,
3305 entry->Entries[entry->EntriesNum].Date.Year, entry->Entries[entry->EntriesNum].Date.Hour,
3306 entry->Entries[entry->EntriesNum].Date.Minute,entry->Entries[entry->EntriesNum].Date.Second);
3307
3308 entry->Entries[entry->EntriesNum].EntryType = CAL_ALARM_DATETIME;
3309 if (msg.Buffer[22]==0x00 && msg.Buffer[23]==0x00 &&
3310 msg.Buffer[24]==0x00 && msg.Buffer[25]==0x00)
3311 {
3312 entry->Entries[entry->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
3313 smprintf(s, "Alarm type : Silent\n");
3314 }
3315 entry->EntriesNum++;
3316 }
3317
3318 N71_65_GetCalendarRecurrance(s, msg.Buffer+40, entry);
3319
3320 if (entry->Type == GSM_CAL_BIRTHDAY) {
3321 if (msg.Buffer[42] == 0xff && msg.Buffer[43] == 0xff) {
3322 entry->Entries[0].Date.Year = 0;
3323 } else {
3324 entry->Entries[0].Date.Year = msg.Buffer[42]*256+msg.Buffer[43];
3325 }
3326 }
3327
3328 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+54, msg.Buffer[51]*2);
3329 entry->Entries[entry->EntriesNum].Text[msg.Buffer[51]*2] = 0;
3330 entry->Entries[entry->EntriesNum].Text[msg.Buffer[51]*2+1] = 0;
3331 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
3332 entry->EntriesNum++;
3333 smprintf(s, "Note text: \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum-1].Text));
3334
3335 if (entry->Type == GSM_CAL_CALL) {
3336 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+(54+msg.Buffer[51]*2), msg.Buffer[52]*2);
3337 entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2] = 0;
3338 entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2+1] = 0;
3339 entry->Entries[entry->EntriesNum].EntryType = CAL_PHONE;
3340 entry->EntriesNum++;
3341 }
3342 if (entry->Type == GSM_CAL_MEETING) {
3343 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+(54+msg.Buffer[51]*2), msg.Buffer[52]*2);
3344 entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2] = 0;
3345 entry->Entries[entry->EntriesNum].Text[msg.Buffer[52]*2+1] = 0;
3346 entry->Entries[entry->EntriesNum].EntryType = CAL_LOCATION;
3347 entry->EntriesNum++;
3348 }
3349
3350 return ERR_NONE;
3351}
3352
3353static GSM_Error N6510_PrivGetCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, int *LastCalendarYear)
3354{
3355 GSM_Error error;
3356 GSM_DateTime date_time;
3357 unsigned char req[] = {N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
3358 0x00,0x99,/* Location */
3359 0xff,0xff,0xff,0xff,0x01};
3360
3361 if (start) {
3362 /* We have to get current year. It's NOT written in frame for
3363 * Birthday
3364 */
3365 error=s->Phone.Functions->GetDateTime(s,&date_time);
3366 switch (error) {
3367 case ERR_EMPTY:
3368 case ERR_NOTIMPLEMENTED:
3369 GSM_GetCurrentDateTime(&date_time);
3370 break;
3371 case ERR_NONE:
3372 break;
3373 default:
3374 return error;
3375 }
3376 *LastCalendarYear = date_time.Year;
3377 }
3378
3379 Note->EntriesNum = 0;
3380 Note->Entries[0].Date.Year = *LastCalendarYear;
3381
3382 req[8] = Note->Location / 256;
3383 req[9] = Note->Location % 256;
3384
3385 s->Phone.Data.Cal=Note;
3386 smprintf(s, "Getting calendar note method 3\n");
3387 return GSM_WaitFor (s, req, 15, 0x13, 4, ID_GetCalendarNote);
3388}
3389
3390/* method 3 */
3391GSM_Error N6510_GetNextCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, GSM_NOKIACalToDoLocations *LastCalendar, int *LastCalendarYear, int *LastCalendarPos)
3392{
3393 GSM_Error error;
3394 bool start2;
3395
3396 if (start) {
3397 error=N6510_GetCalendarInfo3(s,LastCalendar,true);
3398 if (error!=ERR_NONE) return error;
3399 if (LastCalendar->Number == 0) return ERR_EMPTY;
3400
3401 *LastCalendarPos = 0;
3402 } else {
3403 (*LastCalendarPos)++;
3404 }
3405
3406 error = ERR_EMPTY;
3407 start2 = start;
3408 while (error == ERR_EMPTY) {
3409 if (*LastCalendarPos >= LastCalendar->Number) return ERR_EMPTY;
3410
3411 Note->Location = LastCalendar->Location[*LastCalendarPos];
3412 error=N6510_PrivGetCalendar3(s, Note, start2, LastCalendarYear);
3413 if (error == ERR_EMPTY) (*LastCalendarPos)++;
3414
3415 start2 = false;
3416 }
3417 return error;
3418}
3419
3420static GSM_Error N6510_ReplyGetCalendarInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
3421{
3422 switch (msg.Buffer[3]) {
3423 case 0x3B:
3424 /* Old method 1 for accessing calendar */
3425 return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
3426 case 0x9F:
3427 smprintf(s, "Info with calendar notes locations received method 3\n");
3428 return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
3429 }
3430 return ERR_UNKNOWNRESPONSE;
3431}
3432
3433/* method 3 */
3434GSM_Error N6510_ReplyGetCalendarNotePos3(GSM_Protocol_Message msg, GSM_StateMachine *s,int *FirstCalendarPos)
3435{
3436 smprintf(s, "First calendar location: %i\n",msg.Buffer[8]*256+msg.Buffer[9]);
3437 *FirstCalendarPos = msg.Buffer[8]*256+msg.Buffer[9];
3438 return ERR_NONE;
3439}
3440
3441/* method 3 */
3442static GSM_Error N6510_GetCalendarNotePos3(GSM_StateMachine *s)
3443{
3444 unsigned char req[] = {N6110_FRAME_HEADER, 0x95, 0x00};
3445
3446 smprintf(s, "Getting first free calendar note location\n");
3447 return GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNotePos);
3448}
3449
3450static GSM_Error N6510_ReplyGetCalendarNotePos(GSM_Protocol_Message msg, GSM_StateMachine *s)
3451{
3452 switch (msg.Buffer[3]) {
3453 case 0x32:
3454 /* Old method 1 for accessing calendar */
3455 return N71_65_ReplyGetCalendarNotePos1(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
3456 case 0x96:
3457 return N6510_ReplyGetCalendarNotePos3(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
3458 }
3459 return ERR_UNKNOWNRESPONSE;
3460}
3461
3462static GSM_Error N6510_FindCalendarIconID3(GSM_StateMachine *s, GSM_CalendarEntry *Entry, unsigned char *ID)
3463{
3464 int i,j,LastCalendarYear;
3465 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
3466 GSM_CalendarEntry Note;
3467 GSM_NOKIACalToDoLocationsLastCalendar1,LastCalendar2;
3468 GSM_Error error;
3469 bool found;
3470
3471 for(i=0;i<Priv->CalendarIconsNum;i++) {
3472 if (Priv->CalendarIconsTypes[i] == Entry->Type) {
3473 *ID = Priv->CalendarIcons[i];
3474 return ERR_NONE;
3475 }
3476 }
3477
3478 smprintf(s, "Starting finding note ID\n");
3479
3480 error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,true);
3481 memcpy(&LastCalendar1,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
3482 if (error != ERR_NONE) return error;
3483
3484 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35) ||
3485 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
3486 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
3487 error=N71_65_AddCalendar2(s,Entry);
3488 } else {
3489 if (Entry->Type == GSM_CAL_MEETING) {
3490 error=N71_65_AddCalendar1(s, Entry, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
3491 } else {
3492 error=N71_65_AddCalendar2(s,Entry);
3493 }
3494 }
3495 if (error != ERR_NONE) return error;
3496
3497 error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,true);
3498 memcpy(&LastCalendar2,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
3499 if (error != ERR_NONE) return error;
3500
3501 smprintf(s,"Number of entries: %i %i\n",LastCalendar1.Number,LastCalendar2.Number);
3502
3503 for(i=0;i<LastCalendar2.Number;i++) {
3504 found = true;
3505 for(j=0;j<LastCalendar1.Number;j++) {
3506 if (LastCalendar1.Location[j] == LastCalendar2.Location[i]) {
3507 found = false;
3508 break;
3509 }
3510 }
3511 if (found) {
3512 Note.Location = LastCalendar2.Location[i];
3513 error=N6510_PrivGetCalendar3(s, &Note, true, &LastCalendarYear);
3514 if (error != ERR_NONE) return error;
3515
3516 error=N71_65_DelCalendar(s, &Note);
3517 if (error != ERR_NONE) return error;
3518
3519 smprintf(s, "Ending finding note ID\n");
3520
3521 for(j=0;j<Priv->CalendarIconsNum;j++) {
3522 if (Priv->CalendarIconsTypes[j] == Entry->Type) {
3523 *ID = Priv->CalendarIcons[j];
3524 return ERR_NONE;
3525 }
3526 }
3527 return ERR_UNKNOWN;
3528 }
3529 }
3530
3531 return ERR_UNKNOWN;
3532}
3533
3534/* method 3 */
3535static GSM_Error N6510_ReplyAddCalendar3(GSM_Protocol_Message msg, GSM_StateMachine *s)
3536{
3537 smprintf(s, "Calendar note added\n");
3538 return ERR_NONE;
3539}
3540
3541/* method 3 */
3542GSM_Error N6510_AddCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, int *FirstCalendarPos)
3543{
3544 GSM_CalendarNoteTypeNoteType, OldNoteType;
3545 time_t t_time1,t_time2;
3546 long diff;
3547 GSM_Error error;
3548 GSM_DateTime DT,date_time;
3549 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, count=54;
3550 unsigned char req[5000] = {
3551 N6110_FRAME_HEADER, 0x65,
3552 0x00, /* 0 = calendar, 1 = todo */
3553 0x00, 0x00, 0x00,
3554 0x00, 0x00, /* location */
3555 0x00, 0x00, 0x00, 0x00,
3556 0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
3557 0x80, 0x00, 0x00,
3558 0x01, /* note icon */
3559 0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
3560 0x00, /* 0x02 or 0x00 */
3561 0x01, /* note type */
3562 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
3563 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
3564 0x00, 0x00, /* recurrance */
3565 0x00, 0x00, /* birth year */
3566 0x20, /* ToDo priority */
3567 0x00, /* ToDo completed ? */
3568 0x00, 0x00, 0x00,
3569 0x00, /* note text length */
3570 0x00, /* phone length/meeting place*/
3571 0x00, 0x00, 0x00};
3572
3573 error=N6510_GetCalendarNotePos3(s);
3574 if (error!=ERR_NONE) return error;
3575 req[8] = *FirstCalendarPos/256;
3576 req[9] = *FirstCalendarPos%256;
3577
3578 NoteType = N71_65_FindCalendarType(Note->Type, s->Phone.Data.ModelInfo);
3579
3580 switch(NoteType) {
3581 case GSM_CAL_REMINDER : req[27]=0x00; req[26]=0x02; break;
3582 case GSM_CAL_MEETING : req[27]=0x01; break;
3583 case GSM_CAL_CALL : req[27]=0x02; break;
3584 case GSM_CAL_BIRTHDAY : req[27]=0x04; break;
3585 case GSM_CAL_MEMO : req[27]=0x08; break;
3586 default : return ERR_UNKNOWN;
3587 }
3588
3589 OldNoteType = Note->Type;
3590 Note->Type = NoteType;
3591 error=N6510_FindCalendarIconID3(s, Note, &req[21]);
3592 Note->Type = OldNoteType;
3593 if (error!=ERR_NONE) return error;
3594
3595 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
3596
3597 if (Time == -1) return ERR_UNKNOWN;
3598 memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
3599 req[28]= DT.Year / 256;
3600 req[29]= DT.Year % 256;
3601 req[30]= DT.Month;
3602 req[31]= DT.Day;
3603 req[32]= DT.Hour;
3604 req[33]= DT.Minute;
3605
3606 if (NoteType == GSM_CAL_BIRTHDAY) {
3607 error=s->Phone.Functions->GetDateTime(s,&date_time);
3608 switch (error) {
3609 case ERR_EMPTY:
3610 case ERR_NOTIMPLEMENTED:
3611 GSM_GetCurrentDateTime(&date_time);
3612 break;
3613 case ERR_NONE:
3614 break;
3615 default:
3616 return error;
3617 }
3618 req[28]= date_time.Year / 256;
3619 req[29] = date_time.Year % 256;
3620 if (DT.Year == 0) {
3621 req[42]= 0xff;
3622 req[43]= 0xff;
3623 } else {
3624 req[42]= DT.Year / 256;
3625 req[43]= DT.Year % 256;
3626 }
3627 }
3628
3629 if (EndTime != -1) memcpy(&DT,&Note->Entries[EndTime].Date,sizeof(GSM_DateTime));
3630 req[34]= DT.Year / 256;
3631 req[35]= DT.Year % 256;
3632 req[36]= DT.Month;
3633 req[37]= DT.Day;
3634 req[38]= DT.Hour;
3635 req[39]= DT.Minute;
3636 if (NoteType == GSM_CAL_BIRTHDAY) {
3637 req[34]= date_time.Year / 256;
3638 req[35] = date_time.Year % 256;
3639 }
3640
3641 if (Recurrance != -1) {
3642 /* max. 1 Year = 8760 hours */
3643 if (Note->Entries[Recurrance].Number >= 8760) {
3644 req[40] = 0xff;
3645 req[41] = 0xff;
3646 } else {
3647 req[40] = Note->Entries[Recurrance].Number / 256;
3648 req[41] = Note->Entries[Recurrance].Number % 256;
3649 }
3650 }
3651
3652 if (Alarm != -1) {
3653 memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
3654 if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
3655 req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
3656 }
3657 if (NoteType == GSM_CAL_BIRTHDAY) DT.Year = date_time.Year;
3658 t_time2 = Fill_Time_T(DT,8);
3659 t_time1 = Fill_Time_T(Note->Entries[Alarm].Date,8);
3660 diff = (t_time1-t_time2)/60;
3661
3662 smprintf(s, " Difference : %li seconds or minutes\n", -diff);
3663 req[14] = (unsigned char)(-diff >> 24);
3664 req[15] = (unsigned char)(-diff >> 16);
3665 req[16] = (unsigned char)(-diff >> 8);
3666 req[17] = (unsigned char)(-diff);
3667 }
3668
3669 if (Text != -1) {
3670 req[49] = UnicodeLength(Note->Entries[Text].Text);
3671 CopyUnicodeString(req+54,Note->Entries[Text].Text);
3672 count+= req[49]*2;
3673 }
3674
3675 if (Phone != -1 && NoteType == GSM_CAL_CALL) {
3676 req[50] = UnicodeLength(Note->Entries[Phone].Text);
3677 CopyUnicodeString(req+54+req[49]*2,Note->Entries[Phone].Text);
3678 count+= req[50]*2;
3679 }
3680
3681 if (Location != -1 && NoteType == GSM_CAL_MEETING) {
3682 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62) ||
3683 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
3684 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35)) {
3685 } else {
3686 req[50] = UnicodeLength(Note->Entries[Location].Text);
3687 CopyUnicodeString(req+54+req[49]*2,Note->Entries[Location].Text);
3688 count+= req[50]*2;
3689 }
3690 }
3691
3692 req[count++] = 0x00;
3693
3694 smprintf(s, "Writing calendar note method 3\n");
3695 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetCalendarNote);
3696}
3697
3698static GSM_Error N6510_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
3699{
3700#ifdef GSM_FORCE_DCT4_CALENDAR_6210
3701 /* Method 1. Some features missed. Not working with some notes in 3510 */
3702 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);
3703#endif
3704
3705 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
3706 /* Method 1. Some features missed. Not working with some notes in 3510 */
3707 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);
3708
3709 /* Method 2. In known phones texts of notes cut to 50 chars. Some features missed */
3710 // return N71_65_GetNextCalendar2(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
3711 } else {
3712 /* Method 3. All DCT4 features supported. Not supported by 8910 */
3713 return N6510_GetNextCalendar3(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
3714 }
3715}
3716
3717static GSM_Error N6510_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
3718{
3719 GSM_Error error;
3720
3721#ifdef GSM_FORCE_DCT4_CALENDAR_6210
3722 /* Method 1 */
3723 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
3724 if (error!=ERR_NONE) return error;
3725 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
3726 return ERR_NONE;
3727#endif
3728
3729 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
3730 /* Method 1 */
3731 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
3732 if (error!=ERR_NONE) return error;
3733 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
3734 return ERR_NONE;
3735
3736 /* Method 2 */
3737 // return ERR_NOTSUPPORTED;
3738 } else {
3739 /* Method 3 */
3740 error=N6510_GetCalendarInfo3(s,&s->Phone.Data.Priv.N6510.LastCalendar,true);
3741 if (error!=ERR_NONE) return error;
3742 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
3743 return ERR_NONE;
3744 }
3745}
3746
3747static GSM_Error N6510_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
3748{
3749#ifdef GSM_FORCE_DCT4_CALENDAR_6210
3750 return N71_65_AddCalendar2(s,Note);
3751#endif
3752
3753 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
3754 return N71_65_AddCalendar2(s,Note);
3755 // return N71_65_AddCalendar1(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
3756 } else {
3757 /* Method 3. All DCT4 features supported. Not supported by 8910 */
3758 return N6510_AddCalendar3(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
3759 }
3760}
3761
3762static GSM_Error N6510_ReplyLogIntoNetwork(GSM_Protocol_Message msg, GSM_StateMachine *s)
3763{
3764 smprintf(s, "Probably phone says: I log into network\n");
3765 return ERR_NONE;
3766}
3767
3768void N6510_EncodeFMFrequency(double freq, unsigned char *buff)
3769{
3770 double freq0;
3771 unsigned char buffer[20];
3772 unsigned int i,freq2;
3773
3774 sprintf(buffer,"%.3f",freq);
3775 for (i=0;i<strlen(buffer);i++) {
3776 if (buffer[i] == ',' || buffer[i] == '.') buffer[i] = ' ';
3777 }
3778 StringToDouble(buffer, &freq0);
3779 freq2 = (unsigned int)freq0;
3780 dbgprintf("Frequency: %s %i\n",buffer,freq2);
3781 freq2= freq2 - 0xffff;
3782 buff[0] = freq2 / 0x100;
3783 buff[1] = freq2 % 0x100;
3784}
3785
3786void N6510_DecodeFMFrequency(double *freq, unsigned char *buff)
3787{
3788 unsigned char buffer[20];
3789
3790 sprintf(buffer,"%i.%i",(0xffff + buff[0] * 0x100 + buff[1])/1000,
3791 (0xffff + buff[0] * 0x100 + buff[1])%1000);
3792 dbgprintf("Frequency: %s\n",buffer);
3793 StringToDouble(buffer, freq);
3794}
3795
3796static GSM_Error N6510_ReplyGetFMStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
3797{
3798 smprintf(s, "getting FM status OK\n");
3799 memcpy(s->Phone.Data.Priv.N6510.FMStatus,msg.Buffer,msg.Length);
3800 s->Phone.Data.Priv.N6510.FMStatusLength = msg.Length;
3801 return ERR_NONE;
3802}
3803
3804static GSM_Error N6510_GetFMStatus(GSM_StateMachine *s)
3805{
3806 unsigned char req[7] = {N6110_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x01};
3807
3808 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
3809 return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_GetFMStation);
3810}
3811
3812static GSM_Error N6510_ReplyGetFMStation(GSM_Protocol_Message msg, GSM_StateMachine *s)
3813{
3814 unsigned char name[GSM_MAX_FMSTATION_LENGTH*2+2];
3815 int length;
3816 GSM_Phone_Data*Data = &s->Phone.Data;
3817
3818 switch (msg.Buffer[3]) {
3819 case 0x06:
3820 smprintf(s, "Received FM station\n");
3821 length = msg.Buffer[8];
3822 memcpy(name,msg.Buffer+18,length*2);
3823 name[length*2] = 0x00;
3824 name[length*2+1] = 0x00;
3825 CopyUnicodeString(Data->FMStation->StationName,name);
3826 smprintf(s,"Station name: \"%s\"\n",DecodeUnicodeString(Data->FMStation->StationName));
3827 N6510_DecodeFMFrequency(&Data->FMStation->Frequency, msg.Buffer+16);
3828 return ERR_NONE;
3829 case 0x16:
3830 smprintf(s, "Received FM station. Empty ?\n");
3831 return ERR_EMPTY;
3832 }
3833 return ERR_UNKNOWNRESPONSE;
3834}
3835
3836static GSM_Error N6510_GetFMStation (GSM_StateMachine *s, GSM_FMStation *FMStation)
3837{
3838 GSM_Error error;
3839 int location;
3840 unsigned char req[7] = {N6110_FRAME_HEADER, 0x05,
3841 0x00, // location
3842 0x00,0x01};
3843
3844 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
3845 if (FMStation->Location > GSM_MAX_FM_STATION) return ERR_INVALIDLOCATION;
3846
3847 s->Phone.Data.FMStation = FMStation;
3848
3849 error = N6510_GetFMStatus(s);
3850 if (error != ERR_NONE) return error;
3851
3852 location = FMStation->Location-1;
3853 if (s->Phone.Data.Priv.N6510.FMStatus[14+location] == 0xFF) return ERR_EMPTY;
3854 req[4] = s->Phone.Data.Priv.N6510.FMStatus[14+location];
3855
3856 smprintf(s, "Getting FM Station %i\n",FMStation->Location);
3857 return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_GetFMStation);
3858}
3859
3860static GSM_Error N6510_ReplySetFMStation(GSM_Protocol_Message msg, GSM_StateMachine *s)
3861{
3862#ifdef DEBUG
3863 switch (msg.Buffer[4]){
3864 case 0x03: smprintf(s, "FM stations cleaned\n"); break;
3865 case 0x11: smprintf(s, "Setting FM station status OK\n"); break;
3866 case 0x12: smprintf(s, "Setting FM station OK\n"); break;
3867 }
3868#endif
3869 return ERR_NONE;
3870}
3871
3872static GSM_Error N6510_ClearFMStations (GSM_StateMachine *s)
3873{
3874 unsigned char req[7] = {N6110_FRAME_HEADER, 0x03,0x0f,0x00,0x01};
3875
3876 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
3877
3878 smprintf(s, "Cleaning FM Stations\n");
3879 return GSM_WaitFor (s, req, 7, 0x3E, 2, ID_SetFMStation);
3880}
3881
3882static GSM_Error N6510_SetFMStation (GSM_StateMachine *s, GSM_FMStation *FMStation)
3883{
3884 unsigned int len, location;
3885 GSM_Error error;
3886 unsigned char setstatus[36] = {N6110_FRAME_HEADER,0x11,0x00,0x01,0x01,
3887 0x00,0x00,0x1c,0x00,0x14,0x00,0x00,
3888 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3889 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3890 0xff,0xff,0xff,0xff,0xff,0x01};
3891 unsigned char req[64] = {N6110_FRAME_HEADER, 0x12,0x00,0x01,0x00,
3892 0x00, // 0x0e + (strlen(name) * 2)
3893 0x00, // strlen(name)
3894 0x14,0x09,0x00,
3895 0x00, // location
3896 0x00,0x00,0x01,
3897 0x00, // freqHi
3898 0x00, // freqLo
3899 0x01};
3900
3901 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RADIO)) return ERR_NOTSUPPORTED;
3902
3903 s->Phone.Data.FMStation = FMStation;
3904 location = FMStation->Location-1;
3905
3906 error = N6510_GetFMStatus(s);
3907 if (error != ERR_NONE) return error;
3908
3909 memcpy(setstatus+14,s->Phone.Data.Priv.N6510.FMStatus+14,20);
3910 setstatus [14+location] = location;
3911
3912 smprintf(s, "Setting FM status %i\n",FMStation->Location);
3913 error = GSM_WaitFor (s, setstatus, 36 , 0x3E, 2, ID_SetFMStation);
3914 if (error != ERR_NONE) return error;
3915
3916 req[12] = location;
3917
3918 /* Name */
3919 len = UnicodeLength(FMStation->StationName);
3920 req[8] = len;
3921 req[7] = 0x0e + len * 2;
3922 memcpy (req+18,FMStation->StationName,len*2);
3923
3924 /* Frequency */
3925 N6510_EncodeFMFrequency(FMStation->Frequency, req+16);
3926
3927 smprintf(s, "Setting FM Station %i\n",FMStation->Location);
3928 return GSM_WaitFor (s, req, 0x13+len*2, 0x3E, 2, ID_SetFMStation);
3929}
3930
3931static GSM_Error N6510_ReplySetLight(GSM_Protocol_Message msg, GSM_StateMachine *s)
3932{
3933 smprintf(s, "Light set\n");
3934 return ERR_NONE;
3935}
3936
3937GSM_Error N6510_SetLight(GSM_StateMachine *s, N6510_PHONE_LIGHTS light, bool enable)
3938{
3939 unsigned char req[14] = {
3940 N6110_FRAME_HEADER, 0x05,
3941 0x01, /* 0x01 = Display, 0x03 = keypad */
3942 0x01, /* 0x01 = Enable, 0x02 = disable */
3943 0x00, 0x00, 0x00, 0x01,
3944 0x05, 0x04, 0x02, 0x00};
3945
3946 req[4] = light;
3947 if (!enable) req[5] = 0x02;
3948 smprintf(s, "Setting light\n");
3949 return GSM_WaitFor (s, req, 14, 0x3A, 4, ID_SetLight);
3950}
3951
3952static GSM_Error N6510_ShowStartInfo(GSM_StateMachine *s, bool enable)
3953{
3954 GSM_Error error;
3955
3956 if (enable) {
3957 error=N6510_SetLight(s,N6510_LIGHT_DISPLAY,true);
3958 if (error != ERR_NONE) return error;
3959
3960 error=N6510_SetLight(s,N6510_LIGHT_TORCH,true);
3961 if (error != ERR_NONE) return error;
3962
3963 return N6510_SetLight(s,N6510_LIGHT_KEYPAD,true);
3964 } else {
3965 error=N6510_SetLight(s,N6510_LIGHT_DISPLAY,false);
3966 if (error != ERR_NONE) return error;
3967
3968 error=N6510_SetLight(s,N6510_LIGHT_TORCH,false);
3969 if (error != ERR_NONE) return error;
3970
3971 return N6510_SetLight(s,N6510_LIGHT_KEYPAD,false);
3972 }
3973}
3974
3975static int N6510_FindFileCheckSum(unsigned char *ptr, int len)
3976{
3977 int acc, i, accx;
3978
3979 accx = 0;
3980 acc = 0xffff;
3981 while (len--) {
3982 accx = (accx & 0xffff00ff) | (acc & 0xff00);
3983 acc = (acc & 0xffff00ff) | *ptr++ << 8;
3984 for (i = 0; i < 8; i++) {
3985 acc <<= 1;
3986 if (acc & 0x10000) acc ^= 0x1021;
3987 if (accx & 0x80000000) acc ^= 0x1021;
3988 accx <<= 1;
3989 }
3990 }
3991 dbgprintf("Checksum from Gammu is %04X\n",(acc & 0xffff));
3992 return (acc & 0xffff);
3993}
3994
3995static GSM_Error N6510_ReplyGetFileFolderInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
3996{
3997 GSM_File *File = s->Phone.Data.FileInfo;
3998 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
3999 int i;
4000
4001 switch (msg.Buffer[3]) {
4002 case 0x15:
4003 smprintf(s,"File or folder details received\n");
4004 CopyUnicodeString(File->Name,msg.Buffer+10);
4005 if (!strncmp(DecodeUnicodeString(File->Name),"GMSTemp",7)) return ERR_EMPTY;
4006 if (File->Name[0] == 0x00 && File->Name[1] == 0x00) return ERR_UNKNOWN;
4007
4008 i = msg.Buffer[8]*256+msg.Buffer[9];
4009 dbgprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
4010 msg.Buffer[i-5],msg.Buffer[i-4],msg.Buffer[i-3],
4011 msg.Buffer[i-2],msg.Buffer[i-1],msg.Buffer[i],
4012 msg.Buffer[i+1],msg.Buffer[i+2],msg.Buffer[i+3]);
4013
4014 File->Folder = false;
4015 if (msg.Buffer[i-5] == 0x00) File->Folder = true;
4016
4017 File->ReadOnly = false;
4018 File->Protected = false;
4019 File->System= false;
4020 File->Hidden= false;
4021 if (msg.Buffer[i+2] == 0x01) File->Protected = true;
4022 if (msg.Buffer[i+4] == 0x01) File->ReadOnly = true;
4023 if (msg.Buffer[i+5] == 0x01) File->Hidden= true;
4024 if (msg.Buffer[i+6] == 0x01) File->System= true;//fixme
4025
4026 File->ModifiedEmpty = false;
4027 NOKIA_DecodeDateTime(s, msg.Buffer+i-22, &File->Modified);
4028 if (File->Modified.Year == 0x00) File->ModifiedEmpty = true;
4029 dbgprintf("%02x %02x %02x %02x\n",msg.Buffer[i-22],msg.Buffer[i-21],msg.Buffer[i-20],msg.Buffer[i-19]);
4030
4031 Priv->FileToken = msg.Buffer[i-10]*256+msg.Buffer[i-9];
4032 Priv->ParentID = msg.Buffer[i]*256+msg.Buffer[i+1];
4033 smprintf(s,"ParentID is %i\n",Priv->ParentID);
4034
4035 File->Type = GSM_File_Other;
4036 if (msg.Length > 240){
4037 i = 227;
4038 if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x01)
4039 File->Type = GSM_File_Image_JPG;
4040 else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x02)
4041 File->Type = GSM_File_Image_BMP;
4042 else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x07)
4043 File->Type = GSM_File_Image_BMP;
4044 else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x03)
4045 File->Type = GSM_File_Image_PNG;
4046 else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x05)
4047 File->Type = GSM_File_Image_GIF;
4048 else if (msg.Buffer[i]==0x02 && msg.Buffer[i+2]==0x09)
4049 File->Type = GSM_File_Image_WBMP;
4050 else if (msg.Buffer[i]==0x04 && msg.Buffer[i+2]==0x01)
4051 File->Type = GSM_File_Sound_AMR;
4052 else if (msg.Buffer[i]==0x04 && msg.Buffer[i+2]==0x02)
4053 File->Type = GSM_File_Sound_MIDI;
4054 else if (msg.Buffer[i]==0x08 && msg.Buffer[i+2]==0x05)
4055 File->Type = GSM_File_Video_3GP;
4056 else if (msg.Buffer[i]==0x10 && msg.Buffer[i+2]==0x01)
4057 File->Type = GSM_File_Java_JAR;
4058#if DEVELOP
4059 else if (msg.Buffer[i]==0x00 && msg.Buffer[i+2]==0x01)
4060 File->Type = GSM_File_MMS;
4061#endif
4062 }
4063 return ERR_NONE;
4064 case 0x2F:
4065 smprintf(s,"File or folder used bytes received\n");
4066 File->Used = msg.Buffer[6]*256*256*256+
4067 msg.Buffer[7]*256*256+
4068 msg.Buffer[8]*256+
4069 msg.Buffer[9];
4070 return ERR_NONE;
4071 case 0x33:
4072 if (s->Phone.Data.RequestID == ID_GetFileInfo) {
4073 i = Priv->FilesLocationsUsed-1;
4074 while (1) {
4075 if (i==Priv->FilesLocationsCurrent-1) break;
4076 dbgprintf("Copying %i to %i, max %i, current %i\n",
4077 i,i+msg.Buffer[9],
4078 Priv->FilesLocationsUsed,Priv->FilesLocationsCurrent);
4079 Priv->FilesLocations[i+msg.Buffer[9]] = Priv->FilesLocations[i];
4080 Priv->FilesLevels[i+msg.Buffer[9]]= Priv->FilesLevels[i];
4081 i--;
4082 }
4083 Priv->FilesLocationsUsed += msg.Buffer[9];
4084 for (i=0;i<msg.Buffer[9];i++) {
4085 Priv->FilesLocations[Priv->FilesLocationsCurrent+i] = msg.Buffer[13+i*4-1]*256 + msg.Buffer[13+i*4];
4086 Priv->FilesLevels[Priv->FilesLocationsCurrent+i] = File->Level+1;
4087 dbgprintf("%i ",Priv->FilesLocations[Priv->FilesLocationsCurrent+i]);
4088 }
4089 dbgprintf("\n");
4090 }
4091 if (msg.Buffer[9] != 0x00) File->Folder = true;
4092 return ERR_NONE;
4093 case 0x43:
4094 Priv->FileCheckSum = msg.Buffer[6] * 256 + msg.Buffer[7];
4095 smprintf(s,"File checksum from phone is %04X\n",Priv->FileCheckSum);
4096 return ERR_NONE;
4097 }
4098 return ERR_UNKNOWNRESPONSE;
4099}
4100
4101static GSM_Error N6510_GetFileFolderInfo(GSM_StateMachine *s, GSM_File *File, GSM_Phone_RequestID Request)
4102{
4103 GSM_Error error;
4104 unsigned char req[10] = {
4105 N7110_FRAME_HEADER,
4106 0x14, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
4107 0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
4108 0x00, 0x00, 0x01,
4109 0x00, 0x01};/* Folder or file number */
4110 unsigned char GetCRC[] = {
4111 N7110_FRAME_HEADER, 0x42, 0x00, 0x00, 0x00, 0x01,
4112 0x00, 0x1E}; /* file ID */
4113
4114 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4115
4116 s->Phone.Data.FileInfo = File;
4117 req[8] = atoi(File->ID_FullName) / 256;
4118 req[9] = atoi(File->ID_FullName) % 256;
4119
4120 req[3] = 0x14;
4121 req[4] = 0x01;
4122 smprintf(s,"Getting info for file in filesystem\n");
4123 error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
4124 if (error != ERR_NONE) return error;
4125
4126 if (Request != ID_AddFile) {
4127 req[3] = 0x32;
4128 req[4] = 0x00;
4129 smprintf(s,"Getting subfolders for filesystem\n");
4130 error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
4131 if (error != ERR_NONE) return error;
4132
4133 if (!File->Folder) {
4134 req[3] = 0x2E;
4135 req[4] = 0x01;
4136 smprintf(s,"Getting used memory for file in filesystem\n");
4137 error=GSM_WaitFor (s, req, 10, 0x6D, 4, Request);
4138 if (error != ERR_NONE) return error;
4139
4140 GetCRC[8] = atoi(File->ID_FullName) / 256;
4141 GetCRC[9] = atoi(File->ID_FullName) % 256;
4142 smprintf(s,"Getting CRC for file in filesystem\n");
4143 error=GSM_WaitFor (s, GetCRC, 10, 0x6D, 4, Request);
4144 }
4145 }
4146 return error;
4147}
4148
4149static GSM_Error N6510_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start)
4150{
4151 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
4152 GSM_Error error;
4153
4154 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4155
4156 if (start) {
4157 Priv->FilesLocationsUsed = 1;
4158 Priv->FilesLocationsCurrent = 0;
4159 Priv->FilesLocations[0] = 0x01;
4160 Priv->FilesLevels[0] = 1;
4161 }
4162
4163 while (1) {
4164 if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) return ERR_EMPTY;
4165
4166 sprintf(File->ID_FullName,"%i",Priv->FilesLocations[Priv->FilesLocationsCurrent]);
4167 File->Level= Priv->FilesLevels[Priv->FilesLocationsCurrent];
4168 Priv->FilesLocationsCurrent++;
4169
4170 error = N6510_GetFileFolderInfo(s, File, ID_GetFileInfo);
4171 if (error == ERR_EMPTY) continue;
4172 return error;
4173 }
4174}
4175
4176static GSM_Error N6510_ReplyGetFileSystemStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
4177{
4178 switch (msg.Buffer[3]) {
4179 case 0x23:
4180 if (!strcmp(s->Phone.Data.ModelInfo->model,"6310i")) {
4181 smprintf(s,"File or folder total bytes received\n");
4182 s->Phone.Data.FileSystemStatus->Free =
4183 3*256*256 + msg.Buffer[8]*256 + msg.Buffer[9] -
4184 s->Phone.Data.FileSystemStatus->Used;
4185 } else {
4186 smprintf(s,"File or folder free bytes received\n");
4187 s->Phone.Data.FileSystemStatus->Free =
4188 msg.Buffer[6]*256*256*256+
4189 msg.Buffer[7]*256*256+
4190 msg.Buffer[8]*256+
4191 msg.Buffer[9];
4192 }
4193 return ERR_NONE;
4194 case 0x2F:
4195 smprintf(s,"File or folder used bytes received\n");
4196 s->Phone.Data.FileSystemStatus->Used =
4197 msg.Buffer[6]*256*256*256+
4198 msg.Buffer[7]*256*256+
4199 msg.Buffer[8]*256+
4200 msg.Buffer[9];
4201 return ERR_NONE;
4202 }
4203 return ERR_UNKNOWNRESPONSE;
4204}
4205
4206static GSM_Error N6510_GetFileSystemStatus(GSM_StateMachine *s, GSM_FileSystemStatus *status)
4207{
4208 GSM_Error error;
4209 unsigned char req[10] = {
4210 N7110_FRAME_HEADER,
4211 0x22, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
4212 0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
4213 0x00, 0x00, 0x01,
4214 0x00, 0x01};/* Folder or file number */
4215
4216 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4217
4218 s->Phone.Data.FileSystemStatus = status;
4219
4220 status->Free = 0;
4221
4222 req[3] = 0x2E;
4223 req[4] = 0x01;
4224 smprintf(s, "Getting used/total memory in filesystem\n");
4225 error = GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
4226
4227 req[3] = 0x22;
4228 req[4] = 0x01;
4229 smprintf(s, "Getting free memory in filesystem\n");
4230 return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
4231}
4232
4233static GSM_Error N6510_SearchForFileName(GSM_StateMachine *s, GSM_File *File)
4234{
4235 GSM_File File2;
4236 GSM_Error error;
4237 int FilesLocations[1000],FilesLocations2[1000];
4238 int FilesLevels[1000];
4239 int FilesLocationsUsed, FilesLocationsCurrent;
4240 int FilesLocationsUsed2, FilesLocationsCurrent2;
4241 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
4242
4243 memcpy(FilesLocations, Priv->FilesLocations,sizeof(FilesLocations));
4244 memcpy(FilesLevels, Priv->FilesLevels,sizeof(FilesLevels));
4245 FilesLocationsUsed = Priv->FilesLocationsUsed;
4246 FilesLocationsCurrent = Priv->FilesLocationsCurrent;
4247
4248 Priv->FilesLocationsUsed = 1;
4249 Priv->FilesLocationsCurrent = 1;
4250 Priv->FilesLocations[0] = atoi(File->ID_FullName);
4251 Priv->FilesLevels[0] = 1;
4252
4253 strcpy(File2.ID_FullName,File->ID_FullName);
4254 error = N6510_GetFileFolderInfo(s, &File2, ID_GetFileInfo);
4255 memcpy(FilesLocations2, Priv->FilesLocations,sizeof(FilesLocations2));
4256 FilesLocationsUsed2 = Priv->FilesLocationsUsed;
4257 FilesLocationsCurrent2 = Priv->FilesLocationsCurrent;
4258
4259 memcpy(Priv->FilesLocations, FilesLocations, sizeof(FilesLocations));
4260 memcpy(Priv->FilesLevels, FilesLevels, sizeof(FilesLevels));
4261 Priv->FilesLocationsUsed = FilesLocationsUsed;
4262 Priv->FilesLocationsCurrent = FilesLocationsCurrent;
4263 if (error != ERR_NONE) return error;
4264
4265 while (1) {
4266 if (FilesLocationsCurrent2 == FilesLocationsUsed2) return ERR_EMPTY;
4267
4268 sprintf(File2.ID_FullName,"%i",FilesLocations2[FilesLocationsCurrent2]);
4269 dbgprintf("Current is %i\n",FilesLocations2[FilesLocationsCurrent2]);
4270 FilesLocationsCurrent2++;
4271
4272 error = N6510_GetFileFolderInfo(s, &File2, ID_AddFile);
4273 if (error == ERR_EMPTY) continue;
4274 if (error != ERR_NONE) return error;
4275 dbgprintf("%s %s\n",DecodeUnicodeString(File->Name),DecodeUnicodeString(File2.Name));
4276 if (mywstrncasecmp(File2.Name,File->Name,0)) return ERR_NONE;
4277 }
4278 return ERR_EMPTY;
4279}
4280
4281static GSM_Error N6510_ReplyGetFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
4282{
4283 int old;
4284
4285 smprintf(s,"File part received\n");
4286 old = s->Phone.Data.File->Used;
4287 s->Phone.Data.File->Used += msg.Buffer[6]*256*256*256+
4288 msg.Buffer[7]*256*256+
4289 msg.Buffer[8]*256+
4290 msg.Buffer[9];
4291 smprintf(s,"Length of file part: %i\n",
4292 msg.Buffer[6]*256*256*256+
4293 msg.Buffer[7]*256*256+
4294 msg.Buffer[8]*256+
4295 msg.Buffer[9]);
4296 s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
4297 memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+10,s->Phone.Data.File->Used-old);
4298 return ERR_NONE;
4299}
4300
4301static GSM_Error N6510_GetFilePart(GSM_StateMachine *s, GSM_File *File)
4302{
4303 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
4304 int old;
4305 GSM_Error error;
4306 unsigned char req[] = {
4307 N7110_FRAME_HEADER, 0x0E, 0x00, 0x00, 0x00, 0x01,
4308 0x00, 0x01, /* Folder or file number */
4309 0x00, 0x00, 0x00, 0x00,/* Start from xxx byte */
4310 0x00, 0x00,
4311 0x03, 0xE8}; /* Read xxx bytes */
4312
4313 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4314
4315 if (File->Used == 0x00) {
4316 error = N6510_GetFileFolderInfo(s, File, ID_GetFile);
4317 if (error != ERR_NONE) return error;
4318 File->Used = 0;
4319 }
4320
4321 old = File->Used;
4322 req[8] = atoi(File->ID_FullName) / 256;
4323 req[9] = atoi(File->ID_FullName) % 256;
4324 req[10] = old / (256*256*256);
4325 req[11] = old / (256*256);
4326 req[12] = old / 256;
4327 req[13] = old % 256;
4328
4329 s->Phone.Data.File = File;
4330 smprintf(s, "Getting file part from filesystem\n");
4331 error=GSM_WaitFor (s, req, 18, 0x6D, 4, ID_GetFile);
4332 if (error != ERR_NONE) return error;
4333 if (File->Used - old != (0x03 * 256 + 0xE8)) {
4334 if (N6510_FindFileCheckSum(File->Buffer, File->Used) != Priv->FileCheckSum) {
4335 smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum(File->Buffer, File->Used),Priv->FileCheckSum);
4336 return ERR_WRONGCRC;
4337 }
4338 return ERR_EMPTY;
4339 }
4340 return ERR_NONE;
4341}
4342
4343static GSM_Error N6510_SetReadOnly(GSM_StateMachine *s, unsigned char *ID, bool enable)
4344{
4345 unsigned char SetAttr[] = {
4346 N7110_FRAME_HEADER, 0x18, 0x00, 0x00, 0x00, 0x01,
4347 0x00, 0x20}; /* File ID */
4348
4349 if (!enable) SetAttr[4] = 0x06;
4350
4351 SetAttr[8] = atoi(ID) / 256;
4352 SetAttr[9] = atoi(ID) % 256;
4353 smprintf(s, "Setting readonly attribute\n");
4354 return GSM_WaitFor (s, SetAttr, 10, 0x6D, 4, ID_DeleteFile);
4355}
4356
4357static GSM_Error N6510_ReplyAddFileHeader(GSM_Protocol_Message msg, GSM_StateMachine *s)
4358{
4359 switch (msg.Buffer[3]) {
4360 case 0x03:
4361 smprintf(s,"File header added\n");
4362 sprintf(s->Phone.Data.File->ID_FullName,"%i",msg.Buffer[9]);
4363 return ERR_NONE;
4364 case 0x13:
4365 return ERR_NONE;
4366 }
4367 return ERR_UNKNOWNRESPONSE;
4368}
4369
4370static GSM_Error N6510_ReplyAddFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
4371{
4372 return ERR_NONE;
4373}
4374
4375static GSM_Error N6510_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos)
4376{
4377 GSM_Phone_N6510Data*Priv = &s->Phone.Data.Priv.N6510;
4378 GSM_File File2;
4379 GSM_Error error;
4380 int j;
4381 unsigned char Header[400] = {
4382 N7110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x01,
4383 0x00, 0x0C, /* parent folder ID */
4384 0x00, 0x00, 0x00, 0xE8};
4385 unsigned char Add[15000] = {
4386 N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
4387 0x00, 0x04, /* file ID */
4388 0x00, 0x00,
4389 0x01, 0x28}; /* length */
4390 unsigned char end[30] = {
4391 N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
4392 0x00, 0x04, /* file ID */
4393 0x00, 0x00, 0x00, 0x00};
4394
4395 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4396
4397 s->Phone.Data.File = File;
4398
4399 if (*Pos == 0) {
4400 error = N6510_SearchForFileName(s,File);
4401 if (error == ERR_NONE) return ERR_INVALIDLOCATION;
4402 if (error != ERR_EMPTY) return error;
4403
4404 Header[8] = atoi(File->ID_FullName) / 256;
4405 Header[9] = atoi(File->ID_FullName) % 256;
4406 memset(Header+14, 0x00, 300);
4407 CopyUnicodeString(Header+14,File->Name);
4408 Header[222] = File->Used / (256*256*256);
4409 Header[223] = File->Used / (256*256);
4410 Header[224] = File->Used / 256;
4411 Header[225] = File->Used % 256;
4412 switch(File->Type) {
4413 case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
4414 case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
4415 case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
4416 case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
4417 case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
4418 case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
4419 case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; //Header[238]=0x01;
4420 case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
4421 case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
4422 case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
4423#ifdef DEVELOP
4424 case GSM_File_MMS:
4425 Header[214]=0x07;
4426 Header[215]=0xd3;
4427 Header[216]=0x06;
4428 Header[217]=0x01;
4429 Header[218]=0x12;
4430 Header[219]=0x13;
4431 Header[220]=0x29;
4432 Header[233]=0x01;
4433 break;
4434#endif
4435 default : Header[231]=0x01; Header[233]=0x05;
4436 }
4437 Header[235] = 0x01;
4438 Header[236] = atoi(File->ID_FullName) / 256;
4439 Header[237] = atoi(File->ID_FullName) % 256;
4440 if (File->Protected) Header[238] = 0x01; //Nokia forward lock
4441 if (File->Hidden) Header[241] = 0x01;
4442 if (File->System) Header[242] = 0x01; //fixme
4443 smprintf(s, "Adding file header\n");
4444 error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
4445 if (error != ERR_NONE) return error;
4446 }
4447
4448 j = 1000;
4449 if (File->Used - *Pos < 1000) j = File->Used - *Pos;
4450 Add[ 8] = atoi(File->ID_FullName) / 256;
4451 Add[ 9] = atoi(File->ID_FullName) % 256;
4452 Add[12] = j / 256;
4453 Add[13] = j % 256;
4454 memcpy(Add+14,File->Buffer+(*Pos),j);
4455 smprintf(s, "Adding file part %i %i\n",*Pos,j);
4456 error=GSM_WaitFor (s, Add, 14+j, 0x6D, 4, ID_AddFile);
4457 if (error != ERR_NONE) return error;
4458 *Pos = *Pos + j;
4459
4460 if (j < 1000) {
4461 end[8] = atoi(File->ID_FullName) / 256;
4462 end[9] = atoi(File->ID_FullName) % 256;
4463 smprintf(s, "Frame for ending adding file\n");
4464 error = GSM_WaitFor (s, end, 14, 0x6D, 4, ID_AddFile);
4465 if (error != ERR_NONE) return error;
4466
4467 strcpy(File2.ID_FullName,File->ID_FullName);
4468 error = N6510_GetFileFolderInfo(s, &File2, ID_GetFileInfo);
4469 if (error != ERR_NONE) return error;
4470
4471 if (!File->ModifiedEmpty) {
4472 Header[3] = 0x12;
4473 Header[4] = 0x01;
4474 Header[12] = 0x00;
4475 Header[13] = 0xE8;
4476 Header[8] = atoi(File->ID_FullName) / 256;
4477 Header[9] = atoi(File->ID_FullName) % 256;
4478 memset(Header+14, 0x00, 300);
4479 CopyUnicodeString(Header+14,File->Name);
4480 NOKIA_EncodeDateTime(s,Header+214,&File->Modified);
4481 /* When you save too big file for phone and it changes
4482 * size (some part is cut by firmware), you HAVE to write
4483 * here correct file size. In other case filesystem
4484 * will be damaged
4485 */
4486 Header[224] = File2.Used / 256;
4487 Header[225] = File2.Used % 256;
4488 Header[226] = Priv->FileToken / 256;
4489 Header[227] = Priv->FileToken % 256;
4490 switch(File->Type) {
4491 case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
4492 case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
4493 case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
4494 case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
4495 case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
4496 case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
4497 case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; //Header[238]=0x01;
4498 case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
4499 case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
4500 case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
4501#ifdef DEVELOP
4502 case GSM_File_MMS:
4503 Header[214]=0x07;
4504 Header[215]=0xd3;
4505 Header[216]=0x06;
4506 Header[217]=0x01;
4507 Header[218]=0x12;
4508 Header[219]=0x13;
4509 Header[220]=0x29;
4510 Header[233]=0x01;
4511 break;
4512#endif
4513 default : Header[231]=0x01; Header[233]=0x05;
4514 }
4515 Header[235] = 0x01;
4516 Header[236] = Priv->ParentID / 256;
4517 Header[237] = Priv->ParentID % 256;
4518 smprintf(s, "Adding file header\n");
4519 error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
4520 if (error != ERR_NONE) return error;
4521 }
4522
4523 /* Can't delete from phone menu */
4524 if (File->ReadOnly) {
4525 error = N6510_SetReadOnly(s, File->ID_FullName, true);
4526 if (error != ERR_NONE) return error;
4527 }
4528
4529 if (N6510_FindFileCheckSum(File->Buffer, File->Used) != Priv->FileCheckSum) {
4530 smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum(File->Buffer, File->Used),Priv->FileCheckSum);
4531 return ERR_WRONGCRC;
4532 }
4533
4534 return ERR_EMPTY;
4535 }
4536
4537 return ERR_NONE;
4538}
4539
4540static GSM_Error N6510_ReplyDeleteFile(GSM_Protocol_Message msg, GSM_StateMachine *s)
4541{
4542 return ERR_NONE;
4543}
4544
4545static GSM_Error N6510_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
4546{
4547 GSM_Errorerror;
4548 unsigned char Delete[40] = {
4549 N7110_FRAME_HEADER, 0x1E, 0x00, 0x00, 0x00, 0x01,
4550 0x00, 0x35}; /* File ID */
4551
4552 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4553
4554 error = N6510_SetReadOnly(s, ID, false);
4555 if (error != ERR_NONE) return error;
4556
4557 Delete[8] = atoi(ID) / 256;
4558 Delete[9] = atoi(ID) % 256;
4559 return GSM_WaitFor (s, Delete, 10, 0x6D, 4, ID_DeleteFile);
4560}
4561
4562static GSM_Error N6510_ReplyAddFolder(GSM_Protocol_Message msg, GSM_StateMachine *s)
4563{
4564 sprintf(s->Phone.Data.File->ID_FullName,"%i",msg.Buffer[9]);
4565 return ERR_NONE;
4566}
4567
4568static GSM_Error N6510_AddFolder(GSM_StateMachine *s, GSM_File *File)
4569{
4570 GSM_Errorerror;
4571 unsigned char Header[400] = {
4572 N7110_FRAME_HEADER, 0x04, 0x00, 0x00, 0x00, 0x01,
4573 0x00, 0x0C, /* parent folder ID */
4574 0x00, 0x00, 0x00, 0xE8};
4575
4576 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOFILESYSTEM)) return ERR_NOTSUPPORTED;
4577
4578 error = N6510_SearchForFileName(s,File);
4579 if (error == ERR_NONE) return ERR_INVALIDLOCATION;
4580 if (error != ERR_EMPTY) return error;
4581
4582 Header[8] = atoi(File->ID_FullName) / 256;
4583 Header[9] = atoi(File->ID_FullName) % 256;
4584 memset(Header+14, 0x00, 300);
4585 CopyUnicodeString(Header+14,File->Name);
4586 Header[233] = 0x02;
4587 Header[235] = 0x01;
4588 Header[236] = atoi(File->ID_FullName) / 256;
4589 Header[237] = atoi(File->ID_FullName) % 256;
4590
4591 s->Phone.Data.File = File;
4592 smprintf(s, "Adding folder\n");
4593 error = GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFolder);
4594 if (error != ERR_NONE) return error;
4595
4596 /* Can't delete from phone menu */
4597 if (File->ReadOnly) {
4598 error = N6510_SetReadOnly(s, File->ID_FullName, true);
4599 if (error != ERR_NONE) return error;
4600 }
4601
4602 return error;
4603}
4604
4605#ifdef DEVELOP
4606
4607static GSM_Error N6510_ReplyEnableGPRSAccessPoint(GSM_Protocol_Message msg, GSM_StateMachine *s)
4608{
4609 if (msg.Buffer[13] == 0x02) return ERR_NONE;
4610 return ERR_UNKNOWNRESPONSE;
4611}
4612
4613static GSM_Error N6510_EnableGPRSAccessPoint(GSM_StateMachine *s)
4614{
4615 GSM_Errorerror;
4616 int i;
4617 unsigned char req[] = {
4618 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4619 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00};
4620
4621 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOGPRSPOINT)) return ERR_NOTSUPPORTED;
4622
4623 for (i=0;i<3;i++) {
4624 smprintf(s, "Activating full GPRS access point support\n");
4625 error = GSM_WaitFor (s, req, 16, 0x43, 4, ID_EnableGPRSPoint);
4626 if (error != ERR_NONE) return error;
4627 }
4628 return error;
4629}
4630
4631#endif
4632
4633static GSM_Error N6510_ReplyGetGPRSAccessPoint(GSM_Protocol_Message msg, GSM_StateMachine *s)
4634{
4635 GSM_GPRSAccessPoint *point = s->Phone.Data.GPRSPoint;
4636
4637 switch (msg.Buffer[13]) {
4638 case 0x01:
4639 smprintf(s,"Active GPRS point received\n");
4640 point->Active = false;
4641 if (point->Location == msg.Buffer[18]) point->Active = true;
4642 return ERR_NONE;
4643 case 0xD2:
4644 smprintf(s,"Names for GPRS points received\n");
4645 CopyUnicodeString(point->Name,msg.Buffer+18+(point->Location-1)*42);
4646 smprintf(s,"\"%s\"\n",DecodeUnicodeString(point->Name));
4647 return ERR_NONE;
4648 case 0xF2:
4649 smprintf(s,"URL for GPRS points received\n");
4650 CopyUnicodeString(point->URL,msg.Buffer+18+(point->Location-1)*202);
4651 smprintf(s,"\"%s\"\n",DecodeUnicodeString(point->URL));
4652 return ERR_NONE;
4653 }
4654 return ERR_UNKNOWNRESPONSE;
4655}
4656
4657static GSM_Error N6510_GetGPRSAccessPoint(GSM_StateMachine *s, GSM_GPRSAccessPoint *point)
4658{
4659 GSM_Errorerror;
4660 unsigned char URL[] = {
4661 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4662 0x00, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00};
4663 unsigned char Name[] = {
4664 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4665 0x01, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00};
4666 unsigned char Active[] = {
4667 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4668 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
4669
4670 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOGPRSPOINT)) return ERR_NOTSUPPORTED;
4671 if (point->Location < 1) return ERR_UNKNOWN;
4672 if (point->Location > 5) return ERR_INVALIDLOCATION;
4673
4674 s->Phone.Data.GPRSPoint = point;
4675
4676#ifdef DEVELOP
4677 error = N6510_EnableGPRSAccessPoint(s);
4678 if (error != ERR_NONE) return error;
4679#endif
4680
4681 smprintf(s, "Getting GPRS access point name\n");
4682 error=GSM_WaitFor (s, Name, 16, 0x43, 4, ID_GetGPRSPoint);
4683 if (error != ERR_NONE) return error;
4684
4685 smprintf(s, "Getting GPRS access point URL\n");
4686 error=GSM_WaitFor (s, URL, 16, 0x43, 4, ID_GetGPRSPoint);
4687 if (error != ERR_NONE) return error;
4688
4689 smprintf(s, "Getting number of active GPRS access point\n");
4690 error=GSM_WaitFor (s, Active, 16, 0x43, 4, ID_GetGPRSPoint);
4691 if (error != ERR_NONE) return error;
4692
4693 if (UnicodeLength(point->URL)==0 && UnicodeLength(point->Name)==0) return ERR_EMPTY;
4694 return error;
4695}
4696
4697static GSM_Error N6510_ReplySetGPRSAccessPoint1(GSM_Protocol_Message msg, GSM_StateMachine *s)
4698{
4699 switch (msg.Buffer[13]) {
4700 case 0x01:
4701 case 0xD2:
4702 case 0xF2:
4703 memcpy(s->Phone.Data.Priv.N6510.GPRSPoints,msg.Buffer,msg.Length);
4704 s->Phone.Data.Priv.N6510.GPRSPointsLength = msg.Length;
4705 return ERR_NONE;
4706 }
4707 return ERR_UNKNOWNRESPONSE;
4708}
4709
4710static GSM_Error N6510_SetGPRSAccessPoint(GSM_StateMachine *s, GSM_GPRSAccessPoint *point)
4711{
4712 unsigned char*buff = s->Phone.Data.Priv.N6510.GPRSPoints;
4713 GSM_Errorerror;
4714 unsigned char URL[] = {
4715 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4716 0x00, 0x00, 0x00, 0x03, 0xF2, 0x00, 0x00};
4717 unsigned char Name[] = {
4718 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4719 0x01, 0x00, 0x00, 0x00, 0xD2, 0x00, 0x00};
4720 unsigned char Active[] = {
4721 N7110_FRAME_HEADER, 0x05, 0x00, 0x00, 0x00, 0x2C, 0x00,
4722 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
4723
4724 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOGPRSPOINT)) return ERR_NOTSUPPORTED;
4725 if (point->Location < 1) return ERR_UNKNOWN;
4726 if (point->Location > 5) return ERR_INVALIDLOCATION;
4727
4728 s->Phone.Data.GPRSPoint = point;
4729
4730#ifdef DEVELOP
4731 error = N6510_EnableGPRSAccessPoint(s);
4732 if (error != ERR_NONE) return error;
4733#endif
4734
4735 smprintf(s, "Getting GPRS access point name\n");
4736 error=GSM_WaitFor (s, Name, 16, 0x43, 4, ID_SetGPRSPoint);
4737 if (error != ERR_NONE) return error;
4738 CopyUnicodeString(buff+18+(point->Location-1)*42,point->Name);
4739 buff[0] = 0x00;
4740 buff[1] = 0x01;
4741 buff[2] = 0x01;
4742 buff[3] = 0x07;
4743 smprintf(s, "Setting GPRS access point name\n");
4744 error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
4745 if (error != ERR_NONE) return error;
4746
4747 smprintf(s, "Getting GPRS access point URL\n");
4748 error=GSM_WaitFor (s, URL, 16, 0x43, 4, ID_SetGPRSPoint);
4749 if (error != ERR_NONE) return error;
4750 CopyUnicodeString(buff+18+(point->Location-1)*42,point->URL);
4751 buff[0] = 0x00;
4752 buff[1] = 0x01;
4753 buff[2] = 0x01;
4754 buff[3] = 0x07;
4755 smprintf(s, "Setting GPRS access point URL\n");
4756 error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
4757 if (error != ERR_NONE) return error;
4758
4759 if (point->Active) {
4760 smprintf(s, "Getting number of active GPRS access point\n");
4761 error=GSM_WaitFor (s, Active, 16, 0x43, 4, ID_SetGPRSPoint);
4762 if (error != ERR_NONE) return error;
4763 buff[0] = 0x00;
4764 buff[1] = 0x01;
4765 buff[2] = 0x01;
4766 buff[3] = 0x07;
4767 buff[18]= point->Location;
4768 smprintf(s, "Setting number of active GPRS access point\n");
4769 error=GSM_WaitFor (s, buff, s->Phone.Data.Priv.N6510.GPRSPointsLength, 0x43, 4, ID_SetGPRSPoint);
4770 if (error != ERR_NONE) return error;
4771 }
4772
4773 return error;
4774}
4775
4776/* ToDo support - 6310 style */
4777static GSM_Error N6510_ReplyGetToDoStatus1(GSM_Protocol_Message msg, GSM_StateMachine *s)
4778{
4779 int i;
4780 GSM_NOKIACalToDoLocations*Last = &s->Phone.Data.Priv.N6510.LastToDo;
4781
4782 smprintf(s, "TODO locations received\n");
4783 Last->Number=msg.Buffer[6]*256+msg.Buffer[7];
4784 smprintf(s, "Number of Entries: %i\n",Last->Number);
4785 smprintf(s, "Locations: ");
4786 for (i=0;i<Last->Number;i++) {
4787 Last->Location[i]=msg.Buffer[12+(i*4)]*256+msg.Buffer[(i*4)+13];
4788 smprintf(s, "%i ",Last->Location[i]);
4789 }
4790 smprintf(s, "\n");
4791 return ERR_NONE;
4792}
4793
4794/* ToDo support - 6310 style */
4795static GSM_Error N6510_GetToDoStatus1(GSM_StateMachine *s, GSM_ToDoStatus *status)
4796{
4797 GSM_Error error;
4798 GSM_NOKIACalToDoLocations*LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
4799 unsigned char reqLoc[] = {
4800 N6110_FRAME_HEADER,
4801 0x15, 0x01, 0x00, 0x00,
4802 0x00, 0x00, 0x00};
4803
4804 smprintf(s, "Getting ToDo locations\n");
4805 error = GSM_WaitFor (s, reqLoc, 10, 0x55, 4, ID_GetToDo);
4806 if (error != ERR_NONE) return error;
4807
4808 status->Used = LastToDo->Number;
4809 return ERR_NONE;
4810}
4811
4812static GSM_Error N6510_GetToDoStatus2(GSM_StateMachine *s, GSM_ToDoStatus *status)
4813{
4814 GSM_NOKIACalToDoLocations*LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
4815 GSM_Error error;
4816
4817 error = N6510_GetCalendarInfo3(s,LastToDo,false);
4818 if (error!=ERR_NONE) return error;
4819
4820 status->Used = LastToDo->Number;
4821 return ERR_NONE;
4822}
4823
4824static GSM_Error N6510_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
4825{
4826 status->Used = 0;
4827
4828 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
4829 return N6510_GetToDoStatus1(s, status);
4830 } else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
4831 return N6510_GetToDoStatus2(s, status);
4832 } else {
4833 return ERR_NOTSUPPORTED;
4834 }
4835}
4836
4837/* ToDo support - 6310 style */
4838static GSM_Error N6510_ReplyGetToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
4839{
4840 GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
4841
4842 smprintf(s, "TODO received method 1\n");
4843
4844 switch (msg.Buffer[4]) {
4845 case 1 : Last->Priority = GSM_Priority_High; break;
4846 case 2 : Last->Priority = GSM_Priority_Medium; break;
4847 case 3 : Last->Priority = GSM_Priority_Low; break;
4848 default: return ERR_UNKNOWN;
4849 }
4850 smprintf(s, "Priority: %i\n",msg.Buffer[4]);
4851
4852 CopyUnicodeString(Last->Entries[0].Text,msg.Buffer+14);
4853 Last->Entries[0].EntryType = TODO_TEXT;
4854 Last->EntriesNum = 1;
4855 smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
4856
4857 return ERR_NONE;
4858}
4859
4860/* ToDo support - 6310 style */
4861static GSM_Error N6510_GetNextToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
4862{
4863 GSM_Error error;
4864 GSM_ToDoStatus status;
4865 GSM_NOKIACalToDoLocations*LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
4866 unsigned char reqGet[] = {
4867 N6110_FRAME_HEADER,
4868 0x03, 0x00, 0x00, 0x80, 0x00,
4869 0x00, 0x17}; /* Location */
4870
4871 if (refresh) {
4872 error = N6510_GetToDoStatus(s, &status);
4873 if (error != ERR_NONE) return error;
4874 ToDo->Location = 1;
4875 } else {
4876 ToDo->Location++;
4877 }
4878 if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
4879
4880 reqGet[8] = LastToDo->Location[ToDo->Location-1] / 256;
4881 reqGet[9] = LastToDo->Location[ToDo->Location-1] % 256;
4882 s->Phone.Data.ToDo = ToDo;
4883 smprintf(s, "Getting ToDo\n");
4884 return GSM_WaitFor (s, reqGet, 10, 0x55, 4, ID_GetToDo);
4885}
4886
4887static GSM_Error N6510_ReplyGetToDoStatus2(GSM_Protocol_Message msg, GSM_StateMachine *s)
4888{
4889 return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastToDo);
4890}
4891
4892/* Similiar to getting calendar method 3 */
4893static GSM_Error N6510_ReplyGetToDo2(GSM_Protocol_Message msg, GSM_StateMachine *s)
4894{
4895 GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
4896 GSM_DateTime Date;
4897 unsigned long diff;
4898
4899 smprintf(s, "ToDo received method 2\n");
4900
4901 switch (msg.Buffer[44]) {
4902 case 0x10: Last->Priority = GSM_Priority_Low; break;
4903 case 0x20: Last->Priority = GSM_Priority_Medium; break;
4904 case 0x30: Last->Priority = GSM_Priority_High; break;
4905 default : return ERR_UNKNOWN;
4906 }
4907
4908 memcpy(Last->Entries[0].Text,msg.Buffer+54,msg.Buffer[51]*2);
4909 Last->Entries[0].Text[msg.Buffer[51]*2] = 0;
4910 Last->Entries[0].Text[msg.Buffer[51]*2+1] = 0;
4911 Last->Entries[0].EntryType = TODO_TEXT;
4912 smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
4913
4914 smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
4915 msg.Buffer[34]*256+msg.Buffer[35],
4916 msg.Buffer[36],msg.Buffer[37],msg.Buffer[38],
4917 msg.Buffer[39]);
4918 Date.Year = msg.Buffer[34]*256+msg.Buffer[35];
4919 Date.Month = msg.Buffer[36];
4920 Date.Day = msg.Buffer[37];
4921 Date.Hour = msg.Buffer[38];
4922 Date.Minute = msg.Buffer[39];
4923 Date.Second= 0;
4924 Last->Entries[1].EntryType = TODO_END_DATETIME;
4925 memcpy(&Last->Entries[1].Date,&Date,sizeof(GSM_DateTime));
4926
4927 smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
4928 msg.Buffer[28]*256+msg.Buffer[29],
4929 msg.Buffer[30],msg.Buffer[31],msg.Buffer[32],
4930 msg.Buffer[33]);
4931 Date.Year = msg.Buffer[28]*256+msg.Buffer[29];
4932 Date.Month = msg.Buffer[30];
4933 Date.Day = msg.Buffer[31];
4934 Date.Hour = msg.Buffer[32];
4935 Date.Minute = msg.Buffer[33];
4936 Date.Second= 0;
4937
4938 Last->EntriesNum = 2;
4939
4940 if (msg.Buffer[45] == 0x01) {
4941 Last->Entries[2].Number = msg.Buffer[45];
4942 Last->Entries[2].EntryType = TODO_COMPLETED;
4943 Last->EntriesNum++;
4944 smprintf(s,"Completed\n");
4945 }
4946
4947 if (msg.Buffer[14] == 0xFF && msg.Buffer[15] == 0xFF && msg.Buffer[16] == 0xff && msg.Buffer[17] == 0xff)
4948 {
4949 smprintf(s, "No alarm\n");
4950 } else {
4951 diff = ((unsigned int)msg.Buffer[14]) << 24;
4952 diff += ((unsigned int)msg.Buffer[15]) << 16;
4953 diff += ((unsigned int)msg.Buffer[16]) << 8;
4954 diff += msg.Buffer[17];
4955
4956 memcpy(&Last->Entries[Last->EntriesNum].Date,&Date,sizeof(GSM_DateTime));
4957 GetTimeDifference(diff, &Last->Entries[Last->EntriesNum].Date, false, 60);
4958 smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
4959 Last->Entries[Last->EntriesNum].Date.Day, Last->Entries[Last->EntriesNum].Date.Month,
4960 Last->Entries[Last->EntriesNum].Date.Year, Last->Entries[Last->EntriesNum].Date.Hour,
4961 Last->Entries[Last->EntriesNum].Date.Minute,Last->Entries[Last->EntriesNum].Date.Second);
4962
4963 Last->Entries[Last->EntriesNum].EntryType = TODO_ALARM_DATETIME;
4964 if (msg.Buffer[22]==0x00 && msg.Buffer[23]==0x00 &&
4965 msg.Buffer[24]==0x00 && msg.Buffer[25]==0x00)
4966 {
4967 Last->Entries[Last->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
4968 smprintf(s, "Alarm type : Silent\n");
4969 }
4970 Last->EntriesNum++;
4971 }
4972
4973 return ERR_NONE;
4974}
4975
4976/* ToDo support - 6610 style */
4977static GSM_Error N6510_GetNextToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
4978{
4979 GSM_Error error;
4980 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
4981 /* The same to getting calendar method 3 */
4982 unsigned char req[] = {
4983 N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
4984 0x00,0x99, /* Location */
4985 0xff,0xff,0xff,0xff,0x01};
4986
4987 if (refresh) {
4988 error=N6510_GetCalendarInfo3(s,LastToDo,false);
4989 if (error!=ERR_NONE) return error;
4990 ToDo->Location = 1;
4991 } else {
4992 ToDo->Location++;
4993 }
4994
4995 if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
4996
4997 req[8] = LastToDo->Location[ToDo->Location-1] / 256;
4998 req[9] = LastToDo->Location[ToDo->Location-1] % 256;
4999
5000 s->Phone.Data.ToDo = ToDo;
5001 smprintf(s, "Getting todo method 2\n");
5002 return GSM_WaitFor (s, req, 15, 0x13, 4, ID_GetToDo);
5003}
5004
5005static GSM_Error N6510_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, bool refresh)
5006{
5007 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
5008 return N6510_GetNextToDo1(s, ToDo, refresh);
5009 } else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
5010 return N6510_GetNextToDo2(s, ToDo, refresh);
5011 } else {
5012 return ERR_NOTSUPPORTED;
5013 }
5014}
5015
5016/* ToDo support - 6310 style */
5017static GSM_Error N6510_ReplyDeleteAllToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
5018{
5019 smprintf(s, "All TODO deleted\n");
5020 return ERR_NONE;
5021}
5022
5023/* ToDo support - 6310 style */
5024static GSM_Error N6510_DeleteAllToDo1(GSM_StateMachine *s)
5025{
5026 unsigned char req[] = {N6110_FRAME_HEADER, 0x11};
5027
5028 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
5029 return ERR_NOTSUPPORTED;
5030 }
5031
5032 smprintf(s, "Deleting all ToDo method 1\n");
5033 return GSM_WaitFor (s, req, 4, 0x55, 4, ID_DeleteAllToDo);
5034}
5035
5036static GSM_Error N6510_DeleteToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
5037{
5038 GSM_Error error;
5039 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
5040 GSM_CalendarEntry Note;
5041
5042 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
5043 return ERR_NOTSUPPORTED;
5044 }
5045
5046 error=N6510_GetCalendarInfo3(s,LastToDo,false);
5047 if (error!=ERR_NONE) return error;
5048
5049 smprintf(s, "Deleting ToDo method 2\n");
5050
5051 if (ToDo->Location > LastToDo->Number || ToDo->Location == 0) return ERR_INVALIDLOCATION;
5052
5053 Note.Location = LastToDo->Location[ToDo->Location-1];
5054 return N71_65_DelCalendar(s,&Note);
5055}
5056
5057/* ToDo support - 6310 style */
5058static GSM_Error N6510_ReplyGetToDoFirstLoc1(GSM_Protocol_Message msg, GSM_StateMachine *s)
5059{
5060 smprintf(s, "TODO first location received method 1: %02x\n",msg.Buffer[9]);
5061 s->Phone.Data.ToDo->Location = msg.Buffer[9];
5062 return ERR_NONE;
5063}
5064
5065/* ToDo support - 6310 style */
5066static GSM_Error N6510_ReplyAddToDo1(GSM_Protocol_Message msg, GSM_StateMachine *s)
5067{
5068 smprintf(s, "TODO set OK\n");
5069 return ERR_NONE;
5070}
5071
5072/* ToDo support - 6310 style */
5073static GSM_Error N6510_AddToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
5074{
5075 int Text, Alarm, EndTime, Completed, ulen, Phone;
5076 GSM_Error error;
5077 unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x0F};
5078 unsigned char reqSet[500] = {
5079 N6110_FRAME_HEADER, 0x01,
5080 0x03, /* Priority */
5081 0x00, /* Length of text */
5082 0x80,0x00,0x00,
5083 0x18}; /* Location */
5084
5085 s->Phone.Data.ToDo = ToDo;
5086
5087 smprintf(s, "Getting first ToDo location\n");
5088 error = GSM_WaitFor (s, reqLoc, 4, 0x55, 4, ID_SetToDo);
5089 if (error != ERR_NONE) return error;
5090 reqSet[9] = ToDo->Location;
5091
5092 switch (ToDo->Priority) {
5093 case GSM_Priority_Low: reqSet[4] = 3; break;
5094 case GSM_Priority_Medium: reqSet[4] = 2; break;
5095 case GSM_Priority_High: reqSet[4] = 1; break;
5096 }
5097
5098 GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
5099
5100 if (Text == -1) return ERR_NOTSUPPORTED; /* XXX: shouldn't this be handled different way? */
5101 ulen = UnicodeLength(ToDo->Entries[Text].Text);
5102 reqSet[5] = ulen+1;
5103 CopyUnicodeString(reqSet+10,ToDo->Entries[Text].Text);
5104 reqSet[10+ulen*2] = 0x00;
5105 reqSet[10+ulen*2+1] = 0x00;
5106 smprintf(s, "Adding ToDo method 1\n");
5107 return GSM_WaitFor (s, reqSet, 12+ulen*2, 0x55, 4, ID_SetToDo);
5108}
5109
5110static GSM_Error N6510_ReplyAddToDo2(GSM_Protocol_Message msg, GSM_StateMachine *s)
5111{
5112 smprintf(s, "ToDo added method 2\n");
5113 return ERR_NONE;
5114}
5115
5116static GSM_Error N6510_ReplyGetToDoFirstLoc2(GSM_Protocol_Message msg, GSM_StateMachine *s)
5117{
5118 smprintf(s, "First ToDo location method 2: %i\n",msg.Buffer[8]*256+msg.Buffer[9]);
5119 s->Phone.Data.ToDo->Location = msg.Buffer[9];
5120 return ERR_NONE;
5121}
5122
5123static GSM_Error N6510_AddToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
5124{
5125 GSM_CalendarEntryNote;
5126 time_t t_time1,t_time2;
5127 long diff;
5128 GSM_Error error;
5129 GSM_DateTime DT;
5130 int Text, Alarm, EndTime, Completed, count=54, Phone;
5131 unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x95, 0x01};
5132 unsigned char req[5000] = {
5133 N6110_FRAME_HEADER, 0x65,
5134 0x01, /* 0 = calendar, 1 = todo */
5135 0x00, 0x00, 0x00,
5136 0x00, 0x00, /* location */
5137 0x00, 0x00, 0x00, 0x00,
5138 0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
5139 0x80, 0x00, 0x00,
5140 0x01, /* note icon */
5141 0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
5142 0x00, /* 0x02 or 0x00 */
5143 0x01, /* note type */
5144 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
5145 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
5146 0x00, 0x00, /* recurrance */
5147 0x00, 0x00, /* birth year */
5148 0x20, /* ToDo priority */
5149 0x00, /* ToDo completed ? */
5150 0x00, 0x00, 0x00,
5151 0x00, /* note text length */
5152 0x00, /* phone length/meeting place*/
5153 0x00, 0x00, 0x00};
5154
5155 s->Phone.Data.ToDo = ToDo;
5156
5157 smprintf(s, "Getting first free ToDo location method 2\n");
5158 error = GSM_WaitFor (s, reqLoc, 5, 0x13, 4, ID_SetToDo);
5159 if (error!=ERR_NONE) return error;
5160 req[8] = ToDo->Location/256;
5161 req[9] = ToDo->Location%256;
5162
5163 Note.Type = GSM_CAL_MEETING;
5164 DT.Year = 2004; DT.Month = 1; DT.Day = 1;
5165 DT.Hour = 12; DT.Minute = 12; DT.Second = 0;
5166 memcpy(&Note.Entries[0].Date,&DT,sizeof(GSM_DateTime));
5167 Note.Entries[0].EntryType = CAL_START_DATETIME;
5168 memcpy(&Note.Entries[1].Date,&DT,sizeof(GSM_DateTime));
5169 Note.Entries[1].EntryType = CAL_END_DATETIME;
5170 EncodeUnicode(Note.Entries[2].Text,"ala",3);
5171 Note.Entries[2].EntryType = CAL_TEXT;
5172 Note.EntriesNum = 3;
5173 error=N6510_FindCalendarIconID3(s, &Note, &req[21]);
5174 if (error!=ERR_NONE) return error;
5175
5176 switch (ToDo->Priority) {
5177 case GSM_Priority_Low: req[44] = 0x10; break;
5178 case GSM_Priority_Medium: req[44] = 0x20; break;
5179 case GSM_Priority_High: req[44] = 0x30; break;
5180 }
5181
5182 GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
5183
5184 if (Completed != -1) req[45] = 0x01;
5185
5186 if (EndTime == -1) {
5187 GSM_GetCurrentDateTime(&DT);
5188 } else {
5189 memcpy(&DT,&ToDo->Entries[EndTime].Date,sizeof(GSM_DateTime));
5190 }
5191 /*Start time*/
5192 req[28]= DT.Year / 256;
5193 req[29]= DT.Year % 256;
5194 req[30]= DT.Month;
5195 req[31]= DT.Day;
5196 req[32]= DT.Hour;
5197 req[33]= DT.Minute;
5198 /*End time*/
5199 req[34]= DT.Year / 256;
5200 req[35]= DT.Year % 256;
5201 req[36]= DT.Month;
5202 req[37]= DT.Day;
5203 req[38]= DT.Hour;
5204 req[39]= DT.Minute;
5205
5206 if (Alarm != -1) {
5207 if (ToDo->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME)
5208 {
5209 req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
5210 }
5211 t_time2 = Fill_Time_T(DT,8);
5212 t_time1 = Fill_Time_T(ToDo->Entries[Alarm].Date,8);
5213 diff = (t_time1-t_time2)/60;
5214
5215 smprintf(s, " Difference : %li seconds or minutes\n", -diff);
5216 req[14] = (unsigned char)(-diff >> 24);
5217 req[15] = (unsigned char)(-diff >> 16);
5218 req[16] = (unsigned char)(-diff >> 8);
5219 req[17] = (unsigned char)(-diff);
5220 }
5221
5222 if (Text != -1) {
5223 req[49] = UnicodeLength(ToDo->Entries[Text].Text);
5224 CopyUnicodeString(req+54,ToDo->Entries[Text].Text);
5225 count+= req[49]*2;
5226 }
5227
5228 req[count++] = 0x00;
5229
5230 smprintf(s, "Adding ToDo method 2\n");
5231 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetToDo);
5232}
5233
5234static GSM_Error N6510_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
5235{
5236 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
5237 return N6510_AddToDo1(s, ToDo);
5238 } else if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
5239 return N6510_AddToDo2(s, ToDo);
5240 } else {
5241 return ERR_NOTSUPPORTED;
5242 }
5243}
5244
5245static GSM_Error N6510_ReplyGetLocale(GSM_Protocol_Message msg, GSM_StateMachine *s)
5246{
5247 GSM_Locale *locale = s->Phone.Data.Locale;
5248
5249 switch (msg.Buffer[3]) {
5250 case 0x8A:
5251 smprintf(s, "Date settings received\n");
5252 switch (msg.Buffer[4]) {
5253 case 0x00:
5254 locale->DateFormat = GSM_Date_DDMMYYYY;
5255 locale->DateSeparator = '.';
5256 break;
5257 case 0x01:
5258 locale->DateFormat = GSM_Date_MMDDYYYY;
5259 locale->DateSeparator = '.';
5260 break;
5261 case 0x02:
5262 locale->DateFormat = GSM_Date_YYYYMMDD;
5263 locale->DateSeparator = '.';
5264 break;
5265 case 0x04:
5266 locale->DateFormat = GSM_Date_DDMMYYYY;
5267 locale->DateSeparator = '/';
5268 break;
5269 case 0x05:
5270 locale->DateFormat = GSM_Date_MMDDYYYY;
5271 locale->DateSeparator = '/';
5272 break;
5273 case 0x06:
5274 locale->DateFormat = GSM_Date_YYYYMMDD;
5275 locale->DateSeparator = '/';
5276 break;
5277 case 0x08:
5278 locale->DateFormat = GSM_Date_DDMMYYYY;
5279 locale->DateSeparator = '-';
5280 break;
5281 case 0x09:
5282 locale->DateFormat = GSM_Date_MMDDYYYY;
5283 locale->DateSeparator = '-';
5284 break;
5285 case 0x0A:
5286 locale->DateFormat = GSM_Date_YYYYMMDD;
5287 locale->DateSeparator = '-';
5288 break;
5289 default:/* FIXME */
5290 locale->DateFormat = GSM_Date_DDMMYYYY;
5291 locale->DateSeparator = '/';
5292 break;
5293 }
5294 return ERR_NONE;
5295 }
5296 return ERR_UNKNOWNRESPONSE;
5297}
5298
5299static GSM_Error N6510_GetLocale(GSM_StateMachine *s, GSM_Locale *locale)
5300{
5301 unsigned char req[] = {N6110_FRAME_HEADER, 0x89};
5302
5303 s->Phone.Data.Locale = locale;
5304
5305 smprintf(s, "Getting date format\n");
5306 return GSM_WaitFor (s, req, 4, 0x13, 4, ID_GetLocale);
5307}
5308
5309static GSM_Error N6510_ReplyGetCalendarSettings(GSM_Protocol_Message msg, GSM_StateMachine *s)
5310{
5311 GSM_CalendarSettings *sett = s->Phone.Data.CalendarSettings;
5312
5313 switch (msg.Buffer[3]) {
5314 case 0x86:
5315 smprintf(s, "Auto deleting setting received\n");
5316 sett->AutoDelete = msg.Buffer[4];
5317 return ERR_NONE;
5318 case 0x8E:
5319 smprintf(s, "Start day for calendar received\n");
5320 switch(msg.Buffer[4]) {
5321 case 0x03:
5322 sett->StartDay = 6;
5323 return ERR_NONE;
5324 case 0x02:
5325 sett->StartDay = 7;
5326 return ERR_NONE;
5327 case 0x01:
5328 sett->StartDay = 1;
5329 return ERR_NONE;
5330 }
5331 break;
5332 }
5333 return ERR_UNKNOWNRESPONSE;
5334}
5335
5336static GSM_Error N6510_GetCalendarSettings(GSM_StateMachine *s, GSM_CalendarSettings *settings)
5337{
5338 GSM_Errorerror;
5339 unsigned char req1[] = {N6110_FRAME_HEADER, 0x85};
5340 unsigned char req2[] = {N6110_FRAME_HEADER, 0x8D};
5341
5342 s->Phone.Data.CalendarSettings = settings;
5343
5344 smprintf(s, "Getting auto delete\n");
5345 error = GSM_WaitFor (s, req1, 4, 0x13, 4, ID_GetCalendarSettings);
5346 if (error != ERR_NONE) return error;
5347
5348 smprintf(s, "Getting start day for week\n");
5349 return GSM_WaitFor (s, req2, 4, 0x13, 4, ID_GetCalendarSettings);
5350}
5351
5352GSM_Error N6510_CancelCall(GSM_StateMachine *s, int ID, bool all)
5353{
5354 if (all) return ERR_NOTSUPPORTED;
5355 return DCT3DCT4_CancelCall(s,ID);
5356}
5357
5358GSM_Error N6510_AnswerCall(GSM_StateMachine *s, int ID, bool all)
5359{
5360 if (all) return ERR_NOTSUPPORTED;
5361 return DCT3DCT4_AnswerCall(s,ID);
5362}
5363
5364static GSM_Error N6510_ReplyAddSMSFolder(GSM_Protocol_Message msg, GSM_StateMachine *s)
5365{
5366 smprintf(s,"SMS folder \"%s\" has been added\n",DecodeUnicodeString(msg.Buffer+10));
5367 return ERR_NONE;
5368}
5369
5370GSM_Error N6510_AddSMSFolder(GSM_StateMachine *s, unsigned char *name)
5371{
5372 unsigned char req[200] = {N6110_FRAME_HEADER, 0x10, 0x01, 0x00, 0x01,
5373 0x00, /* Length */
5374 0x00, 0x00};
5375
5376
5377 CopyUnicodeString(req+10,name);
5378 req[7] = UnicodeLength(name)*2 + 6;
5379
5380 smprintf(s, "Adding SMS folder\n");
5381 return GSM_WaitFor (s, req, req[7] + 6, 0x14, 4, ID_AddSMSFolder);
5382}
5383
5384static GSM_Error N6510_SetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
5385{
5386 GSM_Error error;
5387 int count=4, location;
5388 unsigned char req[600] = {N6110_FRAME_HEADER, 0x09};
5389
5390 /* We have to enable WAP frames in phone */
5391 error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
5392 if (error!=ERR_NONE) return error;
5393
5394 location = bookmark->Location - 1;
5395 if (bookmark->Location == 0) location = 0xffff;
5396 req[count++] = (location & 0xff00) >> 8;
5397 req[count++] = location & 0x00ff;
5398
5399 count += NOKIA_SetUnicodeString(s, req+count, bookmark->Title, true);
5400 count += NOKIA_SetUnicodeString(s, req+count, bookmark->Address, true);
5401
5402 req[count++] = 0x00;
5403 req[count++] = 0x00;
5404 req[count++] = 0x00;
5405 req[count++] = 0x00;
5406
5407 smprintf(s, "Setting WAP bookmark\n");
5408 error = GSM_WaitFor (s, req, count, 0x3f, 4, ID_SetWAPBookmark);
5409 if (error != ERR_NONE) {
5410 if (error == ERR_INSIDEPHONEMENU || error == ERR_EMPTY || error == ERR_FULL) {
5411 DCT3DCT4_DisableConnectionFunctions(s);
5412 }
5413 return error;
5414 }
5415
5416 return DCT3DCT4_DisableConnectionFunctions(s);
5417}
5418
5419GSM_Error N6510_DeleteWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
5420{
5421 GSM_Error error;
5422
5423 /* We have to enable WAP frames in phone */
5424 error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
5425 if (error!=ERR_NONE) return error;
5426
5427 return DCT3DCT4_DeleteWAPBookmarkPart(s,bookmark);
5428}
5429
5430GSM_Error N6510_GetWAPBookmark(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
5431{
5432 GSM_Error error;
5433
5434 /* We have to enable WAP frames in phone */
5435 error=N6510_EnableConnectionFunctions(s,N6510_WAP_SETTINGS);
5436 if (error!=ERR_NONE) return error;
5437
5438 return DCT3DCT4_GetWAPBookmarkPart(s,bookmark);
5439}
5440
5441static GSM_Reply_Function N6510ReplyFunctions[] = {
5442 {N71_65_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
5443 {N71_65_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
5444 {N71_65_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
5445 {N71_65_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
5446 {N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
5447 {N71_65_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
5448 {N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
5449 {N71_65_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
5450 {N71_65_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
5451 {N71_65_ReplyCallInfo, "\x01",0x03,0x0B,ID_IncomingFrame },
5452 {N71_65_ReplyCallInfo, "\x01",0x03,0x0C,ID_DialVoice },
5453 {N71_65_ReplyCallInfo, "\x01",0x03,0x0C,ID_IncomingFrame },
5454 {N71_65_ReplyCallInfo, "\x01",0x03,0x23,ID_IncomingFrame },
5455 {N71_65_ReplyCallInfo, "\x01",0x03,0x25,ID_IncomingFrame },
5456 {N71_65_ReplyCallInfo, "\x01",0x03,0x27,ID_IncomingFrame },
5457 {N71_65_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
5458 {N71_65_ReplyCallInfo, "\x01",0x03,0x53,ID_IncomingFrame },
5459 {N71_65_ReplySendDTMF, "\x01",0x03,0x59,ID_SendDTMF },
5460 {N71_65_ReplySendDTMF, "\x01",0x03,0x5E,ID_SendDTMF },
5461
5462 {N6510_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
5463 {N6510_ReplyIncomingSMS, "\x02",0x03,0x04,ID_IncomingFrame },
5464 {N6510_ReplySetSMSC, "\x02",0x03,0x13,ID_SetSMSC },
5465 {N6510_ReplyGetSMSC, "\x02",0x03,0x15,ID_GetSMSC },
5466
5467 {N6510_ReplyGetMemoryStatus, "\x03",0x03,0x04,ID_GetMemoryStatus },
5468 {N6510_ReplyGetMemory, "\x03",0x03,0x08,ID_GetMemory },
5469 {N6510_ReplyDeleteMemory, "\x03",0x03,0x10,ID_SetMemory },
5470 {N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetBitmap },
5471 {N71_65_ReplyWritePhonebook, "\x03",0x03,0x0C,ID_SetMemory },
5472
5473 {DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x02,ID_Divert },
5474 {N71_65_ReplyUSSDInfo, "\x06",0x03,0x03,ID_IncomingFrame },
5475 {NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },
5476 {NoneReply, "\x06",0x03,0x09,ID_IncomingFrame },
5477
5478 {N6510_ReplyEnterSecurityCode, "\x08",0x03,0x08,ID_EnterSecurityCode },
5479 {N6510_ReplyEnterSecurityCode, "\x08",0x03,0x09,ID_EnterSecurityCode },
5480 {N6510_ReplyGetSecurityStatus, "\x08",0x03,0x12,ID_GetSecurityStatus },
5481
5482 {N6510_ReplyGetNetworkInfo, "\x0A",0x03,0x01,ID_GetNetworkInfo },
5483 {N6510_ReplyGetNetworkInfo, "\x0A",0x03,0x01,ID_IncomingFrame },
5484 {N6510_ReplyLogIntoNetwork, "\x0A",0x03,0x02,ID_IncomingFrame },
5485 {N6510_ReplyGetSignalQuality, "\x0A",0x03,0x0C,ID_GetSignalQuality },
5486 {N6510_ReplyGetIncSignalQuality, "\x0A",0x03,0x1E,ID_IncomingFrame },
5487 {NoneReply, "\x0A",0x03,0x20,ID_IncomingFrame },
5488 {N6510_ReplyGetOperatorLogo, "\x0A",0x03,0x24,ID_GetBitmap },
5489 {N6510_ReplySetOperatorLogo, "\x0A",0x03,0x26,ID_SetBitmap },
5490
5491 {NoneReply, "\x0B",0x03,0x01,ID_PlayTone },
5492 {NoneReply, "\x0B",0x03,0x15,ID_PlayTone },
5493 {NoneReply, "\x0B",0x03,0x16,ID_PlayTone },
5494
5495 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x02,ID_SetCalendarNote },
5496 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x04,ID_SetCalendarNote },
5497 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x06,ID_SetCalendarNote },
5498 {N71_65_ReplyAddCalendar1, "\x13",0x03,0x08,ID_SetCalendarNote },
5499 {N71_65_ReplyDelCalendar, "\x13",0x03,0x0C,ID_DeleteCalendarNote },
5500 {N71_65_ReplyGetNextCalendar1, "\x13",0x03,0x1A,ID_GetCalendarNote },/*method 1*/
5501 {N6510_ReplyGetCalendarNotePos, "\x13",0x03,0x32,ID_GetCalendarNotePos },/*method 1*/
5502 {N6510_ReplyGetCalendarInfo, "\x13",0x03,0x3B,ID_GetCalendarNotesInfo},/*method 1*/
5503#ifdef DEBUG
5504 {N71_65_ReplyGetNextCalendar2, "\x13",0x03,0x3F,ID_GetCalendarNote },
5505#endif
5506 {N71_65_ReplyAddCalendar2, "\x13",0x03,0x41,ID_SetCalendarNote },/*method 2*/
5507 {N6510_ReplyAddCalendar3, "\x13",0x03,0x66,ID_SetCalendarNote },/*method 3*/
5508 {N6510_ReplyAddToDo2, "\x13",0x03,0x66,ID_SetToDo },
5509 {N6510_ReplyGetCalendar3, "\x13",0x03,0x7E,ID_GetCalendarNote },/*method 3*/
5510 {N6510_ReplyGetToDo2, "\x13",0x03,0x7E,ID_GetToDo },
5511 {N6510_ReplyGetCalendarSettings, "\x13",0x03,0x86,ID_GetCalendarSettings },
5512 {N6510_ReplyGetLocale, "\x13",0x03,0x8A,ID_GetLocale },
5513 {N6510_ReplyGetCalendarSettings, "\x13",0x03,0x8E,ID_GetCalendarSettings },
5514 {N6510_ReplyGetCalendarNotePos, "\x13",0x03,0x96,ID_GetCalendarNotePos },/*method 3*/
5515 {N6510_ReplyGetToDoFirstLoc2, "\x13",0x03,0x96,ID_SetToDo },
5516 {N6510_ReplyGetCalendarInfo, "\x13",0x03,0x9F,ID_GetCalendarNotesInfo},/*method 3*/
5517 {N6510_ReplyGetToDoStatus2, "\x13",0x03,0x9F,ID_GetToDo },
5518
5519 {N6510_ReplySaveSMSMessage, "\x14",0x03,0x01,ID_SaveSMSMessage },
5520 {N6510_ReplySetPicture, "\x14",0x03,0x01,ID_SetBitmap },
5521 {N6510_ReplyGetSMSMessage, "\x14",0x03,0x03,ID_GetSMSMessage },
5522 {N6510_ReplyDeleteSMSMessage, "\x14",0x03,0x05,ID_DeleteSMSMessage },
5523 {N6510_ReplyDeleteSMSMessage, "\x14",0x03,0x06,ID_DeleteSMSMessage },
5524 {N6510_ReplyGetSMSStatus, "\x14",0x03,0x09,ID_GetSMSStatus },
5525 {N6510_ReplyGetSMSFolderStatus, "\x14",0x03,0x0d,ID_GetSMSFolderStatus },
5526 {N6510_ReplyGetSMSMessage, "\x14",0x03,0x0f,ID_GetSMSMessage },
5527 {N6510_ReplyAddSMSFolder, "\x14",0x03,0x11,ID_AddSMSFolder },
5528 {N6510_ReplyGetSMSFolders, "\x14",0x03,0x13,ID_GetSMSFolders },
5529 {N6510_ReplySaveSMSMessage, "\x14",0x03,0x17,ID_SaveSMSMessage },
5530 {N6510_ReplyGetSMSStatus, "\x14",0x03,0x1a,ID_GetSMSStatus },
5531
5532 {DCT4_ReplySetPhoneMode, "\x15",0x03,0x64,ID_Reset },
5533 {DCT4_ReplyGetPhoneMode, "\x15",0x03,0x65,ID_Reset },
5534 {NoneReply, "\x15",0x03,0x68,ID_Reset },
5535
5536 {N6510_ReplyGetBatteryCharge, "\x17",0x03,0x0B,ID_GetBatteryCharge },
5537
5538 {N6510_ReplySetDateTime, "\x19",0x03,0x02,ID_SetDateTime },
5539 {N6510_ReplyGetDateTime, "\x19",0x03,0x0B,ID_GetDateTime },
5540 {N6510_ReplySetAlarm, "\x19",0x03,0x12,ID_SetAlarm },
5541 {N6510_ReplyGetAlarm, "\x19",0x03,0x1A,ID_GetAlarm },
5542 {N6510_ReplyGetAlarm, "\x19",0x03,0x20,ID_GetAlarm },
5543
5544 {DCT4_ReplyGetIMEI, "\x1B",0x03,0x01,ID_GetIMEI },
5545 {NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x08,ID_GetHardware },
5546 {N6510_ReplyGetPPM, "\x1B",0x03,0x08,ID_GetPPM },
5547 {NOKIA_ReplyGetPhoneString, "\x1B",0x03,0x0C,ID_GetProductCode },
5548
5549 /* 0x1C - vibra */
5550
5551 {N6510_ReplyGetRingtonesInfo, "\x1f",0x03,0x08,ID_GetRingtonesInfo },
5552 {N6510_ReplyDeleteRingtones, "\x1f",0x03,0x11,ID_SetRingtone },
5553 {N6510_ReplyGetRingtone, "\x1f",0x03,0x13,ID_GetRingtone },
5554 {N6510_ReplySetBinRingtone, "\x1f",0x03,0x0F,ID_SetRingtone },
5555
5556 /* 0x23 - voice records */
5557
5558 {N6510_ReplyGetProfile, "\x39",0x03,0x02,ID_GetProfile },
5559 {N6510_ReplySetProfile, "\x39",0x03,0x04,ID_SetProfile },
5560 {N6510_ReplyGetProfile, "\x39",0x03,0x06,ID_GetProfile },
5561
5562 {N6510_ReplySetLight, "\x3A",0x03,0x06,ID_SetLight },
5563
5564 {N6510_ReplyGetFMStation, "\x3E",0x03,0x06,ID_GetFMStation },
5565 {N6510_ReplyGetFMStatus, "\x3E",0x03,0x0E,ID_GetFMStation },
5566 {N6510_ReplySetFMStation, "\x3E",0x03,0x15,ID_SetFMStation },
5567 {N6510_ReplyGetFMStation, "\x3E",0x03,0x16,ID_GetFMStation },
5568
5569 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
5570 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
5571 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
5572 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
5573 {N6510_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
5574 {N6510_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
5575 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
5576 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
5577 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
5578 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
5579 {DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
5580 {DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
5581 {N6510_ReplyGetConnectionSettings,"\x3f",0x03,0x16,ID_GetConnectSet },
5582 {N6510_ReplyGetConnectionSettings,"\x3f",0x03,0x17,ID_GetConnectSet },
5583 {N6510_ReplySetConnectionSettings,"\x3f",0x03,0x19,ID_SetConnectSet },
5584 {N6510_ReplySetConnectionSettings,"\x3f",0x03,0x1A,ID_SetConnectSet },
5585 {N6510_ReplySetConnectionSettings,"\x3f",0x03,0x28,ID_SetConnectSet },
5586 {N6510_ReplySetConnectionSettings,"\x3f",0x03,0x2B,ID_SetConnectSet },
5587 {N6510_ReplyGetChatSettings, "\x3f",0x03,0x3B,ID_GetChatSettings },
5588 {N6510_ReplyGetChatSettings, "\x3f",0x03,0x3C,ID_GetChatSettings },
5589
5590 {N6510_ReplyGetOriginalIMEI, "\x42",0x07,0x00,ID_GetOriginalIMEI },
5591 {N6510_ReplyGetManufactureMonth, "\x42",0x07,0x00,ID_GetManufactureMonth },
5592 {N6510_ReplyGetOriginalIMEI, "\x42",0x07,0x01,ID_GetOriginalIMEI },
5593 {N6510_ReplyGetManufactureMonth, "\x42",0x07,0x02,ID_GetManufactureMonth },
5594
5595 {N6510_ReplySetOperatorLogo, "\x43",0x03,0x08,ID_SetBitmap },
5596 {N6510_ReplyGetGPRSAccessPoint, "\x43",0x03,0x06,ID_GetGPRSPoint },
5597 {N6510_ReplySetGPRSAccessPoint1, "\x43",0x03,0x06,ID_SetGPRSPoint },
5598#ifdef DEVELOP
5599 {N6510_ReplyEnableGPRSAccessPoint,"\x43",0x03,0x06,ID_EnableGPRSPoint },
5600#endif
5601 {N6510_ReplyGetSyncMLSettings, "\x43",0x03,0x06,ID_GetSyncMLSettings },
5602 {N6510_ReplyGetSyncMLName, "\x43",0x03,0x06,ID_GetSyncMLName },
5603 {NoneReply, "\x43",0x03,0x08,ID_SetGPRSPoint },
5604
5605 /* 0x4A - voice records */
5606
5607 /* 0x53 - simlock */
5608
5609 {N6510_ReplyAddToDo1, "\x55",0x03,0x02,ID_SetToDo },
5610 {N6510_ReplyGetToDo1, "\x55",0x03,0x04,ID_GetToDo },
5611 {N6510_ReplyGetToDoFirstLoc1, "\x55",0x03,0x10,ID_SetToDo },
5612 {N6510_ReplyDeleteAllToDo1, "\x55",0x03,0x12,ID_DeleteAllToDo },
5613 {N6510_ReplyGetToDoStatus1, "\x55",0x03,0x16,ID_GetToDo },
5614
5615 {N6510_ReplyAddFileHeader, "\x6D",0x03,0x03,ID_AddFile },
5616 {N6510_ReplyAddFolder, "\x6D",0x03,0x05,ID_AddFolder },
5617 {N6510_ReplyGetFilePart, "\x6D",0x03,0x0F,ID_GetFile },
5618 {N6510_ReplyAddFileHeader, "\x6D",0x03,0x13,ID_AddFile },
5619 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_GetFileInfo },
5620 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_GetFile },
5621 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x15,ID_AddFile },
5622 {N6510_ReplyDeleteFile, "\x6D",0x03,0x19,ID_DeleteFile },
5623 {N6510_ReplyDeleteFile, "\x6D",0x03,0x1F,ID_DeleteFile },
5624 {N6510_ReplyGetFileSystemStatus, "\x6D",0x03,0x23,ID_FileSystemStatus },
5625 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x2F,ID_GetFileInfo },
5626 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x2F,ID_GetFile },
5627 {N6510_ReplyGetFileSystemStatus, "\x6D",0x03,0x2F,ID_FileSystemStatus },
5628 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x33,ID_GetFileInfo },
5629 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x33,ID_GetFile },
5630 {N6510_ReplyAddFilePart, "\x6D",0x03,0x41,ID_AddFile },
5631 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_AddFile },
5632 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_GetFile },
5633 {N6510_ReplyGetFileFolderInfo, "\x6D",0x03,0x43,ID_GetFileInfo },
5634
5635 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x01,ID_GetBitmap },
5636 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x01,ID_SetBitmap },
5637 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x0F,ID_GetBitmap },
5638 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x0F,ID_SetBitmap },
5639 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x10,ID_GetBitmap },
5640 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x10,ID_SetBitmap },
5641 {N6510_ReplyStartupNoteLogo, "\x7A",0x04,0x25,ID_SetBitmap },
5642
5643 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
5644 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
5645
5646 /* 0xD7 - Bluetooth */
5647
5648 {N6510_ReplyGetRingtoneID, "\xDB",0x03,0x02,ID_SetRingtone },
5649
5650 {NULL, "\x00",0x00,0x00,ID_None }
5651};
5652
5653GSM_Phone_Functions N6510Phone = {
5654 "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",
5655 N6510ReplyFunctions,
5656 N6510_Initialise,
5657 NONEFUNCTION, /* Terminate */
5658 GSM_DispatchMessage,
5659 N6510_ShowStartInfo,
5660 NOKIA_GetManufacturer,
5661 DCT3DCT4_GetModel,
5662 DCT3DCT4_GetFirmware,
5663 DCT4_GetIMEI,
5664 N6510_GetOriginalIMEI,
5665 N6510_GetManufactureMonth,
5666 DCT4_GetProductCode,
5667 DCT4_GetHardware,
5668 N6510_GetPPM,
5669 NOTSUPPORTED, /* GetSIMIMSI */
5670 N6510_GetDateTime,
5671 N6510_SetDateTime,
5672 N6510_GetAlarm,
5673 N6510_SetAlarm,
5674 N6510_GetLocale,
5675 NOTSUPPORTED, /* SetLocale */
5676 N6510_PressKey,
5677 DCT4_Reset,
5678 NOTIMPLEMENTED, /* ResetPhoneSettings*/
5679 N6510_EnterSecurityCode,
5680 N6510_GetSecurityStatus,
5681 NOTSUPPORTED, /* GetDisplayStatus*/
5682 NOTIMPLEMENTED, /* SetAutoNetworkLogin*/
5683 N6510_GetBatteryCharge,
5684 N6510_GetSignalQuality,
5685 N6510_GetNetworkInfo,
5686 NOTSUPPORTED, /* GetCategory */
5687 NOTSUPPORTED, /* AddCategory */
5688 NOTSUPPORTED, /* GetCategoryStatus */
5689 N6510_GetMemoryStatus,
5690 N6510_GetMemory,
5691 NOTIMPLEMENTED, /* GetNextMemory */
5692 N6510_SetMemory,
5693 NOTIMPLEMENTED, /* AddMemory */
5694 N6510_DeleteMemory,
5695 NOTIMPLEMENTED, /* DeleteAllMemory */
5696 N6510_GetSpeedDial,
5697 NOTIMPLEMENTED, /* SetSpeedDial */
5698 N6510_GetSMSC,
5699 N6510_SetSMSC,
5700 N6510_GetSMSStatus,
5701 N6510_GetSMSMessage,
5702 N6510_GetNextSMSMessage,
5703 N6510_SetSMS,
5704 N6510_AddSMS,
5705 N6510_DeleteSMSMessage,
5706 N6510_SendSMSMessage,
5707 NOTSUPPORTED, /* SendSavedSMS */
5708 NOKIA_SetIncomingSMS,
5709 NOTIMPLEMENTED, /* SetIncomingCB */
5710 N6510_GetSMSFolders,
5711 N6510_AddSMSFolder,
5712 NOTIMPLEMENTED, /* DeleteSMSFolder */
5713 N6510_DialVoice,
5714 N6510_AnswerCall,
5715 N6510_CancelCall,
5716 NOTIMPLEMENTED, /* HoldCall */
5717 NOTIMPLEMENTED, /* UnholdCall */
5718 NOTIMPLEMENTED, /* ConferenceCall */
5719 NOTIMPLEMENTED, /* SplitCall */
5720 NOTIMPLEMENTED, /* TransferCall */
5721 NOTIMPLEMENTED, /* SwitchCall */
5722 DCT3DCT4_GetCallDivert,
5723 DCT3DCT4_SetCallDivert,
5724 DCT3DCT4_CancelAllDiverts,
5725 NOKIA_SetIncomingCall,
5726 NOKIA_SetIncomingUSSD,
5727 DCT3DCT4_SendDTMF,
5728 N6510_GetRingtone,
5729 N6510_SetRingtone,
5730 N6510_GetRingtonesInfo,
5731 N6510_DeleteUserRingtones,
5732 N6510_PlayTone,
5733 N6510_GetWAPBookmark,
5734 N6510_SetWAPBookmark,
5735 N6510_DeleteWAPBookmark,
5736 N6510_GetWAPSettings,
5737 N6510_SetWAPSettings,
5738 N6510_GetMMSSettings,
5739 N6510_SetMMSSettings,
5740 N6510_GetSyncMLSettings,
5741 NOTSUPPORTED, /* SetSyncMLSettings*/
5742 N6510_GetChatSettings,
5743 NOTSUPPORTED, /* SetChatSettings */
5744 N6510_GetBitmap,
5745 N6510_SetBitmap,
5746 N6510_GetToDoStatus,
5747 NOTIMPLEMENTED, /* GetToDo */
5748 N6510_GetNextToDo,
5749 NOTIMPLEMENTED, /* SetToDo */
5750 N6510_AddToDo,
5751 N6510_DeleteToDo2,
5752 N6510_DeleteAllToDo1,
5753 N6510_GetCalendarStatus,
5754 NOTIMPLEMENTED, /* GetCalendar */
5755 N6510_GetNextCalendar,
5756 NOTIMPLEMENTED, /* SetCalendar */
5757 N6510_AddCalendar,
5758 N71_65_DelCalendar,
5759 NOTIMPLEMENTED, /* DeleteAllCalendar*/
5760 N6510_GetCalendarSettings,
5761 NOTSUPPORTED, /* SetCalendarSettings*/
5762 NOTIMPLEMENTED, /* GetNote */
5763 N6510_GetProfile,
5764 N6510_SetProfile,
5765 N6510_GetFMStation,
5766 N6510_SetFMStation,
5767 N6510_ClearFMStations,
5768 N6510_GetNextFileFolder,
5769 N6510_GetFilePart,
5770 N6510_AddFilePart,
5771 N6510_GetFileSystemStatus,
5772 N6510_DeleteFile,
5773 N6510_AddFolder,
5774 N6510_GetGPRSAccessPoint,
5775 N6510_SetGPRSAccessPoint
5776};
5777
5778#endif
5779
5780/* How should editor hadle tabs in this file? Add editor commands here.
5781 * vim: noexpandtab sw=8 ts=8 sts=8:
5782 */
diff --git a/gammu/emb/common/phone/nokia/dct4/n6510.h b/gammu/emb/common/phone/nokia/dct4/n6510.h
new file mode 100644
index 0000000..4717aeb
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct4/n6510.h
@@ -0,0 +1,90 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef n6510_h
4#define n6510_h
5
6#include "../ncommon.h"
7#include "../../../service/sms/gsmsms.h"
8
9typedef enum {
10 N6510_MMS_SETTINGS = 0x01,
11 N6510_CHAT_SETTINGS,
12
13 N6510_WAP_SETTINGS,
14 N6510_SYNCML_SETTINGS
15} N6510_Connection_Settings;
16
17typedef enum {
18 N6510_LIGHT_DISPLAY = 0x01,
19 N6510_LIGHT_KEYPAD = 0x03,
20 N6510_LIGHT_TORCH = 0x10
21} N6510_PHONE_LIGHTS;
22
23typedef struct {
24 int LastCalendarYear;
25 int LastCalendarPos;
26 GSM_NOKIACalToDoLocationsLastCalendar;
27 int FirstCalendarPos;
28 unsigned char CalendarIcons[10];
29 GSM_CalendarNoteType CalendarIconsTypes[10];
30 int CalendarIconsNum;
31
32 GSM_NOKIASMSFolder LastSMSFolder;
33 GSM_SMSFolders LastSMSFolders;
34
35 GSM_NOKIACalToDoLocationsLastToDo;
36
37 unsigned char RingtoneID;/* When set with preview */
38
39 int FilesLocations[1000];
40 int FilesLevels[1000];
41 int FilesLocationsUsed;
42 int FilesLocationsCurrent;
43 int FileToken;
44 int ParentID;
45 int FileCheckSum;
46
47 unsigned char FMStatus[4000];
48 int FMStatusLength;
49
50 unsigned char GPRSPoints[4000];
51 int GPRSPointsLength;
52
53 int BearerNumber;
54
55 unsigned char PhoneMode;
56} GSM_Phone_N6510Data;
57
58void N6510_EncodeFMFrequency(double freq, unsigned char *buff);
59void N6510_DecodeFMFrequency(double *freq, unsigned char *buff);
60
61#ifndef GSM_USED_MBUS2
62# define GSM_USED_MBUS2
63#endif
64#ifndef GSM_USED_FBUS2
65# define GSM_USED_FBUS2
66#endif
67#ifndef GSM_USED_FBUS2DLR3
68# define GSM_USED_FBUS2DLR3
69#endif
70#ifndef GSM_USED_FBUS2DKU5
71# define GSM_USED_FBUS2DKU5
72#endif
73#ifndef GSM_USED_PHONETBLUE
74# define GSM_USED_PHONETBLUE
75#endif
76#ifndef GSM_USED_IRDAPHONET
77# define GSM_USED_IRDAPHONET
78#endif
79#ifndef GSM_USED_BLUEPHONET
80# define GSM_USED_BLUEPHONET
81#endif
82#ifndef GSM_USED_FBUS2PL2303
83# define GSM_USED_FBUS2PL2303
84#endif
85
86#endif
87
88/* How should editor hadle tabs in this file? Add editor commands here.
89 * vim: noexpandtab sw=8 ts=8 sts=8:
90 */
diff --git a/gammu/emb/common/phone/nokia/nauto.c b/gammu/emb/common/phone/nokia/nauto.c
new file mode 100644
index 0000000..bf74bc9
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/nauto.c
@@ -0,0 +1,144 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <time.h>
5
6#include "../../gsmcomon.h"
7#include "../../gsmstate.h"
8#include "nfunc.h"
9
10#if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
11
12static GSM_Reply_Function NAUTOReplyFunctions[] = {
13 {DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetModel },
14 {DCT3DCT4_ReplyGetModelFirmware,"\xD2",0x02,0x00,ID_GetFirmware },
15
16 {NULL, "\x00",0x00,0x00,ID_None }
17};
18
19GSM_Phone_Functions NAUTOPhone = {
20 "NAUTO",
21 NAUTOReplyFunctions,
22 NONEFUNCTION, /* Initialise */
23 NONEFUNCTION, /* Terminate */
24 GSM_DispatchMessage,
25 NOTSUPPORTED, /* ShowStartInfo */
26 NOKIA_GetManufacturer,
27 DCT3DCT4_GetModel,
28 DCT3DCT4_GetFirmware,
29 NOTSUPPORTED, /* GetIMEI */
30 NOTSUPPORTED, /* GetOriginalIMEI */
31 NOTSUPPORTED, /* GetManufactureMonth*/
32 NOTSUPPORTED, /* GetProductCode */
33 NOTSUPPORTED, /* GetHardware */
34 NOTSUPPORTED, /* GetPPM */
35 NOTSUPPORTED, /* GetSIMIMSI */
36 NOTSUPPORTED, /* GetDateTime */
37 NOTSUPPORTED, /* SetDateTime */
38 NOTSUPPORTED, /* GetAlarm */
39 NOTSUPPORTED, /* SetAlarm */
40 NOTSUPPORTED, /* GetLocale */
41 NOTSUPPORTED, /* SetLocale */
42 NOTSUPPORTED, /* PressKey */
43 NOTSUPPORTED, /* Reset */
44 NOTSUPPORTED, /* ResetPhoneSettings*/
45 NOTSUPPORTED, /* EnterSecurityCode*/
46 NOTSUPPORTED, /* GetSecurityStatus*/
47 NOTSUPPORTED, /* GetDisplayStatus*/
48 NOTSUPPORTED, /* SetAutoNetworkLogin*/
49 NOTSUPPORTED, /* GetBatteryCharge*/
50 NOTSUPPORTED, /* GetSignalQuality*/
51 NOTSUPPORTED, /* GetNetworkInfo */
52 NOTSUPPORTED, /* GetCategory */
53 NOTSUPPORTED, /* AddCategory */
54 NOTSUPPORTED, /* GetCategoryStatus */
55 NOTSUPPORTED, /* GetMemoryStatus */
56 NOTSUPPORTED, /* GetMemory */
57 NOTSUPPORTED, /* GetNextMemory */
58 NOTSUPPORTED, /* SetMemory */
59 NOTSUPPORTED, /* AddMemory */
60 NOTSUPPORTED, /* DeleteMemory */
61 NOTIMPLEMENTED, /* DeleteAllMemory */
62 NOTSUPPORTED, /* GetSpeedDial */
63 NOTSUPPORTED, /* SetSpeedDial */
64 NOTSUPPORTED, /* GetSMSC */
65 NOTSUPPORTED, /* SetSMSC */
66 NOTSUPPORTED, /* GetSMSStatus */
67 NOTSUPPORTED, /* GetSMS */
68 NOTSUPPORTED, /* GetNextSMS */
69 NOTSUPPORTED, /* SetSMS */
70 NOTSUPPORTED, /* AddSMS */
71 NOTSUPPORTED, /* DeleteSMS */
72 NOTSUPPORTED, /* SendSMSMessage */
73 NOTSUPPORTED, /* SendSavedSMS */
74 NOTSUPPORTED, /* SetIncomingSMS */
75 NOTSUPPORTED, /* SetIncomingCB */
76 NOTSUPPORTED, /* GetSMSFolders */
77 NOTSUPPORTED, /* AddSMSFolder */
78 NOTSUPPORTED, /* DeleteSMSFolder */
79 NOTSUPPORTED, /* DialVoice */
80 NOTSUPPORTED, /* AnswerCall */
81 NOTSUPPORTED, /* CancelCall */
82 NOTSUPPORTED, /* HoldCall */
83 NOTSUPPORTED, /* UnholdCall */
84 NOTSUPPORTED, /* ConferenceCall */
85 NOTSUPPORTED, /* SplitCall */
86 NOTSUPPORTED, /* TransferCall */
87 NOTSUPPORTED, /* SwitchCall */
88 NOTSUPPORTED, /* GetCallDivert */
89 NOTSUPPORTED, /* SetCallDivert */
90 NOTSUPPORTED, /* CancelAllDiverts*/
91 NOTSUPPORTED, /* SetIncomingCall */
92 NOTSUPPORTED, /* SetIncomingUSSD */
93 NOTSUPPORTED, /* SendDTMF */
94 NOTSUPPORTED, /* GetRingtone */
95 NOTSUPPORTED, /* SetRingtone */
96 NOTSUPPORTED, /* GetRingtonesInfo*/
97 NOTSUPPORTED, /* DeleteUserRingtones*/
98 NOTSUPPORTED, /* PlayTone */
99 NOTSUPPORTED, /* GetWAPBookmark */
100 NOTSUPPORTED, /* SetWAPBookmark */
101 NOTSUPPORTED, /* DeleteWAPBookmark */
102 NOTSUPPORTED, /* GetWAPSettings */
103 NOTSUPPORTED, /* SetWAPSettings */
104 NOTSUPPORTED, /* GetMMSSettings */
105 NOTSUPPORTED, /* SetMMSSettings */
106 NOTSUPPORTED, /* GetBitmap */
107 NOTSUPPORTED, /* SetBitmap */
108 NOTSUPPORTED, /* GetToDoStatus */
109 NOTSUPPORTED, /* GetToDo */
110 NOTSUPPORTED, /* GetNextToDo */
111 NOTSUPPORTED, /* SetToDo */
112 NOTSUPPORTED, /* AddToDo */
113 NOTSUPPORTED, /* DeleteToDo */
114 NOTSUPPORTED, /* DeleteAllToDo */
115 NOTSUPPORTED, /* GetCalendarStatus*/
116 NOTSUPPORTED, /* GetCalendar */
117 NOTSUPPORTED, /* GetNextCalendar */
118 NOTSUPPORTED, /* SetCalendar */
119 NOTSUPPORTED, /* AddCalendar */
120 NOTSUPPORTED, /* DeleteCalendar */
121 NOTSUPPORTED, /* DeleteAllCalendar*/
122 NOTSUPPORTED, /* GetCalendarSettings*/
123 NOTSUPPORTED, /* SetCalendarSettings*/
124 NOTSUPPORTED, /* GetNote */
125 NOTSUPPORTED, /* GetProfile */
126 NOTSUPPORTED, /* SetProfile */
127 NOTSUPPORTED, /* GetFMStation */
128 NOTSUPPORTED, /* SetFMStation */
129 NOTSUPPORTED, /* ClearFMStations */
130 NOTSUPPORTED, /* GetNextFileFolder*/
131 NOTSUPPORTED, /* GetFilePart */
132 NOTSUPPORTED, /* AddFilePart */
133 NOTSUPPORTED, /* GetFileSystemStatus*/
134 NOTSUPPORTED, /* DeleteFile */
135 NOTSUPPORTED, /* AddFolder */
136 NOTSUPPORTED, /* GetGPRSAccessPoint*/
137 NOTSUPPORTED /* SetGPRSAccessPoint*/
138};
139
140#endif
141
142/* How should editor hadle tabs in this file? Add editor commands here.
143 * vim: noexpandtab sw=8 ts=8 sts=8:
144 */
diff --git a/gammu/emb/common/phone/nokia/ncommon.h b/gammu/emb/common/phone/nokia/ncommon.h
new file mode 100644
index 0000000..b8a36aa
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/ncommon.h
@@ -0,0 +1,66 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#ifndef phone_nokia_common_h
4#define phone_nokia_common_h
5
6#include "../../gsmcomon.h"
7
8#define N6110_FRAME_HEADER 0x00, 0x01, 0x00
9#define N7110_FRAME_HEADER 0x00, 0x01, 0x01
10
11typedef enum {
12 MEM7110_CG = 0xf0, /* Caller groups memory */
13 MEM7110_SP = 0xf1 /* Speed dial memory */
14} GSM_71_65MemoryType;
15
16typedef enum {
17 /* DCT3 and DCT4 */
18 N7110_PBK_SIM_SPEEDDIAL = 0x04, /* Speed dial on SIM */
19 N7110_PBK_NAME = 0x07, /* Text: name (always the only one) */
20 N7110_PBK_EMAIL = 0x08, /* Text: email adress */
21 N7110_PBK_POSTAL = 0x09, /* Text: postal address */
22 N7110_PBK_NOTE = 0x0A, /* Text: note */
23 N7110_PBK_NUMBER = 0x0B, /* Phone number */
24 N7110_PBK_RINGTONE_ID = 0x0C, /* Ringtone ID */
25 N7110_PBK_DATETIME = 0x13, /* Call register: date and time*/
26 N7110_PBK_UNKNOWN1 = 0x19, /* Call register: with missed calls*/
27 N7110_PBK_SPEEDDIAL = 0x1A, /* Speed dial */
28 N7110_PBK_GROUPLOGO = 0x1B, /* Caller group: logo */
29 N7110_PBK_LOGOON = 0x1C, /* Caller group: is logo on ? */
30 N7110_PBK_GROUP = 0x1E, /* Caller group number in pbk entry*/
31
32 /* DCT4 only */
33 N6510_PBK_URL = 0x2C, /* Text: URL address */
34 N6510_PBK_SMSLIST_ID = 0x2E, /* SMS list assigment */
35 N6510_PBK_VOICETAG_ID = 0x2F, /* Voice tag assigment */
36 N6510_PBK_PICTURE_ID = 0x33, /* Picture ID assigment */
37 N6510_PBK_RINGTONEFILE_ID= 0x37, /* Ringtone ID from filesystem/internal*/
38 N6510_PBK_USER_ID = 0x38 /* Text: user ID */
39} GSM_71_65_Phonebook_Entries_Types;
40
41typedef enum {
42 N7110_PBK_NUMBER_HOME = 0x02,
43 N7110_PBK_NUMBER_MOBILE = 0x03,
44 N7110_PBK_NUMBER_FAX = 0x04,
45 N7110_PBK_NUMBER_WORK = 0x06,
46 N7110_PBK_NUMBER_GENERAL = 0x0A
47} GSM_71_65_Phonebook_Number_Types;
48
49typedef struct {
50 unsigned charLocation[PHONE_MAXSMSINFOLDER]; /* locations of SMS messages in that folder */
51 int Number; /* number of SMS messages in that folder */
52} GSM_NOKIASMSFolder;
53
54typedef struct {
55 int Location[GSM_MAXCALENDARTODONOTES];
56 int Number;
57} GSM_NOKIACalToDoLocations;
58
59#define NOKIA_PRESSPHONEKEY 0x01
60#define NOKIA_RELEASEPHONEKEY 0x02
61
62#endif
63
64/* How should editor hadle tabs in this file? Add editor commands here.
65 * vim: noexpandtab sw=8 ts=8 sts=8:
66 */
diff --git a/gammu/emb/common/phone/nokia/nfunc.c b/gammu/emb/common/phone/nokia/nfunc.c
new file mode 100644
index 0000000..3acfb10
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/nfunc.c
@@ -0,0 +1,2143 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* based on some work from Ralf Thelen, Gabriele Zappi and MyGnokii */
3
4#include <string.h> /* memcpy only */
5#include <stdio.h>
6#include <ctype.h>
7#include <time.h>
8
9#include "../../gsmstate.h"
10#include "../../misc/coding/coding.h"
11#include "../../service/sms/gsmsms.h"
12#include "../pfunc.h"
13#include "nfunc.h"
14
15unsigned char N71_65_MEMORY_TYPES[] = {
16 MEM_DC, 0x01,
17 MEM_MC, 0x02,
18 MEM_RC, 0x03,
19 MEM_ME, 0x05,
20 MEM_SM, 0x06,
21 MEM_VM, 0x09,
22 MEM7110_SP,0x0e,
23 MEM7110_CG,0x10,
24 MEM_ON, 0x17,
25 0x00, 0x00
26};
27
28int N71_65_PackPBKBlock(GSM_StateMachine *s, int id, int size, int no, unsigned char *buf, unsigned char *block)
29{
30 smprintf(s, "Packing phonebook block with ID = %i, block number = %i, block length = %i\n",id,no+1,size+6);
31
32 block[0] = id;
33 block[1] = 0;
34 block[2] = 0;
35 block[3] = size + 6;
36 block[4] = no + 1;
37 memcpy(block+5, buf, size);
38 block[5+size] = 0;
39
40 return (size + 6);
41}
42
43int N71_65_EncodePhonebookFrame(GSM_StateMachine *s, unsigned char *req, GSM_MemoryEntry entry, int *block2, bool DCT4, bool VoiceTag)
44{
45 int count=0, len, i, block=0, j;
46 char string[500];
47 unsigned chartype;
48
49 for (i = 0; i < entry.EntriesNum; i++) {
50 type = 0;
51 if (entry.Entries[i].EntryType == PBK_Number_General) type = N7110_PBK_NUMBER_GENERAL;
52 if (entry.Entries[i].EntryType == PBK_Number_Mobile) type = N7110_PBK_NUMBER_MOBILE;
53 if (entry.Entries[i].EntryType == PBK_Number_Work) type = N7110_PBK_NUMBER_WORK;
54 if (entry.Entries[i].EntryType == PBK_Number_Fax) type = N7110_PBK_NUMBER_FAX;
55 if (entry.Entries[i].EntryType == PBK_Number_Home) type = N7110_PBK_NUMBER_HOME;
56 if (type != 0) {
57 string[0] = type;
58 len = UnicodeLength(entry.Entries[i].Text);
59
60 string[1] = 0;
61 string[2] = 0;
62
63 /* DCT 3 */
64 if (!DCT4) string[2] = entry.Entries[i].VoiceTag;
65
66 string[3] = 0;
67 string[4] = len*2+2;
68 CopyUnicodeString(string+5,entry.Entries[i].Text);
69 string[len * 2 + 5] = 0;
70 count += N71_65_PackPBKBlock(s, N7110_PBK_NUMBER, len*2+6, block++, string, req+count);
71
72 /* DCT 4 */
73 if (DCT4 && VoiceTag) {
74 block++;
75 req[count++] = N6510_PBK_VOICETAG_ID;
76 req[count++] = 0;
77 req[count++] = 0;
78 req[count++] = 8;
79 req[count++] = 0x00;
80 req[count++] = i+1;
81 req[count++] = 0x00;
82 req[count++] = entry.Entries[i].VoiceTag;
83 }
84 if (DCT4) {
85 j = 0;
86 while (entry.Entries[i].SMSList[j] != 0) {
87 string[0] = i+1;
88 string[1] = 0x00;
89 string[2] = 0x02;
90 string[3] = 0x00;
91 string[4] = entry.Entries[i].SMSList[j];
92 string[5] = 0x00;
93 count += N71_65_PackPBKBlock(s, N6510_PBK_SMSLIST_ID, 6, block++, string, req+count);
94
95 j++;
96 }
97 }
98 continue;
99 }
100 if (entry.Entries[i].EntryType == PBK_Text_Note) type = N7110_PBK_NOTE;
101 if (entry.Entries[i].EntryType == PBK_Text_Postal) type = N7110_PBK_POSTAL;
102 if (entry.Entries[i].EntryType == PBK_Text_Email) type = N7110_PBK_EMAIL;
103 if (entry.Entries[i].EntryType == PBK_Text_Email2) type = N7110_PBK_EMAIL;
104 if (entry.Entries[i].EntryType == PBK_Text_Name) type = N7110_PBK_NAME;
105 if (entry.Entries[i].EntryType == PBK_Text_URL) {
106 type = N7110_PBK_NOTE;
107 if (DCT4) type = N6510_PBK_URL;
108 }
109 if (type != 0) {
110 len = UnicodeLength(entry.Entries[i].Text);
111 string[0] = len*2+2;
112 CopyUnicodeString(string+1,entry.Entries[i].Text);
113 string[len*2+1] = 0;
114 count += N71_65_PackPBKBlock(s, type, len * 2 + 2, block++, string, req + count);
115 continue;
116
117 }
118 if (entry.Entries[i].EntryType == PBK_Caller_Group) {
119 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBK35)) {
120 string[0] = entry.Entries[i].Number;
121 string[1] = 0;
122 count += N71_65_PackPBKBlock(s, N7110_PBK_GROUP, 2, block++, string, req + count);
123 }
124 continue;
125 }
126 if (entry.Entries[i].EntryType == PBK_RingtoneID) {
127 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBK35)) {
128 string[0] = 0x00;
129 string[1] = 0x00;
130 string[2] = entry.Entries[i].Number;
131 count += N71_65_PackPBKBlock(s, N7110_PBK_RINGTONE_ID, 3, block++, string, req + count);
132 count --;
133 req[count-5] = 8;
134 }
135 continue;
136 }
137 if (entry.Entries[i].EntryType == PBK_PictureID) {
138 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBKIMG)) {
139 string[0] = 0x00;
140 string[1] = 0x00;
141 string[2] = 0x00;
142 string[3] = 0x00;
143 string[4] = 0x01;
144 string[5] = entry.Entries[i].Number / 256;
145 string[6] = entry.Entries[i].Number % 256;
146 string[7] = 0x00;
147 string[8] = 0x00;
148 string[9] = 0x00;
149 count += N71_65_PackPBKBlock(s, N6510_PBK_PICTURE_ID, 10, block++, string, req + count);
150 req[count-1] = 0x01;
151 }
152 continue;
153 }
154 if (entry.Entries[i].EntryType == PBK_Text_UserID) {
155 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PBKUSER)) {
156 string[0] = UnicodeLength(entry.Entries[i].Text)*2;
157 CopyUnicodeString(string+1,entry.Entries[i].Text);
158 count += N71_65_PackPBKBlock(s, N6510_PBK_USER_ID, string[0]+2, block++, string, req+count);
159 req[count-1]--;
160 }
161 continue;
162 }
163 }
164
165 *block2=block;
166
167 return count;
168}
169
170 GSM_Error N71_65_DecodePhonebook(GSM_StateMachine*s,
171 GSM_MemoryEntry *entry,
172 GSM_Bitmap *bitmap,
173 GSM_SpeedDial *speed,
174 unsigned char *MessageBuffer,
175 int MessageLength,
176 bool DayMonthReverse)
177{
178 unsigned char *Block;
179 int length = 0, i;
180 GSM_71_65_Phonebook_Entries_TypesType;
181
182 entry->EntriesNum = 0;
183
184 if (entry->MemoryType==MEM7110_CG) {
185 bitmap->Text[0] = 0x00;
186 bitmap->Text[1] = 0x00;
187 bitmap->DefaultBitmap = true;
188 bitmap->DefaultRingtone = true;
189 }
190
191 Block = &MessageBuffer[0];
192 while (length != MessageLength) {
193#ifdef DEBUG
194 smprintf(s, "Phonebook entry block - length %i", Block[3]-6);
195 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, Block+5, Block[3]-6);
196#endif
197 if (entry->EntriesNum==GSM_PHONEBOOK_ENTRIES) {
198 smprintf(s, "Too many entries\n");
199 return ERR_UNKNOWNRESPONSE;
200 }
201
202 Type = 0;
203 if (Block[0] == N7110_PBK_NAME) {
204 Type = PBK_Text_Name; smprintf(s,"Name ");
205 }
206 if (Block[0] == N7110_PBK_EMAIL) {
207 Type = PBK_Text_Email; smprintf(s,"Email ");
208 }
209 if (Block[0] == N7110_PBK_POSTAL) {
210 Type = PBK_Text_Postal; smprintf(s,"Postal ");
211 }
212 if (Block[0] == N7110_PBK_NOTE) {
213 Type = PBK_Text_Note; smprintf(s,"Text note ");
214 }
215 if (Block[0] == N6510_PBK_URL) {
216 Type = PBK_Text_URL; smprintf(s,"URL ");
217 }
218 if (Type != 0) {
219 if (Block[5]/2>GSM_PHONEBOOK_TEXT_LENGTH) {
220 smprintf(s, "Too long text\n");
221 return ERR_UNKNOWNRESPONSE;
222 }
223 memcpy(entry->Entries[entry->EntriesNum].Text,Block+6,Block[5]);
224 entry->Entries[entry->EntriesNum].EntryType=Type;
225 smprintf(s, " \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
226 if (Block[0] == N7110_PBK_NAME) {
227 if (entry->MemoryType==MEM7110_CG) {
228 memcpy(bitmap->Text,Block+6,Block[5]);
229 }
230 }
231 entry->EntriesNum ++;
232
233 length = length + Block[3];
234 Block = &Block[(int) Block[3]];
235 continue;
236 }
237
238 if (Block[0] == N7110_PBK_DATETIME) {
239 entry->Entries[entry->EntriesNum].EntryType=PBK_Date;
240 NOKIA_DecodeDateTime(s, Block+6, &entry->Entries[entry->EntriesNum].Date);
241 if (DayMonthReverse) {
242 i = entry->Entries[entry->EntriesNum].Date.Month;
243 entry->Entries[entry->EntriesNum].Date.Month = entry->Entries[entry->EntriesNum].Date.Day;
244 entry->Entries[entry->EntriesNum].Date.Day = i;
245 }
246 entry->EntriesNum ++;
247
248 length = length + Block[3];
249 Block = &Block[(int) Block[3]];
250 continue;
251 }
252 if (Block[0] == N6510_PBK_PICTURE_ID) {
253 entry->Entries[entry->EntriesNum].EntryType=PBK_PictureID;
254 smprintf(s, "Picture ID \"%i\"\n",Block[10]*256+Block[11]);
255 entry->Entries[entry->EntriesNum].Number=Block[10]*256+Block[11];
256 entry->EntriesNum ++;
257
258 length = length + Block[3];
259 Block = &Block[(int) Block[3]];
260 continue;
261 }
262
263 if (Block[0] == N7110_PBK_NUMBER) {
264 if (Block[5] == 0x00) {
265 Type = PBK_Number_General; smprintf(s,"General number ");
266 }
267 /* Not assigned dialed number */
268 if (Block[5] == 0x01) {
269 Type = PBK_Number_General; smprintf(s,"General number ");
270 }
271 if (Block[5] == 0x0B) {
272 Type = PBK_Number_General; smprintf(s,"General number ");
273 }
274 /* In many firmwares 0x55 visible after using
275 * Save from Call Register menu and saving number
276 * to existing phonebook entry */
277 if (Block[5] == 0x55) {
278 Type = PBK_Number_General; smprintf(s,"General number ");
279 }
280 if (Block[5] == N7110_PBK_NUMBER_GENERAL) {
281 Type = PBK_Number_General; smprintf(s,"General number ");
282 }
283 if (Block[5] == N7110_PBK_NUMBER_WORK) {
284 Type = PBK_Number_Work; smprintf(s,"Work number ");
285 }
286 if (Block[5] == N7110_PBK_NUMBER_FAX) {
287 Type = PBK_Number_Fax; smprintf(s,"Fax number ");
288 }
289 if (Block[5] == N7110_PBK_NUMBER_MOBILE) {
290 Type = PBK_Number_Mobile; smprintf(s,"Mobile number ");
291 }
292 if (Block[5] == N7110_PBK_NUMBER_HOME) {
293 Type = PBK_Number_Home; smprintf(s,"Home number ");
294 }
295 if (Type == 0x00) {
296 smprintf(s, "Unknown number type %02x\n",Block[5]);
297 return ERR_UNKNOWNRESPONSE;
298 }
299 entry->Entries[entry->EntriesNum].EntryType=Type;
300 if (Block[9]/2>GSM_PHONEBOOK_TEXT_LENGTH) {
301 smprintf(s, "Too long text\n");
302 return ERR_UNKNOWNRESPONSE;
303 }
304 memcpy(entry->Entries[entry->EntriesNum].Text,Block+10,Block[9]);
305 smprintf(s, " \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
306 /* DCT3 phones like 6210 */
307 entry->Entries[entry->EntriesNum].VoiceTag = Block[7];
308#ifdef DEBUG
309 if (entry->Entries[entry->EntriesNum].VoiceTag != 0) smprintf(s, "Voice tag %i assigned\n",Block[7]);
310#endif
311 entry->Entries[entry->EntriesNum].SMSList[0] = 0;
312 entry->EntriesNum ++;
313
314 length = length + Block[3];
315 Block = &Block[(int) Block[3]];
316 continue;
317 }
318 if (Block[0] == N7110_PBK_RINGTONE_ID) {
319 if (entry->MemoryType==MEM7110_CG) {
320 bitmap->RingtoneID=Block[5];
321 if (Block[5] == 0x00) bitmap->RingtoneID=Block[7];
322 smprintf(s, "Ringtone ID : %i\n",bitmap->RingtoneID);
323 bitmap->DefaultRingtone = false;
324 bitmap->FileSystemRingtone = false;
325 } else {
326 entry->Entries[entry->EntriesNum].EntryType=PBK_RingtoneID;
327 smprintf(s, "Ringtone ID \"%i\"\n",Block[7]);
328 entry->Entries[entry->EntriesNum].Number=Block[7];
329 entry->EntriesNum ++;
330 }
331
332 length = length + Block[3];
333 Block = &Block[(int) Block[3]];
334 continue;
335 }
336 if (Block[0] == N7110_PBK_LOGOON) {
337 if (entry->MemoryType==MEM7110_CG) {
338 bitmap->BitmapEnabled=(Block[5]==0x00 ? false : true);
339 smprintf(s, "Logo : %s\n", bitmap->BitmapEnabled==true ? "enabled":"disabled");
340 } else {
341 return ERR_UNKNOWNRESPONSE;
342 }
343
344 length = length + Block[3];
345 Block = &Block[(int) Block[3]];
346 continue;
347 }
348 if (Block[0] == N7110_PBK_GROUPLOGO) {
349 if (entry->MemoryType==MEM7110_CG) {
350 smprintf(s, "Caller logo\n");
351 PHONE_DecodeBitmap(GSM_NokiaCallerLogo, Block+10, bitmap);
352 bitmap->DefaultBitmap = false;
353 } else {
354 return ERR_UNKNOWNRESPONSE;
355 }
356
357 length = length + Block[3];
358 Block = &Block[(int) Block[3]];
359 continue;
360 }
361 if (Block[0] == N7110_PBK_GROUP) {
362 entry->Entries[entry->EntriesNum].EntryType=PBK_Caller_Group;
363 smprintf(s, "Caller group \"%i\"\n",Block[5]);
364 entry->Entries[entry->EntriesNum].Number=Block[5];
365 if (Block[5]!=0) entry->EntriesNum ++;
366
367 length = length + Block[3];
368 Block = &Block[(int) Block[3]];
369 continue;
370 }
371 if (Block[0] == N6510_PBK_VOICETAG_ID) {
372 smprintf(s, "Entry %i has voice tag %i\n",Block[5]-1,Block[7]);
373 entry->Entries[Block[5]-1].VoiceTag = Block[7];
374
375 length = length + Block[3];
376 Block = &Block[(int) Block[3]];
377 continue;
378 }
379
380 /* 6210 5.56, SIM speed dials or ME with 1 number */
381 if (Block[0] == N7110_PBK_SIM_SPEEDDIAL) {
382 if (entry->MemoryType==MEM7110_SP) {
383#ifdef DEBUG
384 smprintf(s, "location %i\n",(Block[6]*256+Block[7]));
385 #endif
386 speed->MemoryType = MEM_ME;
387 if (Block[8] == 0x06) speed->MemoryType = MEM_SM;
388 speed->MemoryLocation = (Block[6]*256+Block[7]);
389 speed->MemoryNumberID = 2;
390 } else {
391 return ERR_UNKNOWNRESPONSE;
392 }
393
394 length = length + Block[3];
395 Block = &Block[(int) Block[3]];
396 continue;
397 }
398
399 if (Block[0] == N7110_PBK_SPEEDDIAL) {
400 if (entry->MemoryType==MEM7110_SP) {
401#ifdef DEBUG
402 switch (Block[12]) {
403 case 0x05: smprintf(s, "ME\n"); break;
404 case 0x06: smprintf(s, "SM\n"); break;
405 default : smprintf(s, "%02x\n",Block[12]);
406 }
407 smprintf(s, "location %i, number %i in location\n",
408 (Block[6]*256+Block[7])-1,Block[14]);
409 #endif
410 switch (Block[12]) {
411 case 0x05: speed->MemoryType = MEM_ME; break;
412 case 0x06: speed->MemoryType = MEM_SM; break;
413 }
414 speed->MemoryLocation = (Block[6]*256+Block[7])-1;
415 speed->MemoryNumberID = Block[14];
416 } else {
417 return ERR_UNKNOWNRESPONSE;
418 }
419
420 length = length + Block[3];
421 Block = &Block[(int) Block[3]];
422 continue;
423 }
424 if (Block[0] == N6510_PBK_RINGTONEFILE_ID) {
425 smprintf(s, "Ringtone ID with possibility of using filesystem\n");
426 if (entry->MemoryType==MEM7110_CG) {
427 if (Block[9] == 0x01) {
428 smprintf(s, "Filesystem ringtone ID: %02x\n",Block[10]*256+Block[11]);
429 bitmap->FileSystemRingtone = true;
430 } else {
431 smprintf(s, "Internal ringtone ID: %02x\n",Block[10]*256+Block[11]);
432 bitmap->FileSystemRingtone = false;
433 }
434 bitmap->RingtoneID= Block[10]*256+Block[11];
435 bitmap->DefaultRingtone = false;
436 } else {
437 return ERR_UNKNOWNRESPONSE;
438 }
439
440 length = length + Block[3];
441 Block = &Block[(int) Block[3]];
442 continue;
443 }
444 if (Block[0] == N6510_PBK_SMSLIST_ID) {
445 smprintf(s, "Entry %i is assigned to SMS list %i\n",Block[5]-1,Block[9]);
446 i = 0;
447 while(entry->Entries[Block[5]-1].SMSList[i] != 0) i++;
448 entry->Entries[Block[5]-1].SMSList[i+1] = 0;
449 entry->Entries[Block[5]-1].SMSList[i] = Block[9];
450
451 length = length + Block[3];
452 Block = &Block[(int) Block[3]];
453 continue;
454 }
455 if (Block[0] == N6510_PBK_USER_ID) {
456 smprintf(s, "User ID:");
457 entry->Entries[entry->EntriesNum].EntryType=PBK_Text_UserID;
458 if (Block[5]/2>GSM_PHONEBOOK_TEXT_LENGTH) {
459 smprintf(s, "Too long text\n");
460 return ERR_UNKNOWNRESPONSE;
461 }
462 memcpy(entry->Entries[entry->EntriesNum].Text,Block+6,Block[5]);
463 smprintf(s, " \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
464 entry->EntriesNum ++;
465
466 length = length + Block[3];
467 Block = &Block[(int) Block[3]];
468 continue;
469 }
470 if (Block[0] == N7110_PBK_UNKNOWN1) {
471 smprintf(s,"Unknown entry\n");
472
473 length = length + Block[3];
474 Block = &Block[(int) Block[3]];
475 continue;
476 }
477
478 smprintf(s, "ERROR: unknown pbk entry 0x%02x\n",Block[0]);
479 return ERR_UNKNOWNRESPONSE;
480 }
481
482 if (entry->EntriesNum == 0) return ERR_EMPTY;
483
484 return ERR_NONE;
485}
486
487void NOKIA_GetDefaultCallerGroupName(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
488{
489 Bitmap->DefaultName = false;
490 if (Bitmap->Text[0]==0x00 && Bitmap->Text[1]==0x00) {
491 Bitmap->DefaultName = true;
492 switch(Bitmap->Location) {
493 case 1: EncodeUnicode(Bitmap->Text,GetMsg(s->msg,"Family"),strlen(GetMsg(s->msg,"Family")));
494 break;
495 case 2: EncodeUnicode(Bitmap->Text,GetMsg(s->msg,"VIP"),strlen(GetMsg(s->msg,"VIP")));
496 break;
497 case 3: EncodeUnicode(Bitmap->Text,GetMsg(s->msg,"Friends"),strlen(GetMsg(s->msg,"Friends")));
498 break;
499 case 4: EncodeUnicode(Bitmap->Text,GetMsg(s->msg,"Colleagues"),strlen(GetMsg(s->msg,"Colleagues")));
500 break;
501 case 5: EncodeUnicode(Bitmap->Text,GetMsg(s->msg,"Other"),strlen(GetMsg(s->msg,"Other")));
502 break;
503 }
504 }
505}
506
507void NOKIA_DecodeDateTime(GSM_StateMachine *s, unsigned char* buffer, GSM_DateTime *datetime)
508{
509 datetime->Year= buffer[0] * 256 + buffer[1];
510 datetime->Month= buffer[2];
511 datetime->Day= buffer[3];
512
513 datetime->Hour = buffer[4];
514 datetime->Minute = buffer[5];
515 datetime->Second = buffer[6];
516
517 smprintf(s, "Decoding date and time\n");
518 smprintf(s, " Time: %02d:%02d:%02d\n",
519 datetime->Hour, datetime->Minute, datetime->Second);
520 smprintf(s, " Date: %4d/%02d/%02d\n",
521 datetime->Year, datetime->Month, datetime->Day);
522}
523
524#if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
525
526/* --------------------- Some general Nokia functions ---------------------- */
527
528void NOKIA_DecodeSMSState(GSM_StateMachine *s, unsigned char state, GSM_SMSMessage *sms)
529{
530 switch (state) {
531 case 0x01 : sms->State = SMS_Read; break;
532 case 0x03 : sms->State = SMS_UnRead; break;
533 case 0x05 : sms->State = SMS_Sent; break;
534 case 0x07 : sms->State = SMS_UnSent; break;
535 default : smprintf(s, "Unknown SMS state: %02x\n",state);
536 }
537}
538
539GSM_Error NOKIA_ReplyGetPhoneString(GSM_Protocol_Message msg, GSM_StateMachine *s)
540{
541 strcpy(s->Phone.Data.PhoneString, msg.Buffer+s->Phone.Data.StartPhoneString);
542 return ERR_NONE;
543}
544
545/* Some strings are very easy. Some header, after it required string and 0x00.
546 * We can get them using this function. We give frame to send (*string),
547 * type of message (type), pointer for buffer for response (*value), request
548 * type (request) and what is start byte in response for our string
549 */
550GSM_Error NOKIA_GetPhoneString(GSM_StateMachine *s, unsigned char *msgframe, int msglen, unsigned char msgtype, char *retvalue, GSM_Phone_RequestID request, int startresponse)
551{
552 retvalue[0] = 0;
553 s->Phone.Data.StartPhoneString = startresponse;
554 s->Phone.Data.PhoneString = retvalue;
555 return GSM_WaitFor (s, msgframe, msglen,msgtype, 4, request);
556}
557
558GSM_Error NOKIA_GetManufacturer(GSM_StateMachine *s)
559{
560 strcpy(s->Phone.Data.Manufacturer,"Nokia");
561 return ERR_NONE;
562}
563
564/* Many functions contains such strings:
565 * (1. length/256) - exist or not
566 * 2. length%256
567 * 3. string (unicode, no termination)
568 * This function read string to output and increases counter
569 */
570void NOKIA_GetUnicodeString(GSM_StateMachine *s, int *current, unsigned char *input, unsigned char *output, bool FullLength)
571{
572 int length;
573
574 if (FullLength) {
575 length = (input[*current]*256+input[*current+1])*2;
576 memcpy(output,input+(*current+2),length);
577 *current = *current + 2 + length;
578 } else {
579 length = (input[*current])*2;
580 memcpy(output,input+(*current+1),length);
581 *current = *current + 1 + length;
582 }
583
584 output[length ] = 0;
585 output[length+1] = 0;
586}
587
588int NOKIA_SetUnicodeString(GSM_StateMachine *s, unsigned char *dest, unsigned char *string, bool FullLength)
589{
590 int length;
591
592 length = UnicodeLength(string);
593 if (FullLength) {
594 dest[0] = length / 256;
595 dest[1] = length % 256;
596 CopyUnicodeString(dest + 2, string);
597 return 2+length*2;
598 } else {
599 dest[0] = length % 256;
600 CopyUnicodeString(dest + 1, string);
601 return 1+length*2;
602 }
603}
604
605/* Returns correct ID for concrete memory type */
606GSM_MemoryType NOKIA_GetMemoryType(GSM_StateMachine *s, GSM_MemoryType memory_type, unsigned char *ID)
607{
608 int i=0;
609
610 while (ID[i+1]!=0x00) {
611 if (ID[i]==memory_type) return ID[i+1];
612 i=i+2;
613 }
614 return 0xff;
615}
616
617void NOKIA_EncodeDateTime(GSM_StateMachine *s, unsigned char* buffer, GSM_DateTime *datetime)
618{
619 buffer[0] = datetime->Year / 256;
620 buffer[1] = datetime->Year % 256;
621 buffer[2] = datetime->Month;
622 buffer[3] = datetime->Day;
623
624 buffer[4] = datetime->Hour;
625 buffer[5] = datetime->Minute;
626}
627
628void NOKIA_SortSMSFolderStatus(GSM_StateMachine *s, GSM_NOKIASMSFolder *Folder)
629{
630 int i,j;
631
632 if (Folder->Number!=0) {
633 /* Bouble sorting */
634 i=0;
635 while (i!=Folder->Number-1) {
636 if (Folder->Location[i]>Folder->Location[i+1]) {
637 j=Folder->Location[i];
638 Folder->Location[i]=Folder->Location[i+1];
639 Folder->Location[i+1]=j;
640 i=0;
641 } else {
642 i++;
643 }
644 }
645#ifdef DEBUG
646 smprintf(s, "Locations: ");
647 for (i=0;i<Folder->Number;i++) {
648 smprintf(s, "%i ",Folder->Location[i]);
649 }
650 smprintf(s, "\n");
651#endif
652 }
653}
654
655void NOKIA_GetDefaultProfileName(GSM_StateMachine *s, GSM_Profile *Profile)
656{
657 if (Profile->DefaultName) {
658 switch(Profile->Location) {
659 case 1:EncodeUnicode(Profile->Name,GetMsg(s->msg,"General"),strlen(GetMsg(s->msg,"General")));
660 break;
661 case 2: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Silent"),strlen(GetMsg(s->msg,"Silent")));
662 break;
663 case 3: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Meeting"),strlen(GetMsg(s->msg,"Meeting")));
664 break;
665 case 4:EncodeUnicode(Profile->Name,GetMsg(s->msg,"Outdoor"),strlen(GetMsg(s->msg,"Outdoor")));
666 break;
667 case 5:EncodeUnicode(Profile->Name,GetMsg(s->msg,"Pager"),strlen(GetMsg(s->msg,"Pager")));
668 break;
669 case 6: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Car"),strlen(GetMsg(s->msg,"Car")));
670 break;
671 case 7: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Headset"),strlen(GetMsg(s->msg,"Headset")));
672 break;
673 }
674 }
675}
676
677/* - Shared for DCT3 (n6110.c, n7110.c, n9110.c) and DCT4 (n6510.c) phones - */
678
679GSM_Error DCT3DCT4_ReplyCallDivert(GSM_Protocol_Message msg, GSM_StateMachine *s)
680{
681 GSM_MultiCallDivert *cd = s->Phone.Data.Divert;
682 int i,pos = 11,j;
683
684 switch (msg.Buffer[3]) {
685 case 0x02:
686 smprintf(s,"Message: Call divert status received\n");
687 smprintf(s," Divert type: ");
688 switch (msg.Buffer[6]) {
689 case 0x43: smprintf(s,"when busy"); break;
690 case 0x3d: smprintf(s,"when not answered"); break;
691 case 0x3e: smprintf(s,"when phone off or no coverage");break;
692 case 0x15: smprintf(s,"all types of diverts"); break;
693 default: smprintf(s,"unknown %i",msg.Buffer[6]);break;
694 }
695 /* 6150 */
696 if (msg.Length == 0x0b) {
697 cd->Response.EntriesNum = 0;
698 return ERR_NONE;
699 }
700 cd->Response.EntriesNum = msg.Buffer[10];
701 for (i=0;i<cd->Response.EntriesNum;i++) {
702 smprintf(s,"\n Calls type : ");
703 switch (msg.Buffer[pos]) {
704 case 0x0b:
705 smprintf(s,"voice");
706 cd->Response.Entries[i].CallType = GSM_DIVERT_VoiceCalls;
707 break;
708 case 0x0d:
709 smprintf(s,"fax");
710 cd->Response.Entries[i].CallType = GSM_DIVERT_FaxCalls;
711 break;
712 case 0x19:
713 smprintf(s,"data");
714 cd->Response.Entries[i].CallType = GSM_DIVERT_DataCalls;
715 break;
716 default:
717 smprintf(s,"unknown %i",msg.Buffer[pos]);
718 /* 6310i */
719 cd->Response.EntriesNum = 0;
720 return ERR_NONE;
721 break;
722 }
723 smprintf(s,"\n");
724 j = pos + 2;
725 while (msg.Buffer[j] != 0x00) j++;
726 msg.Buffer[pos+1] = j - pos - 2;
727 GSM_UnpackSemiOctetNumber(cd->Response.Entries[i].Number,msg.Buffer+(pos+1),false);
728 smprintf(s," Number : %s\n",DecodeUnicodeString(cd->Response.Entries[i].Number));
729 cd->Response.Entries[i].Timeout = msg.Buffer[pos+34];
730 smprintf(s," Timeout : %i seconds\n",msg.Buffer[pos+34]);
731 pos+=35;
732 }
733 return ERR_NONE;
734 case 0x03:
735 smprintf(s,"Message: Call divert status receiving error ?\n");
736 return ERR_UNKNOWN;
737 }
738 return ERR_UNKNOWNRESPONSE;
739}
740
741static GSM_Error DCT3DCT4_CallDivert(GSM_StateMachine *s, GSM_MultiCallDivert *divert, bool get)
742{
743 int length = 0x09;
744 unsigned char req[55] = {N6110_FRAME_HEADER, 0x01,
745 0x05, /* operation = Query */
746 0x00,
747 0x00, /* divert type */
748 0x00, /* call type */
749 0x00};
750
751 if (!get) {
752 if (UnicodeLength(divert->Request.Number) == 0) {
753 req[4] = 0x04;
754 } else {
755 req[4] = 0x03;
756 req[8] = 0x01;
757 req[29] = GSM_PackSemiOctetNumber(divert->Request.Number, req + 9, false);
758 req[52] = divert->Request.Timeout;
759 length = 55;
760 }
761 }
762 switch (divert->Request.DivertType) {
763 case GSM_DIVERT_AllTypes : req[6] = 0x15; break;
764 case GSM_DIVERT_Busy : req[6] = 0x43; break;
765 case GSM_DIVERT_NoAnswer : req[6] = 0x3d; break;
766 case GSM_DIVERT_OutOfReach: req[6] = 0x3e; break;
767 default : return ERR_NOTIMPLEMENTED;
768 }
769
770 switch (divert->Request.CallType) {
771 case GSM_DIVERT_AllCalls : break;
772 case GSM_DIVERT_VoiceCalls: req[7] = 0x0b; break;
773 case GSM_DIVERT_FaxCalls : req[7] = 0x0d; break;
774 case GSM_DIVERT_DataCalls : req[7] = 0x19; break;
775 default : return ERR_NOTIMPLEMENTED;
776 }
777
778 s->Phone.Data.Divert = divert;
779 smprintf(s, "Call divert\n");
780 return GSM_WaitFor (s, req, length, 0x06, 10, ID_Divert);
781}
782
783GSM_Error DCT3DCT4_GetCallDivert(GSM_StateMachine *s, GSM_MultiCallDivert *divert)
784{
785 return DCT3DCT4_CallDivert(s,divert,true);
786}
787
788GSM_Error DCT3DCT4_SetCallDivert(GSM_StateMachine *s, GSM_MultiCallDivert *divert)
789{
790 return DCT3DCT4_CallDivert(s,divert,false);
791}
792
793GSM_Error DCT3DCT4_CancelAllDiverts(GSM_StateMachine *s)
794{
795 GSM_MultiCallDivert divert;
796 unsigned char req[55] = {N6110_FRAME_HEADER, 0x01,
797 0x04, /* operation = Disable */
798 0x00,
799 0x02, /* divert type */
800 0x00, /* call type */
801 0x00};
802
803 s->Phone.Data.Divert = &divert;
804 smprintf(s, "Call divert\n");
805 return GSM_WaitFor (s, req, 0x09, 0x06, 10, ID_Divert);
806}
807
808GSM_Error DCT3DCT4_ReplyGetActiveConnectSet(GSM_Protocol_Message msg, GSM_StateMachine *s)
809{
810 GSM_Phone_Data *Data = &s->Phone.Data;
811
812 Data->WAPSettings->Active = false;
813 if (Data->WAPSettings->Location - 1 == msg.Buffer[4]) {
814 Data->WAPSettings->Active = true;
815 }
816 return ERR_NONE;
817}
818
819GSM_Error DCT3DCT4_GetActiveConnectSet(GSM_StateMachine *s)
820{
821 unsigned char GetSetreq[] = {N6110_FRAME_HEADER, 0x0F};
822
823 smprintf(s, "Checking, if connection settings are active\n");
824 return GSM_WaitFor (s, GetSetreq, 4, 0x3f, 4, ID_GetConnectSet);
825}
826
827GSM_Error DCT3DCT4_ReplySetActiveConnectSet(GSM_Protocol_Message msg, GSM_StateMachine *s)
828{
829 smprintf(s, "Connection settings activated\n");
830 return ERR_NONE;
831}
832
833GSM_Error DCT3DCT4_SetActiveConnectSet(GSM_StateMachine *s, GSM_MultiWAPSettings *settings)
834{
835 unsigned charreqActivate[] = {N6110_FRAME_HEADER, 0x12,
836 0x00}; /* Location */
837
838 if (settings->Active) {
839 reqActivate[4] = settings->Location-1;
840 smprintf(s, "Activating connection settings number %i\n",settings->Location);
841 return GSM_WaitFor (s, reqActivate, 5, 0x3f, 4, ID_SetMMSSettings);
842 }
843 return ERR_NONE;
844}
845
846
847GSM_Error DCT3DCT4_SendDTMF(GSM_StateMachine *s, char *DTMFSequence)
848{
849 unsigned char req[100] = {N6110_FRAME_HEADER, 0x50,
850 0x00}; /* Length */
851
852 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NODTMF)) return ERR_NOTSUPPORTED;
853 if (strlen(DTMFSequence) > 100 - 5) return ERR_NOTSUPPORTED;
854
855 req[4] = strlen(DTMFSequence);
856
857 memcpy(req+5,DTMFSequence,strlen(DTMFSequence));
858
859 smprintf(s, "Sending DTMF\n");
860 return GSM_WaitFor (s, req, 5+strlen(DTMFSequence), 0x01, 4, ID_SendDTMF);
861}
862
863GSM_Error DCT3DCT4_ReplyGetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s, bool FullLength)
864{
865 int tmp;
866 GSM_Phone_Data *Data = &s->Phone.Data;
867
868 smprintf(s, "WAP bookmark received\n");
869 switch (msg.Buffer[3]) {
870 case 0x07:
871 tmp = 4;
872
873 Data->WAPBookmark->Location = msg.Buffer[tmp] * 256 + msg.Buffer[tmp+1];
874 smprintf(s, "Location: %i\n",Data->WAPBookmark->Location);
875 tmp = tmp + 2;
876
877 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPBookmark->Title, FullLength);
878 smprintf(s, "Title : \"%s\"\n",DecodeUnicodeString(Data->WAPBookmark->Title));
879
880 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer, Data->WAPBookmark->Address, FullLength);
881 smprintf(s, "Address : \"%s\"\n",DecodeUnicodeString(Data->WAPBookmark->Address));
882
883 return ERR_NONE;
884 case 0x08:
885 switch (msg.Buffer[4]) {
886 case 0x01:
887 smprintf(s, "Security error. Inside WAP bookmarks menu\n");
888 return ERR_INSIDEPHONEMENU;
889 case 0x02:
890 smprintf(s, "Invalid or empty\n");
891 return ERR_INVALIDLOCATION;
892 default:
893 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
894 return ERR_UNKNOWNRESPONSE;
895 }
896 break;
897 }
898 return ERR_UNKNOWNRESPONSE;
899}
900
901GSM_Error DCT3DCT4_ReplySetWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
902{
903 switch (msg.Buffer[3]) {
904 case 0x0A:
905 smprintf(s, "WAP bookmark set OK\n");
906 return ERR_NONE;
907 case 0x0B:
908 smprintf(s, "WAP bookmark setting error\n");
909 switch (msg.Buffer[4]) {
910 case 0x01:
911 smprintf(s, "Security error. Inside WAP bookmarks menu\n");
912 return ERR_INSIDEPHONEMENU;
913 case 0x02:
914 smprintf(s, "Can't write to empty location ?\n");
915 return ERR_EMPTY;
916 case 0x04:
917 smprintf(s, "Full memory\n");
918 return ERR_FULL;
919 default:
920 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
921 return ERR_UNKNOWNRESPONSE;
922 }
923 }
924 return ERR_UNKNOWNRESPONSE;
925}
926
927GSM_Error DCT3DCT4_ReplyEnableConnectFunc(GSM_Protocol_Message msg, GSM_StateMachine *s)
928{
929 smprintf(s, "Connection functions enabled\n");
930 return ERR_NONE;
931}
932
933GSM_Error DCT3DCT4_EnableWAPFunctions(GSM_StateMachine *s)
934{
935 unsigned char req[] = {N6110_FRAME_HEADER, 0x00};
936
937 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOWAP)) return ERR_NOTSUPPORTED;
938
939 smprintf(s, "Enabling WAP\n");
940 return GSM_WaitFor (s, req, 4, 0x3f, 4, ID_EnableConnectFunc);
941}
942
943GSM_Error DCT3DCT4_ReplyDisableConnectFunc(GSM_Protocol_Message msg, GSM_StateMachine *s)
944{
945 smprintf(s, "Connection functions disabled\n");
946 return ERR_NONE;
947}
948
949GSM_Error DCT3DCT4_DisableConnectionFunctions(GSM_StateMachine *s)
950{
951 unsigned char req[] = {N6110_FRAME_HEADER, 0x03};
952
953 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOWAP)) return ERR_NOTSUPPORTED;
954
955 smprintf(s, "Disabling connection settings\n");
956 return GSM_WaitFor (s, req, 4, 0x3f, 4, ID_DisableConnectFunc);
957}
958
959GSM_Error DCT3DCT4_ReplyDelWAPBookmark(GSM_Protocol_Message msg, GSM_StateMachine *s)
960{
961 switch (msg.Buffer[3]) {
962 case 0x0D:
963 smprintf(s, "WAP bookmark deleted OK\n");
964 return ERR_NONE;
965 case 0x0E:
966 smprintf(s, "WAP bookmark deleting error\n");
967 switch (msg.Buffer[4]) {
968 case 0x01:
969 smprintf(s, "Security error. Inside WAP bookmarks menu\n");
970 return ERR_SECURITYERROR;
971 case 0x02:
972 smprintf(s, "Invalid location\n");
973 return ERR_INVALIDLOCATION;
974 default:
975 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
976 return ERR_UNKNOWNRESPONSE;
977 }
978 }
979 return ERR_UNKNOWNRESPONSE;
980}
981
982GSM_Error DCT3DCT4_DeleteWAPBookmarkPart(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
983{
984 GSM_Errorerror;
985 unsigned char req[] = {N6110_FRAME_HEADER, 0x0C,
986 0x00, 0x00}; /* Location */
987
988 req[5] = bookmark->Location;
989
990 smprintf(s, "Deleting WAP bookmark\n");
991 error = GSM_WaitFor (s, req, 6, 0x3f, 4, ID_DeleteWAPBookmark);
992 if (error != ERR_NONE) {
993 if (error == ERR_INVALIDLOCATION || error == ERR_INSIDEPHONEMENU) {
994 DCT3DCT4_DisableConnectionFunctions(s);
995 }
996 return error;
997 }
998
999 return DCT3DCT4_DisableConnectionFunctions(s);
1000}
1001
1002GSM_Error DCT3DCT4_GetWAPBookmarkPart(GSM_StateMachine *s, GSM_WAPBookmark *bookmark)
1003{
1004 GSM_Errorerror;
1005 unsigned char req[] = {N6110_FRAME_HEADER, 0x06,
1006 0x00, 0x00}; /* Location */
1007
1008 req[5]=bookmark->Location-1;
1009
1010 s->Phone.Data.WAPBookmark=bookmark;
1011 smprintf(s, "Getting WAP bookmark\n");
1012 error = GSM_WaitFor (s, req, 6, 0x3f, 4, ID_GetWAPBookmark);
1013 if (error != ERR_NONE) {
1014 if (error == ERR_INVALIDLOCATION || error == ERR_INSIDEPHONEMENU) {
1015 DCT3DCT4_DisableConnectionFunctions(s);
1016 }
1017 return error;
1018 }
1019
1020 return DCT3DCT4_DisableConnectionFunctions(s);
1021}
1022
1023GSM_Error DCT3DCT4_CancelCall(GSM_StateMachine *s, int ID)
1024{
1025 unsigned char req[] = {N6110_FRAME_HEADER, 0x08, 0x00, 0x85};
1026
1027 req[4] = (unsigned char)ID;
1028 s->Phone.Data.CallID = ID;
1029
1030 smprintf(s, "Canceling single call\n");
1031 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_CancelCall);
1032}
1033
1034GSM_Error DCT3DCT4_AnswerCall(GSM_StateMachine *s, int ID)
1035{
1036 unsigned char req[] = {N6110_FRAME_HEADER, 0x06, 0x00, 0x00};
1037
1038 req[4] = (unsigned char)ID;
1039 s->Phone.Data.CallID = ID;
1040
1041 smprintf(s, "Answering single call\n");
1042 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_AnswerCall);
1043}
1044
1045GSM_Error DCT3DCT4_ReplyGetModelFirmware(GSM_Protocol_Message msg, GSM_StateMachine *s)
1046{
1047 GSM_Lineslines;
1048 GSM_Phone_Data*Data = &s->Phone.Data;
1049
1050 SplitLines(msg.Buffer, msg.Length, &lines, "\x20\x0A", 2, false);
1051
1052 strcpy(Data->Model,GetLineString(msg.Buffer, lines, 4));
1053 smprintf(s, "Received model %s\n",Data->Model);
1054 Data->ModelInfo = GetModelData(NULL,Data->Model,NULL);
1055
1056 strcpy(Data->VerDate,GetLineString(msg.Buffer, lines, 3));
1057 smprintf(s, "Received firmware date %s\n",Data->VerDate);
1058
1059 strcpy(Data->Version,GetLineString(msg.Buffer, lines, 2));
1060 smprintf(s, "Received firmware version %s\n",Data->Version);
1061 GSM_CreateFirmwareNumber(s);
1062
1063 return ERR_NONE;
1064}
1065
1066GSM_Error DCT3DCT4_GetModel (GSM_StateMachine *s)
1067{
1068 unsigned char req[5] = {N6110_FRAME_HEADER, 0x03, 0x00};
1069 GSM_Error error;
1070
1071 if (strlen(s->Phone.Data.Model)>0) return ERR_NONE;
1072
1073 smprintf(s, "Getting model\n");
1074 error=GSM_WaitFor (s, req, 5, 0xd1, 3, ID_GetModel);
1075 if (error==ERR_NONE) {
1076 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
1077 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
1078 smprintf(s, "[Connected model - \"%s\"]\n",s->Phone.Data.Model);
1079 smprintf(s, "[Firmware version - \"%s\"]\n",s->Phone.Data.Version);
1080 smprintf(s, "[Firmware date - \"%s\"]\n",s->Phone.Data.VerDate);
1081 }
1082 }
1083 return error;
1084}
1085
1086GSM_Error DCT3DCT4_GetFirmware (GSM_StateMachine *s)
1087{
1088 unsigned char req[5] = {N6110_FRAME_HEADER, 0x03, 0x00};
1089 GSM_Error error;
1090
1091 if (strlen(s->Phone.Data.Version)>0) return ERR_NONE;
1092
1093 smprintf(s, "Getting firmware version\n");
1094 error=GSM_WaitFor (s, req, 5, 0xd1, 3, ID_GetFirmware);
1095 if (error==ERR_NONE) {
1096 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
1097 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
1098 smprintf(s, "[Connected model - \"%s\"]\n",s->Phone.Data.Model);
1099 smprintf(s, "[Firmware version - \"%s\"]\n",s->Phone.Data.Version);
1100 smprintf(s, "[Firmware date - \"%s\"]\n",s->Phone.Data.VerDate);
1101 }
1102 }
1103 return error;
1104}
1105
1106/* ---------- Shared for n7110.c and n6510.c ------------------------------- */
1107
1108GSM_Error N71_65_ReplyGetMemoryError(unsigned char error, GSM_StateMachine *s)
1109{
1110 switch (error) {
1111 case 0x27:
1112 smprintf(s, "No PIN\n");
1113 return ERR_SECURITYERROR;
1114 case 0x30:
1115 smprintf(s, "Invalid memory type\n");
1116 if (s->Phone.Data.Memory->MemoryType == MEM_ME) return ERR_EMPTY;
1117 if (s->Phone.Data.Memory->MemoryType == MEM_SM) return ERR_EMPTY;
1118 return ERR_NOTSUPPORTED;
1119 case 0x33:
1120 smprintf(s, "Empty location\n");
1121 s->Phone.Data.Memory->EntriesNum = 0;
1122 return ERR_EMPTY;
1123 case 0x34:
1124 smprintf(s, "Too high location ?\n");
1125 return ERR_INVALIDLOCATION;
1126 default:
1127 smprintf(s, "ERROR: unknown %i\n",error);
1128 return ERR_UNKNOWNRESPONSE;
1129 }
1130}
1131
1132GSM_Error N71_65_ReplyWritePhonebook(GSM_Protocol_Message msg, GSM_StateMachine *s)
1133{
1134 smprintf(s, "Phonebook entry written ");
1135 switch (msg.Buffer[6]) {
1136 case 0x0f:
1137 smprintf(s, " - error\n");
1138 switch (msg.Buffer[10]) {
1139 case 0x36:
1140 smprintf(s, "Too long name\n");
1141 return ERR_NOTSUPPORTED;
1142 case 0x3c:
1143 smprintf(s, "Can not add entry with 0 subentries\n");
1144 return ERR_NOTSUPPORTED;
1145 case 0x3d:
1146 smprintf(s, "Wrong entry type\n");
1147 return ERR_NOTSUPPORTED;
1148 case 0x3e:
1149 smprintf(s, "Too much entries\n");
1150 return ERR_NOTSUPPORTED;
1151 default:
1152 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[10]);
1153 return ERR_UNKNOWNRESPONSE;
1154 }
1155 default:
1156 smprintf(s, " - OK\n");
1157 return ERR_NONE;
1158 }
1159}
1160
1161bool NOKIA_FindPhoneFeatureValue(GSM_StateMachine *s,
1162 GSM_Profile_PhoneTableValue ProfileTable[],
1163 GSM_Profile_Feat_ID FeatureID,
1164 GSM_Profile_Feat_Value FeatureValue,
1165 unsigned char *PhoneID,
1166 unsigned char *PhoneValue)
1167{
1168 int i=0;
1169
1170 smprintf(s, "Trying to find feature %i with value %i\n",FeatureID,FeatureValue);
1171 while (ProfileTable[i].ID != 0x00) {
1172 if (ProfileTable[i].ID == FeatureID &&
1173 ProfileTable[i].Value == FeatureValue) {
1174 *PhoneID= ProfileTable[i].PhoneID;
1175 *PhoneValue= ProfileTable[i].PhoneValue;
1176 return true;
1177 }
1178 i++;
1179 }
1180 return false;
1181}
1182
1183#define PROFILE_CALLERGROUPS_GROUP1 0x01
1184#define PROFILE_CALLERGROUPS_GROUP2 0x02
1185#define PROFILE_CALLERGROUPS_GROUP3 0x04
1186#define PROFILE_CALLERGROUPS_GROUP4 0x08
1187#define PROFILE_CALLERGROUPS_GROUP5 0x10
1188
1189 void NOKIA_FindFeatureValue(GSM_StateMachine *s,
1190 GSM_Profile_PhoneTableValue ProfileTable[],
1191 unsigned char ID,
1192 unsigned char Value,
1193 GSM_Phone_Data *Data,
1194 bool CallerGroups)
1195{
1196 int i;
1197
1198 if (CallerGroups) {
1199 smprintf(s, "Caller groups: %i\n", Value);
1200 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_CallerGroups;
1201 Data->Profile->FeaturesNumber++;
1202 for (i=0;i<5;i++) Data->Profile->CallerGroups[i] = false;
1203 if ((Value & PROFILE_CALLERGROUPS_GROUP1)==PROFILE_CALLERGROUPS_GROUP1) Data->Profile->CallerGroups[0] = true;
1204 if ((Value & PROFILE_CALLERGROUPS_GROUP2)==PROFILE_CALLERGROUPS_GROUP2) Data->Profile->CallerGroups[1] = true;
1205 if ((Value & PROFILE_CALLERGROUPS_GROUP3)==PROFILE_CALLERGROUPS_GROUP3) Data->Profile->CallerGroups[2] = true;
1206 if ((Value & PROFILE_CALLERGROUPS_GROUP4)==PROFILE_CALLERGROUPS_GROUP4) Data->Profile->CallerGroups[3] = true;
1207 if ((Value & PROFILE_CALLERGROUPS_GROUP5)==PROFILE_CALLERGROUPS_GROUP5) Data->Profile->CallerGroups[4] = true;
1208 return;
1209 }
1210
1211 i = 0;
1212 while (ProfileTable[i].ID != 0x00) {
1213 if (ProfileTable[i].PhoneID == ID &&
1214 ProfileTable[i].PhoneValue == Value) {
1215#ifdef DEBUG
1216 switch (ProfileTable[i].ID) {
1217 case Profile_KeypadTone : smprintf(s, "Keypad tones\n"); break;
1218 case Profile_CallAlert : smprintf(s, "Call alert\n"); break;
1219 case Profile_RingtoneVolume : smprintf(s, "Ringtone volume\n"); break;
1220 case Profile_MessageTone : smprintf(s, "SMS message tones\n"); break;
1221 case Profile_Vibration : smprintf(s, "Vibration\n"); break;
1222 case Profile_WarningTone: smprintf(s, "Warning (ang games) tones\n"); break;
1223 case Profile_AutoAnswer : smprintf(s, "Automatic answer\n"); break;
1224 case Profile_Lights : smprintf(s, "Lights\n"); break;
1225 case Profile_ScreenSaver : smprintf(s, "Screen Saver\n"); break;
1226 case Profile_ScreenSaverTime : smprintf(s, "Screen Saver timeout\n"); break;
1227 default : break;
1228 }
1229#endif
1230 Data->Profile->FeatureID[Data->Profile->FeaturesNumber] = ProfileTable[i].ID;
1231 Data->Profile->FeatureValue[Data->Profile->FeaturesNumber] = ProfileTable[i].Value;
1232 Data->Profile->FeaturesNumber++;
1233 break;
1234 }
1235 i++;
1236 }
1237}
1238
1239GSM_Profile_PhoneTableValue Profile71_65[] = {
1240 {Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0x00},
1241 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x01},
1242 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x02},
1243 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x03},
1244 /* Lights ? */
1245 {Profile_CallAlert, PROFILE_CALLALERT_RINGING,0x02,0x00},
1246 {Profile_CallAlert, PROFILE_CALLALERT_ASCENDING,0x02,0x01},
1247 {Profile_CallAlert, PROFILE_CALLALERT_RINGONCE,0x02,0x02},
1248 {Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE,0x02,0x03},
1249 {Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x02,0x05},
1250 /* {Profile_CallAlert, PROFILE_CALLALERT_CALLERGROUPS,0x02,0x07},*/
1251 /* Ringtone ID */
1252 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x04,0x00},
1253 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x04,0x01},
1254 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x04,0x02},
1255 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x04,0x03},
1256 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x04,0x04},
1257 {Profile_MessageTone, PROFILE_MESSAGE_NOTONE,0x05,0x00},
1258 {Profile_MessageTone, PROFILE_MESSAGE_STANDARD,0x05,0x01},
1259 {Profile_MessageTone, PROFILE_MESSAGE_SPECIAL,0x05,0x02},
1260 {Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE,0x05,0x03},
1261 {Profile_MessageTone, PROFILE_MESSAGE_ASCENDING,0x05,0x04},
1262 {Profile_Vibration, PROFILE_VIBRATION_OFF, 0x06,0x00},
1263 {Profile_Vibration, PROFILE_VIBRATION_ON, 0x06,0x01},
1264 {Profile_WarningTone, PROFILE_WARNING_OFF, 0x07,0x00},
1265 {Profile_WarningTone, PROFILE_WARNING_ON, 0x07,0x01},
1266 /* Caller groups */
1267 {Profile_AutoAnswer, PROFILE_AUTOANSWER_OFF,0x09,0x00},
1268 {Profile_AutoAnswer, PROFILE_AUTOANSWER_ON, 0x09,0x01},
1269 {0x00, 0x00, 0x00,0x00}
1270};
1271
1272GSM_Error NOKIA_SetIncomingSMS(GSM_StateMachine *s, bool enable)
1273{
1274 s->Phone.Data.EnableIncomingSMS = enable;
1275#ifdef DEBUG
1276 if (enable) {
1277 smprintf(s, "Enabling incoming SMS\n");
1278 } else {
1279 smprintf(s, "Disabling incoming SMS\n");
1280 }
1281#endif
1282 return ERR_NONE;
1283}
1284
1285GSM_Error N71_65_ReplyUSSDInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1286{
1287 unsigned char buffer[2000],buffer2[4000];
1288
1289 if (s->Phone.Data.RequestID == ID_Divert) return ERR_NONE;
1290
1291 memcpy(buffer,msg.Buffer+8,msg.Buffer[7]);
1292 buffer[msg.Buffer[7]] = 0x00;
1293
1294 smprintf(s, "USSD reply: \"%s\"\n",buffer);
1295
1296 if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
1297 EncodeUnicode(buffer2,buffer,strlen(buffer));
1298 s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
1299 }
1300
1301 return ERR_NONE;
1302}
1303
1304GSM_Error NOKIA_SetIncomingUSSD(GSM_StateMachine *s, bool enable)
1305{
1306 s->Phone.Data.EnableIncomingUSSD = enable;
1307#ifdef DEBUG
1308 if (enable) {
1309 smprintf(s, "Enabling incoming USSD\n");
1310 } else {
1311 smprintf(s, "Disabling incoming USSD\n");
1312 }
1313#endif
1314 return ERR_NONE;
1315}
1316
1317GSM_Error NOKIA_SetIncomingCall(GSM_StateMachine *s, bool enable)
1318{
1319 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLINFO)) return ERR_NOTSUPPORTED;
1320
1321 s->Phone.Data.EnableIncomingCall = enable;
1322#ifdef DEBUG
1323 if (enable) {
1324 smprintf(s, "Enabling incoming Call\n");
1325 } else {
1326 smprintf(s, "Disabling incoming Call\n");
1327 }
1328#endif
1329 return ERR_NONE;
1330}
1331
1332GSM_Error N71_65_ReplyCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1333{
1334 GSM_Call call;
1335 int tmp;
1336 unsigned char buffer[200];
1337
1338 call.Status = 0;
1339 call.CallIDAvailable = true;
1340 smprintf(s, "Call info, ");
1341 switch (msg.Buffer[3]) {
1342 case 0x02:
1343 smprintf(s, "Call established, waiting for answer\n");
1344 call.Status = GSM_CALL_CallEstablished;
1345 break;
1346 case 0x03:
1347 smprintf(s, "Call started\n");
1348 smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
1349 tmp = 6;
1350 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
1351 smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
1352 /* FIXME: read name from frame */
1353
1354 call.Status = GSM_CALL_CallStart;
1355 break;
1356 case 0x04:
1357 smprintf(s, "Remote end hang up\n");
1358 smprintf(s, "Cause Type : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
1359 smprintf(s, "CC : %i\n",msg.Buffer[6]);
1360 smprintf(s, "MM(?) : %i\n",msg.Buffer[7]);
1361 smprintf(s, "RR(?) : %i\n",msg.Buffer[8]);
1362 call.Status = GSM_CALL_CallRemoteEnd;
1363 call.StatusCode = msg.Buffer[6];
1364 break;
1365 case 0x05:
1366 smprintf(s, "Incoming call\n");
1367 smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
1368 tmp = 6;
1369 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
1370 smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
1371 /* FIXME: read name from frame */
1372 call.Status = GSM_CALL_IncomingCall;
1373 tmp = 6;
1374 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,call.PhoneNumber,false);
1375 break;
1376 case 0x07:
1377 smprintf(s, "Call answer initiated\n");
1378 break;
1379 case 0x09:
1380 smprintf(s, "Call released\n");
1381 call.Status = GSM_CALL_CallLocalEnd;
1382 break;
1383 case 0x0a:
1384 smprintf(s, "Call is being released\n");
1385 break;
1386 case 0x0b:
1387 smprintf(s, "Meaning not known\n");
1388 call.CallIDAvailable = false;
1389 break;
1390 case 0x0c:
1391 smprintf(s, "Audio status\n");
1392 if (msg.Buffer[4] == 0x01) smprintf(s, "Audio enabled\n");
1393 else smprintf(s, "Audio disabled\n");
1394 call.CallIDAvailable = false;
1395 break;
1396 case 0x23:
1397 smprintf(s, "Call held\n");
1398 call.Status = GSM_CALL_CallHeld;
1399 break;
1400 case 0x25:
1401 smprintf(s, "Call resumed\n");
1402 call.Status = GSM_CALL_CallResumed;
1403 break;
1404 case 0x27:
1405 smprintf(s, "Call switched\n");
1406 call.Status = GSM_CALL_CallSwitched;
1407 break;
1408 case 0x53:
1409 smprintf(s, "Outgoing call\n");
1410 smprintf(s, "Call mode : %i\n",msg.Buffer[5]);//such interpretation is in gnokii
1411 tmp = 6;
1412 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,buffer,false);
1413 smprintf(s, "Number : \"%s\"\n",DecodeUnicodeString(buffer));
1414 /* FIXME: read name from frame */
1415 call.Status = GSM_CALL_OutgoingCall;
1416 tmp = 6;
1417 NOKIA_GetUnicodeString(s, &tmp, msg.Buffer,call.PhoneNumber,false);
1418 break;
1419 }
1420 if (call.CallIDAvailable) smprintf(s, "Call ID : %d\n",msg.Buffer[4]);
1421 if (s->Phone.Data.EnableIncomingCall && s->User.IncomingCall!=NULL && call.Status != 0) {
1422 if (call.CallIDAvailable) call.CallID = msg.Buffer[4];
1423 s->User.IncomingCall(s->CurrentConfig->Device, call);
1424 }
1425 if (s->Phone.Data.RequestID == ID_CancelCall) {
1426 if (msg.Buffer[3] == 0x09) {
1427 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1428 /* when we canceled call and see frame about other
1429 * call releasing, we don't give ERR_NONE for "our"
1430 * call release command
1431 */
1432 return ERR_NEEDANOTHERANSWER;
1433 }
1434 }
1435 if (s->Phone.Data.RequestID == ID_AnswerCall) {
1436 if (msg.Buffer[3] == 0x07) {
1437 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1438 return ERR_NEEDANOTHERANSWER;
1439 }
1440 }
1441 return ERR_NONE;
1442}
1443
1444void N71_65_GetCalendarRecurrance(GSM_StateMachine *s, unsigned char *buffer, GSM_CalendarEntry *entry)
1445{
1446 int Recurrance;
1447
1448 Recurrance = buffer[0]*256 + buffer[1];
1449 /* 8760 hours = 1 year */
1450 if (Recurrance == 0xffff) Recurrance=8760;
1451 if (Recurrance != 0) {
1452 smprintf(s, "Recurrance : %i hours\n",Recurrance);
1453 entry->Entries[entry->EntriesNum].EntryType= CAL_RECURRANCE;
1454 entry->Entries[entry->EntriesNum].Number= Recurrance;
1455 entry->EntriesNum++;
1456 }
1457}
1458
1459/* method 2 */
1460GSM_Error N71_65_ReplyAddCalendar2(GSM_Protocol_Message msg, GSM_StateMachine *s)
1461{
1462 smprintf(s, "Calendar note added\n");
1463 return ERR_NONE;
1464}
1465
1466/* method 2 */
1467GSM_Error N71_65_AddCalendar2(GSM_StateMachine *s, GSM_CalendarEntry *Note)
1468{
1469 GSM_CalendarNoteTypeNoteType;
1470 time_t t_time1,t_time2;
1471 GSM_DateTime Date,date_time;
1472 GSM_Error error;
1473 long diff;
1474 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, length=25;
1475 unsigned char req[5000] = {
1476 N6110_FRAME_HEADER,
1477 0x40,
1478 0x00, /* frame length - 7 */
1479 0x00,0x00,0x00,0x00,
1480 0x00,0x00,0x00,0x00, /* start time saved as difference */
1481 0x00,0x00,0xff,0xff, /* alarm saved as difference */
1482 0x00, /* frame length - 7 */
1483 0x00, /* note type */
1484 0x00,0x00, /* recurrance */
1485 0x00,0x00,0x00,0x00,
1486 0x00,0x00,0x00,0x00}; /* rest depends on note type */
1487
1488 NoteType = N71_65_FindCalendarType(Note->Type, s->Phone.Data.ModelInfo);
1489
1490 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62) ||
1491 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65)) {
1492 switch(NoteType) {
1493 case GSM_CAL_MEETING : req[18] = 0x01; length = 25; break;
1494 case GSM_CAL_CALL : req[18] = 0x02; length = 27; break;
1495 case GSM_CAL_BIRTHDAY: req[18] = 0x04; length = 28; break;
1496 case GSM_CAL_MEMO : req[18] = 0x08; length = 25; break;
1497 default : return ERR_UNKNOWN;
1498 }
1499 } else {
1500 switch(NoteType) {
1501 case GSM_CAL_REMINDER: req[18] = 0x01; length = 25; break;
1502 case GSM_CAL_CALL : req[18] = 0x02; length = 27; break;
1503 case GSM_CAL_BIRTHDAY: req[18] = 0x04; length = 28; break;
1504 case GSM_CAL_MEMO : req[18] = 0x08; length = 25; break;
1505 default : return ERR_UNKNOWN;
1506 }
1507 }
1508
1509 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
1510
1511 if (Time == -1) return ERR_UNKNOWN;
1512 if (NoteType != GSM_CAL_BIRTHDAY) {
1513 Date.Year = 2030; Date.Month = 01; Date.Day = 01;
1514 Date.Hour = 00; Date.Minute = 00; Date.Second = 00;
1515 } else {
1516 Date.Year = 2029; Date.Month = 12; Date.Day = 31;
1517 Date.Hour = 22; Date.Minute = 59; Date.Second = 58;
1518 }
1519 t_time1 = Fill_Time_T(Date,8);
1520 memcpy(&Date,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
1521 if (NoteType != GSM_CAL_BIRTHDAY) {
1522 Date.Year -= 20;
1523 } else {
1524 Date.Year = 1980;
1525 Date.Hour = 22; Date.Minute = 58; Date.Second = 58;
1526 }
1527 t_time2 = Fill_Time_T(Date,8);
1528 diff= t_time1-t_time2;
1529 smprintf(s, " Difference : %li seconds\n", -diff);
1530 req[9] = (unsigned char)(-diff >> 24);
1531 req[10] = (unsigned char)(-diff >> 16);
1532 req[11] = (unsigned char)(-diff >> 8);
1533 req[12] = (unsigned char)(-diff);
1534 if (NoteType == GSM_CAL_BIRTHDAY) {
1535 req[25] = Note->Entries[Time].Date.Year / 256;
1536 req[26] = Note->Entries[Time].Date.Year % 256;
1537 /* Recurrance = 1 year */
1538 req[19] = 0xff;
1539 req[20] = 0xff;
1540 }
1541
1542 if (NoteType == GSM_CAL_CALL && Phone != -1) {
1543 req[25] = UnicodeLength(Note->Entries[Phone].Text);
1544 CopyUnicodeString(req+length,Note->Entries[Phone].Text);
1545 length += UnicodeLength(Note->Entries[Phone].Text)*2;
1546 }
1547
1548 if (Alarm != -1) {
1549 if (NoteType == GSM_CAL_BIRTHDAY) {
1550 if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) req[27] = 0x01;
1551 error=s->Phone.Functions->GetDateTime(s,&date_time);
1552 switch (error) {
1553 case ERR_EMPTY:
1554 case ERR_NOTIMPLEMENTED:
1555 GSM_GetCurrentDateTime(&date_time);
1556 break;
1557 case ERR_NONE:
1558 break;
1559 default:
1560 return error;
1561 }
1562 Date.Year= date_time.Year;
1563 Date.Hour = 23;
1564 Date.Minute = 59;
1565 } else {
1566 Date.Year += 20;
1567 }
1568 t_time2 = Fill_Time_T(Date,8);
1569 t_time1 = Fill_Time_T(Note->Entries[Alarm].Date,8);
1570 diff = t_time1-t_time2;
1571
1572 /* Sometimes we have difference in minutes */
1573 if (NoteType == GSM_CAL_MEETING) diff = diff / 60;
1574 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35)) {
1575 if (NoteType == GSM_CAL_MEMO || NoteType == GSM_CAL_CALL) {
1576 diff = diff / 60;
1577 }
1578 }
1579
1580 smprintf(s, " Difference : %li seconds or minutes\n", -diff);
1581 req[13] = (unsigned char)(-diff >> 24);
1582 req[14] = (unsigned char)(-diff >> 16);
1583 req[15] = (unsigned char)(-diff >> 8);
1584 req[16] = (unsigned char)(-diff);
1585 }
1586
1587 if (Recurrance != -1) {
1588 /* 8760 hours = 1 year */
1589 if (Note->Entries[Recurrance].Number >= 8760) {
1590 req[19] = 0xff;
1591 req[20] = 0xff;
1592 } else {
1593 req[19] = Note->Entries[Recurrance].Number / 256;
1594 req[20] = Note->Entries[Recurrance].Number % 256;
1595 }
1596 }
1597
1598 if (Text != -1) {
1599 switch (NoteType) {
1600 case GSM_CAL_CALL:
1601 req[26] = UnicodeLength(Note->Entries[Text].Text);
1602 break;
1603 default:
1604 req[length++] = UnicodeLength(Note->Entries[Text].Text);
1605 if (NoteType == GSM_CAL_MEMO || NoteType == GSM_CAL_MEETING) req[length++] = 0x00;
1606 }
1607 CopyUnicodeString(req+length,Note->Entries[Text].Text);
1608 length += UnicodeLength(Note->Entries[Text].Text)*2;
1609 }
1610
1611 req[length++] = 0x00;
1612 req[length++] = 0x00;
1613
1614 req[4] = req[17] = length-7;
1615
1616 smprintf(s, "Writing calendar note method 2\n");
1617 return GSM_WaitFor (s, req, length, 0x13, 4, ID_SetCalendarNote);
1618}
1619
1620/* method 1*/
1621GSM_Error N71_65_ReplyGetCalendarNotePos1(GSM_Protocol_Message msg, GSM_StateMachine *s,int *FirstCalendarPos)
1622{
1623 smprintf(s, "First calendar location: %i\n",msg.Buffer[4]*256+msg.Buffer[5]);
1624 *FirstCalendarPos = msg.Buffer[4]*256+msg.Buffer[5];
1625 return ERR_NONE;
1626}
1627
1628/* method 1*/
1629static GSM_Error N71_65_GetCalendarNotePos1(GSM_StateMachine *s)
1630{
1631 unsigned char req[] = {N6110_FRAME_HEADER, 0x31};
1632
1633 smprintf(s, "Getting first free calendar note location\n");
1634 return GSM_WaitFor (s, req, 4, 0x13, 4, ID_GetCalendarNotePos);
1635}
1636
1637/* method 1 */
1638GSM_Error N71_65_ReplyAddCalendar1(GSM_Protocol_Message msg, GSM_StateMachine *s)
1639{
1640#ifdef DEBUG
1641 smprintf(s, "Written calendar note type ");
1642 switch ((msg.Buffer[3]/2)-1) {
1643 case 0: smprintf(s, "Meeting");break;
1644 case 1: smprintf(s, "Call");break;
1645 case 2:smprintf(s, "Birthday");break;
1646 case 3:smprintf(s, "Reminder");break;
1647 }
1648 smprintf(s, " on location %d\n",msg.Buffer[4]*256+msg.Buffer[5]);
1649#endif
1650 return ERR_NONE;
1651}
1652
1653/* method 1 */
1654GSM_Error N71_65_AddCalendar1(GSM_StateMachine *s, GSM_CalendarEntry *Note, int *FirstCalendarPos)
1655{
1656 long seconds;
1657 GSM_Error error;
1658 GSM_DateTime DT;
1659 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, count=12;
1660 unsigned char req[5000] = {
1661 N6110_FRAME_HEADER,
1662 0x01, /* note type */
1663 0x00, 0x00, /* location ? */
1664 0x00, /* entry type */
1665 0x00,
1666 0x00, 0x00, /* Year */
1667 0x00, /* Month */
1668 0x00, /* Day */
1669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1670
1671 error=N71_65_GetCalendarNotePos1(s);
1672 if (error!=ERR_NONE) return error;
1673 if (FirstCalendarPos != NULL) {
1674 req[4] = *FirstCalendarPos/256;
1675 req[5] = *FirstCalendarPos%256;
1676 }
1677
1678 switch(Note->Type) {
1679 case GSM_CAL_CALL : req[3]=0x03; req[6]=0x02; break;
1680 case GSM_CAL_BIRTHDAY: req[3]=0x05; req[6]=0x04; break;
1681 case GSM_CAL_MEMO : req[3]=0x07; req[6]=0x08; break;
1682 case GSM_CAL_MEETING :
1683 default : req[3]=0x01; req[6]=0x01; break;
1684 }
1685
1686 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
1687
1688 if (Time == -1) return ERR_UNKNOWN;
1689 memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
1690 req[8]= DT.Year / 256;
1691 req[9]= DT.Year % 256;
1692 req[10]= DT.Month;
1693 req[11]= DT.Day;
1694
1695 switch(Note->Type) {
1696 case GSM_CAL_BIRTHDAY:
1697 /* byte 12 and 13 */
1698 req[count++] = 0x00;
1699 req[count++] = 0x00;
1700
1701 /* Alarm - bytes 14 to 17 */
1702 req[count++] = 0x00;
1703 req[count++] = 0x00;
1704 req[count++] = 0xff;
1705 req[count++] = 0xff;
1706 if (Alarm != -1) {
1707#ifndef ENABLE_LGPL
1708 /* Comment from original source by Gabriele Zappi:
1709 * I try with Time.Year = Alarm.Year. If negative, I increase 1 year,
1710 * but only once ! This thing, because I may have Alarm period across
1711 * a year. (eg. Birthday on 2001-01-10 and Alarm on 2000-12-27)
1712 */
1713#endif
1714 DT.Year = Note->Entries[Alarm].Date.Year;
1715 seconds = Fill_Time_T(DT,8)-Fill_Time_T(Note->Entries[Alarm].Date,8);
1716 if (seconds<0L) {
1717 DT.Year++;
1718 seconds = Fill_Time_T(DT,8)-Fill_Time_T(Note->Entries[Alarm].Date,8);
1719 }
1720 if (seconds>=0L) {
1721 count -= 4;
1722 /* bytes 14 to 17 */
1723 req[count++] = (unsigned char)(seconds>>24);
1724 req[count++] = (unsigned char)((seconds>>16) & 0xff);
1725 req[count++] = (unsigned char)((seconds>>8) & 0xff);
1726 req[count++] = (unsigned char)(seconds & 0xff);
1727 }
1728 /* byte 18 */
1729 if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) req[count++] = 0x01; else req[count++] = 0x00;
1730 }
1731
1732 /* byte 19 and next */
1733 if (Text != -1) {
1734 req[count++] = UnicodeLength(Note->Entries[Text].Text);
1735 CopyUnicodeString(req+count,Note->Entries[Text].Text);
1736 count=count+2*UnicodeLength(Note->Entries[Text].Text);
1737 } else {
1738 req[count++] = 0x00;
1739 }
1740 break;
1741 case GSM_CAL_MEMO:
1742 /* byte 12 and 13 */
1743 if (Recurrance != -1) {
1744 /* 8760 hours = 1 year */
1745 if (Note->Entries[Recurrance].Number >= 8760) {
1746 req[count++] = 0xff;
1747 req[count++] = 0xff;
1748 } else {
1749 req[count++] = Note->Entries[Recurrance].Number / 256;
1750 req[count++] = Note->Entries[Recurrance].Number % 256;
1751 }
1752 } else {
1753 req[count++] = 0x00;
1754 req[count++] = 0x00;
1755 }
1756
1757 /* byte 14 and next */
1758 if (Text != -1) {
1759 req[count++] = UnicodeLength(Note->Entries[Text].Text);
1760 req[count++] = 0x00;
1761 CopyUnicodeString(req+count,Note->Entries[Text].Text);
1762 count=count+2*UnicodeLength(Note->Entries[Text].Text);
1763 } else {
1764 req[count++] = 0x00;
1765 req[count++] = 0x00;
1766 }
1767 break;
1768 case GSM_CAL_MEETING:
1769 case GSM_CAL_CALL:
1770 default:
1771 /* byte 12 and 13 */
1772 req[count++] = DT.Hour;
1773 req[count++] = DT.Minute;
1774
1775 /* Alarm - byte 14 and 15 */
1776 req[count++] = 0xff;
1777 req[count++] = 0xff;
1778 if (Alarm != -1) {
1779 seconds=Fill_Time_T(DT,8)-Fill_Time_T(Note->Entries[Alarm].Date,8);
1780 if (seconds>=0L) {
1781 count -= 2;
1782 req[count++] = ((unsigned char)(seconds/60L)>>8);
1783 req[count++] = (unsigned char)((seconds/60L)&0xff);
1784 }
1785 }
1786
1787 /* byte 16 and 17 */
1788 if (Recurrance != -1) {
1789 /* 8760 hours = 1 year */
1790 if (Note->Entries[Recurrance].Number >= 8760) {
1791 req[count++] = 0xff;
1792 req[count++] = 0xff;
1793 } else {
1794 req[count++] = Note->Entries[Recurrance].Number / 256;
1795 req[count++] = Note->Entries[Recurrance].Number % 256;
1796 }
1797 } else {
1798 req[count++] = 0x00;
1799 req[count++] = 0x00;
1800 }
1801
1802 /* byte 18 */
1803 if (Text != -1) {
1804 req[count++] = UnicodeLength(Note->Entries[Text].Text);
1805 } else {
1806 req[count++] = 0x00;
1807 }
1808 /* byte 19 */
1809 if (Note->Type == GSM_CAL_CALL && Phone != -1) {
1810 req[count++] = UnicodeLength(Note->Entries[Phone].Text);
1811 } else {
1812 req[count++] = 0x00;
1813 }
1814 if (Text != -1) {
1815 CopyUnicodeString(req+count,Note->Entries[Text].Text);
1816 count=count+2*UnicodeLength(Note->Entries[Text].Text);
1817 }
1818 if (Note->Type == GSM_CAL_CALL && Phone != -1) {
1819 CopyUnicodeString(req+count,Note->Entries[Phone].Text);
1820 count=count+2*UnicodeLength(Note->Entries[Phone].Text);
1821 }
1822 break;
1823 }
1824 req[count] = 0x00;
1825 smprintf(s, "Writing calendar note method 1\n");
1826 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetCalendarNote);
1827}
1828
1829GSM_Error N71_65_ReplyDelCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
1830{
1831 smprintf(s, "Deleted calendar note on location %d\n",msg.Buffer[4]*256+msg.Buffer[5]);
1832 return ERR_NONE;
1833}
1834
1835GSM_Error N71_65_DelCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
1836{
1837 unsigned char req[] = {N6110_FRAME_HEADER, 0x0b,
1838 0x00, 0x00};/* location */
1839
1840 req[4] = Note->Location / 256;
1841 req[5] = Note->Location % 256;
1842
1843 smprintf(s, "Deleting calendar note\n");
1844 return GSM_WaitFor (s, req, 6, 0x13, 4, ID_DeleteCalendarNote);
1845}
1846
1847/* method 1 */
1848GSM_Error N71_65_ReplyGetCalendarInfo1(GSM_Protocol_Message msg, GSM_StateMachine *s, GSM_NOKIACalToDoLocations *LastCalendar)
1849{
1850 int i,j=0;
1851
1852 smprintf(s, "Info with calendar notes locations received method 1\n");
1853 while (LastCalendar->Location[j] != 0x00) j++;
1854 if (j >= GSM_MAXCALENDARTODONOTES) {
1855 smprintf(s, "Increase GSM_MAXCALENDARNOTES\n");
1856 return ERR_UNKNOWN;
1857 }
1858 if (j == 0) {
1859 LastCalendar->Number=msg.Buffer[4]*256+msg.Buffer[5];
1860 smprintf(s, "Number of Entries: %i\n",LastCalendar->Number);
1861 }
1862 smprintf(s, "Locations: ");
1863 i = 0;
1864 while (9+(i*2) <= msg.Length) {
1865 LastCalendar->Location[j++]=msg.Buffer[8+(i*2)]*256+msg.Buffer[9+(i*2)];
1866 smprintf(s, "%i ",LastCalendar->Location[j-1]);
1867 i++;
1868 }
1869 smprintf(s, "\nNumber of Entries in frame: %i\n",i);
1870 smprintf(s, "\n");
1871 LastCalendar->Location[j] = 0;
1872 if (i == 1 && msg.Buffer[8+(0*2)]*256+msg.Buffer[9+(0*2)] == 0) return ERR_EMPTY;
1873 if (i == 0) return ERR_EMPTY;
1874 return ERR_NONE;
1875}
1876
1877/* method 1 */
1878GSM_Error N71_65_GetCalendarInfo1(GSM_StateMachine *s, GSM_NOKIACalToDoLocations *LastCalendar)
1879{
1880 GSM_Errorerror;
1881 int i;
1882 unsigned char req[] = {N6110_FRAME_HEADER, 0x3a,
1883 0xFF, 0xFE};/* First location number */
1884
1885 LastCalendar->Location[0] = 0x00;
1886 LastCalendar->Number = 0;
1887
1888 smprintf(s, "Getting locations for calendar method 1\n");
1889 error = GSM_WaitFor (s, req, 6, 0x13, 4, ID_GetCalendarNotesInfo);
1890 if (error != ERR_NONE && error != ERR_EMPTY) return error;
1891
1892 while (1) {
1893 i=0;
1894 while (LastCalendar->Location[i] != 0x00) i++;
1895 if (i == LastCalendar->Number) break;
1896 if (i != LastCalendar->Number && error == ERR_EMPTY) {
1897 smprintf(s, "Phone doesn't support some notes with this method. Workaround\n");
1898 LastCalendar->Number = i;
1899 break;
1900 }
1901 smprintf(s, "i = %i %i\n",i,LastCalendar->Number);
1902 req[4] = LastCalendar->Location[i-1] / 256;
1903 req[5] = LastCalendar->Location[i-1] % 256;
1904 smprintf(s, "Getting locations for calendar\n");
1905 error = GSM_WaitFor (s, req, 6, 0x13, 4, ID_GetCalendarNotesInfo);
1906 if (error != ERR_NONE && error != ERR_EMPTY) return error;
1907 }
1908 return ERR_NONE;
1909}
1910
1911/* method 1 */
1912GSM_Error N71_65_ReplyGetNextCalendar1(GSM_Protocol_Message msg, GSM_StateMachine *s)
1913{
1914 int alarm,i;
1915 GSM_CalendarEntry*entry = s->Phone.Data.Cal;
1916
1917 smprintf(s, "Calendar note received method 1\n");
1918
1919 /* Later these values can change */
1920 if (msg.Buffer[6]!=0x04) { /* Here not birthday */
1921 entry->Entries[0].Date.Year = msg.Buffer[8]*256+msg.Buffer[9];
1922 }
1923 entry->Entries[0].Date.Month = msg.Buffer[10];
1924 entry->Entries[0].Date.Day= msg.Buffer[11];
1925 entry->Entries[0].Date.Hour= msg.Buffer[12];
1926 entry->Entries[0].Date.Minute= msg.Buffer[13];
1927 entry->Entries[0].Date.Second = 0;
1928 entry->Entries[0].EntryType = CAL_START_DATETIME;
1929 entry->EntriesNum++;
1930
1931 switch (msg.Buffer[6]) {
1932 case 0x01:
1933 smprintf(s, "Meeting\n");
1934 entry->Type = GSM_CAL_MEETING;
1935
1936 alarm=msg.Buffer[14]*256+msg.Buffer[15];
1937 if (alarm != 0xffff) {
1938 smprintf(s, " Difference : %i seconds\n", alarm);
1939 memcpy(&entry->Entries[1].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
1940 GetTimeDifference(alarm, &entry->Entries[1].Date, false, 60);
1941 entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
1942 entry->EntriesNum++;
1943 }
1944 N71_65_GetCalendarRecurrance(s, msg.Buffer + 16, entry);
1945
1946 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+20, msg.Buffer[18]*2);
1947 entry->Entries[entry->EntriesNum].Text[msg.Buffer[18]*2] = 0;
1948 entry->Entries[entry->EntriesNum].Text[msg.Buffer[18]*2+1] = 0;
1949 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
1950 smprintf(s, "Text : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
1951 entry->EntriesNum++;
1952 return ERR_NONE;
1953 case 0x02:
1954 smprintf(s, "Call\n");
1955 entry->Type = GSM_CAL_CALL;
1956
1957 alarm=msg.Buffer[14]*256+msg.Buffer[15];
1958 if (alarm != 0xffff) {
1959 smprintf(s, " Difference : %i seconds\n", alarm);
1960 memcpy(&entry->Entries[1].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
1961 GetTimeDifference(alarm, &entry->Entries[1].Date, false, 60);
1962 entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
1963 entry->EntriesNum++;
1964 }
1965 N71_65_GetCalendarRecurrance(s, msg.Buffer + 16, entry);
1966
1967 i = msg.Buffer[18] * 2;
1968 if (i!=0) {
1969 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+20, i);
1970 entry->Entries[entry->EntriesNum].Text[i] = 0;
1971 entry->Entries[entry->EntriesNum].Text[i+1] = 0;
1972 entry->Entries[entry->EntriesNum].EntryType= CAL_TEXT;
1973 smprintf(s, "Text : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
1974 entry->EntriesNum++;
1975 }
1976
1977 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+20+i, msg.Buffer[19]*2);
1978 entry->Entries[entry->EntriesNum].Text[msg.Buffer[19]*2] = 0;
1979 entry->Entries[entry->EntriesNum].Text[msg.Buffer[19]*2+1] = 0;
1980 entry->Entries[entry->EntriesNum].EntryType = CAL_PHONE;
1981 smprintf(s, "Phone : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
1982 entry->EntriesNum++;
1983 return ERR_NONE;
1984 case 0x04:
1985 smprintf(s, "Birthday\n");
1986 entry->Type = GSM_CAL_BIRTHDAY;
1987
1988 entry->Entries[0].Date.Hour= 23;
1989 entry->Entries[0].Date.Minute= 59;
1990 entry->Entries[0].Date.Second= 58;
1991
1992 alarm = ((unsigned int)msg.Buffer[14]) << 24;
1993 alarm += ((unsigned int)msg.Buffer[15]) << 16;
1994 alarm += ((unsigned int)msg.Buffer[16]) << 8;
1995 alarm += msg.Buffer[17];
1996 if (alarm != 0xffff) {
1997 smprintf(s, " Difference : %i seconds\n", alarm);
1998 memcpy(&entry->Entries[1].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
1999 GetTimeDifference(alarm, &entry->Entries[1].Date, false, 1);
2000 entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
2001 if (msg.Buffer[20]!=0x00) {
2002 entry->Entries[1].EntryType = CAL_SILENT_ALARM_DATETIME;
2003 smprintf(s, "Alarm type : Silent\n");
2004 }
2005 entry->EntriesNum++;
2006 }
2007
2008 entry->Entries[0].Date.Year = msg.Buffer[18]*256 + msg.Buffer[19];
2009 if (entry->Entries[0].Date.Year == 65535) entry->Entries[0].Date.Year = 0;
2010 smprintf(s, "Age : %i\n",entry->Entries[0].Date.Year);
2011
2012 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+22, msg.Buffer[21]*2);
2013 entry->Entries[entry->EntriesNum].Text[msg.Buffer[21]*2] = 0;
2014 entry->Entries[entry->EntriesNum].Text[msg.Buffer[21]*2+1] = 0;
2015 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
2016 smprintf(s, "Text : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
2017 entry->EntriesNum++;
2018 return ERR_NONE;
2019 case 0x08:
2020 smprintf(s, "Memo\n");
2021 entry->Type = GSM_CAL_MEMO;
2022
2023 entry->Entries[0].Date.Hour= 0;
2024 entry->Entries[0].Date.Minute= 0;
2025
2026 N71_65_GetCalendarRecurrance(s, msg.Buffer + 12, entry);
2027
2028 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+16, msg.Buffer[14]*2);
2029 entry->Entries[entry->EntriesNum].Text[msg.Buffer[14]*2] = 0;
2030 entry->Entries[entry->EntriesNum].Text[msg.Buffer[14]*2+1] = 0;
2031 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
2032 smprintf(s, "Text : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
2033 entry->EntriesNum++;
2034 return ERR_NONE;
2035 default:
2036 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[6]);
2037 return ERR_UNKNOWNRESPONSE;
2038 }
2039}
2040
2041/* method 1 */
2042GSM_Error N71_65_GetNextCalendar1(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, GSM_NOKIACalToDoLocations *LastCalendar, int *LastCalendarYear, int *LastCalendarPos)
2043{
2044 GSM_Error error;
2045 GSM_DateTime date_time;
2046 unsigned char req[] = {N6110_FRAME_HEADER, 0x19,
2047 0x00, 0x00}; /* Location */
2048
2049 if (start) {
2050 error=N71_65_GetCalendarInfo1(s, LastCalendar);
2051 if (error!=ERR_NONE) return error;
2052 if (LastCalendar->Number == 0) return ERR_EMPTY;
2053
2054 /* We have to get current year. It's NOT written in frame for
2055 * Birthday
2056 */
2057 error=s->Phone.Functions->GetDateTime(s,&date_time);
2058 switch (error) {
2059 case ERR_EMPTY:
2060 case ERR_NOTIMPLEMENTED:
2061 GSM_GetCurrentDateTime(&date_time);
2062 break;
2063 case ERR_NONE:
2064 break;
2065 default:
2066 return error;
2067 }
2068 *LastCalendarYear = date_time.Year;
2069 *LastCalendarPos = 0;
2070 } else {
2071 (*LastCalendarPos)++;
2072 }
2073
2074 if (*LastCalendarPos >= LastCalendar->Number) return ERR_EMPTY;
2075
2076 req[4] = LastCalendar->Location[*LastCalendarPos] / 256;
2077 req[5] = LastCalendar->Location[*LastCalendarPos] % 256;
2078
2079 Note->EntriesNum = 0;
2080 Note->Entries[0].Date.Year = *LastCalendarYear;
2081 Note->Location = LastCalendar->Location[*LastCalendarPos];
2082
2083 s->Phone.Data.Cal=Note;
2084 smprintf(s, "Getting calendar note method 1\n");
2085 return GSM_WaitFor (s, req, 6, 0x13, 4, ID_GetCalendarNote);
2086}
2087
2088GSM_Error N71_65_EnableFunctions(GSM_StateMachine *s,char *buff,int len)
2089{
2090 unsigned char buffer[50] = {N6110_FRAME_HEADER, 0x10,
2091 0x07};/* Length */
2092
2093 buffer[4] = len;
2094 memcpy(buffer+5,buff,len);
2095
2096 /* Enables various things like incoming SMS, call info, etc. */
2097 return s->Protocol.Functions->WriteMessage(s, buffer, 5+len, 0x10);
2098}
2099
2100GSM_Error N71_65_ReplySendDTMF(GSM_Protocol_Message msg, GSM_StateMachine *s)
2101{
2102 switch (msg.Buffer[3]) {
2103 case 0x51:
2104 smprintf(s, "DTMF sent OK\n");
2105 return ERR_NONE;
2106 case 0x59:
2107 case 0x5E:
2108 smprintf(s, "meaning unknown - during sending DTMF\n");
2109 return ERR_NONE;
2110 }
2111 return ERR_UNKNOWNRESPONSE;
2112}
2113
2114GSM_CalendarNoteType N71_65_FindCalendarType(GSM_CalendarNoteType Type, OnePhoneModel *model)
2115{
2116 switch (Type) {
2117 case GSM_CAL_CALL:
2118 return GSM_CAL_CALL;
2119 case GSM_CAL_BIRTHDAY:
2120 return GSM_CAL_BIRTHDAY;
2121 case GSM_CAL_MEETING:
2122 if (IsPhoneFeatureAvailable(model, F_CAL35)) {
2123 return GSM_CAL_REMINDER;
2124 } else return GSM_CAL_MEETING;
2125 case GSM_CAL_MEMO:
2126 if (IsPhoneFeatureAvailable(model, F_CAL35)) {
2127 return GSM_CAL_REMINDER;
2128 } else return GSM_CAL_MEMO;
2129 case GSM_CAL_REMINDER:
2130 if (IsPhoneFeatureAvailable(model, F_CAL62) ||
2131 IsPhoneFeatureAvailable(model, F_CAL65)) {
2132 return GSM_CAL_CALL;
2133 } else return GSM_CAL_REMINDER;
2134 default:
2135 return GSM_CAL_CALL;
2136 }
2137}
2138
2139#endif
2140
2141/* How should editor hadle tabs in this file? Add editor commands here.
2142 * vim: noexpandtab sw=8 ts=8 sts=8:
2143 */
diff --git a/gammu/emb/common/phone/nokia/nfunc.h b/gammu/emb/common/phone/nokia/nfunc.h
new file mode 100644
index 0000000..5ba3df0
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/nfunc.h
@@ -0,0 +1,99 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef phone_nokia_h
4#define phone_nokia_h
5
6#include "ncommon.h"
7#include "../../gsmcomon.h"
8#include "../../gsmstate.h"
9
10extern unsigned char N71_65_MEMORY_TYPES[];
11extern GSM_Profile_PhoneTableValue Profile71_65[];
12
13 GSM_Error NOKIA_ReplyGetPhoneString (GSM_Protocol_Message msg, GSM_StateMachine *s);
14 GSM_Error N71_65_ReplyGetMemoryError (unsigned char error , GSM_StateMachine *s);
15 GSM_Error N71_65_ReplyWritePhonebook (GSM_Protocol_Message msg, GSM_StateMachine *s);
16 GSM_Error N71_65_ReplyGetCalendarInfo1 (GSM_Protocol_Message msg, GSM_StateMachine *s, GSM_NOKIACalToDoLocations *LastCalendar);
17 GSM_Error N71_65_ReplyGetNextCalendar1 (GSM_Protocol_Message msg, GSM_StateMachine *s);
18 GSM_Error N71_65_ReplyGetCalendarNotePos1(GSM_Protocol_Message msg, GSM_StateMachine *s,int *FirstCalendarPos);
19 GSM_Error N71_65_ReplyAddCalendar1 (GSM_Protocol_Message msg, GSM_StateMachine *s);
20 GSM_Error N71_65_ReplyAddCalendar2 (GSM_Protocol_Message msg, GSM_StateMachine *s);
21 GSM_Error N71_65_ReplyDelCalendar (GSM_Protocol_Message msg, GSM_StateMachine *s);
22 GSM_Error N71_65_ReplyCallInfo (GSM_Protocol_Message msg, GSM_StateMachine *s);
23 GSM_Error N71_65_ReplyUSSDInfo (GSM_Protocol_Message msg, GSM_StateMachine *s);
24 GSM_Error DCT3DCT4_ReplyCallDivert (GSM_Protocol_Message msg, GSM_StateMachine *s);
25 GSM_Error DCT3DCT4_ReplyGetActiveConnectSet(GSM_Protocol_Message msg, GSM_StateMachine *s);
26 GSM_Error DCT3DCT4_ReplySetActiveConnectSet(GSM_Protocol_Message msg, GSM_StateMachine *s);
27 GSM_Error DCT3DCT4_ReplyGetWAPBookmark (GSM_Protocol_Message msg, GSM_StateMachine *s, bool FullLength);
28 GSM_Error DCT3DCT4_ReplySetWAPBookmark (GSM_Protocol_Message msg, GSM_StateMachine *s);
29 GSM_Error DCT3DCT4_ReplyDelWAPBookmark (GSM_Protocol_Message msg, GSM_StateMachine *s);
30 GSM_Error DCT3DCT4_ReplyEnableConnectFunc(GSM_Protocol_Message msg, GSM_StateMachine *s);
31GSM_Error DCT3DCT4_ReplyDisableConnectFunc (GSM_Protocol_Message msg, GSM_StateMachine *s);
32 GSM_Error DCT3DCT4_ReplyGetModelFirmware(GSM_Protocol_Message msg, GSM_StateMachine *s);
33 GSM_Error N71_65_ReplySendDTMF (GSM_Protocol_Message msg, GSM_StateMachine *s);
34
35 GSM_Error NOKIA_GetManufacturer (GSM_StateMachine *s);
36 GSM_Error NOKIA_GetPhoneString (GSM_StateMachine *s, unsigned char *msgframe, int msglen, unsigned char msgtype, char *retvalue, GSM_Phone_RequestID request, int startresponse);
37 GSM_Error NOKIA_SetIncomingSMS (GSM_StateMachine *s, bool enable);
38 GSM_Error NOKIA_SetIncomingCall (GSM_StateMachine *s, bool enable);
39 GSM_Error NOKIA_SetIncomingUSSD (GSM_StateMachine *s, bool enable);
40 GSM_Error N71_65_EnableFunctions (GSM_StateMachine *s, char *buff,int len);
41 GSM_Error N71_65_GetNextCalendar1 (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, GSM_NOKIACalToDoLocations *LastCalendar, int *LastCalendarYear, int *LastCalendarPos);
42 GSM_Error N71_65_AddCalendar2 (GSM_StateMachine *s, GSM_CalendarEntry *Note);
43 GSM_Error N71_65_AddCalendar1 (GSM_StateMachine *s, GSM_CalendarEntry *Note, int *FirstCalendarPos);
44 GSM_Error N71_65_DelCalendar (GSM_StateMachine *s, GSM_CalendarEntry *Note);
45 GSM_Error N71_65_GetCalendarInfo1 (GSM_StateMachine *s, GSM_NOKIACalToDoLocations *LastCalendar);
46 GSM_Error DCT3DCT4_EnableWAPFunctions (GSM_StateMachine *s);
47 GSM_Error DCT3DCT4_SendDTMF (GSM_StateMachine *s, char *sequence);
48 GSM_Error DCT3DCT4_DeleteWAPBookmarkPart(GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
49 GSM_Error DCT3DCT4_GetWAPBookmarkPart (GSM_StateMachine *s, GSM_WAPBookmark *bookmark);
50 GSM_Error DCT3DCT4_DisableConnectionFunctions(GSM_StateMachine *s);
51 GSM_Error DCT3DCT4_GetModel (GSM_StateMachine *s);
52 GSM_Error DCT3DCT4_GetFirmware (GSM_StateMachine *s);
53 GSM_Error DCT3DCT4_AnswerCall (GSM_StateMachine *s, int ID);
54 GSM_Error DCT3DCT4_CancelCall (GSM_StateMachine *s, int ID);
55 GSM_Error DCT3DCT4_GetActiveConnectSet (GSM_StateMachine *s);
56 GSM_Error DCT3DCT4_SetActiveConnectSet (GSM_StateMachine *s, GSM_MultiWAPSettings *settings);
57 GSM_Error DCT3DCT4_CancelAllDiverts (GSM_StateMachine *s);
58 GSM_Error DCT3DCT4_SetCallDivert (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
59 GSM_Error DCT3DCT4_GetCallDivert (GSM_StateMachine *s, GSM_MultiCallDivert *divert);
60
61GSM_CalendarNoteType N71_65_FindCalendarType(GSM_CalendarNoteType Type, OnePhoneModel *model);
62 void N71_65_GetCalendarRecurrance(GSM_StateMachine *s, unsigned char *buffer, GSM_CalendarEntry *entry);
63 int NOKIA_SetUnicodeString (GSM_StateMachine *s, unsigned char *dest, unsigned char *string, bool FullLength);
64 void NOKIA_GetUnicodeString (GSM_StateMachine *s, int *current, unsigned char *input, unsigned char *output, bool FullLength);
65 GSM_MemoryType NOKIA_GetMemoryType (GSM_StateMachine *s, GSM_MemoryType memory_type, unsigned char *ID);
66 void NOKIA_DecodeSMSState (GSM_StateMachine *s, unsigned char state, GSM_SMSMessage *sms);
67 void NOKIA_EncodeDateTime (GSM_StateMachine *s, unsigned char* buffer, GSM_DateTime *datetime);
68 void NOKIA_DecodeDateTime (GSM_StateMachine *s, unsigned char* buffer, GSM_DateTime *datetime);
69 void NOKIA_SortSMSFolderStatus(GSM_StateMachine *s, GSM_NOKIASMSFolder *Folder);
70 void NOKIA_GetDefaultCallerGroupName(GSM_StateMachine *s, GSM_Bitmap *Bitmap);
71 void NOKIA_GetDefaultProfileName(GSM_StateMachine *s, GSM_Profile *Profile);
72 void NOKIA_FindFeatureValue(GSM_StateMachine *s,
73 GSM_Profile_PhoneTableValue ProfileTable[],
74 unsigned char ID,
75 unsigned char Value,
76 GSM_Phone_Data *Data,
77 bool CallerGroups);
78 bool NOKIA_FindPhoneFeatureValue(GSM_StateMachine *s,
79 GSM_Profile_PhoneTableValue ProfileTable[],
80 GSM_Profile_Feat_ID FeatureID,
81 GSM_Profile_Feat_Value FeatureValue,
82 unsigned char *PhoneID,
83 unsigned char *PhoneValue);
84
85 GSM_Error N71_65_DecodePhonebook (GSM_StateMachine*s,
86 GSM_MemoryEntry *entry,
87 GSM_Bitmap *bitmap,
88 GSM_SpeedDial *speed,
89 unsigned char *MessageBuffer,
90 int MessageLength,
91 bool DayMonthReverse);
92 int N71_65_EncodePhonebookFrame(GSM_StateMachine *s, unsigned char *req, GSM_MemoryEntry entry, int *block2, bool DCT4, bool VoiceTag);
93 int N71_65_PackPBKBlock (GSM_StateMachine *s, int id, int size, int no, unsigned char *buf, unsigned char *block);
94
95#endif
96
97/* How should editor hadle tabs in this file? Add editor commands here.
98 * vim: noexpandtab sw=8 ts=8 sts=8:
99 */
diff --git a/gammu/emb/common/phone/nokia/nfuncold.c b/gammu/emb/common/phone/nokia/nfuncold.c
new file mode 100644
index 0000000..0e40bc6
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/nfuncold.c
@@ -0,0 +1,226 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h> /* memcpy only */
4#include <stdio.h>
5#include <ctype.h>
6#include <time.h>
7
8#include "../../misc/coding/coding.h"
9#include "../../gsmstate.h"
10#include "../../service/sms/gsmsms.h"
11#include "../pfunc.h"
12#include "nfunc.h"
13
14#ifdef DEBUG
15static void N71_65_GetCalendarAlarm(GSM_StateMachine *s, unsigned char *buffer, GSM_CalendarEntry *entry, int DT, GSM_Phone_Data *Data)
16{
17 unsigned long diff;
18
19 if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0xff && buffer[3] == 0xff) {
20 smprintf(s, "No alarm\n");
21 } else {
22 memcpy(&entry->Entries[entry->EntriesNum].Date,&entry->Entries[DT].Date,sizeof(GSM_DateTime));
23
24 diff = ((unsigned int)buffer[0]) << 24;
25 diff += ((unsigned int)buffer[1]) << 16;
26 diff += ((unsigned int)buffer[2]) << 8;
27 diff += buffer[3];
28 smprintf(s, " Difference : %li seconds\n", diff);
29
30 switch (entry->Type) {
31 case GSM_CAL_MEETING:
32 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 60);
33 break;
34 case GSM_CAL_MEMO:
35 if (!IsPhoneFeatureAvailable(Data->ModelInfo, F_CAL35)) {
36 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 60);
37 break;
38 }
39 case GSM_CAL_CALL:
40 if (!IsPhoneFeatureAvailable(Data->ModelInfo, F_CAL35)) {
41 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 60);
42 break;
43 }
44 default:
45 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, false, 1);
46 }
47 smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
48 entry->Entries[entry->EntriesNum].Date.Day, entry->Entries[entry->EntriesNum].Date.Month,
49 entry->Entries[entry->EntriesNum].Date.Year, entry->Entries[entry->EntriesNum].Date.Hour,
50 entry->Entries[entry->EntriesNum].Date.Minute,entry->Entries[entry->EntriesNum].Date.Second);
51
52 entry->Entries[entry->EntriesNum].EntryType = CAL_ALARM_DATETIME;
53 if (entry->Type == GSM_CAL_BIRTHDAY) {
54 if (buffer[14]!=0x00) entry->Entries[entry->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
55 smprintf(s, "Alarm type : Silent\n");
56 }
57
58 entry->EntriesNum++;
59 }
60}
61
62/* method 2 */
63GSM_Error N71_65_ReplyGetNextCalendar2(GSM_Protocol_Message msg, GSM_StateMachine *s)
64{
65 GSM_DateTime Date;
66 GSM_CalendarEntry*entry = s->Phone.Data.Cal;
67 GSM_Phone_Data *Data = &s->Phone.Data;
68 int i;
69 unsigned long diff;
70
71 smprintf(s, "Calendar note received method 2\n");
72
73 if (msg.Length < 10) return ERR_EMPTY;
74
75 entry->Location = msg.Buffer[4]*256 + msg.Buffer[5];
76 smprintf(s, "Location: %i\n",entry->Location);
77
78 /* Not birthday */
79 if (msg.Buffer[21] != 0x04) {
80 Date.Year = 2030; Date.Month = 01; Date.Day = 01;
81 Date.Hour = 00; Date.Minute = 00; Date.Second = 00;
82 } else {
83 Date.Year = 2029; Date.Month = 12; Date.Day = 31;
84 Date.Hour = 22; Date.Minute = 59; Date.Second = 58;
85 }
86 diff = ((unsigned int)msg.Buffer[12]) << 24;
87 diff += ((unsigned int)msg.Buffer[13]) << 16;
88 diff += ((unsigned int)msg.Buffer[14]) << 8;
89 diff += msg.Buffer[15];
90 smprintf(s, " Difference : %li seconds\n", diff);
91 GetTimeDifference(diff, &Date, true, 1);
92 Date.Year += 20;
93 entry->Entries[0].EntryType = CAL_START_DATETIME;
94
95 smprintf(s, "Note type %02x: ",msg.Buffer[21]);
96 switch (msg.Buffer[21]) {
97 case 0x01:
98 case 0x08:
99 if (msg.Buffer[21] == 0x01) {
100 smprintf(s, "Meeting or Reminder\n");
101 entry->Type = GSM_CAL_MEETING;
102 } else {
103 smprintf(s, "Memo\n");
104 Data->Cal->Type = GSM_CAL_MEMO;
105 }
106
107 memcpy(&entry->Entries[0].Date,&Date,sizeof(GSM_DateTime));
108 entry->EntriesNum++;
109
110 N71_65_GetCalendarAlarm(s, msg.Buffer+16, entry, 0, Data);
111 N71_65_GetCalendarRecurrance(s, msg.Buffer+22, entry);
112
113 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+30, msg.Buffer[28]*2);
114 entry->Entries[entry->EntriesNum].Text[msg.Buffer[28]*2] = 0;
115 entry->Entries[entry->EntriesNum].Text[msg.Buffer[28]*2+1] = 0;
116 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
117 break;
118 case 0x02:
119 smprintf(s, "Call\n");
120 entry->Type = GSM_CAL_CALL;
121
122 memcpy(&entry->Entries[0].Date,&Date,sizeof(GSM_DateTime));
123 entry->EntriesNum++;
124
125 N71_65_GetCalendarAlarm(s, msg.Buffer+16, entry, 0, Data);
126 N71_65_GetCalendarRecurrance(s, msg.Buffer+22, entry);
127
128 i = msg.Buffer[28] * 2;
129 if (i!=0) {
130 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+30, i);
131 entry->Entries[entry->EntriesNum].Text[i] = 0;
132 entry->Entries[entry->EntriesNum].Text[i+1] = 0;
133 entry->Entries[entry->EntriesNum].EntryType= CAL_PHONE;
134 smprintf(s, "Phone : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
135 entry->EntriesNum++;
136 }
137
138 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+30+i, msg.Buffer[29]*2);
139 entry->Entries[entry->EntriesNum].Text[msg.Buffer[29]*2] = 0;
140 entry->Entries[entry->EntriesNum].Text[msg.Buffer[29]*2+1] = 0;
141 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
142 break;
143 case 0x04:
144 smprintf(s, "Birthday\n");
145 Data->Cal->Type = GSM_CAL_BIRTHDAY;
146
147 /* Year was set earlier */
148 entry->Entries[0].Date.Month= Date.Month;
149 entry->Entries[0].Date.Day= Date.Day;
150 entry->Entries[0].Date.Hour= 23;
151 entry->Entries[0].Date.Minute= 59;
152 entry->Entries[0].Date.Second= 58;
153 entry->EntriesNum++;
154
155 N71_65_GetCalendarAlarm(s, msg.Buffer+16, entry, 0, Data);
156 N71_65_GetCalendarRecurrance(s, msg.Buffer+22, entry);
157
158 /* Birthday year */
159 entry->Entries[0].Date.Year = msg.Buffer[28]*256 + msg.Buffer[29];
160 if (msg.Buffer[28] == 0xff && msg.Buffer[29] == 0xff) entry->Entries[0].Date.Year = 0;
161 smprintf(s, "Birthday date: %02i-%02i-%04i\n",
162 entry->Entries[0].Date.Day,entry->Entries[0].Date.Month,
163 entry->Entries[0].Date.Year);
164
165 memcpy(entry->Entries[entry->EntriesNum].Text, msg.Buffer+32, msg.Buffer[31]*2);
166 entry->Entries[entry->EntriesNum].Text[msg.Buffer[31]*2] = 0;
167 entry->Entries[entry->EntriesNum].Text[msg.Buffer[31]*2+1] = 0;
168 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
169 break;
170 default:
171 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[6]);
172 return ERR_UNKNOWNRESPONSE;
173 }
174 smprintf(s, "Text : \"%s\"\n", DecodeUnicodeString(entry->Entries[entry->EntriesNum].Text));
175 entry->EntriesNum++;
176 return ERR_NONE;
177}
178
179/* method 2 */
180/* Note: in known phones texts of notes cut to 50 chars */
181GSM_Error N71_65_GetNextCalendar2(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, int *LastCalendarYear, int *LastCalendarPos)
182{
183 GSM_Error error;
184 GSM_DateTime date_time;
185 unsigned char req[] = {N6110_FRAME_HEADER, 0x3e,
186 0xFF, 0xFE}; /* Location */
187
188 if (start) {
189 /* We have to get current year. It's NOT written in frame for
190 * Birthday
191 */
192 error=s->Phone.Functions->GetDateTime(s,&date_time);
193 switch (error) {
194 case ERR_EMPTY:
195 case ERR_NOTIMPLEMENTED:
196 GSM_GetCurrentDateTime(&date_time);
197 break;
198 case ERR_NONE:
199 break;
200 default:
201 return error;
202 }
203 *LastCalendarYear = date_time.Year;
204
205 /* First location at all */
206 req[4] = 0xFF;
207 req[5] = 0xFE;
208 } else {
209 req[4] = *LastCalendarPos / 256;
210 req[5] = *LastCalendarPos % 256;
211 }
212 Note->EntriesNum = 0;
213 Note->Entries[0].Date.Year = *LastCalendarYear;
214
215 s->Phone.Data.Cal = Note;
216 smprintf(s, "Getting calendar note method 2\n");
217 error=GSM_WaitFor (s, req, 6, 0x13, 4, ID_GetCalendarNote);
218 *LastCalendarPos = Note->Location;
219 return error;
220}
221
222#endif
223
224/* How should editor hadle tabs in this file? Add editor commands here.
225 * vim: noexpandtab sw=8 ts=8 sts=8:
226 */
diff --git a/gammu/emb/common/phone/nokia/nfuncold.h b/gammu/emb/common/phone/nokia/nfuncold.h
new file mode 100644
index 0000000..236189c
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/nfuncold.h
@@ -0,0 +1,19 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef phone_nokia2_h
4#define phone_nokia2_h
5
6#include "ncommon.h"
7#include "../../gsmcomon.h"
8#include "../../gsmstate.h"
9
10#ifdef DEBUG
11 GSM_Error N71_65_ReplyGetNextCalendar2 (GSM_Protocol_Message msg, GSM_StateMachine *s);
12 GSM_Error N71_65_GetNextCalendar2 (GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start, int *LastCalendarYear, int *LastCalendarPos);
13#endif
14
15#endif
16
17/* How should editor hadle tabs in this file? Add editor commands here.
18 * vim: noexpandtab sw=8 ts=8 sts=8:
19 */
diff --git a/gammu/emb/common/phone/obex/obexgen.c b/gammu/emb/common/phone/obex/obexgen.c
new file mode 100644
index 0000000..dd14f8e
--- a/dev/null
+++ b/gammu/emb/common/phone/obex/obexgen.c
@@ -0,0 +1,851 @@
1/* (c) 2003 by Marcin Wiacek */
2/* www.irda.org OBEX specs 1.3 */
3
4/* Module connects to F9EC7BC4-953c-11d2-984E-525400DC9E09 UUID and in the
5 * future there will required implementing reconnecting. See "ifdef xxxx"
6 */
7
8#include <string.h>
9#include <time.h>
10
11#include "../../misc/coding/coding.h"
12#include "../../gsmcomon.h"
13#include "../../gsmstate.h"
14#include "../../service/gsmmisc.h"
15#include "../../protocol/obex/obex.h"
16
17#ifdef GSM_ENABLE_OBEXGEN
18
19static GSM_Error OBEXGEN_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start);
20
21static void OBEXGEN_FindNextDir(unsigned char *Path, int *Pos, unsigned char *Return)
22{
23 unsigned char buff[200];
24
25 buff[0] = 0;
26 while(1) {
27 if (Path[*Pos] == 0x00) break;
28 if (Path[*Pos] == '\\') {
29 (*Pos)++;
30 break;
31 }
32 buff[strlen(buff)+1] = 0;
33 buff[strlen(buff)] = Path[(*Pos)];
34 (*Pos)++;
35 }
36 EncodeUnicode(Return,buff,strlen(buff));
37}
38
39static GSM_Error OBEXGEN_ReplyConnect(GSM_Protocol_Message msg, GSM_StateMachine *s)
40{
41 switch (msg.Type) {
42 case 0xA0:
43 smprintf(s,"Connected/disconnected OK\n");
44 if (msg.Length != 0) {
45 s->Phone.Data.Priv.OBEXGEN.FrameSize = msg.Buffer[2]*256+msg.Buffer[3];
46 smprintf(s,"Maximal size of frame is %i 0x%x\n",s->Phone.Data.Priv.OBEXGEN.FrameSize,s->Phone.Data.Priv.OBEXGEN.FrameSize);
47 }
48 return ERR_NONE;
49 }
50 return ERR_UNKNOWNRESPONSE;
51}
52
53GSM_Error OBEXGEN_Disconnect(GSM_StateMachine *s)
54{
55 smprintf(s, "Disconnecting\n");
56 return GSM_WaitFor (s, NULL, 0, 0x81, 2, ID_Initialise);
57}
58
59GSM_Error OBEXGEN_Connect(GSM_StateMachine *s, OBEX_Service service)
60{
61 int Current=4;
62 unsigned char req2[200];
63 unsigned char req[200] = {
64 0x10, /* Version 1.0 */
65 0x00, /* no flags */
66 0x20,0x00}; /* 0x2000 max size of packet */
67
68 if (service == s->Phone.Data.Priv.OBEXGEN.Service) return ERR_NONE;
69
70 switch (service) {
71 case OBEX_None:
72 break;
73 case OBEX_BrowsingFolders:
74 /* Server ID */
75 req2[0] = 0xF9; req2[1] = 0xEC; req2[2] = 0x7B;
76 req2[3] = 0xC4; req2[4] = 0x95; req2[5] = 0x3C;
77 req2[6] = 0x11; req2[7] = 0xD2; req2[8] = 0x98;
78 req2[9] = 0x4E; req2[10]= 0x52; req2[11]= 0x54;
79 req2[12]= 0x00; req2[13]= 0xDC; req2[14]= 0x9E;
80 req2[15]= 0x09;
81
82 /* Target block */
83 OBEXAddBlock(req, &Current, 0x46, req2, 16);
84 }
85
86#ifndef xxxx
87 //disconnect old service
88#else
89 if (s->Phone.Data.Priv.OBEXGEN.Service != 0) return ERR_NONE;
90#endif
91
92 s->Phone.Data.Priv.OBEXGEN.Service = service;
93
94 smprintf(s, "Connecting\n");
95 return GSM_WaitFor (s, req, Current, 0x80, 2, ID_Initialise);
96}
97
98
99GSM_Error OBEXGEN_Initialise(GSM_StateMachine *s)
100{
101 // GSM_File File;
102 // GSM_Errorerror = ERR_NONE;
103
104 s->Phone.Data.Priv.OBEXGEN.Service = 0;
105
106 strcpy(s->Phone.Data.Model,"obex");
107
108 s->Phone.Data.VerNum = 0;
109 s->Phone.Data.Version[0] = 0;
110 s->Phone.Data.Manufacturer[0] = 0;
111
112 // File.Used = 0;
113 // File.ID_FullName[0] = 0;
114 // File.Buffer = NULL;
115 //while (error == ERR_NONE) error = OBEXGEN_GetFilePart(s,&File);
116
117 return ERR_NONE;
118}
119
120static GSM_Error OBEXGEN_ReplyChangePath(GSM_Protocol_Message msg, GSM_StateMachine *s)
121{
122 switch (msg.Type) {
123 case 0xA0:
124 smprintf(s,"Path set OK\n");
125 return ERR_NONE;
126 case 0xA1:
127 smprintf(s,"Folder created\n");
128 return ERR_NONE;
129 case 0xC3:
130 smprintf(s,"Security error\n");
131 return ERR_SECURITYERROR;
132 }
133 return ERR_UNKNOWNRESPONSE;
134}
135
136static GSM_Error OBEXGEN_ChangePath(GSM_StateMachine *s, char *Name, unsigned char Flag1)
137{
138 unsigned char req[400];
139 int Current = 2;
140
141 /* Flags */
142 req[0] = Flag1;
143 req[1] = 0x00;
144
145 /* Name block */
146 if (Name != NULL && UnicodeLength(Name) != 0) {
147 OBEXAddBlock(req, &Current, 0x01, Name, UnicodeLength(Name)*2+2);
148 } else {
149 OBEXAddBlock(req, &Current, 0x01, NULL, 0);
150 }
151
152 /* connection ID block */
153 req[Current++] = 0xCB; // ID
154 req[Current++] = 0x00; req[Current++] = 0x00;
155 req[Current++] = 0x00; req[Current++] = 0x01;
156
157 return GSM_WaitFor (s, req, Current, 0x85, 4, ID_SetPath);
158}
159
160static GSM_Error OBEXGEN_ReplyAddFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
161{
162 switch (msg.Type) {
163 case 0x90:
164 smprintf(s,"Last part of file added OK\n");
165 return ERR_NONE;
166 case 0xA0:
167 smprintf(s,"Part of file added OK\n");
168 return ERR_NONE;
169 case 0xC0:
170 smprintf(s,"Not understand. Probably not supported\n");
171 return ERR_NOTSUPPORTED;
172 }
173 return ERR_UNKNOWNRESPONSE;
174}
175
176GSM_Error OBEXGEN_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos)
177{
178 GSM_Error error;
179 int j;
180 unsigned int Pos2, Current = 0;
181 unsigned char req[2000],req2[200];
182
183 s->Phone.Data.File = File;
184
185 if (*Pos == 0) {
186 if (!strcmp(File->ID_FullName,"")) {
187#ifndef xxxx
188 error = OBEXGEN_Connect(s,OBEX_None);
189#else
190 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
191#endif
192 if (error != ERR_NONE) return error;
193 } else {
194 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
195 if (error != ERR_NONE) return error;
196
197 if (strcmp(s->CurrentConfig->Model,"seobex")) {
198 smprintf(s,"Changing to root\n");
199 error = OBEXGEN_ChangePath(s, NULL, 2);
200 if (error != ERR_NONE) return error;
201
202 Pos2 = 0;
203 do {
204 OBEXGEN_FindNextDir(File->ID_FullName, &Pos2, req2);
205 smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos2,strlen(File->ID_FullName));
206 smprintf(s,"Changing path down\n");
207 error=OBEXGEN_ChangePath(s, req2, 2);
208 if (error != ERR_NONE) return error;
209 if (Pos2 == strlen(File->ID_FullName)) break;
210 } while (1);
211 }
212 }
213
214 /* Name block */
215 OBEXAddBlock(req, &Current, 0x01, File->Name, UnicodeLength(File->Name)*2+2);
216
217 /* File size block */
218 req[Current++] = 0xC3; // ID
219 req[Current++] = 0;
220 req[Current++] = 0;
221 req[Current++] = File->Used / 256;
222 req[Current++] = File->Used % 256;
223 }
224
225 if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) {
226 /* connection ID block */
227 req[Current++] = 0xCB; // ID
228 req[Current++] = 0x00; req[Current++] = 0x00;
229 req[Current++] = 0x00; req[Current++] = 0x01;
230 }
231
232 j = s->Phone.Data.Priv.OBEXGEN.FrameSize - Current - 20;
233 if (j > 1000) j = 1000;
234
235 if (File->Used - *Pos < j) {
236 j = File->Used - *Pos;
237 /* End of file body block */
238 OBEXAddBlock(req, &Current, 0x49, File->Buffer+(*Pos), j);
239 smprintf(s, "Adding file part %i %i\n",*Pos,j);
240 *Pos = *Pos + j;
241 error = GSM_WaitFor (s, req, Current, 0x82, 4, ID_AddFile);
242 if (error != ERR_NONE) return error;
243 return ERR_EMPTY;
244 } else {
245 /* File body block */
246 OBEXAddBlock(req, &Current, 0x48, File->Buffer+(*Pos), j);
247 smprintf(s, "Adding file part %i %i\n",*Pos,j);
248 *Pos = *Pos + j;
249 error=GSM_WaitFor (s, req, Current, 0x02, 4, ID_AddFile);
250 }
251 return error;
252}
253
254static GSM_Error OBEXGEN_ReplyGetFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s)
255{
256 int old,Pos=0;
257
258 switch (msg.Type) {
259 case 0xA0:
260 smprintf(s,"File part received\n");
261 s->Phone.Data.Priv.OBEXGEN.FileLastPart = true;
262 case 0x90:
263 // if (msg.Length < 11) return ERR_NONE;
264 if (msg.Type == 0x90) smprintf(s,"Last file part received\n");
265 while(1) {
266 if (Pos >= msg.Length) break;
267 switch (msg.Buffer[Pos]) {
268 case 0x48:
269 case 0x49:
270 smprintf(s,"File part received\n");
271 old = s->Phone.Data.File->Used;
272 s->Phone.Data.File->Used += msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3;
273 smprintf(s,"Length of file part: %i\n",
274 msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3);
275 s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
276 memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+Pos+3,s->Phone.Data.File->Used-old);
277 return ERR_NONE;
278 default:
279 break;
280 }
281 Pos+=msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2];
282 }
283 return ERR_UNKNOWNRESPONSE;
284 case 0xC3:
285 return ERR_NOTSUPPORTED;
286 case 0xC4:
287 smprintf(s,"Not found\n");
288 return ERR_SECURITYERROR;
289 }
290 return ERR_UNKNOWNRESPONSE;
291}
292
293static GSM_Error OBEXGEN_ReplyGetFileInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
294{
295 int old,Pos=0;
296
297 switch (msg.Type) {
298 case 0x83:
299 smprintf(s,"Not available ?\n");
300 return ERR_NONE;
301 case 0x90:
302 smprintf(s,"Last part of file info received\n");
303 return ERR_NONE;
304 case 0xA0:
305 while(1) {
306 if (Pos >= msg.Length) break;
307 switch (msg.Buffer[Pos]) {
308 case 0x48:
309 case 0x49:
310 /* SE T310 */
311 smprintf(s,"File part received\n");
312 old = s->Phone.Data.File->Used;
313 s->Phone.Data.File->Used += msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3;
314 smprintf(s,"Length of file part: %i\n",
315 msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3);
316 s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
317 memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+Pos+3,s->Phone.Data.File->Used-old);
318 return ERR_EMPTY;
319 default:
320 break;
321 }
322 Pos+=msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2];
323 }
324 return ERR_UNKNOWNRESPONSE;
325 }
326 return ERR_UNKNOWNRESPONSE;
327}
328
329static GSM_Error OBEXGEN_PrivGetFilePart(GSM_StateMachine *s, GSM_File *File, bool FolderList)
330{
331 unsigned int Current = 0, Pos;
332 GSM_Error error;
333 unsigned char req[2000], req2[200];
334
335 s->Phone.Data.File = File;
336 File->ReadOnly = false;
337 File->Protected = false;
338 File->Hidden = false;
339 File->System = false;
340
341 if (File->Used == 0x00) {
342 if (FolderList) {
343 /* Type block */
344 strcpy(req2,"x-obex/folder-listing");
345 OBEXAddBlock(req, &Current, 0x42, req2, strlen(req2)+1);
346
347 /* Name block */
348 if (UnicodeLength(File->Name) == 0x00) {
349 OBEXAddBlock(req, &Current, 0x01, NULL, 0);
350 } else {
351 CopyUnicodeString(req2,File->Name);
352 OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2);
353 }
354 } else {
355 File->Folder = false;
356
357 if (File->ID_FullName[0] == 0x00) {
358#ifndef xxxx
359 error = OBEXGEN_Connect(s,OBEX_None);
360#else
361 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
362#endif
363 if (error != ERR_NONE) return error;
364
365 EncodeUnicode(File->Name,"one",3);
366
367 if (strcmp(s->CurrentConfig->Model,"seobex")) {
368 strcpy(req2,"x-obex/capability");
369 // strcpy(req2,"x-obex/object-profile");
370
371 /* Type block */
372 OBEXAddBlock(req, &Current, 0x42, req2, strlen(req2)+1);
373 } else {
374 EncodeUnicode(req2,"telecom/devinfo.txt",19);
375
376 /* Name block */
377 OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2);
378 }
379 } else {
380 // error = OBEXGEN_Connect(s,OBEX_None);
381 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
382 if (error != ERR_NONE) return error;
383
384 if (strcmp(s->CurrentConfig->Model,"seobex")) {
385 smprintf(s,"Changing to root\n");
386 error = OBEXGEN_ChangePath(s, NULL, 2);
387 if (error != ERR_NONE) return error;
388
389 Pos = 0;
390 do {
391 OBEXGEN_FindNextDir(File->ID_FullName, &Pos, req2);
392 smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(File->ID_FullName));
393 if (Pos == strlen(File->ID_FullName)) break;
394 smprintf(s,"Changing path down\n");
395 error=OBEXGEN_ChangePath(s, req2, 2);
396 if (error != ERR_NONE) return error;
397 } while (1);
398 } else {
399 EncodeUnicode(req2,File->ID_FullName,strlen(File->ID_FullName));
400 }
401 CopyUnicodeString(File->Name,req2);
402
403 s->Phone.Data.File = File;
404
405 Current = 0;
406 /* Name block */
407 OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2);
408 }
409 }
410 }
411
412 if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) {
413 /* connection ID block */
414 req[Current++] = 0xCB; // ID
415 req[Current++] = 0x00; req[Current++] = 0x00;
416 req[Current++] = 0x00; req[Current++] = 0x01;
417 }
418
419 smprintf(s, "Getting file info from filesystem\n");
420 error=GSM_WaitFor (s, req, Current, 0x03, 4, ID_GetFileInfo);
421 if (error != ERR_NONE) return error;
422
423 s->Phone.Data.Priv.OBEXGEN.FileLastPart = false;
424
425 while (!s->Phone.Data.Priv.OBEXGEN.FileLastPart) {
426 Current = 0;
427 if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) {
428 /* connection ID block */
429 req[Current++] = 0xCB; // ID
430 req[Current++] = 0x00; req[Current++] = 0x00;
431 req[Current++] = 0x00; req[Current++] = 0x01;
432 }
433 smprintf(s, "Getting file part from filesystem\n");
434 error=GSM_WaitFor (s, req, Current, 0x83, 4, ID_GetFile);
435 if (error != ERR_NONE) return error;
436 }
437 return ERR_EMPTY;
438}
439
440GSM_Error OBEXGEN_GetFilePart(GSM_StateMachine *s, GSM_File *File)
441{
442 return OBEXGEN_PrivGetFilePart(s,File,false);
443}
444
445static GSM_Error OBEXGEN_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start)
446{
447 GSM_Phone_OBEXGENData*Priv = &s->Phone.Data.Priv.OBEXGEN;
448 GSM_Error error;
449 unsigned char Line[500],Line2[500],*name,*size;
450 int Pos,i,j,num,pos2,Current,z;
451
452 if (start) {
453 if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED;
454
455 Priv->Files[0].Folder = true;
456 Priv->Files[0].Level = 1;
457 Priv->Files[0].Name[0] = 0;
458 Priv->Files[0].Name[1] = 0;
459 Priv->Files[0].ID_FullName[0]= 0;
460 Priv->Files[0].ID_FullName[1]= 0;
461
462 Priv->FilesLocationsUsed = 1;
463 Priv->FilesLocationsCurrent = 0;
464 Priv->FileLev = 1;
465
466 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
467 if (error != ERR_NONE) return error;
468
469 smprintf(s,"Changing to root\n");
470 error = OBEXGEN_ChangePath(s, NULL, 2);
471 if (error != ERR_NONE) return error;
472
473 Current = 0;
474 }
475
476 while (1) {
477 if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) {
478 dbgprintf("Last file\n");
479 return ERR_EMPTY;
480 }
481
482 strcpy(File->ID_FullName,Priv->Files[Priv->FilesLocationsCurrent].ID_FullName);
483 File->Level= Priv->Files[Priv->FilesLocationsCurrent].Level;
484 File->Folder= Priv->Files[Priv->FilesLocationsCurrent].Folder;
485 CopyUnicodeString(File->Name,Priv->Files[Priv->FilesLocationsCurrent].Name);
486 Priv->FilesLocationsCurrent++;
487
488 if (File->Folder) {
489 if (File->Level < Priv->FileLev) {
490 for (i=0;i<File->Level;i++) {
491 smprintf(s,"Changing path up\n");
492 error=OBEXGEN_ChangePath(s, NULL, 2);
493 if (error != ERR_NONE) return error;
494 }
495 }
496
497 smprintf(s,"Level %i %i\n",File->Level,Priv->FileLev);
498
499 File->Buffer = NULL;
500 File->Used = 0;
501 OBEXGEN_PrivGetFilePart(s, File,true);
502
503 num = 0;
504 Pos = 0;
505 while (1) {
506 MyGetLine(File->Buffer, &Pos, Line, File->Used);
507 if (strlen(Line) == 0) break;
508 name = strstr(Line,"folder name=\"");
509 if (name != NULL) {
510 name += 13;
511 j = 0;
512 while(1) {
513 if (name[j] == '"') break;
514 j++;
515 }
516 name[j] = 0;
517
518 if (strcmp(name,".")) num++;
519 }
520 name = strstr(Line,"file name=\"");
521 if (name != NULL) num++;
522 }
523 if (num != 0) {
524 i = Priv->FilesLocationsUsed-1;
525 while (1) {
526 if (i==Priv->FilesLocationsCurrent-1) break;
527 memcpy(&Priv->Files[i+num],&Priv->Files[i],sizeof(GSM_File));
528 i--;
529 }
530 }
531
532 Pos = 0;
533 pos2 = 0;
534 while (1) {
535 MyGetLine(File->Buffer, &Pos, Line, File->Used);
536 if (strlen(Line) == 0) break;
537 strcpy(Line2,Line);
538 name = strstr(Line2,"folder name=\"");
539 if (name != NULL) {
540 name += 13;
541 j = 0;
542 while(1) {
543 if (name[j] == '"') break;
544 j++;
545 }
546 name[j] = 0;
547 if (strcmp(name,".")) {
548 dbgprintf("copying folder %s to %i parent %i\n",name,Priv->FilesLocationsCurrent+pos2,Priv->FilesLocationsCurrent);
549 strcpy(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,File->ID_FullName);
550 if (strlen(File->ID_FullName) != 0) strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,"\\");
551 strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,name);
552 Priv->Files[Priv->FilesLocationsCurrent+pos2].Level = File->Level+1;
553 Priv->Files[Priv->FilesLocationsCurrent+pos2].Folder = true;
554 EncodeUnicode(Priv->Files[Priv->FilesLocationsCurrent+pos2].Name,name,strlen(name));
555 Priv->FilesLocationsUsed++;
556 pos2++;
557 }
558 }
559 strcpy(Line2,Line);
560 name = strstr(Line2,"file name=\"");
561 if (name != NULL) {
562 name += 11;
563 j = 0;
564 while(1) {
565 if (name[j] == '"') break;
566 j++;
567 }
568 name[j] = 0;
569 dbgprintf("copying file %s to %i\n",name,Priv->FilesLocationsCurrent+pos2);
570 Priv->Files[Priv->FilesLocationsCurrent+pos2].Level= File->Level+1;
571 Priv->Files[Priv->FilesLocationsCurrent+pos2].Folder = false;
572 strcpy(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,File->ID_FullName);
573 if (strlen(File->ID_FullName) != 0) strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,"\\");
574 strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,name);
575 EncodeUnicode(Priv->Files[Priv->FilesLocationsCurrent+pos2].Name,name,strlen(name));
576
577 Priv->Files[Priv->FilesLocationsCurrent+pos2].Used = 0;
578 strcpy(Line2,Line);
579 size = strstr(Line2,"size=\"");
580 if (size != NULL) Priv->Files[Priv->FilesLocationsCurrent+pos2].Used = atoi(size+6);
581
582 Priv->Files[Priv->FilesLocationsCurrent+pos2].ModifiedEmpty = true;
583 strcpy(Line2,Line);
584 size = strstr(Line2,"modified=\"");
585 if (size != NULL) {
586 Priv->Files[Priv->FilesLocationsCurrent+pos2].ModifiedEmpty = false;
587 ReadVCALDateTime(size+10, &Priv->Files[Priv->FilesLocationsCurrent+pos2].Modified);
588 }
589 Priv->FilesLocationsUsed++;
590 pos2++;
591 }
592 }
593
594 z = Priv->FilesLocationsCurrent;
595 if (z != 1) {
596 while (1) {
597 if (z == Priv->FilesLocationsUsed) break;
598 if (Priv->Files[z].Folder) {
599 if (Priv->Files[z].Level > File->Level) {
600 smprintf(s,"Changing path down\n");
601 error=OBEXGEN_ChangePath(s, File->Name, 2);
602 if (error != ERR_NONE) return error;
603 }
604 break;
605 }
606 z++;
607 }
608 }
609
610 Priv->FileLev = File->Level;
611 free(File->Buffer);
612 } else {
613 File->Used = Priv->Files[Priv->FilesLocationsCurrent-1].Used;
614 File->ModifiedEmpty = Priv->Files[Priv->FilesLocationsCurrent-1].ModifiedEmpty;
615 if (!File->ModifiedEmpty) {
616 memcpy(&File->Modified,&Priv->Files[Priv->FilesLocationsCurrent-1].Modified,sizeof(GSM_DateTime));
617 }
618 File->ReadOnly = false;
619 File->Protected = false;
620 File->Hidden = false;
621 File->System = false;
622
623 }
624 return ERR_NONE;
625 }
626}
627
628static GSM_Error OBEXGEN_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
629{
630 GSM_Error error;
631 unsigned int Current = 0, Pos;
632 unsigned char req[200],req2[200];
633
634 if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED;
635
636 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
637 if (error != ERR_NONE) return error;
638
639 smprintf(s,"Changing to root\n");
640 error = OBEXGEN_ChangePath(s, NULL, 2);
641 if (error != ERR_NONE) return error;
642
643 Pos = 0;
644 do {
645 OBEXGEN_FindNextDir(ID, &Pos, req2);
646 smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(ID));
647 if (Pos == strlen(ID)) break;
648 smprintf(s,"Changing path down\n");
649 error=OBEXGEN_ChangePath(s, req2, 2);
650 if (error != ERR_NONE) return error;
651 } while (1);
652
653 /* Name block */
654 OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2);
655
656 /* connection ID block */
657 req[Current++] = 0xCB; // ID
658 req[Current++] = 0x00; req[Current++] = 0x00;
659 req[Current++] = 0x00; req[Current++] = 0x01;
660
661 return GSM_WaitFor (s, req, Current, 0x82, 4, ID_AddFile);
662}
663
664static GSM_Error OBEXGEN_AddFolder(GSM_StateMachine *s, GSM_File *File)
665{
666 GSM_Error error;
667 unsigned char req2[200];
668 unsigned int Pos;
669
670 if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED;
671
672 error = OBEXGEN_Connect(s,OBEX_BrowsingFolders);
673 if (error != ERR_NONE) return error;
674
675 smprintf(s,"Changing to root\n");
676 error = OBEXGEN_ChangePath(s, NULL, 2);
677 if (error != ERR_NONE) return error;
678
679 Pos = 0;
680 do {
681 OBEXGEN_FindNextDir(File->ID_FullName, &Pos, req2);
682 smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(File->ID_FullName));
683 smprintf(s,"Changing path down\n");
684 error=OBEXGEN_ChangePath(s, req2, 2);
685 if (error != ERR_NONE) return error;
686 if (Pos == strlen(File->ID_FullName)) break;
687 } while (1);
688
689 smprintf(s,"Adding directory\n");
690 return OBEXGEN_ChangePath(s, File->Name, 0);
691}
692
693GSM_Reply_Function OBEXGENReplyFunctions[] = {
694 /* CONTINUE block */
695 {OBEXGEN_ReplyAddFilePart, "\x90",0x00,0x00,ID_AddFile },
696 {OBEXGEN_ReplyGetFilePart, "\x90",0x00,0x00,ID_GetFile },
697 {OBEXGEN_ReplyGetFileInfo, "\x90",0x00,0x00,ID_GetFileInfo },
698
699 /* OK block */
700 {OBEXGEN_ReplyChangePath, "\xA0",0x00,0x00,ID_SetPath },
701 {OBEXGEN_ReplyConnect, "\xA0",0x00,0x00,ID_Initialise },
702 {OBEXGEN_ReplyAddFilePart, "\xA0",0x00,0x00,ID_AddFile },
703 {OBEXGEN_ReplyGetFilePart, "\xA0",0x00,0x00,ID_GetFile },
704 {OBEXGEN_ReplyGetFileInfo, "\xA0",0x00,0x00,ID_GetFileInfo },
705
706 /* FOLDER CREATED block */
707 {OBEXGEN_ReplyChangePath, "\xA1",0x00,0x00,ID_SetPath },
708
709 /* NOT UNDERSTAND block */
710 {OBEXGEN_ReplyAddFilePart, "\xC0",0x00,0x00,ID_AddFile },
711
712 /* FORBIDDEN block */
713 {OBEXGEN_ReplyChangePath, "\xC3",0x00,0x00,ID_SetPath },
714 {OBEXGEN_ReplyGetFilePart, "\xC3",0x00,0x00,ID_GetFile },
715
716 /* NOT FOUND block */
717 {OBEXGEN_ReplyGetFilePart, "\xC4",0x00,0x00,ID_GetFile },
718
719 {NULL, "\x00",0x00,0x00,ID_None }
720};
721
722GSM_Phone_Functions OBEXGENPhone = {
723 "obex|seobex",
724 OBEXGENReplyFunctions,
725 OBEXGEN_Initialise,
726 NONEFUNCTION, /* Terminate */
727 GSM_DispatchMessage,
728 NOTIMPLEMENTED, /* ShowStartInfo */
729 NONEFUNCTION, /* GetManufacturer */
730 NONEFUNCTION, /* GetModel */
731 NONEFUNCTION, /* GetFirmware */
732 NOTIMPLEMENTED, /* GetIMEI */
733 NOTIMPLEMENTED, /* GetOriginalIMEI */
734 NOTIMPLEMENTED, /* GetManufactureMonth*/
735 NOTIMPLEMENTED, /* GetProductCode */
736 NOTIMPLEMENTED, /* GetHardware */
737 NOTIMPLEMENTED, /* GetPPM */
738 NOTIMPLEMENTED, /* GetSIMIMSI */
739 NOTIMPLEMENTED, /* GetDateTime */
740 NOTIMPLEMENTED, /* SetDateTime */
741 NOTIMPLEMENTED, /* GetAlarm */
742 NOTIMPLEMENTED, /* SetAlarm */
743 NOTSUPPORTED, /* GetLocale */
744 NOTSUPPORTED, /* SetLocale */
745 NOTIMPLEMENTED, /* PressKey */
746 NOTIMPLEMENTED, /* Reset */
747 NOTIMPLEMENTED, /* ResetPhoneSettings*/
748 NOTIMPLEMENTED, /* EnterSecurityCode*/
749 NOTIMPLEMENTED, /* GetSecurityStatus*/
750 NOTIMPLEMENTED, /* GetDisplayStatus*/
751 NOTIMPLEMENTED, /* SetAutoNetworkLogin*/
752 NOTIMPLEMENTED, /* GetBatteryCharge*/
753 NOTIMPLEMENTED, /* GetSignalQuality*/
754 NOTIMPLEMENTED, /* GetNetworkInfo */
755 NOTIMPLEMENTED, /* GetCategory */
756 NOTSUPPORTED, /* AddCategory */
757 NOTIMPLEMENTED, /* GetCategoryStatus */
758 NOTIMPLEMENTED, /* GetMemoryStatus */
759 NOTIMPLEMENTED, /* GetMemory */
760 NOTIMPLEMENTED, /* GetNextMemory */
761 NOTIMPLEMENTED, /* SetMemory */
762 NOTIMPLEMENTED, /* AddMemory */
763 NOTIMPLEMENTED, /* DeleteMemory */
764 NOTIMPLEMENTED, /* DeleteAllMemory */
765 NOTIMPLEMENTED, /* GetSpeedDial */
766 NOTIMPLEMENTED, /* SetSpeedDial */
767 NOTIMPLEMENTED, /* GetSMSC */
768 NOTIMPLEMENTED, /* SetSMSC */
769 NOTIMPLEMENTED, /* GetSMSStatus */
770 NOTIMPLEMENTED, /* GetSMS */
771 NOTIMPLEMENTED, /* GetNextSMS */
772 NOTIMPLEMENTED, /* SetSMS */
773 NOTIMPLEMENTED, /* AddSMS */
774 NOTIMPLEMENTED, /* DeleteSMS */
775 NOTIMPLEMENTED, /* SendSMSMessage */
776 NOTSUPPORTED, /* SendSavedSMS */
777 NOTIMPLEMENTED, /* SetIncomingSMS */
778 NOTIMPLEMENTED, /* SetIncomingCB */
779 NOTIMPLEMENTED, /* GetSMSFolders */
780 NOTIMPLEMENTED, /* AddSMSFolder */
781 NOTIMPLEMENTED, /* DeleteSMSFolder */
782 NOTIMPLEMENTED, /* DialVoice */
783 NOTIMPLEMENTED, /* AnswerCall */
784 NOTIMPLEMENTED, /* CancelCall */
785 NOTIMPLEMENTED, /* HoldCall */
786 NOTIMPLEMENTED, /* UnholdCall */
787 NOTIMPLEMENTED, /* ConferenceCall */
788 NOTIMPLEMENTED, /* SplitCall */
789 NOTIMPLEMENTED, /* TransferCall */
790 NOTIMPLEMENTED, /* SwitchCall */
791 NOTIMPLEMENTED, /* GetCallDivert */
792 NOTIMPLEMENTED, /* SetCallDivert */
793 NOTIMPLEMENTED, /* CancelAllDiverts*/
794 NOTIMPLEMENTED, /* SetIncomingCall */
795 NOTIMPLEMENTED, /* SetIncomingUSSD */
796 NOTIMPLEMENTED, /* SendDTMF */
797 NOTIMPLEMENTED, /* GetRingtone */
798 NOTIMPLEMENTED, /* SetRingtone */
799 NOTIMPLEMENTED, /* GetRingtonesInfo*/
800 NOTIMPLEMENTED, /* DeleteUserRingtones*/
801 NOTIMPLEMENTED, /* PlayTone */
802 NOTIMPLEMENTED, /* GetWAPBookmark */
803 NOTIMPLEMENTED, /* SetWAPBookmark */
804 NOTIMPLEMENTED, /* DeleteWAPBookmark */
805 NOTIMPLEMENTED, /* GetWAPSettings */
806 NOTIMPLEMENTED, /* SetWAPSettings */
807 NOTIMPLEMENTED, /* GetMMSSettings */
808 NOTIMPLEMENTED, /* SetMMSSettings */
809 NOTSUPPORTED, /* GetSyncMLSettings*/
810 NOTSUPPORTED, /* SetSyncMLSettings*/
811 NOTSUPPORTED, /* GetChatSettings */
812 NOTSUPPORTED, /* SetChatSettings */
813 NOTIMPLEMENTED, /* GetBitmap */
814 NOTIMPLEMENTED, /* SetBitmap */
815 NOTIMPLEMENTED, /* GetToDoStatus */
816 NOTIMPLEMENTED, /* GetToDo */
817 NOTIMPLEMENTED, /* GetNextToDo */
818 NOTIMPLEMENTED, /* SetToDo */
819 NOTIMPLEMENTED, /* AddToDo */
820 NOTIMPLEMENTED, /* DeleteToDo */
821 NOTIMPLEMENTED, /* DeleteAllToDo */
822 NOTIMPLEMENTED, /* GetCalendarStatus*/
823 NOTIMPLEMENTED, /* GetCalendar */
824 NOTIMPLEMENTED, /* GetNextCalendar */
825 NOTIMPLEMENTED, /* SetCalendar */
826 NOTIMPLEMENTED, /* AddCalendar */
827 NOTIMPLEMENTED, /* DeleteCalendar */
828 NOTIMPLEMENTED, /* DeleteAllCalendar*/
829 NOTSUPPORTED, /* GetCalendarSettings*/
830 NOTSUPPORTED, /* SetCalendarSettings*/
831 NOTSUPPORTED, /* GetNote */
832 NOTIMPLEMENTED, /* GetProfile */
833 NOTIMPLEMENTED, /* SetProfile */
834 NOTIMPLEMENTED, /* GetFMStation */
835 NOTIMPLEMENTED, /* SetFMStation */
836 NOTIMPLEMENTED, /* ClearFMStations */
837 OBEXGEN_GetNextFileFolder,
838 OBEXGEN_GetFilePart,
839 OBEXGEN_AddFilePart,
840 NOTIMPLEMENTED, /* GetFileSystemStatus*/
841 OBEXGEN_DeleteFile,
842 OBEXGEN_AddFolder,
843 NOTIMPLEMENTED, /* GetGPRSAccessPoint*/
844 NOTIMPLEMENTED /* SetGPRSAccessPoint*/
845};
846
847#endif
848
849/* How should editor hadle tabs in this file? Add editor commands here.
850 * vim: noexpandtab sw=8 ts=8 sts=8:
851 */
diff --git a/gammu/emb/common/phone/obex/obexgen.h b/gammu/emb/common/phone/obex/obexgen.h
new file mode 100644
index 0000000..466fef5
--- a/dev/null
+++ b/gammu/emb/common/phone/obex/obexgen.h
@@ -0,0 +1,38 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef obexgen_h
4#define obexgen_h
5
6#include "../../gsmcomon.h"
7#include "../../gsmstate.h"
8#include "../../service/gsmmisc.h"
9#include "../../service/sms/gsmsms.h"
10
11#ifndef GSM_USED_IRDAOBEX
12# define GSM_USED_IRDAOBEX
13#endif
14#ifndef GSM_USED_BLUEOBEX
15# define GSM_USED_BLUEOBEX
16#endif
17
18typedef enum {
19 OBEX_None = 1,
20 OBEX_BrowsingFolders
21} OBEX_Service;
22
23typedef struct {
24 int FileLev;
25 int FilesLocationsUsed;
26 int FilesLocationsCurrent;
27 GSM_File Files[500];
28 bool FileLastPart;
29
30 int FrameSize;
31 OBEX_Service Service;
32} GSM_Phone_OBEXGENData;
33
34#endif
35
36/* How should editor hadle tabs in this file? Add editor commands here.
37 * vim: noexpandtab sw=8 ts=8 sts=8:
38 */
diff --git a/gammu/emb/common/phone/pfunc.c b/gammu/emb/common/phone/pfunc.c
new file mode 100644
index 0000000..a03a81d
--- a/dev/null
+++ b/gammu/emb/common/phone/pfunc.c
@@ -0,0 +1,138 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../gsmstate.h"
7#include "../service/sms/gsmsms.h"
8#include "../misc/coding/coding.h"
9
10/* These SMS layouts are used exactly as written in Nokia DCT3 phones.
11 * In AT module(s) we have to use some layouts to convert AT frame to format
12 * understod by SMS module. To share source the same layouts are used */
13GSM_SMSMessageLayout PHONE_SMSDeliver = {
14 35 /* SMS Text */, 16 /* Phone number*/,
15 0 /* SMSC Number */, 14 /* TPDCS */,
16 28 /* SendingDateTime */, 255 /* SMSCDateTime*/,
17 255 /* TPStatus */, 15 /* TPUDL */,
18 255 /* TPVP */, 12 /* firstbyte*/,
19 255 /* TPMR */, 13 /* TPPID */};
20GSM_SMSMessageLayout PHONE_SMSSubmit = {
21 36 /* SMS Text */, 17 /* Phone number*/,
22 0 /* SMSC Number */, 15 /* TPDCS */,
23 255 /* SendingDateTime */, 255 /* SMSCDateTime*/,
24 255 /* TPStatus */, 16 /* TPUDL */,
25 29 /* TPVP */, 12 /* firstbyte*/,
26 13 /* TPMR */, 14 /* TPPID */};
27GSM_SMSMessageLayout PHONE_SMSStatusReport = {
28 255 /* SMS Text */, 15 /* Phone number*/,
29 0 /* SMSC Number */, 255 /* TPDCS */,
30 27 /* SendingDateTime */, 34 /* SMSCDateTime*/,
31 14 /* TPStatus */, 255 /* TPUDL */,
32 255 /* TPVP */, 12 /* firstbyte*/,
33 13 /* TPMR */, 255 /* TPPID?? */};
34
35GSM_Error PHONE_GetSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
36{
37 folders->Number=2;
38 EncodeUnicode(folders->Folder[0].Name,GetMsg(s->msg,"Inbox"),strlen(GetMsg(s->msg,"Inbox")));
39 EncodeUnicode(folders->Folder[1].Name,GetMsg(s->msg,"Outbox"),strlen(GetMsg(s->msg,"Outbox")));
40 folders->Folder[0].InboxFolder = true;
41 folders->Folder[1].InboxFolder = false;
42 folders->Folder[0].Memory = MEM_SM;
43 folders->Folder[1].Memory = MEM_SM;
44 return ERR_NONE;
45}
46
47void GSM_CreateFirmwareNumber(GSM_StateMachine *s)
48{
49 StringToDouble(s->Phone.Data.Version, &s->Phone.Data.VerNum);
50 dbgprintf("Number version is \"%f\"\n", s->Phone.Data.VerNum);
51}
52
53GSM_Error PHONE_EncodeSMSFrame(GSM_StateMachine *s, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear)
54{
55 GSM_Error error;
56
57 if (SMS->SMSC.Location!=0) {
58 error = s->Phone.Functions->GetSMSC(s, &SMS->SMSC);
59 if (error != ERR_NONE) return error;
60 SMS->SMSC.Location = 0;
61 }
62 if (SMS->PDU == SMS_Deliver) {
63 if (SMS->SMSC.Number[0] == 0x00 && SMS->SMSC.Number[1] == 0x00) {
64 return ERR_EMPTYSMSC;
65 }
66 }
67 return GSM_EncodeSMSFrame(SMS, buffer, Layout, length, clear);
68}
69
70GSM_Error PHONE_Terminate(GSM_StateMachine *s)
71{
72 GSM_Error error;
73
74 if (s->Phone.Data.EnableIncomingCB==true) {
75 error=s->Phone.Functions->SetIncomingCB(s,false);
76 if (error!=ERR_NONE) return error;
77 }
78 if (s->Phone.Data.EnableIncomingSMS==true) {
79 error=s->Phone.Functions->SetIncomingSMS(s,false);
80 if (error!=ERR_NONE) return error;
81 }
82 return ERR_NONE;
83}
84
85GSM_Error PHONE_RTTLPlayOneNote(GSM_StateMachine *s, GSM_RingNote note, bool first)
86{
87 int duration, Hz;
88 GSM_Error error;
89
90 Hz=GSM_RingNoteGetFrequency(note);
91
92 error=s->Phone.Functions->PlayTone(s,Hz,5,first);
93 if (error!=ERR_NONE) return error;
94
95 duration = GSM_RingNoteGetFullDuration(note);
96
97 /* Is it correct ? Experimental values here */
98 switch (note.Style) {
99 case StaccatoStyle:
100 my_sleep (7500);
101 error=s->Phone.Functions->PlayTone(s,0,0,false);
102 if (error != ERR_NONE) return error;
103 my_sleep ((1400000/note.Tempo*duration)-(7500));
104 break;
105 case ContinuousStyle:
106 my_sleep (1400000/note.Tempo*duration);
107 break;
108 case NaturalStyle:
109 my_sleep (1400000/note.Tempo*duration-50);
110 error=s->Phone.Functions->PlayTone(s,0,0,false);
111 if (error != ERR_NONE) return error;
112 my_sleep (50);
113 break;
114 }
115 return ERR_NONE;
116}
117
118GSM_Error PHONE_Beep(GSM_StateMachine *s)
119{
120 GSM_Error error;
121
122 error=s->Phone.Functions->PlayTone(s, 4000, 5,true);
123 if (error!=ERR_NONE) return error;
124
125 my_sleep(500);
126
127 return s->Phone.Functions->PlayTone(s,255*255,0,false);
128}
129
130GSM_Error NoneReply(GSM_Protocol_Message msg, GSM_StateMachine *s)
131{
132 smprintf(s,"None answer\n");
133 return ERR_NONE;
134}
135
136/* How should editor hadle tabs in this file? Add editor commands here.
137 * vim: noexpandtab sw=8 ts=8 sts=8:
138 */
diff --git a/gammu/emb/common/phone/pfunc.h b/gammu/emb/common/phone/pfunc.h
new file mode 100644
index 0000000..859085c
--- a/dev/null
+++ b/gammu/emb/common/phone/pfunc.h
@@ -0,0 +1,30 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef phone_common2_h
4#define phone_common2_h
5
6#include "../service/sms/gsmsms.h"
7
8extern GSM_SMSMessageLayout PHONE_SMSSubmit;
9extern GSM_SMSMessageLayout PHONE_SMSDeliver;
10extern GSM_SMSMessageLayout PHONE_SMSStatusReport;
11
12 GSM_Error PHONE_GetSMSFolders (GSM_StateMachine *s, GSM_SMSFolders *folders);
13
14 void GSM_CreateFirmwareNumber(GSM_StateMachine *s);
15
16 GSM_Error PHONE_EncodeSMSFrame (GSM_StateMachine *s, GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear);
17
18 GSM_Error PHONE_Terminate (GSM_StateMachine *s);
19
20 GSM_Error PHONE_RTTLPlayOneNote (GSM_StateMachine *s, GSM_RingNote note, bool first);
21
22 GSM_Error PHONE_Beep (GSM_StateMachine *s);
23
24GSM_Error NoneReply(GSM_Protocol_Message msg, GSM_StateMachine *s);
25
26#endif
27
28/* How should editor hadle tabs in this file? Add editor commands here.
29 * vim: noexpandtab sw=8 ts=8 sts=8:
30 */
diff --git a/gammu/emb/common/phone/symbian/mroutgen.c b/gammu/emb/common/phone/symbian/mroutgen.c
new file mode 100644
index 0000000..2c339be
--- a/dev/null
+++ b/gammu/emb/common/phone/symbian/mroutgen.c
@@ -0,0 +1,220 @@
1/* (c) 2003 by Marcin Wiacek */
2/* EXPERIMENTAL. NOT FUNCTIONAL */
3
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../gsmstate.h"
9#include "../../misc/coding/coding.h"
10#include "../../service/gsmmisc.h"
11
12#ifdef GSM_ENABLE_MROUTERGEN
13
14GSM_Error MROUTERGEN_StartModem(GSM_StateMachine *s)
15{
16 return ERR_NONE;
17}
18
19GSM_Error MROUTERGEN_Initialise(GSM_StateMachine *s)
20{
21
22unsigned char req2[]={0xFF,0x03,0x80,0xFD,0x04,0x01,0x00,0x09,0x11,
230x05,0x00,0x01,0x03,0x77,0xBC};
24
25unsigned char req0[]={
260xFF,0x7D,0x23,0xC0,0x21,0x7D,0x21,0x7D,0x24,0x7D,
270x20,0x7D,0x2E,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,
280x20,0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,
290x28,0x7D,0x22,0x69,0x27,
300x7E,
31
320x7E,
330xFF,0x7D,0x23,0xC0,0x21,0x7D,0x22,0x7D,0x21,0x7D,
340x20,0x7D,0x34,0x7D,0x25,0x7D,0x26,0x87,0xB9,0x7D,
350x28,0xCF,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,0x20,
360x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,0x28,
370x7D,0x22,0x82,0xB0,
380x7E,
39
400x7E,
410xFF,0x7D,0x23,0xC0,0x21,0x7D,0x21,0x7D,0x24,0x7D,
420x20,0x7D,0x2E,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,
430x20,0x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,
440x28,0x7D,0x22,0x69,0x27,
450x7E,
46
470x7E,
480xFF,0x7D,0x23,0xC0,0x21,0x7D,0x22,0x7D,0x21,0x7D,
490x20,0x7D,0x34,0x7D,0x25,0x7D,0x26,0x87,0xB9,0x7D,
500x28,0xCF,0x7D,0x22,0x7D,0x26,0x7D,0x20,0x7D,0x20,
510x7D,0x20,0x7D,0x20,0x7D,0x27,0x7D,0x22,0x7D,0x28,
520x7D,0x22,0x82,0xB0};
53
54unsigned char req[]={0x2F,0x45,0x00,0x00,0x34,0x00,0xC6,
55 0x00,0x00,0x0A,0x0D,0x59,0xB4,0xA9,0xFE,0x01,
56 0x44,0xA9,0xFE,0x01,0x0A,0x04,0x09,0x0B,0xB8,
57 0x10,0x00,0x02,0x79,0x69,0x81,0x74,0x99,0x50,
58 0x18,0x60,0x00,0x9D,0x0C,0x00,0x00,0x08,0x00,
59 0x00,0x00,0x12,0x00,0x41,0x00,0x01,0x14,0x00,
60 0x00,0xBA,0x4A};
61
62unsigned char req3[]={0x2D,0x5C,0x0D,0xEC,0x4C,0x10,0x26,0x08,0x00,
630x00,0x00,0x12,0x00,0x15,0x00,0x01,0x08,0x00,0x00,
640xAD,0xDE};
65smprintf(s,"writing\n");
66 GSM_WaitFor (s, req0, 164, 0x00, 200, ID_Initialise);
67smprintf(s,"writing\n");
68 GSM_WaitFor (s, req3, 21, 0x00, 200, ID_Initialise);
69 GSM_WaitFor (s, req, 55, 0x00, 200, ID_Initialise);
70
71 GSM_WaitFor (s, req2, 15, 0x00, 200, ID_Initialise);
72
73
74 while (1) {
75 GSM_ReadDevice(s,false);
76 }
77
78
79
80 while (1) {
81 GSM_ReadDevice(s,false);
82 }
83
84
85return ERR_UNKNOWN;
86}
87
88static GSM_Reply_Function MROUTERGENReplyFunctions[] = {
89 {NULL, "\x00",0x00,0x00,ID_None }
90};
91
92GSM_Phone_Functions MROUTERGENPhone = {
93 "mrouter",
94 MROUTERGENReplyFunctions,
95 MROUTERGEN_Initialise,
96 NONEFUNCTION, /* Terminate */
97 GSM_DispatchMessage,
98 NOTSUPPORTED, /* ShowStartInfo */
99 NONEFUNCTION, /* GetManufacturer */
100 NONEFUNCTION, /* GetModel */
101 NONEFUNCTION, /* GetFirmware */
102 NOTIMPLEMENTED, /* GetIMEI */
103 NOTSUPPORTED, /* GetOriginalIMEI */
104 NOTSUPPORTED, /* GetManufactureMonth*/
105 NOTSUPPORTED, /* GetProductCode */
106 NOTSUPPORTED, /* GetHardware */
107 NOTSUPPORTED, /* GetPPM */
108 NOTSUPPORTED, /* GetSIMIMSI */
109 NOTSUPPORTED, /* GetDateTime */
110 NOTSUPPORTED, /* SetDateTime */
111 NOTSUPPORTED, /* GetAlarm */
112 NOTSUPPORTED, /* SetAlarm */
113 NOTSUPPORTED, /* GetLocale */
114 NOTSUPPORTED, /* SetLocale */
115 NOTSUPPORTED, /* PressKey */
116 NOTSUPPORTED, /* Reset */
117 NOTSUPPORTED, /* ResetPhoneSettings*/
118 NOTSUPPORTED, /* EnterSecurityCode*/
119 NOTSUPPORTED, /* GetSecurityStatus*/
120 NOTSUPPORTED, /* GetDisplayStatus*/
121 NOTSUPPORTED, /* SetAutoNetworkLogin*/
122 NOTSUPPORTED, /* GetBatteryCharge*/
123 NOTSUPPORTED, /* GetSignalQuality*/
124 NOTSUPPORTED, /* GetNetworkInfo */
125 NOTSUPPORTED, /* GetCategory */
126 NOTSUPPORTED, /* GetCategoryStatus */
127 NOTSUPPORTED, /* GetMemoryStatus */
128 NOTSUPPORTED, /* GetMemory */
129 NOTSUPPORTED, /* GetNextMemory */
130 NOTSUPPORTED, /* SetMemory */
131 NOTSUPPORTED, /* AddMemory */
132 NOTSUPPORTED, /* DeleteMemory */
133 NOTIMPLEMENTED, /* DeleteAllMemory */
134 NOTSUPPORTED, /* GetSpeedDial */
135 NOTSUPPORTED, /* SetSpeedDial */
136 NOTSUPPORTED, /* GetSMSC */
137 NOTSUPPORTED, /* SetSMSC */
138 NOTSUPPORTED, /* GetSMSStatus */
139 NOTSUPPORTED, /* GetSMS */
140 NOTSUPPORTED, /* GetNextSMS */
141 NOTSUPPORTED, /* SetSMS */
142 NOTSUPPORTED, /* AddSMS */
143 NOTSUPPORTED, /* DeleteSMS */
144 NOTSUPPORTED, /* SendSMSMessage */
145 NOTSUPPORTED, /* SendSavedSMS */
146 NOTSUPPORTED, /* SetIncomingSMS */
147 NOTSUPPORTED, /* SetIncomingCB */
148 NOTSUPPORTED, /* GetSMSFolders */
149 NOTSUPPORTED, /* AddSMSFolder */
150 NOTSUPPORTED, /* DeleteSMSFolder */
151 NOTSUPPORTED, /* DialVoice */
152 NOTSUPPORTED, /* AnswerCall */
153 NOTSUPPORTED, /* CancelCall */
154 NOTSUPPORTED, /* HoldCall */
155 NOTSUPPORTED, /* UnholdCall */
156 NOTSUPPORTED, /* ConferenceCall */
157 NOTSUPPORTED, /* SplitCall */
158 NOTSUPPORTED, /* TransferCall */
159 NOTSUPPORTED, /* SwitchCall */
160 NOTSUPPORTED, /* GetCallDivert */
161 NOTSUPPORTED, /* SetCallDivert */
162 NOTSUPPORTED, /* CancelAllDiverts*/
163 NOTSUPPORTED, /* SetIncomingCall */
164 NOTSUPPORTED, /* SetIncomingUSSD */
165 NOTSUPPORTED, /* SendDTMF */
166 NOTSUPPORTED, /* GetRingtone */
167 NOTSUPPORTED, /* SetRingtone */
168 NOTSUPPORTED, /* GetRingtonesInfo*/
169 NOTSUPPORTED, /* DeleteUserRingtones*/
170 NOTSUPPORTED, /* PlayTone */
171 NOTSUPPORTED, /* GetWAPBookmark */
172 NOTSUPPORTED, /* SetWAPBookmark */
173 NOTSUPPORTED, /* DeleteWAPBookmark */
174 NOTSUPPORTED, /* GetWAPSettings */
175 NOTSUPPORTED, /* SetWAPSettings */
176 NOTSUPPORTED, /* GetMMSSettings */
177 NOTSUPPORTED, /* SetMMSSettings */
178 NOTSUPPORTED, /* GetSyncMLSettings*/
179 NOTSUPPORTED, /* SetSyncMLSettings*/
180 NOTSUPPORTED, /* GetChatSettings */
181 NOTSUPPORTED, /* SetChatSettings */
182 NOTSUPPORTED, /* GetBitmap */
183 NOTSUPPORTED, /* SetBitmap */
184 NOTSUPPORTED, /* GetToDoStatus */
185 NOTSUPPORTED, /* GetToDo */
186 NOTSUPPORTED, /* GetNextToDo */
187 NOTSUPPORTED, /* SetToDo */
188 NOTSUPPORTED, /* AddToDo */
189 NOTSUPPORTED, /* DeleteToDo */
190 NOTSUPPORTED, /* DeleteAllToDo */
191 NOTSUPPORTED, /* GetCalendarStatus*/
192 NOTSUPPORTED, /* GetCalendar */
193 NOTSUPPORTED, /* GetNextCalendar */
194 NOTSUPPORTED, /* SetCalendar */
195 NOTSUPPORTED, /* AddCalendar */
196 NOTSUPPORTED, /* DeleteCalendar */
197 NOTSUPPORTED, /* DeleteAllCalendar*/
198 NOTSUPPORTED, /* GetCalendarSettings*/
199 NOTSUPPORTED, /* SetCalendarSettings*/
200 NOTSUPPORTED, /* GetNote */
201 NOTSUPPORTED, /* GetProfile */
202 NOTSUPPORTED, /* SetProfile */
203 NOTSUPPORTED, /* GetFMStation */
204 NOTSUPPORTED, /* SetFMStation */
205 NOTSUPPORTED, /* ClearFMStations */
206 NOTSUPPORTED, /* GetNextFileFolder*/
207 NOTSUPPORTED, /* GetFilePart */
208 NOTSUPPORTED, /* AddFilePart */
209 NOTSUPPORTED, /* GetFileSystemStatus*/
210 NOTSUPPORTED, /* DeleteFile */
211 NOTSUPPORTED, /* AddFolder */
212 NOTSUPPORTED, /* GetGPRSAccessPoint*/
213 NOTSUPPORTED /* SetGPRSAccessPoint*/
214};
215
216#endif
217
218/* How should editor hadle tabs in this file? Add editor commands here.
219 * vim: noexpandtab sw=8 ts=8 sts=8:
220 */
diff --git a/gammu/emb/common/phone/symbian/mroutgen.h b/gammu/emb/common/phone/symbian/mroutgen.h
new file mode 100644
index 0000000..af38fe5
--- a/dev/null
+++ b/gammu/emb/common/phone/symbian/mroutgen.h
@@ -0,0 +1,29 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef mroutgen_h
4#define mroutgen_h
5
6#include "../../gsmcomon.h"
7#include "../../gsmstate.h"
8#include "../../service/gsmmisc.h"
9#include "../../service/sms/gsmsms.h"
10
11#ifndef GSM_USED_MROUTERBLUE
12# define GSM_USED_MROUTERBLUE
13#endif
14#ifndef GSM_USED_IRDAMROUTER
15# define GSM_USED_IRDAMROUTER
16#endif
17#ifndef GSM_USED_BLUEMROUTER
18# define GSM_USED_BLUEMROUTER
19#endif
20
21typedef struct {
22 int fake;
23} GSM_Phone_MROUTERGENData;
24
25#endif
26
27/* How should editor hadle tabs in this file? Add editor commands here.
28 * vim: noexpandtab sw=8 ts=8 sts=8:
29 */
diff --git a/gammu/emb/common/protocol/alcatel/alcabus.c b/gammu/emb/common/protocol/alcatel/alcabus.c
new file mode 100644
index 0000000..b5b5a30
--- a/dev/null
+++ b/gammu/emb/common/protocol/alcatel/alcabus.c
@@ -0,0 +1,255 @@
1/* (c) 2002-2003 by Michal Cihar
2 *
3 * Low level functions for communication with Alcatel One Touch phones.
4 *
5 * This code implements the protocol used for synchronisation with PC.
6 */
7#include "../../gsmstate.h"
8
9#if defined(GSM_ENABLE_ALCABUS)
10
11#include <stdio.h>
12#include <string.h>
13
14#include "../../gsmcomon.h"
15#include "alcabus.h"
16
17static GSM_Error ALCABUS_WriteMessage (GSM_StateMachine *s, unsigned char *data, int len, unsigned char type)
18{
19 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
20 unsigned char buffer[1024];
21 int size = 0;
22 int sent = 0;
23 int i = 0, checksum = 0;
24
25 if ((type == 0) && (len == 0)) return ERR_NONE;
26
27 buffer[0] = ALCATEL_HEADER;
28 buffer[1] = type;
29 switch (type) {
30 case ALCATEL_CONNECT:
31 buffer[2] = 0x0A;
32 buffer[3] = 0x04;
33 buffer[4] = 0x00;
34 size = 5;
35 d->next_frame = ALCATEL_CONNECT_ACK;
36 d->busy = true;
37 break;
38 case ALCATEL_DISCONNECT:
39 size = 2;
40 d->next_frame = ALCATEL_DISCONNECT_ACK;
41 d->busy = true;
42 break;
43 case ALCATEL_DATA:
44 buffer[2] = d->out_counter;
45
46 /* Increase outgoing packet counter */
47 if (d->out_counter == ALCATEL_MAX_COUNTER) d->out_counter = 0;
48 else d->out_counter++;
49
50 buffer[3] = '\0';
51 buffer[4] = len;
52 memcpy(buffer+5, data, len);
53 size = 5 + len;
54 d->next_frame = ALCATEL_ACK;
55 d->busy = true;
56 break;
57 case ALCATEL_ACK:
58 buffer[2] = d->in_counter;
59 if (d->in_counter == 0) d->in_counter = 1;
60 size = 3;
61 d->next_frame = ALCATEL_DATA;
62 break;
63 default:
64 /* In fact, other types probably can came just from mobile... */
65 smprintf(s,"WARNING: Wanted to send some unknown packet (%02X)\n", type);
66 return ERR_NOTIMPLEMENTED;
67 }
68
69 /* Calculate packet checksum */
70 for (i=0; i<size; i++) checksum ^= buffer[i];
71
72 buffer[size] = checksum;
73 size ++;
74
75 GSM_DumpMessageLevel2(s, buffer, size, type);
76 GSM_DumpMessageLevel3(s, buffer, size, type);
77 while (sent != size ) {
78 if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, size - sent)) == 0) {
79 return ERR_DEVICEWRITEERROR;
80 }
81 sent += i;
82 }
83
84 if (type == ALCATEL_CONNECT || type == ALCATEL_DISCONNECT) {
85 /* For connect and disconnect we need a bit larger delay */
86 // my_sleep(10);
87 while (d->busy) {
88 GSM_ReadDevice(s,true);
89 my_sleep(1);
90 i++;
91 if (i == 10) return ERR_TIMEOUT;
92 }
93 }
94 return ERR_NONE;
95}
96
97static GSM_Error ALCABUS_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
98{
99 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
100 int i;
101 int checksum = 0;
102
103 if (d->Msg.BufferUsed < d->Msg.Length + 1) {
104 d->Msg.BufferUsed= d->Msg.Length + 1;
105 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
106 }
107
108 /* Check for header */
109 if ((d->Msg.Length == 0) && (rx_char != ALCATEL_HEADER)) {
110 smprintf(s,"WARNING: Expecting alcatel header (%02X) but got (%02X)\n", ALCATEL_HEADER, rx_char);
111 return ERR_UNKNOWNRESPONSE;
112 /* Check for packet type */
113 } else if (d->Msg.Length == 1){
114 d->Msg.Type = rx_char;
115 /* Was it unexpected packet? */
116 if ((rx_char != d->next_frame) && (rx_char != ALCATEL_CONTROL)) {
117 smprintf(s,"WARNING: Expecting alcatel packet type (%02X) but got (%02X)\n", d->next_frame, rx_char);
118 }
119 /* Determine packet size */
120 switch (rx_char) {
121 case ALCATEL_ACK:
122 d->expected_size = 4;
123 break;
124 case ALCATEL_DATA:
125 /* Packet length is in it's header */
126 d->expected_size = -1;
127 break;
128 case ALCATEL_CONTROL:
129 d->expected_size = 4;
130 break;
131 case ALCATEL_CONNECT_ACK:
132 d->expected_size = 6;
133 break;
134 case ALCATEL_DISCONNECT_ACK:
135 d->expected_size = 3;
136 break;
137 default:
138 smprintf(s,"WARNING: Something went wrong, unknown packet received (%02X)\n", rx_char);
139 return ERR_UNKNOWNRESPONSE;
140 }
141 /* Check counter, we can probably ignore error here ;-) */
142 } else if ((d->Msg.Length == 2) && (d->Msg.Type == ALCATEL_DATA)) {
143 if (rx_char != d->in_counter) {
144 smprintf(s,"WARNING: Unexpected packet number, ignoring (expected %02X, received %02X)\n", d->in_counter, rx_char);
145 d->in_counter = rx_char;
146 }
147 /* Increase incoming packet counter */
148 if (d->in_counter == ALCATEL_MAX_COUNTER) d->in_counter = 0;
149 else d->in_counter++;
150 /* Read size for data packet */
151 } else if ((d->Msg.Length == 4) && (d->Msg.Type == ALCATEL_DATA)) {
152 /* Header till now + checksum */
153 d->expected_size = (int)rx_char + 6;
154 }
155
156 /* Write received byte into buffer */
157 d->Msg.Buffer[d->Msg.Length++] = rx_char;
158
159 /* Did we received whole packet? */
160 if (d->expected_size == d->Msg.Length) {
161 /* Check checksum */
162 for (i=0; i< (d->Msg.Length - 1); i++) checksum ^= d->Msg.Buffer[i];
163 if (checksum != d->Msg.Buffer[d->Msg.Length - 1]) {
164 /* We can only warn, as we don't know what should happend now... */
165 smprintf(s,"WARNING: Ignoring incorrect packet checksum!\n");
166 }
167
168 /* Was it data? */
169 if (d->Msg.Type == ALCATEL_DATA) {
170 /* Dispatch message */
171 s->Phone.Data.RequestMsg= &d->Msg;
172 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
173 /* Send ack */
174 ALCABUS_WriteMessage (s, 0, 0, ALCATEL_ACK);
175 /* Reset message length */
176 d->Msg.Length = 0;
177 /* Was it ack? */
178 } else if ((d->Msg.Type == ALCATEL_ACK) ||
179 (d->Msg.Type == ALCATEL_CONTROL) ||
180 (d->Msg.Type == ALCATEL_CONNECT_ACK) ||
181 (d->Msg.Type == ALCATEL_DISCONNECT_ACK)) {
182 /* TODO: check counter of ack? */
183 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
184 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
185 smprintf(s, "Received %s ack ",
186 (d->Msg.Type == ALCATEL_ACK) ? "normal" :
187 (d->Msg.Type == ALCATEL_CONTROL) ? "control" :
188 (d->Msg.Type == ALCATEL_CONNECT_ACK) ? "connect" :
189 (d->Msg.Type == ALCATEL_DISCONNECT_ACK) ? "disconnect" :
190 "BUG");
191 smprintf(s, "0x%02x / 0x%04x", d->Msg.Type, d->Msg.Length);
192 DumpMessage(s->di.df, s->di.dl, d->Msg.Buffer, d->Msg.Length);
193 fflush(s->di.df);
194 }
195 if (s->di.dl==DL_BINARY) {
196 smprintf(s,"%c",0x02);/* Receiving */
197 smprintf(s,"%c",d->Msg.Type);
198 smprintf(s,"%c",d->Msg.Length/256);
199 smprintf(s,"%c",d->Msg.Length%256);
200 for (i=0;i<d->Msg.Length;i++) smprintf(s,"%c",d->Msg.Buffer[i]);
201 }
202 if (d->Msg.Type != ALCATEL_CONTROL) {
203 d->next_frame = ALCATEL_DATA;
204 d->busy = false;
205 }
206 /* Reset message length */
207 d->Msg.Length = 0;
208 }
209
210 /* Was it unexpected type? */
211 if ((d->Msg.Type != d->next_frame) && (d->Msg.Type != ALCATEL_CONTROL)) {
212 return ERR_FRAMENOTREQUESTED;
213 }
214 } /* Last byte of packet */
215
216 return ERR_NONE;
217}
218
219static GSM_Error ALCABUS_Initialise(GSM_StateMachine *s)
220{
221 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
222
223 /* Initialise some variables */
224 d->Msg.BufferUsed= 0;
225 d->Msg.Buffer = NULL;
226 d->Msg.Length = 0;
227 d->Msg.Type = 0;
228 d->in_counter = 1;
229 d->out_counter = 0;
230 d->busy = false;
231
232 /* Initialise protocol */
233 dbgprintf ("Initializing binary mode\n");
234 return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_CONNECT);
235}
236
237static GSM_Error ALCABUS_Terminate(GSM_StateMachine *s)
238{
239 /* Terminate protocol */
240 dbgprintf ("Closing binary mode\n");
241 return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_DISCONNECT);
242}
243
244GSM_Protocol_Functions ALCABUSProtocol = {
245 ALCABUS_WriteMessage,
246 ALCABUS_StateMachine,
247 ALCABUS_Initialise,
248 ALCABUS_Terminate
249};
250
251#endif
252
253/* How should editor hadle tabs in this file? Add editor commands here.
254 * vim: noexpandtab sw=8 ts=8 sts=8:
255 */
diff --git a/gammu/emb/common/protocol/alcatel/alcabus.h b/gammu/emb/common/protocol/alcatel/alcabus.h
new file mode 100644
index 0000000..3b9b44e
--- a/dev/null
+++ b/gammu/emb/common/protocol/alcatel/alcabus.h
@@ -0,0 +1,61 @@
1/* (c) 2002-2003 by Michal Cihar */
2/*
3 * Low level functions for communication with Alcatel One Touch phones.
4 *
5 * This code implements the protocol used for synchronisation with PC.
6 */
7
8#ifndef alcabus_h
9#define alcabus_h
10
11#include "../protocol.h"
12
13 #define ALCATEL_HEADER 0x7E
14
15/* packet types: */
16/* used for starting binary connection (must be preceeded by
17 * AT+CPROT=16,"V1.0",16 and phone should response to it by CONNECT_ACK)
18 */
19 #define ALCATEL_CONNECT 0x0A
20/* received when connect suceeded */
21 #define ALCATEL_CONNECT_ACK 0x0C
22/* used for stopping binary connection */
23 #define ALCATEL_DISCONNECT 0x0D
24/* received when binnary connection ends */
25 #define ALCATEL_DISCONNECT_ACK 0x0E
26/* some control ack, I really don't know what should it do, so currently it
27 * is just ignored. It comes time to time, and communication continues OK also
28 * if no reply was made. */
29 #define ALCATEL_CONTROL 0x0F
30/* sending/recieving data */
31 #define ALCATEL_DATA 0x02
32/* acknowledge to data */
33 #define ALCATEL_ACK 0x06
34
35/* Maximal value for packet counter */
36 #define ALCATEL_MAX_COUNTER 0x3D
37
38typedef struct {
39 GSM_Protocol_Message Msg;
40 /* Incoming packets ID counter */
41 int in_counter;
42 /* Outgoing packets ID counter */
43 int out_counter;
44 /* Expected size of incoming packet */
45 int expected_size;
46 /* What is type of frame we expect next */
47 unsigned char next_frame;
48 /* State of mobile, if we expect something (generally some ack) we set
49 * this to true and no other action can be performed until it is false. */
50 bool busy;
51} GSM_Protocol_ALCABUSData;
52
53#ifndef GSM_USED_SERIALDEVICE
54# define GSM_USED_SERIALDEVICE
55#endif
56
57#endif
58
59/* How should editor hadle tabs in this file? Add editor commands here.
60 * vim: noexpandtab sw=8 ts=8 sts=8:
61 */
diff --git a/gammu/emb/common/protocol/at/at.c b/gammu/emb/common/protocol/at/at.c
new file mode 100644
index 0000000..f4a75b7
--- a/dev/null
+++ b/gammu/emb/common/protocol/at/at.c
@@ -0,0 +1,229 @@
1/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
2
3#include "../../gsmstate.h"
4
5#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
6
7#include <stdio.h>
8#include <string.h>
9
10#include "../../gsmcomon.h"
11#include "at.h"
12
13static GSM_Error AT_WriteMessage (GSM_StateMachine *s, unsigned char *buffer,
14 int length, unsigned char type)
15{
16 int i,sent = 0;
17
18 GSM_DumpMessageLevel2(s, buffer, length, type);
19 GSM_DumpMessageLevel3(s, buffer, length, type);
20 if (s->Protocol.Data.AT.FastWrite) {
21 while (sent != length) {
22 if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, length - sent)) == 0) {
23 return ERR_DEVICEWRITEERROR;
24 }
25 sent += i;
26 }
27 } else {
28 for (i=0;i<length;i++) {
29 if (s->Device.Functions->WriteDevice(s,buffer+i,1)!=1) return ERR_DEVICEWRITEERROR;
30 /* For some phones like Siemens M20 we need to wait a little
31 * after writing each char. Possible reason: these phones
32 * can't receive so fast chars or there is bug here in Gammu */
33 my_sleep(1);
34 }
35 my_sleep(400);
36 }
37
38 return ERR_NONE;
39}
40
41typedef struct {
42 char*text;
43 intlines;
44} SpecialAnswersStruct;
45
46static GSM_Error AT_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
47{
48 GSM_Protocol_Message Msg2;
49 GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
50 int i;
51
52 /* These are lines with end of "normal" answers */
53 static char *StartStrings[] = {
54 "OK" , "ERROR" ,
55 "+CME ERROR:" , "+CMS ERROR:",
56
57 "+CPIN: " ,/*A2D issue*/
58
59 NULL};
60
61 /* Some info from phone can be inside "normal" answers
62 * It starts with strings written here
63 */
64 static SpecialAnswersStructSpecialAnswers[] = {
65 {"_OSIGQ:" ,1}, {"_OBS:",1},
66 {"^SCN:" ,1}, {"+CGREG:",1},
67 {"+CBM:" ,1}, {"+CMT:",2},
68 {"+CMTI:" ,1}, {"+CDS:",2},
69 {"+CREG:",1},
70
71 {"RING" ,1}, {"NO CARRIER",1},
72 {"NO ANSWER" ,1}, {"+COLP",1},
73 {"+CLIP",1},
74
75 {NULL ,1}};
76
77 /* Ignore leading CR, LF and ESC */
78 if (d->Msg.Length == 0) {
79 if (rx_char == 10 || rx_char == 13 || rx_char == 27) return ERR_NONE;
80 d->LineStart = d->Msg.Length;
81 }
82
83 if (d->Msg.BufferUsed < d->Msg.Length + 2) {
84 d->Msg.BufferUsed= d->Msg.Length + 2;
85 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
86 }
87 d->Msg.Buffer[d->Msg.Length++] = rx_char;
88 d->Msg.Buffer[d->Msg.Length ] = 0;
89
90 switch (rx_char) {
91 case 0:
92 break;
93 case 10:
94 case 13:
95 if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
96 d->wascrlf = true;
97 if (d->Msg.Length > 0 && rx_char == 10 && d->Msg.Buffer[d->Msg.Length-2]==13) {
98 i = 0;
99 while (StartStrings[i] != NULL) {
100 if (strncmp(StartStrings[i],d->Msg.Buffer+d->LineStart,strlen(StartStrings[i])) == 0) {
101 s->Phone.Data.RequestMsg= &d->Msg;
102 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
103 d->Msg.Length = 0;
104 break;
105 }
106 i++;
107 }
108 if (d->Msg.Length == 0) break;
109
110 i = 0;
111 while (SpecialAnswers[i].text != NULL) {
112 if (strncmp(SpecialAnswers[i].text,d->Msg.Buffer+d->LineStart,strlen(SpecialAnswers[i].text)) == 0) {
113 /* We need something better here */
114 if (s->Phone.Data.RequestID == ID_GetNetworkInfo && strncmp(SpecialAnswers[i].text,"+CREG:",6) == 0) {
115 i++;
116 continue;
117 }
118 d->SpecialAnswerStart = d->LineStart;
119 d->SpecialAnswerLines= SpecialAnswers[i].lines;
120 }
121 i++;
122 }
123
124
125 if (d->SpecialAnswerLines == 1) {
126 /* This is end of special answer. We copy it and send to phone module */
127 Msg2.Buffer = malloc(d->LineEnd - d->SpecialAnswerStart + 3);
128 memcpy(Msg2.Buffer,d->Msg.Buffer+d->SpecialAnswerStart,d->LineEnd - d->SpecialAnswerStart + 2);
129 Msg2.Length = d->LineEnd - d->SpecialAnswerStart + 2;
130 Msg2.Buffer[Msg2.Length] = 0;
131
132 s->Phone.Data.RequestMsg= &Msg2;
133 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
134 free(Msg2.Buffer);
135
136 /* We cut special answer from main buffer */
137 d->Msg.Length = d->SpecialAnswerStart;
138 if (d->Msg.Length != 0) d->Msg.Length = d->Msg.Length - 2;
139
140 /* We need to find earlier values of all variables */
141 d->wascrlf = false;
142 d->LineStart = 0;
143 for (i=0;i<d->Msg.Length;i++) {
144 switch(d->Msg.Buffer[i]) {
145 case 0:
146 break;
147 case 10:
148 case 13:
149 if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
150 d->wascrlf = true;
151 break;
152 default:
153 if (d->wascrlf) {
154 d->LineStart= d->Msg.Length-1;
155 d->wascrlf = false;
156 }
157 }
158 }
159 d->Msg.Buffer[d->Msg.Length] = 0;
160 }
161 if (d->SpecialAnswerLines > 0) d->SpecialAnswerLines--;
162 }
163 break;
164 case 'T':
165 /* When CONNECT string received, we know there will not follow
166 * anything AT related, after CONNECT can follow ppp data, alcabus
167 * data and also other things.
168 */
169 if (strncmp(d->Msg.Buffer+d->LineStart, "CONNECT", 7) == 0) {
170 s->Phone.Data.RequestMsg = &d->Msg;
171 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
172 d->LineStart = -1;
173 d->Msg.Length = 0;
174 break;
175 }
176 default:
177 if (d->wascrlf) {
178 d->LineStart= d->Msg.Length-1;
179 d->wascrlf = false;
180 }
181 if (d->EditMode) {
182 if (strlen(d->Msg.Buffer+d->LineStart) == 2 && strncmp(d->Msg.Buffer+d->LineStart,"> ",2)==0) {
183 s->Phone.Data.RequestMsg= &d->Msg;
184 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
185 }
186 }
187 }
188 return ERR_NONE;
189}
190
191static GSM_Error AT_Initialise(GSM_StateMachine *s)
192{
193 GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
194
195 d->Msg.Buffer = NULL;
196 d->Msg.BufferUsed= 0;
197 d->Msg.Length = 0;
198 d->Msg.Type = 0;
199
200 d->SpecialAnswerLines= 0;
201 d->LineStart = -1;
202 d->LineEnd = -1;
203 d->wascrlf = false;
204 d->EditMode = false;
205 d->FastWrite = false;
206
207 s->Device.Functions->DeviceSetDtrRts(s,true,true);
208
209 return s->Device.Functions->DeviceSetSpeed(s,s->Speed);
210}
211
212static GSM_Error AT_Terminate(GSM_StateMachine *s)
213{
214 free(s->Protocol.Data.AT.Msg.Buffer);
215 return ERR_NONE;
216}
217
218GSM_Protocol_Functions ATProtocol = {
219 AT_WriteMessage,
220 AT_StateMachine,
221 AT_Initialise,
222 AT_Terminate
223};
224
225#endif
226
227/* How should editor hadle tabs in this file? Add editor commands here.
228 * vim: noexpandtab sw=8 ts=8 sts=8:
229 */
diff --git a/gammu/emb/common/protocol/at/at.h b/gammu/emb/common/protocol/at/at.h
new file mode 100644
index 0000000..e200646
--- a/dev/null
+++ b/gammu/emb/common/protocol/at/at.h
@@ -0,0 +1,36 @@
1/* (c) 2002-2003 by Marcin Wiacek and Michal Cihar */
2
3#ifndef at_h
4#define at_h
5
6#include "../protocol.h"
7
8typedef struct {
9 GSM_Protocol_Message Msg;
10 bool wascrlf;
11 int LineStart,LineEnd;
12 int SpecialAnswerLines,SpecialAnswerStart;
13
14 bool EditMode;/* wait for modem answer or not */
15 bool FastWrite;
16} GSM_Protocol_ATData;
17
18#ifndef GSM_USED_SERIALDEVICE
19# define GSM_USED_SERIALDEVICE
20#endif
21#if defined(GSM_ENABLE_BLUEAT)
22# ifndef GSM_USED_BLUETOOTHDEVICE
23# define GSM_USED_BLUETOOTHDEVICE
24# endif
25#endif
26#if defined(GSM_ENABLE_IRDAAT)
27# ifndef GSM_USED_IRDADEVICE
28# define GSM_USED_IRDADEVICE
29# endif
30#endif
31
32#endif
33
34/* How should editor hadle tabs in this file? Add editor commands here.
35 * vim: noexpandtab sw=8 ts=8 sts=8:
36 */
diff --git a/gammu/emb/common/protocol/nokia/fbus2.c b/gammu/emb/common/protocol/nokia/fbus2.c
new file mode 100644
index 0000000..8b3e024
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/fbus2.c
@@ -0,0 +1,444 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2/* based on some work from Gnokii and MyGnokii */
3
4#include "../../gsmstate.h"
5
6#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)
7
8#include <stdio.h>
9#include <string.h>
10
11#include "../../gsmcomon.h"
12#include "fbus2.h"
13
14 static GSM_Error FBUS2_WriteFrame(GSM_StateMachine *s,
15 unsigned char *MsgBuffer,
16 int MsgLength,
17 unsigned char MsgType)
18{
19 unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 10];
20 unsigned char checksum=0;
21 int i, len, sent;
22
23 buffer2[0] = FBUS2_FRAME_ID;
24 if (s->ConnectionType==GCT_FBUS2IRDA) buffer2[0] = FBUS2_IRDA_FRAME_ID;
25
26 buffer2[1] = FBUS2_DEVICE_PHONE; //destination
27 buffer2[2] = FBUS2_DEVICE_PC; //source
28 buffer2[3]= MsgType;
29 buffer2[4]= MsgLength / 256;
30 buffer2[5]= MsgLength % 256;
31
32 memcpy(buffer2 + 6, MsgBuffer, MsgLength);
33 len = MsgLength + 6;
34
35 /* Odd messages require additional 0x00 byte */
36 if (MsgLength % 2) buffer2[len++] = 0x00;
37
38 checksum = 0;
39 for (i = 0; i < len; i+=2) checksum ^= buffer2[i];
40 buffer2[len++] = checksum;
41
42 checksum = 0;
43 for (i = 1; i < len; i+=2) checksum ^= buffer2[i];
44 buffer2[len++] = checksum;
45
46 /* Sending to phone */
47 sent=s->Device.Functions->WriteDevice(s,buffer2,len);
48 if (sent!=len) return ERR_DEVICEWRITEERROR;
49
50 return ERR_NONE;
51}
52
53 static GSM_Error FBUS2_WriteMessage (GSM_StateMachine *s,
54 unsigned char *MsgBuffer,
55 int MsgLength,
56 unsigned char MsgType)
57{
58 int i, nom, togo, thislength; /* number of messages, ... */
59 unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 2], seqnum;
60 GSM_Protocol_FBUS2Data*d = &s->Protocol.Data.FBUS2;
61 GSM_Error error;
62
63 GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
64
65 nom = (MsgLength + FBUS2_MAX_TRANSMIT_LENGTH - 1) / FBUS2_MAX_TRANSMIT_LENGTH;
66 togo = MsgLength;
67
68 for (i = 0; i < nom; i++) {
69 seqnum = d->MsgSequenceNumber;
70 if (i==0) seqnum = seqnum + 0x40;
71 d->MsgSequenceNumber = (d->MsgSequenceNumber + 1) & 0x07;
72
73 thislength = togo;
74 if (togo > FBUS2_MAX_TRANSMIT_LENGTH) thislength = FBUS2_MAX_TRANSMIT_LENGTH;
75 memcpy(buffer2, MsgBuffer + (MsgLength - togo), thislength);
76 buffer2[thislength]= nom - i;
77 buffer2[thislength + 1]= seqnum;
78 togo = togo - thislength;
79
80 GSM_DumpMessageLevel2(s, buffer2, thislength, MsgType);
81
82 error=FBUS2_WriteFrame(s, buffer2, thislength + 2, MsgType);
83 if (error!=ERR_NONE) return error;
84 }
85
86 return ERR_NONE;
87}
88
89 static GSM_Error FBUS2_SendAck(GSM_StateMachine *s,
90 unsigned char MsgType,
91 unsigned char MsgSequence)
92{
93 unsigned char buffer2[2];
94
95 buffer2[0] = MsgType;
96 buffer2[1] = MsgSequence;
97
98 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
99 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
100 smprintf(s,"[Sending Ack of type %02x, seq %x]\n",buffer2[0],buffer2[1]);
101 }
102
103 /* Sending to phone */
104 return FBUS2_WriteFrame(s, buffer2, 2, FBUS2_ACK_BYTE);
105}
106
107static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
108{
109 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
110 unsigned char frm_num, seq_num;
111 bool correct = false;
112
113 /* XOR the byte with the earlier checksum */
114 d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char;
115
116 if (d->MsgRXState == RX_GetMessage) {
117 d->Msg.Buffer[d->Msg.Count] = rx_char;
118 d->Msg.Count++;
119
120 /* This is not last byte in frame */
121 if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE;
122
123 /* Checksum is incorrect */
124 if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) {
125 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
126 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
127 smprintf(s,"[ERROR: checksum]\n");
128 }
129 free(d->Msg.Buffer);
130 d->Msg.Length = 0;
131 d->Msg.Buffer = NULL;
132
133 d->MsgRXState = RX_Sync;
134 return ERR_NONE;
135 }
136
137 seq_num = d->Msg.Buffer[d->Msg.Length-1];
138
139 if (d->Msg.Type == FBUS2_ACK_BYTE) {
140 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
141 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
142 smprintf(s, "[Received Ack of type %02x, seq %02x]\n",d->Msg.Buffer[0],seq_num);
143 }
144
145 d->MsgRXState = RX_Sync;
146 return ERR_NONE;
147 }
148
149 frm_num = d->Msg.Buffer[d->Msg.Length-2];
150
151 if ((seq_num & 0x40) == 0x40) {
152 d->FramesToGo = frm_num;
153 d->MultiMsg.Length= 0;
154 d->MultiMsg.Type= d->Msg.Type;
155 d->MultiMsg.Destination= d->Msg.Destination;
156 d->MultiMsg.Source= d->Msg.Source;
157 }
158
159 if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) {
160 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
161 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
162 smprintf(s, "[ERROR: Missed part of multiframe msg]\n");
163 }
164
165 free(d->Msg.Buffer);
166 d->Msg.Length = 0;
167 d->Msg.Buffer = NULL;
168
169 d->MsgRXState = RX_Sync;
170 return ERR_NONE;
171 }
172
173 if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) {
174 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
175 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
176 smprintf(s, "[ERROR: Multiframe msg in multiframe msg]\n");
177 }
178
179 free(d->Msg.Buffer);
180 d->Msg.Length = 0;
181 d->Msg.Buffer = NULL;
182
183 d->MsgRXState = RX_Sync;
184 return ERR_NONE;
185 }
186
187 if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) {
188 d->MultiMsg.BufferUsed = d->MultiMsg.Length+d->Msg.Length-2;
189 d->MultiMsg.Buffer = (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed);
190 }
191 memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2);
192 d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2;
193
194 free(d->Msg.Buffer);
195 d->Msg.Length = 0;
196 d->Msg.Buffer = NULL;
197
198 d->FramesToGo--;
199
200 /* do not ack debug trace, as this could generate a
201 * (feedback loop) flood of which even Noah would be scared.
202 */
203 if (d->Msg.Type != 0) {
204 FBUS2_SendAck(s,d->Msg.Type,((unsigned char)(seq_num & 0x0f)));
205 }
206
207 if (d->FramesToGo == 0) {
208 s->Phone.Data.RequestMsg= &d->MultiMsg;
209 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
210 }
211 d->MsgRXState = RX_Sync;
212 return ERR_NONE;
213 }
214 if (d->MsgRXState == RX_GetLength2) {
215 d->Msg.Length = d->Msg.Length + rx_char;
216 d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length+3);
217 d->MsgRXState = RX_GetMessage;
218 return ERR_NONE;
219 }
220 if (d->MsgRXState == RX_GetLength1) {
221 d->Msg.Length = rx_char * 256;
222 d->MsgRXState = RX_GetLength2;
223 return ERR_NONE;
224 }
225 if (d->MsgRXState == RX_GetType) {
226 d->Msg.Type = rx_char;
227 d->MsgRXState = RX_GetLength1;
228 return ERR_NONE;
229 }
230 if (d->MsgRXState == RX_GetSource) {
231 if (rx_char != FBUS2_DEVICE_PHONE) {
232 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
233 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
234 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PHONE);
235 }
236
237 d->MsgRXState = RX_Sync;
238 return ERR_NONE;
239 }
240 d->Msg.Source = rx_char;
241
242 d->MsgRXState = RX_GetType;
243 return ERR_NONE;
244 }
245 if (d->MsgRXState == RX_GetDestination) {
246 if (rx_char != FBUS2_DEVICE_PC) {
247 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
248 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
249 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PC);
250 }
251
252 d->MsgRXState = RX_Sync;
253 return ERR_NONE;
254 }
255 d->Msg.Destination = rx_char;
256
257 d->MsgRXState = RX_GetSource;
258 return ERR_NONE;
259 }
260 if (d->MsgRXState == RX_Sync) {
261 switch (s->ConnectionType) {
262 case GCT_FBUS2:
263 case GCT_FBUS2DLR3:
264 case GCT_FBUS2DKU5:
265 case GCT_FBUS2PL2303:
266 case GCT_FBUS2BLUE:
267 case GCT_BLUEFBUS2:
268 if (rx_char == FBUS2_FRAME_ID) correct = true;
269 break;
270 case GCT_FBUS2IRDA:
271 if (rx_char == FBUS2_IRDA_FRAME_ID) correct = true;
272 break;
273 default:
274 break;
275 }
276 if (!correct) {
277 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
278 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
279 if (s->ConnectionType==GCT_FBUS2IRDA) {
280 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_IRDA_FRAME_ID);
281 } else {
282 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_FRAME_ID);
283 }
284 }
285 return ERR_NONE;
286 }
287
288 d->Msg.CheckSum[0] = rx_char;
289 d->Msg.CheckSum[1] = 0;
290 d->Msg.Count = 0;
291
292 d->MsgRXState = RX_GetDestination;
293 return ERR_NONE;
294 }
295 return ERR_NONE;
296}
297
298#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
299static void FBUS2_WriteDLR3(GSM_StateMachine *s, char *command, int length, int timeout)
300{
301 unsigned char buff[300];
302 int w = 0;
303 bool wassomething = false;
304
305 s->Device.Functions->WriteDevice(s,command,length);
306
307 for (w=0;w<timeout;w++) {
308 if (wassomething) {
309 if (s->Device.Functions->ReadDevice(s, buff, 255)==0) return;
310 } else {
311 if (s->Device.Functions->ReadDevice(s, buff, 255)>0) wassomething = true;
312 }
313 my_sleep(50);
314 }
315}
316#endif
317
318static GSM_Error FBUS2_Initialise(GSM_StateMachine *s)
319{
320 unsigned char init_char= 0x55;
321#ifdef GSM_ENABLE_FBUS2IRDA
322 unsigned char end_init_char= 0xc1;
323#endif
324
325 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
326 GSM_Device_Functions *Device = s->Device.Functions;
327 GSM_Error error;
328 int count;
329
330 d->Msg.Length = 0;
331 d->Msg.Buffer = NULL;
332 d->MultiMsg.BufferUsed= 0;
333 d->MultiMsg.Length= 0;
334 d->MultiMsg.Buffer= NULL;
335
336 d->MsgSequenceNumber= 0;
337 d->FramesToGo = 0;
338 d->MsgRXState = RX_Sync;
339
340 error=Device->DeviceSetParity(s,false);
341 if (error!=ERR_NONE) return error;
342
343 switch (s->ConnectionType) {
344#if defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2BLUE)
345 case GCT_FBUS2BLUE:
346 case GCT_BLUEFBUS2:
347 FBUS2_WriteDLR3(s,"AT\r\n", 4,10);
348 FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10);
349 FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n",14,10);
350 break;
351#endif
352#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303)
353 case GCT_FBUS2DKU5:
354 case GCT_FBUS2PL2303:
355 case GCT_FBUS2DLR3:
356 error=Device->DeviceSetDtrRts(s,false,false);
357 if (error!=ERR_NONE) return error;
358 my_sleep(1000);
359
360 error=Device->DeviceSetDtrRts(s,true,true);
361 if (error!=ERR_NONE) return error;
362 error=Device->DeviceSetSpeed(s,19200);
363 if (error!=ERR_NONE) return error;
364
365 FBUS2_WriteDLR3(s,"AT\r\n", 4,10);
366 FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10);
367 FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n",14,10);
368
369 error=Device->CloseDevice(s);
370 if (error!=ERR_NONE) return error;
371 my_sleep(1000);
372
373 error=Device->OpenDevice(s);
374 if (error!=ERR_NONE) return error;
375 error=Device->DeviceSetParity(s,false);
376 if (error!=ERR_NONE) return error;
377 error=Device->DeviceSetSpeed(s,115200);
378 if (error!=ERR_NONE) return error;
379 error=Device->DeviceSetDtrRts(s,false,false);
380 if (error!=ERR_NONE) return error;
381
382 for (count = 0; count < 55; count ++) {
383 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
384 }
385 break;
386#endif
387 case GCT_FBUS2:
388 error=Device->DeviceSetSpeed(s,115200);
389 if (error!=ERR_NONE) return error;
390
391 error=Device->DeviceSetDtrRts(s,true,false); /*DTR high,RTS low*/
392 if (error!=ERR_NONE) return error;
393
394 for (count = 0; count < 55; count ++) {
395 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
396 my_sleep(10);
397 }
398 break;
399#ifdef GSM_ENABLE_FBUS2IRDA
400 case GCT_FBUS2IRDA:
401 error=Device->DeviceSetSpeed(s,9600);
402 if (error!=ERR_NONE) return error;
403
404 for (count = 0; count < 55; count ++) {
405 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
406 my_sleep(10);
407 }
408
409 if (Device->WriteDevice(s,&end_init_char,1)!=1) return ERR_DEVICEWRITEERROR;
410 my_sleep(20);
411
412 error=Device->DeviceSetSpeed(s,115200);
413 if (error!=ERR_NONE) return error;
414
415 break;
416#endif
417 default:
418 break;
419 }
420
421 return ERR_NONE;
422}
423
424static GSM_Error FBUS2_Terminate(GSM_StateMachine *s)
425{
426 free(s->Protocol.Data.FBUS2.Msg.Buffer);
427 free(s->Protocol.Data.FBUS2.MultiMsg.Buffer);
428
429 my_sleep(200);
430 return ERR_NONE;
431}
432
433GSM_Protocol_Functions FBUS2Protocol = {
434 FBUS2_WriteMessage,
435 FBUS2_StateMachine,
436 FBUS2_Initialise,
437 FBUS2_Terminate
438};
439
440#endif
441
442/* How should editor hadle tabs in this file? Add editor commands here.
443 * vim: noexpandtab sw=8 ts=8 sts=8:
444 */
diff --git a/gammu/emb/common/protocol/nokia/fbus2.h b/gammu/emb/common/protocol/nokia/fbus2.h
new file mode 100644
index 0000000..5dd45d7
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/fbus2.h
@@ -0,0 +1,38 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2/* based on some work from Gnokii and MyGnokii */
3
4#ifndef fbus2_h
5#define fbus2_h
6
7#include "../protocol.h"
8
9 #define FBUS2_FRAME_ID 0x1e
10 #define FBUS2_IRDA_FRAME_ID 0x1c
11 #define FBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */
12 #define FBUS2_DEVICE_PC 0x0c /* Our PC */
13 #define FBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */
14
15#define FBUS2_MAX_TRANSMIT_LENGTH 120
16
17typedef struct {
18 int MsgSequenceNumber;
19 int MsgRXState;
20 int FramesToGo;
21 GSM_Protocol_MessageMultiMsg;
22 GSM_Protocol_MessageMsg;
23} GSM_Protocol_FBUS2Data;
24
25#ifndef GSM_USED_SERIALDEVICE
26# define GSM_USED_SERIALDEVICE
27#endif
28#if defined(GSM_ENABLE_BLUEFBUS2)
29# ifndef GSM_USED_BLUETOOTHDEVICE
30# define GSM_USED_BLUETOOTHDEVICE
31# endif
32#endif
33
34#endif
35
36/* How should editor hadle tabs in this file? Add editor commands here.
37 * vim: noexpandtab sw=8 ts=8 sts=8:
38 */
diff --git a/gammu/emb/common/protocol/nokia/mbus2.c b/gammu/emb/common/protocol/nokia/mbus2.c
new file mode 100644
index 0000000..f07d6c5
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/mbus2.c
@@ -0,0 +1,252 @@
1/* (c) 2001-2003 by Marcin Wiacek */
2/* based on some work from MyGnokii */
3
4#include "../../gsmstate.h"
5
6#ifdef GSM_ENABLE_MBUS2
7
8#include <stdio.h>
9#include <string.h>
10
11#include "../../gsmcomon.h"
12#include "mbus2.h"
13
14 static GSM_Error MBUS2_WriteMessage (GSM_StateMachine *s,
15 unsigned char *MsgBuffer,
16 int MsgLength,
17 unsigned char MsgType)
18{
19 unsigned char *buffer2, checksum = 0;
20 GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2;
21 int i, sent, len;
22
23 GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
24
25 buffer2 = (unsigned char *)malloc(MsgLength + 8);
26
27 buffer2[0] = MBUS2_FRAME_ID;
28 buffer2[1] = MBUS2_DEVICE_PHONE; // destination
29 buffer2[2] = MBUS2_DEVICE_PC; // source
30 buffer2[3] = MsgType;
31 buffer2[4] = MsgLength / 256;
32 buffer2[5] = MsgLength % 256;
33
34 memcpy(buffer2 + 6, MsgBuffer, MsgLength);
35 len = 6 + MsgLength;
36
37 /* According to http://www.flosys.com/tdma/n5160.html some phones
38 * can have problems with checksum equal 0x1F. Phones can recognize
39 * received frame, but won't send ACK for it. When checksum is 0x1F,
40 * we increment the sequence number
41 */
42 do {
43 d->MsgSequenceNumber++;
44
45 buffer2[len] = d->MsgSequenceNumber;
46
47 /* Calculating checksum */
48 checksum = 0;
49 for (i = 0; i < len + 1; i++) checksum ^= buffer2[i];
50 } while (checksum == 0x1f);
51
52 buffer2[len++] = d->MsgSequenceNumber;
53 buffer2[len++] = checksum;
54
55 GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType);
56
57 /* Sending to phone */
58 my_sleep(10);
59 sent=s->Device.Functions->WriteDevice(s,buffer2,len);
60
61 free(buffer2);
62
63 if (sent!=len) return ERR_DEVICEWRITEERROR;
64 return ERR_NONE;
65}
66
67 static GSM_Error MBUS2_SendAck(GSM_StateMachine *s,
68 unsigned char type,
69 unsigned char sequence)
70{
71 GSM_Device_Functions *Device = s->Device.Functions;
72 unsigned char buffer2[6];
73 int i;
74
75 buffer2[0] = MBUS2_FRAME_ID;
76 buffer2[1] = MBUS2_DEVICE_PHONE;//destination
77 buffer2[2] = MBUS2_DEVICE_PC; //source
78 buffer2[3] = MBUS2_ACK_BYTE;
79 buffer2[4] = sequence;
80 buffer2[5] = 0;
81
82 /* Calculating checksum */
83 for (i = 0; i < 5; i++) buffer2[5] ^= buffer2[i];
84
85 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
86 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
87 smprintf(s,"[Sending Ack of type %02x, seq: %x]\n",type,sequence);
88 }
89
90 /* Sending to phone */
91 my_sleep(10);
92 if (Device->WriteDevice(s,buffer2,6)!=6) return ERR_DEVICEWRITEERROR;
93
94 return ERR_NONE;
95}
96
97static GSM_Error MBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
98{
99 GSM_Phone_Functions *Phone= s->Phone.Functions;
100 GSM_Protocol_MBUS2Data *d= &s->Protocol.Data.MBUS2;
101
102 d->Msg.CheckSum[0] = d->Msg.CheckSum[1];
103 d->Msg.CheckSum[1] ^= rx_char;
104
105 if (d->MsgRXState == RX_GetMessage) {
106 d->Msg.Buffer[d->Msg.Count] = rx_char;
107 d->Msg.Count++;
108
109 /* This is not last byte in frame */
110 if (d->Msg.Count != d->Msg.Length+2) return ERR_NONE;
111
112 /* Checksum is incorrect */
113 if (d->Msg.CheckSum[0] != rx_char) {
114 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
115 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
116 smprintf(s,"[ERROR: checksum]\n");
117 }
118
119 d->MsgRXState = RX_Sync;
120 return ERR_NONE;
121 }
122
123 if (d->Msg.Destination != MBUS2_DEVICE_PHONE) {
124 MBUS2_SendAck(s, d->Msg.Type, d->Msg.Buffer[d->Msg.Count-2]);
125 s->Phone.Data.RequestMsg= &d->Msg;
126 s->Phone.Data.DispatchError= Phone->DispatchMessage(s);
127 }
128
129 d->MsgRXState = RX_Sync;
130 return ERR_NONE;
131 }
132 if (d->MsgRXState == RX_GetLength2) {
133 if (d->Msg.Type == MBUS2_ACK_BYTE) {
134 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
135 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
136 smprintf(s,"[Received Ack]\n");
137 }
138
139 d->MsgRXState = RX_Sync;
140 return ERR_NONE;
141 }
142
143 d->Msg.Length = d->Msg.Length + rx_char;
144 if (d->Msg.BufferUsed < d->Msg.Length+2) {
145 d->Msg.BufferUsed = d->Msg.Length+2;
146 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
147 }
148
149 d->MsgRXState = RX_GetMessage;
150 return ERR_NONE;
151 }
152 if (d->MsgRXState == RX_GetLength1) {
153 d->Msg.Length = rx_char * 256;
154
155 d->MsgRXState = RX_GetLength2;
156 return ERR_NONE;
157 }
158 if (d->MsgRXState == RX_GetType) {
159 d->Msg.Type = rx_char;
160
161 d->MsgRXState = RX_GetLength1;
162 return ERR_NONE;
163 }
164 if (d->MsgRXState == RX_GetSource) {
165 if (rx_char != MBUS2_DEVICE_PHONE && rx_char != MBUS2_DEVICE_PC) {
166 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
167 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
168 smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
169 }
170 d->MsgRXState = RX_Sync;
171 return ERR_NONE;
172 }
173 d->Msg.Source = rx_char;
174
175 d->MsgRXState = RX_GetType;
176 return ERR_NONE;
177 }
178 if (d->MsgRXState == RX_GetDestination) {
179 if (rx_char != MBUS2_DEVICE_PC && rx_char != MBUS2_DEVICE_PHONE) {
180 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
181 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
182 smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
183 }
184 d->MsgRXState = RX_Sync;
185 return ERR_NONE;
186 }
187 d->Msg.Destination = rx_char;
188
189 d->MsgRXState = RX_GetSource;
190 return ERR_NONE;
191 }
192 if (d->MsgRXState == RX_Sync) {
193 if (rx_char != MBUS2_FRAME_ID) {
194 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
195 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
196 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, MBUS2_FRAME_ID);
197 }
198 return ERR_NONE;
199 }
200 d->Msg.CheckSum[1] = MBUS2_FRAME_ID;
201 d->Msg.Count = 0;
202
203 d->MsgRXState = RX_GetDestination;
204 return ERR_NONE;
205 }
206 return ERR_NONE;
207}
208
209static GSM_Error MBUS2_Initialise(GSM_StateMachine *s)
210{
211 GSM_Device_Functions *Device= s->Device.Functions;
212 GSM_Protocol_MBUS2Data *d= &s->Protocol.Data.MBUS2;
213 GSM_Error error;
214
215 d->Msg.Length = 0;
216 d->Msg.BufferUsed= 0;
217 d->Msg.Buffer = NULL;
218
219 d->MsgSequenceNumber= 0;
220 d->MsgRXState = RX_Sync;
221
222 error=Device->DeviceSetSpeed(s,9600);
223 if (error!=ERR_NONE) return error;
224
225 error=Device->DeviceSetParity(s,true);
226 if (error!=ERR_NONE) return error;
227
228 error=Device->DeviceSetDtrRts(s,false,true); /*DTR low,RTS high*/
229 if (error!=ERR_NONE) return error;
230 my_sleep(200);
231
232 return ERR_NONE;
233}
234
235static GSM_Error MBUS2_Terminate(GSM_StateMachine *s)
236{
237 free(s->Protocol.Data.MBUS2.Msg.Buffer);
238 return ERR_NONE;
239}
240
241GSM_Protocol_Functions MBUS2Protocol = {
242 MBUS2_WriteMessage,
243 MBUS2_StateMachine,
244 MBUS2_Initialise,
245 MBUS2_Terminate
246};
247
248#endif
249
250/* How should editor hadle tabs in this file? Add editor commands here.
251 * vim: noexpandtab sw=8 ts=8 sts=8:
252 */
diff --git a/gammu/emb/common/protocol/nokia/mbus2.h b/gammu/emb/common/protocol/nokia/mbus2.h
new file mode 100644
index 0000000..86fcab6
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/mbus2.h
@@ -0,0 +1,28 @@
1/* (c) 2001-2003 by Marcin Wiacek */
2/* based on some work from MyGnokii */
3
4#ifndef mbus2_h
5#define mbus2_h
6
7#include "../protocol.h"
8
9#define MBUS2_FRAME_ID 0x1f
10#define MBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */
11#define MBUS2_DEVICE_PC 0x10 /* Our PC (MBUS) */
12 #define MBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */
13
14typedef struct {
15 int MsgSequenceNumber;
16 int MsgRXState;
17 GSM_Protocol_MessageMsg;
18} GSM_Protocol_MBUS2Data;
19
20#ifndef GSM_USED_SERIALDEVICE
21# define GSM_USED_SERIALDEVICE
22#endif
23
24#endif
25
26/* How should editor hadle tabs in this file? Add editor commands here.
27 * vim: noexpandtab sw=8 ts=8 sts=8:
28 */
diff --git a/gammu/emb/common/protocol/nokia/phonet.c b/gammu/emb/common/protocol/nokia/phonet.c
new file mode 100644
index 0000000..bc5717d
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/phonet.c
@@ -0,0 +1,217 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2/* based on some work from Gnokii */
3
4#include "../../gsmstate.h"
5
6#if defined(GSM_ENABLE_IRDA) || defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_BLUEPHONET)
7
8#include <stdio.h>
9#include <string.h>
10
11#include "../../gsmcomon.h"
12#include "phonet.h"
13
14 static GSM_Error PHONET_WriteMessage (GSM_StateMachine *s,
15 unsigned char *MsgBuffer,
16 int MsgLength,
17 unsigned char MsgType)
18{
19 unsigned char *buffer2;
20 int sent;
21
22 GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
23
24 buffer2 = (unsigned char *)malloc(MsgLength + 6);
25
26 buffer2[0] = PHONET_FRAME_ID,
27 buffer2[1] = PHONET_DEVICE_PHONE; //destination
28 buffer2[2] = PHONET_DEVICE_PC; //source
29
30 if (s->ConnectionType==GCT_PHONETBLUE || s->ConnectionType==GCT_BLUEPHONET) {
31 buffer2[0] = PHONET_BLUE_FRAME_ID;
32 buffer2[1] = PHONET_DEVICE_PHONE;//destination
33 buffer2[2] = PHONET_BLUE_DEVICE_PC;//source
34 }
35
36 buffer2[3] = MsgType;
37 buffer2[4] = MsgLength / 256;
38 buffer2[5] = MsgLength % 256;
39
40 memcpy(buffer2 + 6, MsgBuffer, MsgLength);
41
42 GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType);
43
44 /* Sending to phone */
45 sent = s->Device.Functions->WriteDevice(s,buffer2,MsgLength+6);
46
47 free(buffer2);
48
49 if (sent!=MsgLength+6) return ERR_DEVICEWRITEERROR;
50 return ERR_NONE;
51}
52
53static GSM_Error PHONET_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
54{
55 GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET;
56 bool correct = false;
57
58 if (d->MsgRXState==RX_GetMessage) {
59 d->Msg.Buffer[d->Msg.Count] = rx_char;
60 d->Msg.Count++;
61
62 /* This is not last byte in frame */
63 if (d->Msg.Count != d->Msg.Length) return ERR_NONE;
64
65 s->Phone.Data.RequestMsg= &d->Msg;
66 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
67
68 free(d->Msg.Buffer);
69 d->Msg.Length = 0;
70 d->Msg.Buffer = NULL;
71
72 d->MsgRXState = RX_Sync;
73 return ERR_NONE;
74 }
75 if (d->MsgRXState==RX_GetLength2) {
76 d->Msg.Length = d->Msg.Length + rx_char;
77 d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length);
78
79 d->MsgRXState = RX_GetMessage;
80 return ERR_NONE;
81 }
82 if (d->MsgRXState==RX_GetLength1) {
83 d->Msg.Length = rx_char * 256;
84
85 d->MsgRXState = RX_GetLength2;
86 return ERR_NONE;
87 }
88 if (d->MsgRXState==RX_GetType) {
89 d->Msg.Type = rx_char;
90
91 d->MsgRXState = RX_GetLength1;
92 return ERR_NONE;
93 }
94 if (d->MsgRXState==RX_GetSource) {
95 if (rx_char != PHONET_DEVICE_PHONE) {
96 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
97 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
98 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PHONE);
99 }
100 d->MsgRXState = RX_Sync;
101 return ERR_NONE;
102 }
103 d->Msg.Source = rx_char;
104
105 d->MsgRXState = RX_GetType;
106 return ERR_NONE;
107 }
108 if (d->MsgRXState==RX_GetDestination) {
109 switch (s->ConnectionType) {
110 case GCT_IRDAPHONET:
111 if (rx_char == PHONET_DEVICE_PC) correct = true;
112 break;
113 case GCT_PHONETBLUE:
114 case GCT_BLUEPHONET:
115 if (rx_char == PHONET_BLUE_DEVICE_PC) correct = true;
116 break;
117 default:
118 break;
119 }
120 if (!correct) {
121 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
122 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
123 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PC);
124 }
125 d->MsgRXState = RX_Sync;
126 return ERR_NONE;
127 }
128 d->Msg.Destination = rx_char;
129
130 d->MsgRXState = RX_GetSource;
131 return ERR_NONE;
132 }
133 if (d->MsgRXState==RX_Sync) {
134 switch (s->ConnectionType) {
135 case GCT_IRDAPHONET:
136 if (rx_char == PHONET_FRAME_ID) correct = true;
137 break;
138 case GCT_PHONETBLUE:
139 case GCT_BLUEPHONET:
140 if (rx_char == PHONET_BLUE_FRAME_ID) correct = true;
141 break;
142 default:
143 break;
144 }
145 if (!correct) {
146 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
147 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
148 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_FRAME_ID);
149 }
150 return ERR_NONE;
151 }
152 d->Msg.Count = 0;
153
154 d->MsgRXState = RX_GetDestination;
155 return ERR_NONE;
156 }
157 return ERR_NONE;
158}
159
160static GSM_Error PHONET_Initialise(GSM_StateMachine *s)
161{
162 int total = 0, i, n;
163 GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET;
164 unsigned char req[50];
165
166 d->Msg.Length= 0;
167 d->Msg.Buffer= NULL;
168 d->MsgRXState= RX_Sync;
169
170 if (s->ConnectionType == GCT_PHONETBLUE || s->ConnectionType == GCT_BLUEPHONET) {
171 /* Send frame in PHONET style */
172 req[0] = PHONET_BLUE_FRAME_ID; req[1] = PHONET_DEVICE_PHONE;
173 req[2] = PHONET_BLUE_DEVICE_PC; req[3] = 0xD0;
174 req[4] = 0x00; req[5] = 0x01;
175 req[6] = 0x04;
176 if (s->Device.Functions->WriteDevice(s,req,7) != 7) return ERR_DEVICEWRITEERROR;
177
178 while (total < 7) {
179 n = s->Device.Functions->ReadDevice(s, req + total, 50 - total);
180 total += n;
181 }
182
183 /* Answer frame in PHONET style */
184 req[10] = PHONET_BLUE_FRAME_ID; req[11] = PHONET_BLUE_DEVICE_PC;
185 req[12] = PHONET_DEVICE_PHONE;req[13] = 0xD0;
186 req[14] = 0x00; req[15] = 0x01;
187 req[16] = 0x05;
188
189 for (i = 0; i < 7; i++) {
190 if (req[i] != req[10+i]) {
191 smprintf(s,"Incorrect byte in the answer\n");
192 return ERR_UNKNOWN;
193 }
194 }
195 }
196
197 return ERR_NONE;
198}
199
200static GSM_Error PHONET_Terminate(GSM_StateMachine *s)
201{
202 free(s->Protocol.Data.PHONET.Msg.Buffer);
203 return ERR_NONE;
204}
205
206GSM_Protocol_Functions PHONETProtocol = {
207 PHONET_WriteMessage,
208 PHONET_StateMachine,
209 PHONET_Initialise,
210 PHONET_Terminate
211};
212
213#endif
214
215/* How should editor hadle tabs in this file? Add editor commands here.
216 * vim: noexpandtab sw=8 ts=8 sts=8:
217 */
diff --git a/gammu/emb/common/protocol/nokia/phonet.h b/gammu/emb/common/protocol/nokia/phonet.h
new file mode 100644
index 0000000..2f6e836
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/phonet.h
@@ -0,0 +1,35 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2/* based on some work from Gnokii */
3
4#ifndef PHONET_h
5#define PHONET_h
6
7#include "../protocol.h"
8
9 #define PHONET_FRAME_ID 0x14
10 #define PHONET_BLUE_FRAME_ID0x19
11 #define PHONET_DEVICE_PHONE 0x00 /* Nokia mobile phone */
12 #define PHONET_DEVICE_PC 0x0c /* Our PC */
13#define PHONET_BLUE_DEVICE_PC 0x10 /* Our PC */
14
15typedef struct {
16 int MsgRXState;
17 GSM_Protocol_MessageMsg;
18} GSM_Protocol_PHONETData;
19
20#if defined(GSM_ENABLE_IRDAPHONET)
21# ifndef GSM_USED_IRDADEVICE
22# define GSM_USED_IRDADEVICE
23# endif
24#endif
25#if defined(GSM_ENABLE_BLUEPHONET)
26# ifndef GSM_USED_BLUETOOTHDEVICE
27# define GSM_USED_BLUETOOTHDEVICE
28# endif
29#endif
30
31#endif
32
33/* How should editor hadle tabs in this file? Add editor commands here.
34 * vim: noexpandtab sw=8 ts=8 sts=8:
35 */
diff --git a/gammu/emb/common/protocol/obex/obex.c b/gammu/emb/common/protocol/obex/obex.c
new file mode 100644
index 0000000..942c084
--- a/dev/null
+++ b/gammu/emb/common/protocol/obex/obex.c
@@ -0,0 +1,120 @@
1/* (c) 2003 by Marcin Wiacek */
2/* www.irda.org OBEX specs 1.3 */
3
4#include "../../gsmstate.h"
5
6#include <stdio.h>
7#include <string.h>
8
9#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX)
10
11#include "../../gsmcomon.h"
12#include "obex.h"
13
14static GSM_Error OBEX_WriteMessage (GSM_StateMachine *s, unsigned char *buffer,
15 int length, unsigned char type)
16{
17 unsigned char*out_buffer;
18 int current=0,sent;
19
20 out_buffer = (unsigned char *)malloc(length + 3);
21
22 OBEXAddBlock(out_buffer, &current, type, buffer, length);
23
24 GSM_DumpMessageLevel2(s, out_buffer+3, length, type);
25 GSM_DumpMessageLevel3(s, out_buffer+3, length, type);
26
27 /* Send it out... */
28 sent = s->Device.Functions->WriteDevice(s,out_buffer,current);
29
30 free(out_buffer);
31
32 if (sent!=current) return ERR_DEVICEWRITEERROR;
33 return ERR_NONE;
34}
35
36static GSM_Error OBEX_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
37{
38 GSM_Phone_Functions *Phone= s->Phone.Functions;
39 GSM_Protocol_OBEXData *d= &s->Protocol.Data.OBEX;
40
41 switch (d->MsgRXState) {
42 case RX_Sync:
43 d->Msg.Type = rx_char;
44 d->MsgRXState = RX_GetLength1;
45 break;
46 case RX_GetLength1:
47 d->Msg.Length = rx_char * 256;
48 d->MsgRXState = RX_GetLength2;
49 break;
50 case RX_GetLength2:
51 d->Msg.Length = d->Msg.Length + rx_char - 3;
52 d->Msg.Count = 0;
53 if (d->Msg.Count == d->Msg.Length) {
54 s->Phone.Data.RequestMsg= &d->Msg;
55 s->Phone.Data.DispatchError= Phone->DispatchMessage(s);
56 d->MsgRXState = RX_Sync;
57 } else {
58 if (d->Msg.BufferUsed < d->Msg.Length) {
59 d->Msg.BufferUsed = d->Msg.Length;
60 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
61 }
62 d->MsgRXState = RX_GetMessage;
63 }
64 break;
65 case RX_GetMessage:
66 d->Msg.Buffer[d->Msg.Count] = rx_char;
67 d->Msg.Count++;
68 if (d->Msg.Count == d->Msg.Length) {
69 s->Phone.Data.RequestMsg= &d->Msg;
70 s->Phone.Data.DispatchError= Phone->DispatchMessage(s);
71 d->MsgRXState = RX_Sync;
72 }
73 break;
74 }
75
76 return ERR_NONE;
77}
78
79static GSM_Error OBEX_Initialise(GSM_StateMachine *s)
80{
81 GSM_Protocol_OBEXData *d = &s->Protocol.Data.OBEX;
82
83 d->Msg.BufferUsed= 0;
84 d->Msg.Buffer = NULL;
85 d->Msg.Length = 0;
86
87 d->MsgRXState = RX_Sync;
88
89 return ERR_NONE;
90}
91
92static GSM_Error OBEX_Terminate(GSM_StateMachine *s)
93{
94 free(s->Protocol.Data.OBEX.Msg.Buffer);
95 return ERR_NONE;
96}
97
98GSM_Protocol_Functions OBEXProtocol = {
99 OBEX_WriteMessage,
100 OBEX_StateMachine,
101 OBEX_Initialise,
102 OBEX_Terminate
103};
104
105#endif
106
107void OBEXAddBlock(char *Buffer, int *Pos, unsigned char ID, char *AddBuffer, int AddLength)
108{
109 Buffer[(*Pos)++] = ID;
110 Buffer[(*Pos)++] = (AddLength+3)/256;
111 Buffer[(*Pos)++] = (AddLength+3)%256;
112 if (AddBuffer != NULL) {
113 memcpy(Buffer+(*Pos),AddBuffer,AddLength);
114 (*Pos) += AddLength;
115 }
116}
117
118/* How should editor hadle tabs in this file? Add editor commands here.
119 * vim: noexpandtab sw=8 ts=8 sts=8:
120 */
diff --git a/gammu/emb/common/protocol/obex/obex.h b/gammu/emb/common/protocol/obex/obex.h
new file mode 100644
index 0000000..0e927c7
--- a/dev/null
+++ b/gammu/emb/common/protocol/obex/obex.h
@@ -0,0 +1,33 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef obex_h
4#define obex_h
5
6#include "../protocol.h"
7
8typedef struct {
9 int MsgRXState;
10 GSM_Protocol_Message Msg;
11} GSM_Protocol_OBEXData;
12
13#ifndef GSM_USED_SERIALDEVICE
14# define GSM_USED_SERIALDEVICE
15#endif
16#if defined(GSM_ENABLE_BLUEOBEX)
17# ifndef GSM_USED_BLUETOOTHDEVICE
18# define GSM_USED_BLUETOOTHDEVICE
19# endif
20#endif
21#if defined(GSM_ENABLE_IRDAOBEX)
22# ifndef GSM_USED_IRDADEVICE
23# define GSM_USED_IRDADEVICE
24# endif
25#endif
26
27void OBEXAddBlock(char *Buffer, int *Pos, unsigned char ID, char *AddBuffer, int AddLength);
28
29#endif
30
31/* How should editor hadle tabs in this file? Add editor commands here.
32 * vim: noexpandtab sw=8 ts=8 sts=8:
33 */
diff --git a/gammu/emb/common/protocol/protocol.h b/gammu/emb/common/protocol/protocol.h
new file mode 100644
index 0000000..f8e1fe5
--- a/dev/null
+++ b/gammu/emb/common/protocol/protocol.h
@@ -0,0 +1,31 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef protocol_common_h
4#define protocol_common_h
5
6typedef enum {
7 RX_Sync,
8 RX_GetDestination,
9 RX_GetSource,
10 RX_GetType,
11 RX_GetLength1,
12 RX_GetLength2,
13 RX_GetMessage
14} GSM_Protocol_RXState;
15
16typedef struct {
17 int Length;
18 int Count;
19 unsigned char Type;
20 unsigned char Source;
21 unsigned char Destination;
22 unsigned char*Buffer;
23 int BufferUsed;
24 unsigned char CheckSum[2];
25} GSM_Protocol_Message;
26
27#endif
28
29/* How should editor hadle tabs in this file? Add editor commands here.
30 * vim: noexpandtab sw=8 ts=8 sts=8:
31 */
diff --git a/gammu/emb/common/protocol/symbian/mrouter.c b/gammu/emb/common/protocol/symbian/mrouter.c
new file mode 100644
index 0000000..2ca7af1
--- a/dev/null
+++ b/gammu/emb/common/protocol/symbian/mrouter.c
@@ -0,0 +1,110 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include "../../gsmstate.h"
4
5#if defined(GSM_ENABLE_MROUTERBLUE)
6
7#include <stdio.h>
8#include <string.h>
9
10#include "../../gsmcomon.h"
11#include "mrouter.h"
12
13static GSM_Error MROUTER_WriteMessage (GSM_StateMachine *s, unsigned char *buffer,
14 int length, unsigned char type)
15{
16 unsigned char*out_buffer;
17 int current=0,sent;
18
19 out_buffer = (unsigned char *)malloc(length+1);
20
21 memcpy(out_buffer,buffer,length);
22 out_buffer[length]=0x7E;
23
24 GSM_DumpMessageLevel2(s, out_buffer, length, type);
25 GSM_DumpMessageLevel3(s, out_buffer, length, type);
26
27 /* Send it out... */
28 sent = s->Device.Functions->WriteDevice(s,out_buffer,length+1);
29
30 free(out_buffer);
31
32 if (sent!=current) return ERR_DEVICEWRITEERROR;
33 return ERR_NONE;
34}
35
36static GSM_Error MROUTER_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
37{
38 GSM_Phone_Functions *Phone= s->Phone.Functions;
39 GSM_Protocol_MROUTERData *d= &s->Protocol.Data.MROUTER;
40
41 switch (d->MsgRXState) {
42 case RX_Sync:
43 if (rx_char == 0x7E) {
44 d->MsgRXState = RX_GetMessage;
45 d->Msg.Count = 0;
46 d->Msg.Length = 0;
47 } else smprintf(s,"Sync error: %02x\n",rx_char);
48 break;
49 case RX_GetMessage:
50 if (rx_char == 0x7E) {
51 s->Phone.Data.RequestMsg= &d->Msg;
52 s->Phone.Data.DispatchError= Phone->DispatchMessage(s);
53 d->Msg.Count = 0;
54 d->Msg.Length = 0;
55 } else {
56 d->Msg.BufferUsed = d->Msg.Length+1;
57 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
58
59 d->Msg.Buffer[d->Msg.Count] = rx_char;
60 d->Msg.Count++;
61 d->Msg.Length++;
62 }
63 break;
64 }
65
66 return ERR_NONE;
67}
68
69static GSM_Error MROUTER_Initialise(GSM_StateMachine *s)
70{
71 GSM_Protocol_MROUTERData *d = &s->Protocol.Data.MROUTER;
72GSM_Error error;
73
74 d->Msg.BufferUsed= 0;
75 d->Msg.Buffer = NULL;
76 d->Msg.Length = 0;
77
78 d->MsgRXState = RX_Sync;
79
80 //error=s->Device.Functions->DeviceSetDtrRts(s,false,false);
81 // if (error!=ERR_NONE) return error;
82
83 error=s->Device.Functions->DeviceSetSpeed(s,115200);
84 if (error!=ERR_NONE) return error;
85
86
87 //error=s->Device.Functions->DeviceSetSpeed(s,115200);
88 // if (error!=ERR_NONE) return error;
89
90 return ERR_NONE;
91}
92
93static GSM_Error MROUTER_Terminate(GSM_StateMachine *s)
94{
95 free(s->Protocol.Data.MROUTER.Msg.Buffer);
96 return ERR_NONE;
97}
98
99GSM_Protocol_Functions MROUTERProtocol = {
100 MROUTER_WriteMessage,
101 MROUTER_StateMachine,
102 MROUTER_Initialise,
103 MROUTER_Terminate
104};
105
106#endif
107
108/* How should editor hadle tabs in this file? Add editor commands here.
109 * vim: noexpandtab sw=8 ts=8 sts=8:
110 */
diff --git a/gammu/emb/common/protocol/symbian/mrouter.h b/gammu/emb/common/protocol/symbian/mrouter.h
new file mode 100644
index 0000000..7d72cdd
--- a/dev/null
+++ b/gammu/emb/common/protocol/symbian/mrouter.h
@@ -0,0 +1,31 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef mrouter_h
4#define mrouter_h
5
6#include "../protocol.h"
7
8typedef struct {
9 int MsgRXState;
10 GSM_Protocol_Message Msg;
11} GSM_Protocol_MROUTERData;
12
13#ifndef GSM_USED_SERIALDEVICE
14# define GSM_USED_SERIALDEVICE
15#endif
16//#if defined(GSM_ENABLE_BLUEOBEX)
17//# ifndef GSM_USED_BLUETOOTHDEVICE
18//# define GSM_USED_BLUETOOTHDEVICE
19//# endif
20//#endif
21//#if defined(GSM_ENABLE_IRDAOBEX)
22//# ifndef GSM_USED_IRDADEVICE
23//# define GSM_USED_IRDADEVICE
24//# endif
25//#endif
26
27#endif
28
29/* How should editor hadle tabs in this file? Add editor commands here.
30 * vim: noexpandtab sw=8 ts=8 sts=8:
31 */
diff --git a/gammu/emb/common/service/backup/backgen.h b/gammu/emb/common/service/backup/backgen.h
new file mode 100644
index 0000000..9d7d973
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backgen.h
@@ -0,0 +1,69 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_backgen_h
4#define __gsm_backgen_h
5
6#include "../../config.h"
7#include "../../misc/misc.h"
8#include "../gsmpbk.h"
9#include "../gsmcal.h"
10#include "../gsmlogo.h"
11#include "../gsmring.h"
12#include "../gsmdata.h"
13#include "../gsmprof.h"
14#include "../gsmmisc.h"
15#include "../sms/gsmsms.h"
16
17 #define GSM_BACKUP_MAX_PHONEPHONEBOOK 501
18 #define GSM_BACKUP_MAX_SIMPHONEBOOK 251
19 #define GSM_BACKUP_MAX_CALLER 6
20 #define GSM_BACKUP_MAX_SMSC 10
21 #define GSM_BACKUP_MAX_WAPBOOKMARK40
22 #define GSM_BACKUP_MAX_WAPSETTINGS30
23 #define GSM_BACKUP_MAX_MMSSETTINGS30
24 #define GSM_BACKUP_MAX_RINGTONES30
25 #define GSM_BACKUP_MAX_PROFILES 10
26 #define GSM_BACKUP_MAX_FMSTATIONS20
27 #define GSM_BACKUP_MAX_GPRSPOINT10
28 #define GSM_BACKUP_MAX_NOTE 10/* FIXME */
29
30typedef struct {
31 char IMEI [MAX_IMEI_LENGTH];
32 char Model [MAX_MODEL_LENGTH+MAX_VERSION_LENGTH];
33 char Creator [80];
34 GSM_DateTime DateTime;
35 bool DateTimeAvailable;
36 char MD5Original[100];
37 char MD5Calculated[100];
38 GSM_MemoryEntry *PhonePhonebook[GSM_BACKUP_MAX_PHONEPHONEBOOK + 1];
39 GSM_MemoryEntry *SIMPhonebook[GSM_BACKUP_MAX_SIMPHONEBOOK + 1];
40 GSM_CalendarEntry *Calendar[GSM_MAXCALENDARTODONOTES + 1];
41 GSM_Bitmap *CallerLogos[GSM_BACKUP_MAX_CALLER + 1];
42 GSM_SMSC *SMSC [GSM_BACKUP_MAX_SMSC + 1];
43 GSM_WAPBookmark *WAPBookmark[GSM_BACKUP_MAX_WAPBOOKMARK + 1];
44 GSM_MultiWAPSettings *WAPSettings[GSM_BACKUP_MAX_WAPSETTINGS + 1];
45 GSM_MultiWAPSettings *MMSSettings[GSM_BACKUP_MAX_MMSSETTINGS + 1];
46 GSM_Ringtone *Ringtone[GSM_BACKUP_MAX_RINGTONES + 1];
47 GSM_ToDoEntry *ToDo [GSM_MAXCALENDARTODONOTES + 1];
48 GSM_Profile *Profiles[GSM_BACKUP_MAX_PROFILES + 1];
49 GSM_FMStation *FMStation[GSM_BACKUP_MAX_FMSTATIONS +1];
50 GSM_GPRSAccessPoint *GPRSPoint[GSM_BACKUP_MAX_GPRSPOINT + 1];
51 GSM_NoteEntry *Note [GSM_BACKUP_MAX_NOTE + 1];
52 GSM_Bitmap *StartupLogo;
53 GSM_Bitmap *OperatorLogo;
54} GSM_Backup;
55
56 #define GSM_BACKUP_MAX_SMS500
57
58typedef struct {
59 GSM_SMSMessage *SMS[GSM_BACKUP_MAX_SMS];
60} GSM_SMS_Backup;
61
62extern GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
63extern GSM_Error GSM_SaveSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
64
65#endif
66
67/* How should editor hadle tabs in this file? Add editor commands here.
68 * vim: noexpandtab sw=8 ts=8 sts=8:
69 */
diff --git a/gammu/emb/common/service/backup/backics.c b/gammu/emb/common/service/backup/backics.c
new file mode 100644
index 0000000..3e6b083
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backics.c
@@ -0,0 +1,42 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backics.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveICS(char *FileName, GSM_Backup *backup)
16{
17 FILE *file;
18
19 file = fopen(FileName, "wb");
20 if (file == NULL) return ERR_CANTOPENFILE;
21
22 fclose(file);
23 return ERR_NONE;
24}
25
26GSM_Error LoadICS(char *FileName, GSM_Backup *backup)
27{
28 GSM_File File;
29 GSM_Error error;
30
31 File.Buffer = NULL;
32 error = GSM_ReadFile(FileName, &File);
33 if (error != ERR_NONE) return error;
34
35 return ERR_NONE;
36}
37
38#endif
39
40/* How should editor hadle tabs in this file? Add editor commands here.
41 * vim: noexpandtab sw=8 ts=8 sts=8:
42 */
diff --git a/gammu/emb/common/service/backup/backics.h b/gammu/emb/common/service/backup/backics.h
new file mode 100644
index 0000000..80e2b15
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backics.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backics_h
4#define __gsm_backics_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveICS(char *FileName, GSM_Backup *backup);
10GSM_Error LoadICS(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backldif.c b/gammu/emb/common/service/backup/backldif.c
new file mode 100644
index 0000000..ab16160
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backldif.c
@@ -0,0 +1,297 @@
1/* (c) 2003-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backldif.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15static void SaveLDIFText(FILE *file, unsigned char *Name, unsigned char *Value)
16{
17 unsigned char Buffer[1000],Buffer2[1000];
18
19 if (EncodeUTF8(Buffer, Value)) {
20 // dbgprintf("%s\n",Buffer);
21 EncodeBASE64(Buffer, Buffer2, strlen(Buffer));
22 fprintf(file,"%s:: %s%c%c",Name,Buffer2,13,10);
23 } else {
24 fprintf(file,"%s: %s%c%c",Name,DecodeUnicodeString(Value),13,10);
25 }
26}
27
28GSM_Error SaveLDIF(char *FileName, GSM_Backup *backup)
29{
30 int i, j;
31 FILE *file;
32
33 file = fopen(FileName, "wb");
34 if (file == NULL) return ERR_CANTOPENFILE;
35
36 i=0;
37 while (backup->PhonePhonebook[i]!=NULL) {
38 for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
39 switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
40 case PBK_Text_Name:
41 SaveLDIFText(file, "dn", backup->PhonePhonebook[i]->Entries[j].Text);
42 break;
43 default:
44 break;
45 }
46 }
47 fprintf(file, "objectclass: top%c%c",13,10);
48 fprintf(file, "objectclass: person%c%c",13,10);
49 fprintf(file, "objectclass: organizationalPerson%c%c",13,10);
50 fprintf(file, "objectclass: inetOrgPerson%c%c",13,10);
51 fprintf(file, "objectclass: mozillaAbPersonObsolete%c%c",13,10);
52 for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
53 switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
54 case PBK_Text_Postal:
55 SaveLDIFText(file, "HomePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
56 break;
57 case PBK_Text_URL:
58 SaveLDIFText(file, "homeurl", backup->PhonePhonebook[i]->Entries[j].Text);
59 break;
60 case PBK_Text_Name:
61 SaveLDIFText(file, "givenName", backup->PhonePhonebook[i]->Entries[j].Text);
62 SaveLDIFText(file, "cn", backup->PhonePhonebook[i]->Entries[j].Text);
63 break;
64 case PBK_Text_Note:
65 SaveLDIFText(file, "Description", backup->PhonePhonebook[i]->Entries[j].Text);
66 break;
67 case PBK_Number_Work:
68 SaveLDIFText(file, "workPhone", backup->PhonePhonebook[i]->Entries[j].Text);//not exist in Mozilla 1.4 win32
69 break;
70 case PBK_Number_Mobile:
71 SaveLDIFText(file, "mobile", backup->PhonePhonebook[i]->Entries[j].Text);
72 break;
73 case PBK_Number_Pager:
74 SaveLDIFText(file, "pager", backup->PhonePhonebook[i]->Entries[j].Text);
75 break;
76 case PBK_Number_Fax:
77 SaveLDIFText(file, "fax", backup->PhonePhonebook[i]->Entries[j].Text);//facsimileTelephoneNumber
78 break;
79 case PBK_Number_Home:
80 SaveLDIFText(file, "homePhone", backup->PhonePhonebook[i]->Entries[j].Text);
81 break;
82 case PBK_Number_General:
83 SaveLDIFText(file, "telephoneNumber", backup->PhonePhonebook[i]->Entries[j].Text);//work in Mozilla 1.4 win32
84 break;
85 case PBK_Text_Email:
86 SaveLDIFText(file, "mail", backup->PhonePhonebook[i]->Entries[j].Text);
87 break;
88 case PBK_Text_Email2:
89 SaveLDIFText(file, "mozillaSecondEmail", backup->PhonePhonebook[i]->Entries[j].Text);
90 break;
91 case PBK_Text_Custom1:
92 SaveLDIFText(file, "custom1", backup->PhonePhonebook[i]->Entries[j].Text);
93 break;
94 case PBK_Text_Custom2:
95 SaveLDIFText(file, "custom2", backup->PhonePhonebook[i]->Entries[j].Text);
96 break;
97 case PBK_Text_Custom3:
98 SaveLDIFText(file, "custom3", backup->PhonePhonebook[i]->Entries[j].Text);
99 break;
100 case PBK_Text_Custom4:
101 SaveLDIFText(file, "custom4", backup->PhonePhonebook[i]->Entries[j].Text);
102 break;
103 case PBK_Text_Company:
104 SaveLDIFText(file, "o", backup->PhonePhonebook[i]->Entries[j].Text);
105 break;
106 case PBK_Text_JobTitle:
107 SaveLDIFText(file, "title", backup->PhonePhonebook[i]->Entries[j].Text);
108 break;
109 case PBK_Text_StreetAddress:
110 SaveLDIFText(file, "homePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
111 break;
112 case PBK_Text_City:
113 SaveLDIFText(file, "mozillaHomeLocalityName", backup->PhonePhonebook[i]->Entries[j].Text);
114 break;
115 case PBK_Text_State:
116 SaveLDIFText(file, "mozillaHomeState", backup->PhonePhonebook[i]->Entries[j].Text);
117 break;
118 case PBK_Text_Zip:
119 SaveLDIFText(file, "mozillaHomePostalCode", backup->PhonePhonebook[i]->Entries[j].Text);
120 break;
121 case PBK_Text_Country:
122 SaveLDIFText(file, "mozillaHomeCountryName", backup->PhonePhonebook[i]->Entries[j].Text);
123 break;
124 case PBK_Number_Other:
125 case PBK_Caller_Group:
126 case PBK_RingtoneID:
127 case PBK_PictureID:
128 case PBK_Date:
129 case PBK_RingtoneFileSystemID:
130 case PBK_Text_UserID:
131 case PBK_SMSListID:
132 case PBK_Category:
133 case PBK_Private:
134 case PBK_Text_LastName:
135 case PBK_Text_FirstName:
136 dbgprintf("Feature missed\n");
137 break;
138 }
139 }
140 fprintf(file, "%c%c",13,10);
141 i++;
142 }
143 fclose(file);
144 return ERR_NONE;
145}
146
147static bool ReadLDIFText(char *Buffer, char *Start, char *Value)
148{
149 unsigned char Buffer2[1000],buff[200];
150 int i;
151
152 Value[0] = 0x00;
153
154 strcpy(buff,Start);
155 strcat(buff,":: ");
156 if (!strncmp(Buffer,buff,strlen(buff))) {
157 i = DecodeBASE64(Buffer+strlen(Start)+3, Buffer2, strlen(Buffer)-(strlen(Start)+3));
158 dbgprintf("Text after DecodeBASE64 is \"%s\"\n",Buffer2);
159 DecodeUTF8(Value, Buffer2, i);
160 dbgprintf("Text after DecodeUTF8 is \"%s\"\n",DecodeUnicodeString(Value));
161 return true;
162 }
163 strcpy(buff,Start);
164 strcat(buff,": ");
165 if (!strncmp(Buffer,buff,strlen(buff))) {
166 EncodeUnicode(Value,Buffer+strlen(Start)+2,strlen(Buffer)-(strlen(Start)+2));
167 dbgprintf("Text after EncodeUnicode is \"%s\"\n",DecodeUnicodeString(Value));
168 return true;
169 }
170 return false;
171}
172
173static GSM_Error GSM_DecodeLDIFEntry(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk)
174{
175 unsigned char Line[2000],Buff[2000],Buff2[2000];
176 int Level = 0;
177
178 Buff[0] = 0;
179 Pbk->EntriesNum = 0;
180
181 while (1) {
182 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
183 if (strlen(Line) == 0) break;
184 switch (Level) {
185 case 0:
186 if (ReadLDIFText(Line, "objectclass", Buff)) {
187 sprintf(Buff2,"%s",DecodeUnicodeString(Buff));
188 if (!strcmp("mozillaAbPersonObsolete",Buff2)) {
189 dbgprintf("level1\n");
190 Level = 1;
191 }
192 }
193 break;
194 case 1:
195 if (ReadLDIFText(Line, "dn", Buff)) {
196 dbgprintf("entries num is %i\n",Pbk->EntriesNum);
197 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
198 return ERR_NONE;
199 }
200 if (ReadLDIFText(Line, "givenName", Buff)) {
201 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
202 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
203 Pbk->EntriesNum++;
204 }
205 if (ReadLDIFText(Line, "telephoneNumber", Buff)) {
206 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
207 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
208 Pbk->EntriesNum++;
209 }
210 if (ReadLDIFText(Line, "mobile", Buff)) {
211 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
212 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
213 Pbk->EntriesNum++;
214 }
215 if (ReadLDIFText(Line, "workPhone", Buff)) {
216 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
217 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
218 Pbk->EntriesNum++;
219 }
220 if (ReadLDIFText(Line, "fax", Buff)) {
221 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
222 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
223 Pbk->EntriesNum++;
224 }
225 if (ReadLDIFText(Line, "homePhone",Buff)) {
226 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
227 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
228 Pbk->EntriesNum++;
229 }
230 if (ReadLDIFText(Line, "Description", Buff)) {
231 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
233 Pbk->EntriesNum++;
234 }
235 if (ReadLDIFText(Line, "HomePostalAddress", Buff)) {
236 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
237 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
238 Pbk->EntriesNum++;
239 }
240 if (ReadLDIFText(Line, "mail", Buff)) {
241 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
242 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
243 Pbk->EntriesNum++;
244 }
245 if (ReadLDIFText(Line, "homeurl", Buff)) {
246 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
247 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
248 Pbk->EntriesNum++;
249 }
250 /* FIXME: add rest */
251 break;
252 }
253 }
254
255 dbgprintf("entries num is %i\n",Pbk->EntriesNum);
256 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
257 return ERR_NONE;
258}
259
260GSM_Error LoadLDIF(char *FileName, GSM_Backup *backup)
261{
262 GSM_File File;
263 GSM_Error error;
264 GSM_MemoryEntryPbk;
265 int numPbk = 0, Pos;
266
267 File.Buffer = NULL;
268 error = GSM_ReadFile(FileName, &File);
269 if (error != ERR_NONE) return error;
270
271 Pos = 0;
272 while (1) {
273 error = GSM_DecodeLDIFEntry(File.Buffer, &Pos, &Pbk);
274 if (error == ERR_EMPTY) break;
275 if (error != ERR_NONE) return error;
276 if (numPbk < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
277 backup->PhonePhonebook[numPbk] = malloc(sizeof(GSM_MemoryEntry));
278 if (backup->PhonePhonebook[numPbk] == NULL) return ERR_MOREMEMORY;
279 backup->PhonePhonebook[numPbk + 1] = NULL;
280 } else {
281 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
282 return ERR_MOREMEMORY;
283 }
284 memcpy(backup->PhonePhonebook[numPbk],&Pbk,sizeof(GSM_MemoryEntry));
285 backup->PhonePhonebook[numPbk]->Location = numPbk + 1;
286 backup->PhonePhonebook[numPbk]->MemoryType = MEM_ME;
287 numPbk++;
288 }
289
290 return ERR_NONE;
291}
292
293#endif
294
295/* How should editor hadle tabs in this file? Add editor commands here.
296 * vim: noexpandtab sw=8 ts=8 sts=8:
297 */
diff --git a/gammu/emb/common/service/backup/backldif.h b/gammu/emb/common/service/backup/backldif.h
new file mode 100644
index 0000000..212c048
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backldif.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backldif_h
4#define __gsm_backldif_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveLDIF(char *FileName, GSM_Backup *backup);
10GSM_Error LoadLDIF(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backlmb.c b/gammu/emb/common/service/backup/backlmb.c
new file mode 100644
index 0000000..d7f845a
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backlmb.c
@@ -0,0 +1,413 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backlmb.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15static void SaveLMBStartupEntry(FILE *file, GSM_Bitmap bitmap)
16{
17 int count=13;
18 GSM_Phone_Bitmap_Types Type;
19 /* Welcome note and logo header block */
20 char req[1000] = {
21 'W','E','L',' ', /*block identifier*/
22 00,00, /*block data size*/
23 0x02,00,00,00,00,00,
24 0x00}; /*number of blocks (like in 6110 frame)*/
25
26 if (bitmap.Type == GSM_StartupLogo) {
27 req[count++] = 0x01;
28 req[count++] = bitmap.BitmapHeight;
29 req[count++] = bitmap.BitmapWidth;
30 Type = GSM_NokiaStartupLogo;
31 switch (bitmap.BitmapHeight) {
32 case 65: Type = GSM_Nokia7110StartupLogo; break;
33 case 60: Type = GSM_Nokia6210StartupLogo; break;
34 }
35 PHONE_EncodeBitmap(Type, req+count, &bitmap);
36 count = count + PHONE_GetBitmapSize(Type, 0, 0);
37
38 req[12]++;
39 }
40 if (bitmap.Type == GSM_WelcomeNote_Text) {
41 req[count++]=0x02;
42 req[count++]=UnicodeLength(bitmap.Text);
43 memcpy(req+count,DecodeUnicodeString(bitmap.Text),UnicodeLength(bitmap.Text));
44 count=count+UnicodeLength(bitmap.Text);
45
46 req[12]++;
47 }
48
49 req[4]=(count-12)%256;
50 req[5]=(count-12)/256;
51
52 fwrite(req, 1, count, file);
53 }
54
55static void SaveLMBCallerEntry(FILE *file, GSM_Bitmap bitmap)
56{
57 int count=12, textlen;
58 char req[500] = {
59 'C','G','R',' ', /*block identifier*/
60 00,00, /*block data size*/
61 02,00,
62 00, /*group number=0,1,etc.*/
63 00,00,00};
64
65 req[count++] = bitmap.Location - 1;
66 if (bitmap.DefaultName) {
67 req[count++] = 0;
68 } else {
69 textlen = UnicodeLength(bitmap.Text);
70 req[count++] = textlen;
71 memcpy(req+count,DecodeUnicodeString(bitmap.Text),textlen);
72 count += textlen;
73 }
74 if (bitmap.DefaultRingtone) {
75 req[count++] = 0x16;
76 } else {
77 req[count++] = bitmap.RingtoneID;
78 }
79 if (bitmap.BitmapEnabled) req[count++] = 0x01; else req[count++] = 0x00;
80 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) >> 8;
81 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) % 0xff;
82 if (bitmap.DefaultBitmap) {
83 bitmap.BitmapWidth = 72;
84 bitmap.BitmapHeight = 14;
85 GSM_ClearBitmap(&bitmap);
86 }
87 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &bitmap, req, &count);
88 req[count++]=0;
89
90 req[4]=(count-12)%256;
91 req[5]=(count-12)/256;
92 req[8]=bitmap.Location;
93
94 fwrite(req, 1, count, file);
95 }
96
97void SaveLMBPBKEntry(FILE *file, GSM_MemoryEntry *entry)
98{
99 int count = 16, blocks;
100 char req[500] = {
101 'P','B','E','2', /*block identifier*/
102 00,00, /*block data size*/
103 00,00,
104 00,00, /*position of phonebook entry*/
105 03, /*memory type. ME=02;SM=03*/
106 00,
107 00,00, /*position of phonebook entry*/
108 03, /*memory type. ME=02;SM=03*/
109 00};
110
111 count=count+N71_65_EncodePhonebookFrame(NULL, req+16, *entry, &blocks, true, true);
112
113 req[4]=(count-12)%256;
114 req[5]=(count-12)/256;
115 req[8]=req[12] = entry->Location & 0xff;
116 req[9]=req[13] = (entry->Location >> 8);
117 if (entry->MemoryType==MEM_ME) req[10]=req[14]=2;
118
119 fwrite(req, 1, count, file);
120}
121
122GSM_Error SaveLMB(char *FileName, GSM_Backup *backup)
123{
124 FILE *file;
125 int i;
126 char LMBHeader[] = {'L','M','B',' '}; /*file identifier*/
127 char PBKHeader[] = { /*Phonebook header block */
128 'P','B','K',' ', /*block identifier*/
129 0x08,00, /*block data size*/
130 0x02,00,
131 03, /*memory type. ME=02;SM=03*/
132 00,00,00,
133 00,00, /*size of phonebook*/
134 14, /*max length of each position*/
135 00,00,00,00,00};
136
137
138 file = fopen(FileName, "wb");
139 if (file == NULL) return ERR_CANTOPENFILE;
140
141 /* Write the header of the file. */
142 fwrite(LMBHeader, 1, sizeof(LMBHeader), file);
143
144 if (backup->PhonePhonebook[0]!=NULL) {
145 PBKHeader[8] = 2; /* memory type=MEM_ME */
146 PBKHeader[12] = (unsigned char)(500 % 256);
147 PBKHeader[13] = 500 / 256;
148 fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
149 i=0;
150 while (backup->PhonePhonebook[i]!=NULL) {
151 SaveLMBPBKEntry(file, backup->PhonePhonebook[i]);
152 i++;
153 }
154 }
155 if (backup->SIMPhonebook[0]!=NULL) {
156 PBKHeader[8] = 3; /* memory type=MEM_SM */
157 PBKHeader[12] = (unsigned char)(250 % 256);
158 PBKHeader[13] = 250 / 256;
159 PBKHeader[14] = 0x16; /* max size of one entry */
160 fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
161 i=0;
162 while (backup->SIMPhonebook[i]!=NULL) {
163 SaveLMBPBKEntry(file, backup->SIMPhonebook[i]);
164 i++;
165 }
166 }
167 i=0;
168 while (backup->CallerLogos[i]!=NULL) {
169 SaveLMBCallerEntry(file, *backup->CallerLogos[i]);
170 i++;
171 }
172 if (backup->StartupLogo!=NULL) {
173 SaveLMBStartupEntry(file, *backup->StartupLogo);
174 }
175
176 fclose(file);
177 return ERR_NONE;
178}
179
180static GSM_Error LoadLMBCallerEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
181{
182 GSM_Bitmap bitmap;
183 int num;
184
185#ifdef DEBUG
186 dbgprintf("Number %i, name \"", buffer2[0]+1);
187 for (num=0;num<buffer2[1];num++) dbgprintf("%c", buffer2[num+2]);
188 dbgprintf("\"\n");
189 dbgprintf("Ringtone ID=%i\n", buffer2[num+2]);
190 if (buffer2[num+3]==1) {
191 dbgprintf("Logo enabled\n");
192 } else {
193 dbgprintf("Logo disabled\n");
194 }
195#endif
196
197 bitmap.Location = buffer2[0] + 1;
198 bitmap.Type = GSM_CallerGroupLogo;
199 bitmap.DefaultRingtone = false;
200 bitmap.RingtoneID = buffer2[buffer2[1]+2];
201
202 EncodeUnicode(bitmap.Text,buffer2+2,buffer2[1]);
203 if (bitmap.Text[0] == 0x00 && bitmap.Text[1] == 0x00) {
204 bitmap.DefaultName = true;
205 } else {
206 bitmap.DefaultName = false;
207 }
208
209 bitmap.BitmapEnabled = false;
210 if (buffer2[buffer2[1]+3]==1) bitmap.BitmapEnabled=true;
211
212 bitmap.DefaultBitmap = false;
213 PHONE_DecodeBitmap(GSM_NokiaCallerLogo, buffer2+(buffer2[1]+10), &bitmap);
214
215#ifdef DEBUG
216 dbgprintf("Caller logo\n");
217 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&bitmap);
218#endif
219
220 num = 0;
221 while (backup->CallerLogos[num] != NULL) num++;
222 if (num < GSM_BACKUP_MAX_CALLER) {
223 backup->CallerLogos[num] = malloc(sizeof(GSM_Bitmap));
224 if (backup->CallerLogos[num] == NULL) return ERR_MOREMEMORY;
225 backup->CallerLogos[num + 1] = NULL;
226 } else {
227 dbgprintf("Increase GSM_BACKUP_MAX_CALLER\n");
228 return ERR_MOREMEMORY;
229 }
230 *backup->CallerLogos[num] = bitmap;
231
232 return ERR_NONE;
233 }
234
235static GSM_Error LoadLMBStartupEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
236{
237 int i,j;
238#ifdef DEBUG
239 int z;
240#endif
241 GSM_Phone_Bitmap_Types Type;
242
243 j=1;
244 for (i=0;i<buffer2[0];i++) {
245 switch (buffer2[j++]) {
246 case 1:
247 dbgprintf("Block 1 - startup logo\n");
248 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
249 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
250 backup->StartupLogo->Location= 1;
251 backup->StartupLogo->BitmapHeight= buffer2[j++];
252 backup->StartupLogo->BitmapWidth= buffer2[j++];
253 Type = GSM_NokiaStartupLogo;
254 switch (backup->StartupLogo->BitmapHeight) {
255 case 65: Type = GSM_Nokia7110StartupLogo; break;
256 case 60: Type = GSM_Nokia6210StartupLogo; break;
257 }
258 PHONE_DecodeBitmap(Type, buffer2+j, backup->StartupLogo);
259#ifdef DEBUG
260 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,backup->StartupLogo);
261#endif
262 j = j + PHONE_GetBitmapSize(Type,0,0);
263 break;
264 case 2:
265#ifdef DEBUG
266 dbgprintf("Block 2 - welcome note \"");
267 for (z=0;z<buffer2[j];z++) dbgprintf("%c",buffer2[j+z+1]);
268 dbgprintf("\"\n");
269#endif
270 if (backup->StartupLogo == NULL) {
271 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
272 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
273 backup->StartupLogo->Type = GSM_WelcomeNote_Text;
274 EncodeUnicode(backup->StartupLogo->Text,buffer2+j,buffer2[j]);
275 }
276 j = j + buffer2[j];
277 break;
278 default:
279 dbgprintf("Unknown block %02x\n",buffer2[j]);
280 break;
281 }
282 }
283 return ERR_NONE;
284}
285
286static GSM_Error LoadLMBPbkEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
287{
288 GSM_MemoryEntry pbk;
289 int num;
290
291#ifdef DEBUG
292 dbgprintf("Memory : ");
293 switch(buffer[10]) {
294 case 2 : dbgprintf("(internal)\n"); break;
295 case 3 : dbgprintf("(sim)\n"); break;
296 default: dbgprintf("(unknown)\n"); break;
297 }
298 dbgprintf("Location : %i\n",buffer2[0]+buffer2[1]*256);
299#endif
300
301 N71_65_DecodePhonebook(NULL, &pbk, NULL,NULL,buffer2+4,(buffer[4]+buffer[5]*256)-4,false);
302
303 pbk.MemoryType=MEM_SM;
304 if (buffer[10]==2) pbk.MemoryType=MEM_ME;
305
306 pbk.Location=buffer2[0]+256*buffer2[1];
307
308 num = 0;
309 if (buffer[10]==2) {
310 while (backup->PhonePhonebook[num] != NULL) num++;
311 if (num < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
312 backup->PhonePhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
313 if (backup->PhonePhonebook[num] == NULL) return ERR_MOREMEMORY;
314 backup->PhonePhonebook[num + 1] = NULL;
315 } else {
316 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
317 return ERR_MOREMEMORY;
318 }
319 *backup->PhonePhonebook[num] = pbk;
320 } else {
321 while (backup->SIMPhonebook[num] != NULL) num++;
322 if (num < GSM_BACKUP_MAX_SIMPHONEBOOK) {
323 backup->SIMPhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
324 if (backup->SIMPhonebook[num] == NULL) return ERR_MOREMEMORY;
325 backup->SIMPhonebook[num + 1] = NULL;
326 } else {
327 dbgprintf("Increase GSM_BACKUP_MAX_SIMPHONEBOOK\n");
328 return ERR_MOREMEMORY;
329 }
330 *backup->SIMPhonebook[num] = pbk;
331 }
332 return ERR_NONE;
333}
334
335GSM_Error LoadLMB(char *FileName, GSM_Backup *backup)
336{
337#ifdef DEBUG
338 int i;
339#endif
340 unsigned char buffer[12], buffer2[1000];
341 FILE *file;
342 GSM_Errorerror;
343
344 file = fopen(FileName, "rb");
345 if (file == NULL) return(ERR_CANTOPENFILE);
346
347 /* Read the header of the file. */
348 fread(buffer, 1, 4, file);
349
350 /* while we have something to read */
351 while (fread(buffer, 1, 12, file)==12) {
352#ifdef DEBUG
353 /* Info about block in the file */
354 dbgprintf("Block \"");
355 for (i=0;i<4;i++) {dbgprintf("%c",buffer[i]);}
356 dbgprintf("\" (");
357 if (memcmp(buffer, "PBK ",4)==0) { dbgprintf("Phonebook");
358 } else if (memcmp(buffer, "PBE2",4)==0) { dbgprintf("Phonebook entry");
359 } else if (memcmp(buffer, "CGR ",4)==0) { dbgprintf("Caller group");
360 } else if (memcmp(buffer, "SPD ",4)==0) { dbgprintf("Speed dial");
361 } else if (memcmp(buffer, "OLG ",4)==0) { dbgprintf("Operator logo");
362 } else if (memcmp(buffer, "WEL ",4)==0) { dbgprintf("Startup logo and welcome text");
363 } else { dbgprintf("unknown - ignored");
364 }
365 dbgprintf(") - length %i\n", buffer[4]+buffer[5]*256);
366#endif
367 /* reading block data */
368 fread(buffer2, 1, buffer[4]+buffer[5]*256, file);
369
370#ifdef DEBUG
371 if (memcmp(buffer, "PBK ",4)==0) {
372 dbgprintf("Size of phonebook %i, type %i ",(buffer2[0]+buffer2[1]*256),buffer[8]);
373 switch(buffer[8]) {
374 case 2 : dbgprintf("(internal)");break;
375 case 3 : dbgprintf("(sim)") ;break;
376 default: dbgprintf("(unknown)") ;break;
377 }
378 dbgprintf(", length of each position - %i\n",buffer2[2]);
379 }
380#endif
381 if (memcmp(buffer, "PBE2",4)==0) {
382 error = LoadLMBPbkEntry(buffer,buffer2,backup);
383 if (error != ERR_NONE) {
384 fclose(file);
385 return error;
386 }
387 }
388 if (memcmp(buffer, "CGR ",4)==0) {
389 error = LoadLMBCallerEntry(buffer, buffer2, backup);
390 if (error != ERR_NONE) {
391 fclose(file);
392 return error;
393 }
394 }
395 if (memcmp(buffer, "WEL ",4)==0) {
396 error = LoadLMBStartupEntry(buffer, buffer2, backup);
397 if (error != ERR_NONE) {
398 fclose(file);
399 return error;
400 }
401 }
402 }
403
404 fclose(file);
405
406 return ERR_NONE;
407}
408
409#endif
410
411/* How should editor hadle tabs in this file? Add editor commands here.
412 * vim: noexpandtab sw=8 ts=8 sts=8:
413 */
diff --git a/gammu/emb/common/service/backup/backlmb.h b/gammu/emb/common/service/backup/backlmb.h
new file mode 100644
index 0000000..18bba66
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backlmb.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backlmb_h
4#define __gsm_backlmb_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveLMB(char *FileName, GSM_Backup *backup);
10GSM_Error LoadLMB(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backtext.c b/gammu/emb/common/service/backup/backtext.c
new file mode 100644
index 0000000..fee0f73
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backtext.c
@@ -0,0 +1,2908 @@
1/* (c) 2002-2004 by Marcin Wiacek, Walek and Michal Cihar */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/cfg.h"
9#include "../../misc/coding/coding.h"
10#include "../../misc/coding/md5.h"
11#include "../gsmlogo.h"
12#include "../gsmmisc.h"
13#include "backtext.h"
14
15#ifdef GSM_ENABLE_BACKUP
16
17GSM_Error FindBackupChecksum(char *FileName, bool UseUnicode, char *checksum)
18{
19 INI_Section *file_info, *h;
20 INI_Entry *e;
21 char *buffer = NULL,buff[100];
22 int len=0;
23
24 //int i;
25
26 file_info = INI_ReadFile(FileName, UseUnicode);
27
28 if (UseUnicode) {
29 for (h = file_info; h != NULL; h = h->Next) {
30 EncodeUnicode(buff,"Checksum",8);
31 if (mywstrncasecmp(buff, h->SectionName, 8)) continue;
32
33 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(h->SectionName)*2+2);
34 CopyUnicodeString(buffer+len,h->SectionName);
35 len+=UnicodeLength(h->SectionName)*2;
36 // dbgprintf("[%s]\n",DecodeUnicodeConsole(h->SectionName));
37
38 for (e = h->SubEntries; e != NULL; e = e->Next) {
39 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryName)*2+2);
40 CopyUnicodeString(buffer+len,e->EntryName);
41 len+=UnicodeLength(e->EntryName)*2;
42 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryValue)*2+2);
43 CopyUnicodeString(buffer+len,e->EntryValue);
44 len+=UnicodeLength(e->EntryValue)*2;
45 // dbgprintf("\"%s\"",DecodeUnicodeConsole(e->EntryName));
46 // dbgprintf("=\"%s\"\n",DecodeUnicodeConsole(e->EntryValue));
47 }
48 }
49 } else {
50 for (h = file_info; h != NULL; h = h->Next) {
51 if (mystrncasecmp("Checksum", h->SectionName, 8)) continue;
52
53 buffer = (unsigned char *)realloc(buffer,len+strlen(h->SectionName)+1);
54 strcpy(buffer+len,h->SectionName);
55 len+=strlen(h->SectionName);
56
57 for (e = h->SubEntries; e != NULL; e = e->Next) {
58 // dbgprintf("%s=%s\n",e->EntryName,e->EntryValue);
59 buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryName)+1);
60 strcpy(buffer+len,e->EntryName);
61 len+=strlen(e->EntryName);
62 buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryValue)+1);
63 strcpy(buffer+len,e->EntryValue);
64 len+=strlen(e->EntryValue);
65 }
66 }
67 }
68
69 //for (i=0;i<len;i++) printf("%02x",buffer[i]);
70 CalculateMD5(buffer, len, checksum);
71 free(buffer);
72
73 return ERR_NONE;
74}
75
76static unsigned char *ReadCFGText(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode)
77{
78 unsigned char Buffer[500],Buffer2[500],*retval;
79
80 if (Unicode) {
81 EncodeUnicode(Buffer2,key,strlen(key));
82 retval = INI_GetValue(cfg,section,Buffer2,Unicode);
83 if (retval != NULL) return DecodeUnicodeString(retval);
84 return NULL;
85 } else {
86 strcpy(Buffer,section);
87 strcpy(Buffer2,key);
88 return INI_GetValue(cfg,section,key,Unicode);
89 }
90}
91
92static void SaveLinkedBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
93{
94 int w,current;
95 unsigned char buffer2[1000],buffer3[1000];
96
97 current = strlen(myvalue); w = 0;
98 while (true) {
99 if (current > 200) {
100 memcpy(buffer2,myvalue+(strlen(myvalue)-current),200);
101 buffer2[200] = 0;
102 current = current - 200;
103 } else {
104 memcpy(buffer2,myvalue+(strlen(myvalue)-current),current);
105 buffer2[current] = 0;
106 current = 0;
107 }
108 if (UseUnicode) {
109 sprintf(buffer3,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
110 EncodeUnicode(buffer2,buffer3,strlen(buffer3));
111 fwrite(buffer2,1,strlen(buffer3)*2,file);
112 } else {
113 fprintf(file,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
114 }
115 if (current == 0) break;
116 w++;
117 }
118}
119
120static void ReadLinkedBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
121{
122 unsigned char buffer2[300];
123 char *readvalue;
124 int i;
125
126 i=0;
127 myvalue[0] = 0;
128 while (true) {
129 sprintf(buffer2,"%s%02i",myname,i);
130 readvalue = ReadCFGText(file_info, section, buffer2, UseUnicode);
131 if (readvalue!=NULL) {
132 myvalue[strlen(myvalue)+strlen(readvalue)]=0;
133 memcpy(myvalue+strlen(myvalue),readvalue,strlen(readvalue));
134 } else break;
135 i++;
136 }
137}
138
139static void SaveBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
140{
141 unsigned char buffer[10000], buffer2[10000];
142
143 if (myname[0] == 0x00) {
144 if (UseUnicode) {
145 EncodeUnicode(buffer,myvalue,strlen(myvalue));
146 fwrite(buffer,1,strlen(myvalue)*2,file);
147 } else fprintf(file,"%s",myvalue);
148 } else {
149 if (UseUnicode) {
150 sprintf(buffer,"%s = \"",myname);
151 EncodeUnicode(buffer2,buffer,strlen(buffer));
152 fwrite(buffer2,1,strlen(buffer)*2,file);
153
154 fwrite(myvalue,1,UnicodeLength(myvalue)*2,file);
155
156 sprintf(buffer,"\"%c%c",13,10);
157 EncodeUnicode(buffer2,buffer,strlen(buffer));
158 fwrite(buffer2,1,strlen(buffer)*2,file);
159 } else {
160 sprintf(buffer,"%s = \"%s\"%c%c",myname,DecodeUnicodeString(myvalue),13,10);
161 fprintf(file,"%s",buffer);
162
163 EncodeHexBin(buffer,myvalue,UnicodeLength(myvalue)*2);
164 fprintf(file,"%sUnicode = %s%c%c",myname,buffer,13,10);
165 }
166 }
167}
168
169static bool ReadBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
170{
171 unsigned char paramname[10000],*readvalue;
172
173 if (UseUnicode) {
174 EncodeUnicode(paramname,myname,strlen(myname));
175 readvalue = INI_GetValue(file_info, section, paramname, UseUnicode);
176 if (readvalue!=NULL) {
177 CopyUnicodeString(myvalue,readvalue+2);
178 myvalue[UnicodeLength(readvalue)*2-4]=0;
179 myvalue[UnicodeLength(readvalue)*2-3]=0;
180 dbgprintf("%s\n",DecodeUnicodeString(readvalue));
181 } else {
182 myvalue[0]=0;
183 myvalue[1]=0;
184 return false;
185 }
186 } else {
187 strcpy(paramname,myname);
188 strcat(paramname,"Unicode");
189 readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
190 if (readvalue!=NULL) {
191 dbgprintf("%s %i\n",readvalue,strlen(readvalue));
192 DecodeHexBin (myvalue, readvalue, strlen(readvalue));
193 myvalue[strlen(readvalue)/2]=0;
194 myvalue[strlen(readvalue)/2+1]=0;
195 dbgprintf("%s\n",DecodeUnicodeString(myvalue));
196 } else {
197 strcpy(paramname,myname);
198 readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
199 if (readvalue!=NULL) {
200 EncodeUnicode(myvalue,readvalue+1,strlen(readvalue)-2);
201 } else {
202 myvalue[0]=0;
203 myvalue[1]=0;
204 return false;
205 }
206 }
207 }
208 return true;
209}
210
211static void SaveVCalDateTime(FILE *file, GSM_DateTime *dt, bool UseUnicode)
212{
213 unsigned char buffer[100];
214 int Length = 3;
215
216 sprintf(buffer, " = ");
217 SaveVCALDateTime(buffer, &Length, dt, NULL);
218 SaveBackupText(file, "", buffer, UseUnicode);
219}
220
221static void SaveVCalDate(FILE *file, GSM_DateTime *dt, bool UseUnicode)
222{
223 unsigned char buffer[100];
224
225 sprintf(buffer, " = %04d%02d%02d%c%c", dt->Year, dt->Month, dt->Day,13,10);
226 SaveBackupText(file, "", buffer, UseUnicode);
227}
228
229/* ---------------------- backup files ------------------------------------- */
230
231static void SavePbkEntry(FILE *file, GSM_MemoryEntry *Pbk, bool UseUnicode)
232{
233 booltext;
234 charbuffer[1000];
235 intj, i;
236
237 sprintf(buffer,"Location = %03i%c%c",Pbk->Location,13,10);
238 SaveBackupText(file, "", buffer, UseUnicode);
239 for (j=0;j<Pbk->EntriesNum;j++) {
240 text = true;
241 switch (Pbk->Entries[j].EntryType) {
242 case PBK_Number_General:
243 sprintf(buffer,"Entry%02iType = NumberGeneral%c%c",j,13,10);
244 SaveBackupText(file, "", buffer, UseUnicode);
245 break;
246 case PBK_Number_Mobile:
247 sprintf(buffer,"Entry%02iType = NumberMobile%c%c",j,13,10);
248 SaveBackupText(file, "", buffer, UseUnicode);
249 break;
250 case PBK_Number_Work:
251 sprintf(buffer,"Entry%02iType = NumberWork%c%c",j,13,10);
252 SaveBackupText(file, "", buffer, UseUnicode);
253 break;
254 case PBK_Number_Fax:
255 sprintf(buffer,"Entry%02iType = NumberFax%c%c",j,13,10);
256 SaveBackupText(file, "", buffer, UseUnicode);
257 break;
258 case PBK_Number_Home:
259 sprintf(buffer,"Entry%02iType = NumberHome%c%c",j,13,10);
260 SaveBackupText(file, "", buffer, UseUnicode);
261 break;
262 case PBK_Number_Pager:
263 sprintf(buffer,"Entry%02iType = NumberPager%c%c",j,13,10);
264 SaveBackupText(file, "", buffer, UseUnicode);
265 break;
266 case PBK_Number_Other:
267 sprintf(buffer,"Entry%02iType = NumberOther%c%c",j,13,10);
268 SaveBackupText(file, "", buffer, UseUnicode);
269 break;
270 case PBK_Text_Note:
271 sprintf(buffer,"Entry%02iType = Note%c%c",j,13,10);
272 SaveBackupText(file, "", buffer, UseUnicode);
273 break;
274 case PBK_Text_Postal:
275 sprintf(buffer,"Entry%02iType = Postal%c%c",j,13,10);
276 SaveBackupText(file, "", buffer, UseUnicode);
277 break;
278 case PBK_Text_Email:
279 sprintf(buffer,"Entry%02iType = Email%c%c",j,13,10);
280 SaveBackupText(file, "", buffer, UseUnicode);
281 break;
282 case PBK_Text_Email2:
283 sprintf(buffer,"Entry%02iType = Email2%c%c",j,13,10);
284 SaveBackupText(file, "", buffer, UseUnicode);
285 break;
286 case PBK_Text_URL:
287 sprintf(buffer,"Entry%02iType = URL%c%c",j,13,10);
288 SaveBackupText(file, "", buffer, UseUnicode);
289 break;
290 case PBK_Text_Name:
291 sprintf(buffer,"Entry%02iType = Name%c%c",j,13,10);
292 SaveBackupText(file, "", buffer, UseUnicode);
293 break;
294 case PBK_Caller_Group:
295 sprintf(buffer,"Entry%02iType = CallerGroup%c%c",j,13,10);
296 SaveBackupText(file, "", buffer, UseUnicode);
297 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
298 SaveBackupText(file, "", buffer, UseUnicode);
299 text = false;
300 break;
301 case PBK_RingtoneID:
302 sprintf(buffer,"Entry%02iType = RingtoneID%c%c",j,13,10);
303 SaveBackupText(file, "", buffer, UseUnicode);
304 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
305 SaveBackupText(file, "", buffer, UseUnicode);
306 text = false;
307 break;
308 case PBK_PictureID:
309 sprintf(buffer,"Entry%02iType = PictureID%c%c",j,13,10);
310 SaveBackupText(file, "", buffer, UseUnicode);
311 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
312 SaveBackupText(file, "", buffer, UseUnicode);
313 text = false;
314 break;
315 case PBK_Text_UserID:
316 sprintf(buffer,"Entry%02iType = UserID%c%c",j,13,10);
317 SaveBackupText(file, "", buffer, UseUnicode);
318 break;
319 case PBK_Category:
320 sprintf(buffer,"Entry%02iType = Category%c%c",j,13,10);
321 SaveBackupText(file, "", buffer, UseUnicode);
322 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
323 SaveBackupText(file, "", buffer, UseUnicode);
324 text = false;
325 break;
326 case PBK_Private:
327 sprintf(buffer,"Entry%02iType = Private%c%c",j,13,10);
328 SaveBackupText(file, "", buffer, UseUnicode);
329 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
330 SaveBackupText(file, "", buffer, UseUnicode);
331 text = false;
332 break;
333 case PBK_Text_LastName:
334 sprintf(buffer,"Entry%02iType = LastName%c%c",j,13,10);
335 SaveBackupText(file, "", buffer, UseUnicode);
336 break;
337 case PBK_Text_FirstName:
338 sprintf(buffer,"Entry%02iType = FirstName%c%c",j,13,10);
339 SaveBackupText(file, "", buffer, UseUnicode);
340 break;
341 case PBK_Text_Company:
342 sprintf(buffer,"Entry%02iType = Company%c%c",j,13,10);
343 SaveBackupText(file, "", buffer, UseUnicode);
344 break;
345 case PBK_Text_JobTitle:
346 sprintf(buffer,"Entry%02iType = JobTitle%c%c",j,13,10);
347 SaveBackupText(file, "", buffer, UseUnicode);
348 break;
349 case PBK_Text_StreetAddress:
350 sprintf(buffer,"Entry%02iType = Address%c%c",j,13,10);
351 SaveBackupText(file, "", buffer, UseUnicode);
352 break;
353 case PBK_Text_City:
354 sprintf(buffer,"Entry%02iType = City%c%c",j,13,10);
355 SaveBackupText(file, "", buffer, UseUnicode);
356 break;
357 case PBK_Text_State:
358 sprintf(buffer,"Entry%02iType = State%c%c",j,13,10);
359 SaveBackupText(file, "", buffer, UseUnicode);
360 break;
361 case PBK_Text_Zip:
362 sprintf(buffer,"Entry%02iType = Zip%c%c",j,13,10);
363 SaveBackupText(file, "", buffer, UseUnicode);
364 break;
365 case PBK_Text_Country:
366 sprintf(buffer,"Entry%02iType = Country%c%c",j,13,10);
367 SaveBackupText(file, "", buffer, UseUnicode);
368 break;
369 case PBK_Text_Custom1:
370 sprintf(buffer,"Entry%02iType = Custom1%c%c",j,13,10);
371 SaveBackupText(file, "", buffer, UseUnicode);
372 break;
373 case PBK_Text_Custom2:
374 sprintf(buffer,"Entry%02iType = Custom2%c%c",j,13,10);
375 SaveBackupText(file, "", buffer, UseUnicode);
376 break;
377 case PBK_Text_Custom3:
378 sprintf(buffer,"Entry%02iType = Custom3%c%c",j,13,10);
379 SaveBackupText(file, "", buffer, UseUnicode);
380 break;
381 case PBK_Text_Custom4:
382 sprintf(buffer,"Entry%02iType = Custom4%c%c",j,13,10);
383 SaveBackupText(file, "", buffer, UseUnicode);
384 break;
385 case PBK_SMSListID:
386 case PBK_RingtoneFileSystemID:
387 case PBK_Date:
388 break;
389 }
390 if (text) {
391 sprintf(buffer,"Entry%02iText",j);
392 SaveBackupText(file,buffer,Pbk->Entries[j].Text, UseUnicode);
393 }
394 switch (Pbk->Entries[j].EntryType) {
395 case PBK_Number_General:
396 case PBK_Number_Mobile:
397 case PBK_Number_Work:
398 case PBK_Number_Fax:
399 case PBK_Number_Home:
400 case PBK_Number_Other:
401 case PBK_Number_Pager:
402 if (Pbk->Entries[j].VoiceTag!=0) {
403 sprintf(buffer,"Entry%02iVoiceTag = %i%c%c",j,Pbk->Entries[j].VoiceTag,13,10);
404 SaveBackupText(file, "", buffer, UseUnicode);
405 }
406 i = 0;
407 while (Pbk->Entries[j].SMSList[i]!=0) {
408 sprintf(buffer,"Entry%02iSMSList%02i = %i%c%c",j,i,Pbk->Entries[j].SMSList[i],13,10);
409 SaveBackupText(file, "", buffer, UseUnicode);
410 i++;
411 }
412 break;
413 default:
414 break;
415 }
416 }
417 sprintf(buffer,"%c%c",13,10);
418 SaveBackupText(file, "", buffer, UseUnicode);
419}
420
421static void SaveCalendarEntry(FILE *file, GSM_CalendarEntry *Note, bool UseUnicode)
422{
423 int i;
424 charbuffer[1000];
425
426 sprintf(buffer,"Location = %d%c%c", Note->Location,13,10);
427 SaveBackupText(file, "", buffer, UseUnicode);
428 SaveBackupText(file, "", "Type = ", UseUnicode);
429 switch (Note->Type) {
430 case GSM_CAL_REMINDER : sprintf(buffer,"Reminder%c%c", 13,10); break;
431 case GSM_CAL_CALL : sprintf(buffer,"Call%c%c", 13,10); break;
432 case GSM_CAL_MEETING : sprintf(buffer,"Meeting%c%c", 13,10); break;
433 case GSM_CAL_BIRTHDAY : sprintf(buffer,"Birthday%c%c", 13,10); break;
434 case GSM_CAL_TRAVEL : sprintf(buffer,"Travel%c%c", 13,10); break;
435 case GSM_CAL_VACATION : sprintf(buffer,"Vacation%c%c", 13,10); break;
436 case GSM_CAL_MEMO : sprintf(buffer,"Memo%c%c", 13,10); break;
437 case GSM_CAL_ALARM : sprintf(buffer,"Alarm%c%c", 13,10); break;
438 case GSM_CAL_DAILY_ALARM : sprintf(buffer,"DailyAlarm%c%c", 13,10); break;
439 case GSM_CAL_T_ATHL : sprintf(buffer,"Training/Athletism%c%c", 13,10); break;
440 case GSM_CAL_T_BALL : sprintf(buffer,"Training/BallGames%c%c", 13,10); break;
441 case GSM_CAL_T_CYCL : sprintf(buffer,"Training/Cycling%c%c", 13,10); break;
442 case GSM_CAL_T_BUDO : sprintf(buffer,"Training/Budo%c%c", 13,10); break;
443 case GSM_CAL_T_DANC : sprintf(buffer,"Training/Dance%c%c", 13,10); break;
444 case GSM_CAL_T_EXTR : sprintf(buffer,"Training/ExtremeSports%c%c", 13,10); break;
445 case GSM_CAL_T_FOOT : sprintf(buffer,"Training/Football%c%c", 13,10); break;
446 case GSM_CAL_T_GOLF : sprintf(buffer,"Training/Golf%c%c", 13,10); break;
447 case GSM_CAL_T_GYM : sprintf(buffer,"Training/Gym%c%c", 13,10); break;
448 case GSM_CAL_T_HORS : sprintf(buffer,"Training/HorseRaces%c%c", 13,10); break;
449 case GSM_CAL_T_HOCK : sprintf(buffer,"Training/Hockey%c%c", 13,10); break;
450 case GSM_CAL_T_RACE : sprintf(buffer,"Training/Races%c%c", 13,10); break;
451 case GSM_CAL_T_RUGB : sprintf(buffer,"Training/Rugby%c%c", 13,10); break;
452 case GSM_CAL_T_SAIL : sprintf(buffer,"Training/Sailing%c%c", 13,10); break;
453 case GSM_CAL_T_STRE : sprintf(buffer,"Training/StreetGames%c%c",13,10); break;
454 case GSM_CAL_T_SWIM : sprintf(buffer,"Training/Swimming%c%c", 13,10); break;
455 case GSM_CAL_T_TENN : sprintf(buffer,"Training/Tennis%c%c", 13,10); break;
456 case GSM_CAL_T_TRAV : sprintf(buffer,"Training/Travels%c%c", 13,10); break;
457 case GSM_CAL_T_WINT : sprintf(buffer,"Training/WinterGames%c%c", 13,10); break;
458 }
459 SaveBackupText(file, "", buffer, UseUnicode);
460 for (i=0;i<Note->EntriesNum;i++) {
461 switch (Note->Entries[i].EntryType) {
462 case CAL_START_DATETIME:
463 SaveBackupText(file, "", "StartTime", UseUnicode);
464 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
465 break;
466 case CAL_END_DATETIME:
467 SaveBackupText(file, "", "StopTime", UseUnicode);
468 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
469 break;
470 case CAL_ALARM_DATETIME:
471 SaveBackupText(file, "", "Alarm", UseUnicode);
472 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
473 sprintf(buffer,"AlarmType = Tone%c%c",13,10);
474 SaveBackupText(file, "", buffer, UseUnicode);
475 break;
476 case CAL_SILENT_ALARM_DATETIME:
477 SaveBackupText(file, "", "Alarm", UseUnicode);
478 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
479 sprintf(buffer,"AlarmType = Silent%c%c",13,10);
480 SaveBackupText(file, "", buffer, UseUnicode);
481 break;
482 case CAL_PRIVATE:
483 sprintf(buffer, "Private = %d%c%c",Note->Entries[i].Number,13,10);
484 SaveBackupText(file, "", buffer, UseUnicode);
485 break;
486 case CAL_LOCATION:
487 SaveBackupText(file, "EventLocation", Note->Entries[i].Text, UseUnicode);
488 break;
489 case CAL_CONTACTID:
490 sprintf(buffer, "ContactID = %d%c%c",Note->Entries[i].Number,13,10);
491 SaveBackupText(file, "", buffer, UseUnicode);
492 break;
493 case CAL_RECURRANCE:
494 sprintf(buffer, "Recurrance = %d%c%c",Note->Entries[i].Number/24,13,10);
495 SaveBackupText(file, "", buffer, UseUnicode);
496 break;
497 case CAL_TEXT:
498 SaveBackupText(file, "Text", Note->Entries[i].Text, UseUnicode);
499 break;
500 case CAL_PHONE:
501 SaveBackupText(file, "Phone", Note->Entries[i].Text, UseUnicode);
502 break;
503 case CAL_REPEAT_STOPDATE:
504 SaveBackupText(file, "", "RepeatStopDate", UseUnicode);
505 SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
506 break;
507 case CAL_REPEAT_STARTDATE:
508 SaveBackupText(file, "", "RepeatStartDate", UseUnicode);
509 SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
510 break;
511 case CAL_REPEAT_DAYOFWEEK:
512 sprintf(buffer, "RepeatDayOfWeek = %d%c%c",Note->Entries[i].Number,13,10);
513 SaveBackupText(file, "", buffer, UseUnicode);
514 break;
515 case CAL_REPEAT_DAY:
516 sprintf(buffer, "RepeatDay = %d%c%c",Note->Entries[i].Number,13,10);
517 SaveBackupText(file, "", buffer, UseUnicode);
518 break;
519 case CAL_REPEAT_WEEKOFMONTH:
520 sprintf(buffer, "RepeatWeekOfMonth = %d%c%c",Note->Entries[i].Number,13,10);
521 SaveBackupText(file, "", buffer, UseUnicode);
522 break;
523 case CAL_REPEAT_MONTH:
524 sprintf(buffer, "RepeatMonth = %d%c%c",Note->Entries[i].Number,13,10);
525 SaveBackupText(file, "", buffer, UseUnicode);
526 break;
527 case CAL_REPEAT_FREQUENCY:
528 sprintf(buffer, "RepeatFrequency = %d%c%c",Note->Entries[i].Number,13,10);
529 SaveBackupText(file, "", buffer, UseUnicode);
530 break;
531 }
532 }
533 sprintf(buffer, "%c%c",13,10);
534 SaveBackupText(file, "", buffer, UseUnicode);
535}
536
537static void SaveWAPSettingsEntry(FILE *file, GSM_MultiWAPSettings *settings, bool UseUnicode)
538{
539 int i;
540 char buffer[10000];
541
542 if (settings->Active) {
543 sprintf(buffer,"Active = Yes%c%c",13,10);
544 SaveBackupText(file, "", buffer, UseUnicode);
545 }
546 switch (settings->ActiveBearer) {
547 case WAPSETTINGS_BEARER_SMS : sprintf(buffer,"Bearer = SMS%c%c",13,10); break;
548 case WAPSETTINGS_BEARER_GPRS: sprintf(buffer,"Bearer = GPRS%c%c",13,10); break;
549 case WAPSETTINGS_BEARER_DATA: sprintf(buffer,"Bearer = Data%c%c",13,10); break;
550 case WAPSETTINGS_BEARER_USSD: sprintf(buffer,"Bearer = USSD%c%c",13,10);
551 }
552 SaveBackupText(file, "", buffer, UseUnicode);
553 if (settings->ReadOnly) {
554 sprintf(buffer,"ReadOnly = Yes%c%c",13,10);
555 SaveBackupText(file, "", buffer, UseUnicode);
556 }
557 sprintf(buffer,"Proxy");
558 SaveBackupText(file, buffer, settings->Proxy, UseUnicode);
559 sprintf(buffer,"ProxyPort = %i%c%c",settings->ProxyPort,13,10);
560 SaveBackupText(file, "", buffer, UseUnicode);
561 sprintf(buffer,"Proxy2");
562 SaveBackupText(file, buffer, settings->Proxy2, UseUnicode);
563 sprintf(buffer,"Proxy2Port = %i%c%c",settings->Proxy2Port,13,10);
564 SaveBackupText(file, "", buffer, UseUnicode);
565 sprintf(buffer,"%c%c",13,10);
566 SaveBackupText(file, "", buffer, UseUnicode);
567 for (i=0;i<settings->Number;i++) {
568 sprintf(buffer,"Title%02i",i);
569 SaveBackupText(file, buffer, settings->Settings[i].Title, UseUnicode);
570 sprintf(buffer,"HomePage%02i",i);
571 SaveBackupText(file, buffer, settings->Settings[i].HomePage, UseUnicode);
572 if (settings->Settings[i].IsContinuous) {
573 sprintf(buffer,"Type%02i = Continuous%c%c",i,13,10);
574 } else {
575 sprintf(buffer,"Type%02i = Temporary%c%c",i,13,10);
576 }
577 SaveBackupText(file, "", buffer, UseUnicode);
578 if (settings->Settings[i].IsSecurity) {
579 sprintf(buffer,"Security%02i = On%c%c",i,13,10);
580 } else {
581 sprintf(buffer,"Security%02i = Off%c%c",i,13,10);
582 }
583 SaveBackupText(file, "", buffer, UseUnicode);
584 switch (settings->Settings[i].Bearer) {
585 case WAPSETTINGS_BEARER_SMS:
586 sprintf(buffer,"Bearer%02i = SMS%c%c",i,13,10);
587 SaveBackupText(file, "", buffer, UseUnicode);
588 sprintf(buffer,"Server%02i",i);
589 SaveBackupText(file, buffer, settings->Settings[i].Server, UseUnicode);
590 sprintf(buffer,"Service%02i",i);
591 SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
592 break;
593 case WAPSETTINGS_BEARER_GPRS:
594 sprintf(buffer,"Bearer%02i = GPRS%c%c",i,13,10);
595 SaveBackupText(file, "", buffer, UseUnicode);
596 sprintf(buffer,"IP%02i",i);
597 SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
598 case WAPSETTINGS_BEARER_DATA:
599 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) {
600 sprintf(buffer,"Bearer%02i = Data%c%c",i,13,10);
601 SaveBackupText(file, "", buffer, UseUnicode);
602 if (settings->Settings[i].IsISDNCall) {
603 sprintf(buffer,"CallType%02i = ISDN%c%c",i,13,10);
604 } else {
605 sprintf(buffer,"CallType%02i = Analogue%c%c",i,13,10);
606 }
607 SaveBackupText(file, "", buffer, UseUnicode);
608 sprintf(buffer,"IP%02i",i);
609 SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
610 }
611 sprintf(buffer,"Number%02i",i);
612 SaveBackupText(file, buffer, settings->Settings[i].DialUp, UseUnicode);
613 if (settings->Settings[i].ManualLogin) {
614 sprintf(buffer,"Login%02i = Manual%c%c",i,13,10);
615 } else {
616 sprintf(buffer,"Login%02i = Automatic%c%c",i,13,10);
617 }
618 SaveBackupText(file, "", buffer, UseUnicode);
619 if (settings->Settings[i].IsNormalAuthentication) {
620 sprintf(buffer,"Authentication%02i = Normal%c%c",i,13,10);
621 } else {
622 sprintf(buffer,"Authentication%02i = Secure%c%c",i,13,10);
623 }
624 SaveBackupText(file, "", buffer, UseUnicode);
625 switch (settings->Settings[i].Speed) {
626 case WAPSETTINGS_SPEED_9600 : sprintf(buffer,"CallSpeed%02i = 9600%c%c" ,i,13,10); break;
627 case WAPSETTINGS_SPEED_14400: sprintf(buffer,"CallSpeed%02i = 14400%c%c",i,13,10); break;
628 case WAPSETTINGS_SPEED_AUTO : sprintf(buffer,"CallSpeed%02i = auto%c%c" ,i,13,10); break;
629 }
630 switch (settings->Settings[i].Speed) {
631 case WAPSETTINGS_SPEED_9600 :
632 case WAPSETTINGS_SPEED_14400:
633 case WAPSETTINGS_SPEED_AUTO :
634 SaveBackupText(file, "", buffer, UseUnicode);
635 default:
636 break;
637 }
638 sprintf(buffer,"User%02i",i);
639 SaveBackupText(file, buffer, settings->Settings[i].User, UseUnicode);
640 sprintf(buffer,"Password%02i",i);
641 SaveBackupText(file, buffer, settings->Settings[i].Password, UseUnicode);
642 break;
643 case WAPSETTINGS_BEARER_USSD:
644 sprintf(buffer,"Bearer%02i = USSD%c%c",i,13,10);
645 SaveBackupText(file, "", buffer, UseUnicode);
646 sprintf(buffer,"ServiceCode%02i",i);
647 SaveBackupText(file, buffer, settings->Settings[i].Code, UseUnicode);
648 if (settings->Settings[i].IsIP) {
649 sprintf(buffer,"IP%02i",i);
650 } else {
651 sprintf(buffer,"Number%02i",i);
652 }
653 SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
654 }
655 sprintf(buffer,"%c%c",13,10);
656 SaveBackupText(file, "", buffer, UseUnicode);
657 }
658}
659
660static void SaveBitmapEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
661{
662 unsigned char buffer[10000],buffer2[10000];
663 int x,y;
664
665 sprintf(buffer,"Width = %i%c%c",bitmap->BitmapWidth,13,10);
666 SaveBackupText(file, "", buffer, UseUnicode);
667 sprintf(buffer,"Height = %i%c%c",bitmap->BitmapHeight,13,10);
668 SaveBackupText(file, "", buffer, UseUnicode);
669 for (y=0;y<bitmap->BitmapHeight;y++) {
670 for (x=0;x<bitmap->BitmapWidth;x++) {
671 buffer[x] = ' ';
672 if (GSM_IsPointBitmap(bitmap,x,y)) buffer[x]='#';
673 }
674 buffer[bitmap->BitmapWidth] = 0;
675 sprintf(buffer2,"Bitmap%02i = \"%s\"%c%c",y,buffer,13,10);
676 SaveBackupText(file, "", buffer2, UseUnicode);
677 }
678}
679
680static void SaveCallerEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
681{
682 unsigned char buffer[1000];
683
684 sprintf(buffer,"Location = %03i%c%c",bitmap->Location,13,10);
685 SaveBackupText(file, "", buffer, UseUnicode);
686 if (!bitmap->DefaultName) SaveBackupText(file, "Name", bitmap->Text, UseUnicode);
687 if (!bitmap->DefaultRingtone) {
688 if (bitmap->FileSystemRingtone) {
689 sprintf(buffer,"FileRingtone = %02x%c%c",bitmap->RingtoneID,13,10);
690 } else {
691 sprintf(buffer,"Ringtone = %02x%c%c",bitmap->RingtoneID,13,10);
692 }
693 SaveBackupText(file, "", buffer, UseUnicode);
694 }
695 if (bitmap->BitmapEnabled) {
696 sprintf(buffer,"Enabled = True%c%c",13,10);
697 } else {
698 sprintf(buffer,"Enabled = False%c%c",13,10);
699 }
700 SaveBackupText(file, "", buffer, UseUnicode);
701 if (!bitmap->DefaultBitmap) SaveBitmapEntry(file, bitmap, UseUnicode);
702 sprintf(buffer,"%c%c",13,10);
703 SaveBackupText(file, "", buffer, UseUnicode);
704}
705
706static void SaveWAPBookmarkEntry(FILE *file, GSM_WAPBookmark *bookmark, bool UseUnicode)
707{
708 unsigned char buffer[1000];
709
710 SaveBackupText(file, "URL", bookmark->Address, UseUnicode);
711 SaveBackupText(file, "Title", bookmark->Title, UseUnicode);
712 sprintf(buffer,"%c%c",13,10);
713 SaveBackupText(file, "", buffer, UseUnicode);
714}
715
716static void SaveStartupEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
717{
718 unsigned char buffer[1000];
719
720 sprintf(buffer,"[Startup]%c%c",13,10);
721 SaveBackupText(file, "", buffer, UseUnicode);
722 if (bitmap->Type == GSM_WelcomeNote_Text) {
723 SaveBackupText(file, "Text", bitmap->Text, UseUnicode);
724 }
725 if (bitmap->Type == GSM_StartupLogo) {
726 SaveBitmapEntry(file, bitmap, UseUnicode);
727 }
728 sprintf(buffer,"%c%c",13,10);
729 SaveBackupText(file, "", buffer, UseUnicode);
730}
731
732static void SaveSMSCEntry(FILE *file, GSM_SMSC *SMSC, bool UseUnicode)
733{
734 unsigned char buffer[1000];
735
736 sprintf(buffer,"Location = %03i%c%c",SMSC->Location,13,10);
737 SaveBackupText(file, "", buffer, UseUnicode);
738 SaveBackupText(file, "Name", SMSC->Name, UseUnicode);
739 SaveBackupText(file, "Number", SMSC->Number, UseUnicode);
740 SaveBackupText(file, "DefaultNumber", SMSC->DefaultNumber, UseUnicode);
741 SaveBackupText(file, "", "Format = ", UseUnicode);
742 switch (SMSC->Format) {
743 case SMS_FORMAT_Text: sprintf(buffer,"Text"); break;
744 case SMS_FORMAT_Fax: sprintf(buffer,"Fax"); break;
745 case SMS_FORMAT_Email: sprintf(buffer,"Email"); break;
746 case SMS_FORMAT_Pager: sprintf(buffer,"Pager"); break;
747 }
748 SaveBackupText(file, "", buffer, UseUnicode);
749 sprintf(buffer,"%c%cValidity = ",13,10);
750 SaveBackupText(file, "", buffer, UseUnicode);
751 switch (SMSC->Validity.Relative) {
752 case SMS_VALID_1_Hour : sprintf(buffer, "1hour"); break;
753 case SMS_VALID_6_Hours : sprintf(buffer, "6hours"); break;
754 case SMS_VALID_1_Day : sprintf(buffer, "24hours"); break;
755 case SMS_VALID_3_Days : sprintf(buffer, "72hours"); break;
756 case SMS_VALID_1_Week : sprintf(buffer, "1week"); break;
757 case SMS_VALID_Max_Time:
758 default : sprintf(buffer,"MaximumTime"); break;
759 }
760 SaveBackupText(file, "", buffer, UseUnicode);
761 sprintf(buffer,"%c%c%c%c",13,10,13,10);
762 SaveBackupText(file, "", buffer, UseUnicode);
763}
764
765static void SaveRingtoneEntry(FILE *file, GSM_Ringtone *ringtone, bool UseUnicode)
766{
767 unsigned char buffer[45000];
768 int i,j;
769
770 sprintf(buffer,"Location = %i%c%c",ringtone->Location,13,10);
771 SaveBackupText(file, "", buffer, UseUnicode);
772 SaveBackupText(file, "Name", ringtone->Name, UseUnicode);
773 switch (ringtone->Format) {
774 case RING_NOKIABINARY:
775 j = 0; i = 0;
776 EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
777 SaveLinkedBackupText(file, "NokiaBinary", buffer, UseUnicode);
778 break;
779 case RING_MIDI:
780 j = 0; i = 0;
781 EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
782 SaveLinkedBackupText(file, "Pure Midi", buffer, UseUnicode);
783 break;
784 case RING_NOTETONE:
785 break;
786 }
787 sprintf(buffer,"%c%c",13,10);
788 SaveBackupText(file, "", buffer, UseUnicode);
789}
790
791static void SaveOperatorEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
792{
793 unsigned char buffer[1000];
794
795 sprintf(buffer,"[Operator]%c%c",13,10);
796 SaveBackupText(file, "", buffer, UseUnicode);
797 sprintf(buffer,"Network = \"%s\"%c%c", bitmap->NetworkCode,13,10);
798 SaveBackupText(file, "", buffer, UseUnicode);
799 SaveBitmapEntry(file, bitmap, UseUnicode);
800 sprintf(buffer,"%c%c",13,10);
801 SaveBackupText(file, "", buffer, UseUnicode);
802}
803
804static void SaveToDoEntry(FILE *file, GSM_ToDoEntry *ToDo, bool UseUnicode)
805{
806 unsigned char buffer[1000];
807 int j;
808
809 sprintf(buffer,"Location = %i%c%c",ToDo->Location,13,10);
810 SaveBackupText(file, "", buffer, UseUnicode);
811 switch (ToDo->Priority) {
812 case GSM_Priority_High:
813 sprintf(buffer,"Priority = High%c%c",13,10);
814 break;
815 case GSM_Priority_Medium:
816 sprintf(buffer,"Priority = Medium%c%c",13,10);
817 break;
818 case GSM_Priority_Low:
819 sprintf(buffer,"Priority = Low%c%c",13,10);
820 break;
821 }
822 SaveBackupText(file, "", buffer, UseUnicode);
823
824 for (j=0;j<ToDo->EntriesNum;j++) {
825 switch (ToDo->Entries[j].EntryType) {
826 case TODO_END_DATETIME:
827 SaveBackupText(file, "", "DueTime", UseUnicode);
828 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
829 break;
830 case TODO_COMPLETED:
831 sprintf(buffer,"Completed = %s%c%c",ToDo->Entries[j].Number == 1 ? "yes" : "no" ,13,10);
832 SaveBackupText(file, "", buffer, UseUnicode);
833 break;
834 case TODO_ALARM_DATETIME:
835 SaveBackupText(file, "", "Alarm", UseUnicode);
836 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
837 break;
838 case TODO_SILENT_ALARM_DATETIME:
839 SaveBackupText(file, "", "SilentAlarm", UseUnicode);
840 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
841 break;
842 case TODO_TEXT:
843 SaveBackupText(file, "Text", ToDo->Entries[j].Text, UseUnicode);
844 break;
845 case TODO_PRIVATE:
846 sprintf(buffer,"Private = %i%c%c",ToDo->Entries[j].Number,13,10);
847 SaveBackupText(file, "", buffer, UseUnicode);
848 break;
849 case TODO_CATEGORY:
850 sprintf(buffer,"Category = %i%c%c",ToDo->Entries[j].Number,13,10);
851 SaveBackupText(file, "", buffer, UseUnicode);
852 break;
853 case TODO_CONTACTID:
854 sprintf(buffer,"ContactID = %i%c%c",ToDo->Entries[j].Number,13,10);
855 SaveBackupText(file, "", buffer, UseUnicode);
856 break;
857 case TODO_PHONE:
858 SaveBackupText(file, "Phone", ToDo->Entries[j].Text, UseUnicode);
859 break;
860 }
861 }
862 sprintf(buffer,"%c%c",13,10);
863 SaveBackupText(file, "", buffer, UseUnicode);
864}
865
866static void SaveProfileEntry(FILE *file, GSM_Profile *Profile, bool UseUnicode)
867{
868 int j,k;
869 bool special;
870 unsigned char buffer[1000];
871
872 sprintf(buffer,"Location = %i%c%c",Profile->Location,13,10);
873 SaveBackupText(file, "", buffer, UseUnicode);
874 SaveBackupText(file, "Name",Profile->Name, UseUnicode);
875
876 if (Profile->DefaultName) {
877 sprintf(buffer,"DefaultName = true%c%c",13,10);
878 SaveBackupText(file, "", buffer, UseUnicode);
879 }
880 if (Profile->HeadSetProfile) {
881 sprintf(buffer,"HeadSetProfile = true%c%c",13,10);
882 SaveBackupText(file, "", buffer, UseUnicode);
883 }
884 if (Profile->CarKitProfile) {
885 sprintf(buffer,"CarKitProfile = true%c%c",13,10);
886 SaveBackupText(file, "", buffer, UseUnicode);
887 }
888
889 for (j=0;j<Profile->FeaturesNumber;j++) {
890 sprintf(buffer,"Feature%02i = ",j);
891 SaveBackupText(file, "", buffer, UseUnicode);
892 special = false;
893 switch (Profile->FeatureID[j]) {
894 case Profile_MessageToneID:
895 case Profile_RingtoneID:
896 special = true;
897 if (Profile->FeatureID[j] == Profile_RingtoneID) {
898 sprintf(buffer,"RingtoneID%c%c",13,10);
899 } else {
900 sprintf(buffer,"MessageToneID%c%c",13,10);
901 }
902 SaveBackupText(file, "", buffer, UseUnicode);
903 sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
904 SaveBackupText(file, "", buffer, UseUnicode);
905 break;
906 case Profile_CallerGroups:
907 special = true;
908 sprintf(buffer,"CallerGroups%c%c",13,10);
909 SaveBackupText(file, "", buffer, UseUnicode);
910 sprintf(buffer,"Value%02i = ",j);
911 SaveBackupText(file, "", buffer, UseUnicode);
912 for (k=0;k<5;k++) {
913 if (Profile->CallerGroups[k]) {
914 sprintf(buffer,"%i",k);
915 SaveBackupText(file, "", buffer, UseUnicode);
916 }
917 }
918 sprintf(buffer,"%c%c",13,10);
919 SaveBackupText(file, "", buffer, UseUnicode);
920 break;
921 case Profile_ScreenSaverNumber:
922 special = true;
923 sprintf(buffer,"ScreenSaverNumber%c%c",13,10);
924 SaveBackupText(file, "", buffer, UseUnicode);
925 sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
926 SaveBackupText(file, "", buffer, UseUnicode);
927 break;
928 case Profile_CallAlert : sprintf(buffer,"IncomingCallAlert%c%c",13,10); break;
929 case Profile_RingtoneVolume : sprintf(buffer,"RingtoneVolume%c%c",13,10); break;
930 case Profile_Vibration : sprintf(buffer,"Vibrating%c%c",13,10); break;
931 case Profile_MessageTone : sprintf(buffer,"MessageTone%c%c",13,10); break;
932 case Profile_KeypadTone : sprintf(buffer,"KeypadTones%c%c",13,10); break;
933 case Profile_WarningTone : sprintf(buffer,"WarningTones%c%c",13,10); break;
934 case Profile_ScreenSaver : sprintf(buffer,"ScreenSaver%c%c",13,10); break;
935 case Profile_ScreenSaverTime : sprintf(buffer,"ScreenSaverTimeout%c%c",13,10); break;
936 case Profile_AutoAnswer : sprintf(buffer,"AutomaticAnswer%c%c",13,10); break;
937 case Profile_Lights : sprintf(buffer,"Lights%c%c",13,10); break;
938 default : special = true;
939 }
940 if (!special) {
941 SaveBackupText(file, "", buffer, UseUnicode);
942 sprintf(buffer,"Value%02i = ",j);
943 SaveBackupText(file, "", buffer, UseUnicode);
944 switch (Profile->FeatureValue[j]) {
945 case PROFILE_VOLUME_LEVEL1 :
946 case PROFILE_KEYPAD_LEVEL1 : sprintf(buffer,"Level1%c%c",13,10); break;
947 case PROFILE_VOLUME_LEVEL2 :
948 case PROFILE_KEYPAD_LEVEL2 : sprintf(buffer,"Level2%c%c",13,10); break;
949 case PROFILE_VOLUME_LEVEL3 :
950 case PROFILE_KEYPAD_LEVEL3 : sprintf(buffer,"Level3%c%c",13,10); break;
951 case PROFILE_VOLUME_LEVEL4 : sprintf(buffer,"Level4%c%c",13,10); break;
952 case PROFILE_VOLUME_LEVEL5 : sprintf(buffer,"Level5%c%c",13,10); break;
953 case PROFILE_MESSAGE_NOTONE :
954 case PROFILE_AUTOANSWER_OFF :
955 case PROFILE_LIGHTS_OFF :
956 case PROFILE_SAVER_OFF :
957 case PROFILE_WARNING_OFF :
958 case PROFILE_CALLALERT_OFF :
959 case PROFILE_VIBRATION_OFF :
960 case PROFILE_KEYPAD_OFF : sprintf(buffer,"Off%c%c",13,10); break;
961 case PROFILE_CALLALERT_RINGING : sprintf(buffer,"Ringing%c%c",13,10); break;
962 case PROFILE_CALLALERT_RINGONCE : sprintf(buffer,"RingOnce%c%c",13,10); break;
963 case PROFILE_CALLALERT_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
964 case PROFILE_CALLALERT_CALLERGROUPS : sprintf(buffer,"CallerGroups%c%c",13,10);break;
965 case PROFILE_MESSAGE_STANDARD : sprintf(buffer,"Standard%c%c",13,10); break;
966 case PROFILE_MESSAGE_SPECIAL : sprintf(buffer,"Special%c%c",13,10); break;
967 case PROFILE_MESSAGE_BEEPONCE :
968 case PROFILE_CALLALERT_BEEPONCE : sprintf(buffer,"BeepOnce%c%c",13,10); break;
969 case PROFILE_MESSAGE_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
970 case PROFILE_MESSAGE_PERSONAL : sprintf(buffer,"Personal%c%c",13,10); break;
971 case PROFILE_AUTOANSWER_ON :
972 case PROFILE_WARNING_ON :
973 case PROFILE_SAVER_ON :
974 case PROFILE_VIBRATION_ON : sprintf(buffer,"On%c%c",13,10); break;
975 case PROFILE_VIBRATION_FIRST : sprintf(buffer,"VibrateFirst%c%c",13,10);break;
976 case PROFILE_LIGHTS_AUTO : sprintf(buffer,"Auto%c%c",13,10); break;
977 case PROFILE_SAVER_TIMEOUT_5SEC : sprintf(buffer,"5Seconds%c%c",13,10); break;
978 case PROFILE_SAVER_TIMEOUT_20SEC : sprintf(buffer,"20Seconds%c%c",13,10); break;
979 case PROFILE_SAVER_TIMEOUT_1MIN : sprintf(buffer,"1Minute%c%c",13,10); break;
980 case PROFILE_SAVER_TIMEOUT_2MIN : sprintf(buffer,"2Minutes%c%c",13,10); break;
981 case PROFILE_SAVER_TIMEOUT_5MIN : sprintf(buffer,"5Minutes%c%c",13,10); break;
982 case PROFILE_SAVER_TIMEOUT_10MIN : sprintf(buffer,"10Minutes%c%c",13,10);break;
983 default : sprintf(buffer,"UNKNOWN%c%c",13,10);
984 }
985 SaveBackupText(file, "", buffer, UseUnicode);
986 }
987 }
988 sprintf(buffer,"%c%c",13,10);
989 SaveBackupText(file, "", buffer, UseUnicode);
990}
991
992static void SaveFMStationEntry(FILE *file, GSM_FMStation *FMStation, bool UseUnicode)
993{
994 unsigned char buffer[1000];
995
996 sprintf(buffer,"Location = %i%c%c",FMStation->Location,13,10);
997 SaveBackupText(file, "", buffer, UseUnicode);
998 SaveBackupText(file, "StationName", FMStation->StationName, UseUnicode);
999 sprintf(buffer,"Frequency = %f%c%c",FMStation->Frequency,13,10);
1000 SaveBackupText(file, "", buffer, UseUnicode);
1001 sprintf(buffer,"%c%c",13,10);
1002 SaveBackupText(file, "", buffer, UseUnicode);
1003}
1004
1005static void SaveGPRSPointEntry(FILE *file, GSM_GPRSAccessPoint *GPRSPoint, bool UseUnicode)
1006{
1007 unsigned char buffer[1000];
1008
1009 sprintf(buffer,"Location = %i%c%c",GPRSPoint->Location,13,10);
1010 SaveBackupText(file, "", buffer, UseUnicode);
1011 SaveBackupText(file, "Name", GPRSPoint->Name, UseUnicode);
1012 SaveBackupText(file, "URL", GPRSPoint->URL, UseUnicode);
1013 if (GPRSPoint->Active) {
1014 sprintf(buffer,"Active = Yes%c%c",13,10);
1015 SaveBackupText(file, "", buffer, UseUnicode);
1016 }
1017 sprintf(buffer,"%c%c",13,10);
1018 SaveBackupText(file, "", buffer, UseUnicode);
1019}
1020
1021GSM_Error SaveBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
1022{
1023 int i;
1024 unsigned char buffer[1000],checksum[200];
1025 FILE *file;
1026
1027 file = fopen(FileName, "wb");
1028 if (file == NULL) return ERR_CANTOPENFILE;
1029
1030 if (UseUnicode) {
1031 sprintf(buffer,"%c%c", 0xFE, 0xFF);
1032 SaveBackupText(file, "", buffer, false);
1033 }
1034
1035 sprintf(buffer,"# Format of this file was designed for Gammu (see www.mwiacek.com)%c%c%c%c",13,10,13,10);
1036 SaveBackupText(file, "", buffer, UseUnicode);
1037 sprintf(buffer,"[Backup]%c%c",13,10);
1038 SaveBackupText(file, "", buffer, UseUnicode);
1039 sprintf(buffer,"IMEI = \"%s\"%c%c",backup->IMEI,13,10);
1040 SaveBackupText(file, "", buffer, UseUnicode);
1041 sprintf(buffer,"Phone = \"%s\"%c%c",backup->Model,13,10);
1042 SaveBackupText(file, "", buffer, UseUnicode);
1043 if (backup->Creator[0] != 0) {
1044 sprintf(buffer,"Creator = \"%s\"%c%c",backup->Creator,13,10);
1045 SaveBackupText(file, "", buffer, UseUnicode);
1046 }
1047 if (backup->DateTimeAvailable) {
1048 SaveBackupText(file, "", "DateTime", UseUnicode);
1049 SaveVCalDateTime(file, &backup->DateTime, UseUnicode);
1050 }
1051 sprintf(buffer,"Format = 1.03%c%c",13,10);
1052 SaveBackupText(file, "", buffer, UseUnicode);
1053 sprintf(buffer,"%c%c",13,10);
1054 SaveBackupText(file, "", buffer, UseUnicode);
1055
1056 i=0;
1057 while (backup->PhonePhonebook[i]!=NULL) {
1058 sprintf(buffer,"[PhonePBK%03i]%c%c",i+1,13,10);
1059 SaveBackupText(file, "", buffer, UseUnicode);
1060 SavePbkEntry(file, backup->PhonePhonebook[i], UseUnicode);
1061 i++;
1062 }
1063 i=0;
1064 while (backup->SIMPhonebook[i]!=NULL) {
1065 sprintf(buffer,"[SIMPBK%03i]%c%c",i+1,13,10);
1066 SaveBackupText(file, "", buffer, UseUnicode);
1067 SavePbkEntry(file, backup->SIMPhonebook[i], UseUnicode);
1068 i++;
1069 }
1070 i=0;
1071 while (backup->Calendar[i]!=NULL) {
1072 sprintf(buffer,"[Calendar%03i]%c%c",i+1,13,10);
1073 SaveBackupText(file, "", buffer, UseUnicode);
1074 SaveCalendarEntry(file, backup->Calendar[i], UseUnicode);
1075 i++;
1076 }
1077 i=0;
1078 while (backup->CallerLogos[i]!=NULL) {
1079 sprintf(buffer,"[Caller%03i]%c%c",i+1,13,10);
1080 SaveBackupText(file, "", buffer, UseUnicode);
1081 SaveCallerEntry(file, backup->CallerLogos[i], UseUnicode);
1082 i++;
1083 }
1084 i=0;
1085 while (backup->SMSC[i]!=NULL) {
1086 sprintf(buffer,"[SMSC%03i]%c%c",i+1,13,10);
1087 SaveBackupText(file, "", buffer, UseUnicode);
1088 SaveSMSCEntry(file, backup->SMSC[i], UseUnicode);
1089 i++;
1090 }
1091 i=0;
1092 while (backup->WAPBookmark[i]!=NULL) {
1093 sprintf(buffer,"[WAPBookmark%03i]%c%c",i+1,13,10);
1094 SaveBackupText(file, "", buffer, UseUnicode);
1095 SaveWAPBookmarkEntry(file, backup->WAPBookmark[i], UseUnicode);
1096 i++;
1097 }
1098 i=0;
1099 while (backup->WAPSettings[i]!=NULL) {
1100 sprintf(buffer,"[WAPSettings%03i]%c%c",i+1,13,10);
1101 SaveBackupText(file, "", buffer, UseUnicode);
1102 SaveWAPSettingsEntry(file, backup->WAPSettings[i], UseUnicode);
1103 i++;
1104 }
1105 i=0;
1106 while (backup->MMSSettings[i]!=NULL) {
1107 sprintf(buffer,"[MMSSettings%03i]%c%c",i+1,13,10);
1108 SaveBackupText(file, "", buffer, UseUnicode);
1109 SaveWAPSettingsEntry(file, backup->MMSSettings[i], UseUnicode);
1110 i++;
1111 }
1112 i=0;
1113 while (backup->Ringtone[i]!=NULL) {
1114 sprintf(buffer,"[Ringtone%03i]%c%c",i+1,13,10);
1115 SaveBackupText(file, "", buffer, UseUnicode);
1116 SaveRingtoneEntry(file, backup->Ringtone[i], UseUnicode);
1117 i++;
1118 }
1119 i=0;
1120 while (backup->ToDo[i]!=NULL) {
1121 sprintf(buffer,"[TODO%03i]%c%c",i+1,13,10);
1122 SaveBackupText(file, "", buffer, UseUnicode);
1123 SaveToDoEntry(file, backup->ToDo[i], UseUnicode);
1124 i++;
1125 }
1126 i=0;
1127 while (backup->Profiles[i]!=NULL) {
1128 sprintf(buffer,"[Profile%03i]%c%c",i+1,13,10);
1129 SaveBackupText(file, "", buffer, UseUnicode);
1130 SaveProfileEntry(file, backup->Profiles[i], UseUnicode);
1131 i++;
1132 }
1133 i=0;
1134 while (backup->FMStation[i]!=NULL) {
1135 sprintf(buffer,"[FMStation%03i]%c%c",i+1,13,10);
1136 SaveBackupText(file, "", buffer, UseUnicode);
1137 SaveFMStationEntry(file, backup->FMStation[i], UseUnicode);
1138 i++;
1139 }
1140 i=0;
1141 while (backup->GPRSPoint[i]!=NULL) {
1142 sprintf(buffer,"[GPRSPoint%03i]%c%c",i+1,13,10);
1143 SaveBackupText(file, "", buffer, UseUnicode);
1144 SaveGPRSPointEntry(file, backup->GPRSPoint[i], UseUnicode);
1145 i++;
1146 }
1147
1148 if (backup->StartupLogo!=NULL) {
1149 SaveStartupEntry(file, backup->StartupLogo, UseUnicode);
1150 }
1151 if (backup->OperatorLogo!=NULL) {
1152 SaveOperatorEntry(file, backup->OperatorLogo, UseUnicode);
1153 }
1154
1155 fclose(file);
1156
1157 FindBackupChecksum(FileName, UseUnicode, checksum);
1158
1159 file = fopen(FileName, "ab");
1160 if (file == NULL) return ERR_CANTOPENFILE;
1161 sprintf(buffer,"[Checksum]%c%c",13,10);
1162 SaveBackupText(file, "", buffer, UseUnicode);
1163 sprintf(buffer,"MD5=%s%c%c",checksum,13,10);
1164 SaveBackupText(file, "", buffer, UseUnicode);
1165 fclose(file);
1166
1167 return ERR_NONE;
1168}
1169
1170static void ReadPbkEntry(INI_Section *file_info, char *section, GSM_MemoryEntry *Pbk, bool UseUnicode)
1171{
1172 unsigned char buffer[10000];
1173 char *readvalue;
1174 int num,i;
1175 INI_Entry *e;
1176
1177 Pbk->EntriesNum = 0;
1178 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1179
1180 while (e != NULL) {
1181 num = -1;
1182 if (UseUnicode) {
1183 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1184 } else {
1185 sprintf(buffer,"%s",e->EntryName);
1186 }
1187 if (strlen(buffer) == 11) {
1188 if (mystrncasecmp("Entry", buffer, 5) &&
1189 mystrncasecmp("Type", buffer+7, 4)) {
1190 num = atoi(buffer+5);
1191 }
1192 }
1193 e = e->Prev;
1194 if (num != -1) {
1195 sprintf(buffer,"Entry%02iType",num);
1196 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1197 if (mystrncasecmp(readvalue,"NumberGeneral",0)) {
1198 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
1199 } else if (mystrncasecmp(readvalue,"NumberMobile",0)) {
1200 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
1201 } else if (mystrncasecmp(readvalue,"NumberWork",0)) {
1202 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
1203 } else if (mystrncasecmp(readvalue,"NumberFax",0)) {
1204 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
1205 } else if (mystrncasecmp(readvalue,"NumberHome",0)) {
1206 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
1207 } else if (mystrncasecmp(readvalue,"NumberOther",0)) {
1208 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Other;
1209 } else if (mystrncasecmp(readvalue,"NumberPager",0)) {
1210 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Pager;
1211 } else if (mystrncasecmp(readvalue,"Note",0)) {
1212 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
1213 } else if (mystrncasecmp(readvalue,"Postal",0)) {
1214 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
1215 } else if (mystrncasecmp(readvalue,"Email",0)) {
1216 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
1217 } else if (mystrncasecmp(readvalue,"Email2",0)) {
1218 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email2;
1219 } else if (mystrncasecmp(readvalue,"URL",0)) {
1220 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
1221 } else if (mystrncasecmp(readvalue,"FirstName",0)) {
1222 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_FirstName;
1223 } else if (mystrncasecmp(readvalue,"LastName",0)) {
1224 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_LastName;
1225 } else if (mystrncasecmp(readvalue,"Company",0)) {
1226 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Company;
1227 } else if (mystrncasecmp(readvalue,"JobTitle",0)) {
1228 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_JobTitle;
1229 } else if (mystrncasecmp(readvalue,"Address",0)) {
1230 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_StreetAddress;
1231 } else if (mystrncasecmp(readvalue,"City",0)) {
1232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_City;
1233 } else if (mystrncasecmp(readvalue,"State",0)) {
1234 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_State;
1235 } else if (mystrncasecmp(readvalue,"Zip",0)) {
1236 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Zip;
1237 } else if (mystrncasecmp(readvalue,"Country",0)) {
1238 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Country;
1239 } else if (mystrncasecmp(readvalue,"Custom1",0)) {
1240 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom1;
1241 } else if (mystrncasecmp(readvalue,"Custom2",0)) {
1242 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom2;
1243 } else if (mystrncasecmp(readvalue,"Custom3",0)) {
1244 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom3;
1245 } else if (mystrncasecmp(readvalue,"Custom4",0)) {
1246 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom4;
1247 } else if (mystrncasecmp(readvalue,"Name",0)) {
1248 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
1249 } else if (mystrncasecmp(readvalue,"Category",0)) {
1250 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Category;
1251 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1252 sprintf(buffer,"Entry%02iNumber",num);
1253 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1254 if (readvalue!=NULL) {
1255 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1256 }
1257 Pbk->EntriesNum ++;
1258 continue;
1259 } else if (mystrncasecmp(readvalue,"Private",0)) {
1260 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Private;
1261 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1262 sprintf(buffer,"Entry%02iNumber",num);
1263 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1264 if (readvalue!=NULL) {
1265 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1266 }
1267 Pbk->EntriesNum ++;
1268 continue;
1269 } else if (mystrncasecmp(readvalue,"CallerGroup",0)) {
1270 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Caller_Group;
1271 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1272 sprintf(buffer,"Entry%02iNumber",num);
1273 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1274 if (readvalue!=NULL) {
1275 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1276 }
1277 Pbk->EntriesNum ++;
1278 continue;
1279 } else if (mystrncasecmp(readvalue,"RingtoneID",0)) {
1280 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_RingtoneID;
1281 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1282 sprintf(buffer,"Entry%02iNumber",num);
1283 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1284 if (readvalue!=NULL) {
1285 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1286 }
1287 Pbk->EntriesNum ++;
1288 continue;
1289 } else if (mystrncasecmp(readvalue,"PictureID",0)) {
1290 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_PictureID;
1291 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1292 sprintf(buffer,"Entry%02iNumber",num);
1293 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1294 if (readvalue!=NULL) {
1295 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1296 }
1297 Pbk->EntriesNum ++;
1298 continue;
1299 } else if (mystrncasecmp(readvalue,"UserID",0)) {
1300 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_UserID;
1301 }
1302 sprintf(buffer,"Entry%02iText",num);
1303 ReadBackupText(file_info, section, buffer, Pbk->Entries[Pbk->EntriesNum].Text,UseUnicode);
1304 dbgprintf("text \"%s\", type %i\n",DecodeUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text),Pbk->Entries[Pbk->EntriesNum].EntryType);
1305 Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
1306 sprintf(buffer,"Entry%02iVoiceTag",num);
1307 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1308 if (readvalue!=NULL) {
1309 Pbk->Entries[Pbk->EntriesNum].VoiceTag = atoi(readvalue);
1310 }
1311 i = 0;
1312 while (1) {
1313 Pbk->Entries[Pbk->EntriesNum].SMSList[i] = 0;
1314 sprintf(buffer,"Entry%02iSMSList%02i",num,i);
1315 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1316 if (readvalue==NULL) break;
1317 Pbk->Entries[Pbk->EntriesNum].SMSList[i] = atoi(readvalue);
1318 i++;
1319 }
1320 Pbk->EntriesNum ++;
1321 }
1322 }
1323}
1324
1325static void ReadCalendarEntry(INI_Section *file_info, char *section, GSM_CalendarEntry *note, bool UseUnicode)
1326{
1327 unsigned char buffer[10000];
1328 char *readvalue;
1329
1330 sprintf(buffer,"Location");
1331 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1332 if (readvalue!=NULL) note->Location = atoi(readvalue);
1333
1334 sprintf(buffer,"Type");
1335 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1336 note->Type = GSM_CAL_REMINDER;
1337 if (readvalue!=NULL)
1338 {
1339 if (mystrncasecmp(readvalue,"Call",0)) {
1340 note->Type = GSM_CAL_CALL;
1341 } else if (mystrncasecmp(readvalue,"Meeting",0)) {
1342 note->Type = GSM_CAL_MEETING;
1343 } else if (mystrncasecmp(readvalue,"Birthday",0)) {
1344 note->Type = GSM_CAL_BIRTHDAY;
1345 } else if (mystrncasecmp(readvalue,"Memo",0)) {
1346 note->Type = GSM_CAL_MEMO;
1347 } else if (mystrncasecmp(readvalue,"Travel",0)) {
1348 note->Type = GSM_CAL_TRAVEL;
1349 } else if (mystrncasecmp(readvalue,"Vacation",0)) {
1350 note->Type = GSM_CAL_VACATION;
1351 } else if (mystrncasecmp(readvalue,"DailyAlarm",0)) {
1352 note->Type = GSM_CAL_DAILY_ALARM;
1353 } else if (mystrncasecmp(readvalue,"Alarm",0)) {
1354 note->Type = GSM_CAL_ALARM;
1355 } else if (mystrncasecmp(readvalue,"Training/Athletism",0)) {
1356 note->Type = GSM_CAL_T_ATHL;
1357 } else if (mystrncasecmp(readvalue,"Training/BallGames",0)) {
1358 note->Type = GSM_CAL_T_BALL;
1359 } else if (mystrncasecmp(readvalue,"Training/Cycling",0)) {
1360 note->Type = GSM_CAL_T_CYCL;
1361 } else if (mystrncasecmp(readvalue,"Training/Budo",0)) {
1362 note->Type = GSM_CAL_T_BUDO;
1363 } else if (mystrncasecmp(readvalue,"Training/Dance",0)) {
1364 note->Type = GSM_CAL_T_DANC;
1365 } else if (mystrncasecmp(readvalue,"Training/ExtremeSports",0)) {
1366 note->Type = GSM_CAL_T_EXTR;
1367 } else if (mystrncasecmp(readvalue,"Training/Football",0)) {
1368 note->Type = GSM_CAL_T_FOOT;
1369 } else if (mystrncasecmp(readvalue,"Training/Golf",0)) {
1370 note->Type = GSM_CAL_T_GOLF;
1371 } else if (mystrncasecmp(readvalue,"Training/Gym",0)) {
1372 note->Type = GSM_CAL_T_GYM;
1373 } else if (mystrncasecmp(readvalue,"Training/HorseRaces",0)) {
1374 note->Type = GSM_CAL_T_HORS;
1375 } else if (mystrncasecmp(readvalue,"Training/Hockey",0)) {
1376 note->Type = GSM_CAL_T_HOCK;
1377 } else if (mystrncasecmp(readvalue,"Training/Races",0)) {
1378 note->Type = GSM_CAL_T_RACE;
1379 } else if (mystrncasecmp(readvalue,"Training/Rugby",0)) {
1380 note->Type = GSM_CAL_T_RUGB;
1381 } else if (mystrncasecmp(readvalue,"Training/Sailing",0)) {
1382 note->Type = GSM_CAL_T_SAIL;
1383 } else if (mystrncasecmp(readvalue,"Training/StreetGames",0)) {
1384 note->Type = GSM_CAL_T_STRE;
1385 } else if (mystrncasecmp(readvalue,"Training/Swimming",0)) {
1386 note->Type = GSM_CAL_T_SWIM;
1387 } else if (mystrncasecmp(readvalue,"Training/Tennis",0)) {
1388 note->Type = GSM_CAL_T_TENN;
1389 } else if (mystrncasecmp(readvalue,"Training/Travels",0)) {
1390 note->Type = GSM_CAL_T_TRAV;
1391 } else if (mystrncasecmp(readvalue,"Training/WinterGames",0)) {
1392 note->Type = GSM_CAL_T_WINT;
1393 }
1394 }
1395 note->EntriesNum = 0;
1396 sprintf(buffer,"Text");
1397 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1398 note->Entries[note->EntriesNum].EntryType = CAL_TEXT;
1399 note->EntriesNum++;
1400 }
1401 sprintf(buffer,"Phone");
1402 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1403 note->Entries[note->EntriesNum].EntryType = CAL_PHONE;
1404 note->EntriesNum++;
1405 }
1406 sprintf(buffer,"Private");
1407 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1408 if (readvalue!=NULL) {
1409 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1410 note->Entries[note->EntriesNum].EntryType = CAL_PRIVATE;
1411 note->EntriesNum++;
1412 }
1413 sprintf(buffer,"EventLocation");
1414 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1415 note->Entries[note->EntriesNum].EntryType = CAL_LOCATION;
1416 note->EntriesNum++;
1417 }
1418 sprintf(buffer,"ContactID");
1419 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1420 if (readvalue!=NULL) {
1421 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1422 note->Entries[note->EntriesNum].EntryType = CAL_CONTACTID;
1423 note->EntriesNum++;
1424 }
1425 sprintf(buffer,"Recurrance");
1426 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1427 if (readvalue!=NULL) {
1428 note->Entries[note->EntriesNum].Number = atoi(readvalue) * 24;
1429 note->Entries[note->EntriesNum].EntryType = CAL_RECURRANCE;
1430 note->EntriesNum++;
1431 }
1432 sprintf(buffer,"StartTime");
1433 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1434 if (readvalue!=NULL) {
1435 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1436 note->Entries[note->EntriesNum].EntryType = CAL_START_DATETIME;
1437 note->EntriesNum++;
1438 }
1439 sprintf(buffer,"StopTime");
1440 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1441 if (readvalue!=NULL) {
1442 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1443 note->Entries[note->EntriesNum].EntryType = CAL_END_DATETIME;
1444 note->EntriesNum++;
1445 }
1446 sprintf(buffer,"Alarm");
1447 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1448 if (readvalue!=NULL)
1449 {
1450 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1451 note->Entries[note->EntriesNum].EntryType = CAL_ALARM_DATETIME;
1452 sprintf(buffer,"AlarmType");
1453 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1454 if (readvalue!=NULL)
1455 {
1456 if (mystrncasecmp(readvalue,"Silent",0)) {
1457 note->Entries[note->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
1458 }
1459 }
1460 note->EntriesNum++;
1461 }
1462 sprintf(buffer,"RepeatStartDate");
1463 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1464 if (readvalue!=NULL) {
1465 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1466 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_STARTDATE;
1467 note->EntriesNum++;
1468 }
1469 sprintf(buffer,"RepeatStopDate");
1470 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1471 if (readvalue!=NULL) {
1472 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1473 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_STOPDATE;
1474 note->EntriesNum++;
1475 }
1476 sprintf(buffer,"RepeatDayOfWeek");
1477 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1478 if (readvalue!=NULL) {
1479 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1480 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_DAYOFWEEK;
1481 note->EntriesNum++;
1482 }
1483 sprintf(buffer,"RepeatDay");
1484 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1485 if (readvalue!=NULL) {
1486 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1487 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_DAY;
1488 note->EntriesNum++;
1489 }
1490 sprintf(buffer,"RepeatWeekOfMonth");
1491 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1492 if (readvalue!=NULL) {
1493 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1494 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_WEEKOFMONTH;
1495 note->EntriesNum++;
1496 }
1497 sprintf(buffer,"RepeatMonth");
1498 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1499 if (readvalue!=NULL) {
1500 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1501 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_MONTH;
1502 note->EntriesNum++;
1503 }
1504 sprintf(buffer,"RepeatFrequency");
1505 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1506 if (readvalue!=NULL) {
1507 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1508 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
1509 note->EntriesNum++;
1510 }
1511}
1512
1513static void ReadToDoEntry(INI_Section *file_info, char *section, GSM_ToDoEntry *ToDo, bool UseUnicode)
1514{
1515 unsigned char buffer[10000];
1516 char *readvalue;
1517
1518 ToDo->EntriesNum = 0;
1519
1520 sprintf(buffer,"Location");
1521 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1522 if (readvalue!=NULL) ToDo->Location = atoi(readvalue);
1523
1524 ToDo->Priority = GSM_Priority_High;
1525 sprintf(buffer,"Priority");
1526 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1527 if (readvalue!=NULL) {
1528 if (!strcmp(readvalue,"3") || !strcmp(readvalue,"Low")) {
1529 ToDo->Priority = GSM_Priority_Low;
1530 }
1531 if (!strcmp(readvalue,"2") || !strcmp(readvalue,"Medium")) {
1532 ToDo->Priority = GSM_Priority_Medium;
1533 }
1534 }
1535
1536 sprintf(buffer,"Text");
1537 if (ReadBackupText(file_info, section, buffer, ToDo->Entries[ToDo->EntriesNum].Text,UseUnicode)) {
1538 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_TEXT;
1539 ToDo->EntriesNum++;
1540 }
1541
1542 sprintf(buffer,"Phone");
1543 if (ReadBackupText(file_info, section, buffer, ToDo->Entries[ToDo->EntriesNum].Text,UseUnicode)) {
1544 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_PHONE;
1545 ToDo->EntriesNum++;
1546 }
1547
1548 sprintf(buffer,"Private");
1549 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1550 if (readvalue!=NULL) {
1551 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1552 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_PRIVATE;
1553 ToDo->EntriesNum++;
1554 }
1555
1556 sprintf(buffer,"Completed");
1557 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1558 if (readvalue!=NULL) {
1559 if (strncmp(readvalue, "yes", 3) == 0) {
1560 ToDo->Entries[ToDo->EntriesNum].Number = 1;
1561 } else {
1562 ToDo->Entries[ToDo->EntriesNum].Number = 0;
1563 }
1564 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_COMPLETED;
1565 ToDo->EntriesNum++;
1566 }
1567
1568 sprintf(buffer,"Category");
1569 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1570 if (readvalue!=NULL) {
1571 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1572 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_CATEGORY;
1573 ToDo->EntriesNum++;
1574 }
1575
1576 sprintf(buffer,"ContactID");
1577 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1578 if (readvalue!=NULL) {
1579 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1580 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_CONTACTID;
1581 ToDo->EntriesNum++;
1582 }
1583
1584 sprintf(buffer,"DueTime");
1585 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1586 if (readvalue!=NULL) {
1587 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1588 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_END_DATETIME;
1589 ToDo->EntriesNum++;
1590 }
1591
1592 sprintf(buffer,"Alarm");
1593 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1594 if (readvalue!=NULL) {
1595 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1596 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_ALARM_DATETIME;
1597 ToDo->EntriesNum++;
1598 }
1599
1600 sprintf(buffer,"SilentAlarm");
1601 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1602 if (readvalue!=NULL) {
1603 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1604 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
1605 ToDo->EntriesNum++;
1606 }
1607}
1608
1609static bool ReadBitmapEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1610{
1611 char *readvalue;
1612 unsigned charbuffer[10000];
1613 unsigned char Width, Height;
1614 int x, y;
1615
1616 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &Width, &Height);
1617 sprintf(buffer,"Width");
1618 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1619 if (readvalue==NULL) bitmap->BitmapWidth = Width; else bitmap->BitmapWidth = atoi(readvalue);
1620 sprintf(buffer,"Height");
1621 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1622 if (readvalue==NULL) bitmap->BitmapHeight = Height; else bitmap->BitmapHeight = atoi(readvalue);
1623 GSM_ClearBitmap(bitmap);
1624 for (y=0;y<bitmap->BitmapHeight;y++) {
1625 sprintf(buffer,"Bitmap%02i",y);
1626 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1627 if (readvalue!=NULL) {
1628 for (x=0;x<bitmap->BitmapWidth;x++) {
1629 if (readvalue[x+1]=='#') GSM_SetPointBitmap(bitmap,x,y);
1630 }
1631 } else return false;
1632 }
1633 return true;
1634}
1635
1636static void ReadCallerEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1637{
1638 unsigned char buffer[10000];
1639 char *readvalue;
1640
1641 bitmap->Type = GSM_CallerGroupLogo;
1642 bitmap->DefaultBitmap = !ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1643 if (bitmap->DefaultBitmap) {
1644 bitmap->BitmapWidth = 72;
1645 bitmap->BitmapHeight = 14;
1646 GSM_ClearBitmap(bitmap);
1647 }
1648 sprintf(buffer,"Name");
1649 ReadBackupText(file_info, section, buffer, bitmap->Text,UseUnicode);
1650 if (bitmap->Text[0] == 0x00 && bitmap->Text[1] == 0x00) {
1651 bitmap->DefaultName = true;
1652 } else {
1653 bitmap->DefaultName = false;
1654 }
1655 sprintf(buffer,"Ringtone");
1656 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1657 if (readvalue==NULL) {
1658 sprintf(buffer,"FileRingtone");
1659 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1660 if (readvalue==NULL) {
1661 bitmap->DefaultRingtone = true;
1662 } else {
1663 DecodeHexBin (&bitmap->RingtoneID, readvalue, 2);
1664 bitmap->DefaultRingtone = false;
1665 bitmap->FileSystemRingtone = true;
1666 }
1667 } else {
1668 DecodeHexBin (&bitmap->RingtoneID, readvalue, 2);
1669 bitmap->DefaultRingtone = false;
1670 bitmap->FileSystemRingtone = false;
1671 }
1672 sprintf(buffer,"Enabled");
1673 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1674 bitmap->BitmapEnabled = true;
1675 if (readvalue!=NULL) {
1676 if (mystrncasecmp(readvalue,"False",0)) bitmap->BitmapEnabled = false;
1677 }
1678}
1679
1680static void ReadStartupEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1681{
1682 unsigned char buffer[10000];
1683
1684 sprintf(buffer,"Text");
1685 ReadBackupText(file_info, section, buffer, bitmap->Text,UseUnicode);
1686 if (bitmap->Text[0]!=0 || bitmap->Text[1]!=0) {
1687 bitmap->Type = GSM_WelcomeNote_Text;
1688 } else {
1689 bitmap->Type = GSM_StartupLogo;
1690 bitmap->Location = 1;
1691 ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1692#ifdef DEBUG
1693 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,bitmap);
1694#endif
1695 }
1696}
1697
1698static void ReadWAPBookmarkEntry(INI_Section *file_info, char *section, GSM_WAPBookmark *bookmark, bool UseUnicode)
1699{
1700 unsigned char buffer[10000];
1701
1702 sprintf(buffer,"URL");
1703 ReadBackupText(file_info, section, buffer, bookmark->Address,UseUnicode);
1704 sprintf(buffer,"Title");
1705 ReadBackupText(file_info, section, buffer, bookmark->Title,UseUnicode);
1706}
1707
1708static void ReadOperatorEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1709{
1710 unsigned char buffer[10000];
1711 char *readvalue;
1712
1713 sprintf(buffer,"Network");
1714 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1715 memcpy(bitmap->NetworkCode, readvalue + 1, 6);
1716 bitmap->NetworkCode[6] = 0;
1717 bitmap->Type = GSM_OperatorLogo;
1718 ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1719}
1720
1721static void ReadSMSCEntry(INI_Section *file_info, char *section, GSM_SMSC *SMSC, bool UseUnicode)
1722{
1723 unsigned char buffer[10000];
1724 char *readvalue;
1725
1726 sprintf(buffer,"Name");
1727 ReadBackupText(file_info, section, buffer, SMSC->Name,UseUnicode);
1728 sprintf(buffer,"Number");
1729 ReadBackupText(file_info, section, buffer, SMSC->Number,UseUnicode);
1730 sprintf(buffer,"DefaultNumber");
1731 ReadBackupText(file_info, section, buffer, SMSC->DefaultNumber,UseUnicode);
1732 sprintf(buffer,"Format");
1733 SMSC->Format = SMS_FORMAT_Text;
1734 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1735 if (readvalue!=NULL) {
1736 if (mystrncasecmp(readvalue,"Fax",0)) {
1737 SMSC->Format = SMS_FORMAT_Fax;
1738 } else if (mystrncasecmp(readvalue,"Email",0)) {
1739 SMSC->Format = SMS_FORMAT_Email;
1740 } else if (mystrncasecmp(readvalue,"Pager",0)) {
1741 SMSC->Format = SMS_FORMAT_Pager;
1742 }
1743 }
1744 sprintf(buffer,"Validity");
1745 SMSC->Validity.Relative = SMS_VALID_Max_Time;
1746 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1747 if (readvalue!=NULL) {
1748 if (mystrncasecmp(readvalue,"1hour",0)) {
1749 SMSC->Validity.Relative = SMS_VALID_1_Hour;
1750 } else if (mystrncasecmp(readvalue,"6hours",0)) {
1751 SMSC->Validity.Relative = SMS_VALID_6_Hours;
1752 } else if (mystrncasecmp(readvalue,"24hours",0)) {
1753 SMSC->Validity.Relative = SMS_VALID_1_Day;
1754 } else if (mystrncasecmp(readvalue,"72hours",0)) {
1755 SMSC->Validity.Relative = SMS_VALID_3_Days;
1756 } else if (mystrncasecmp(readvalue,"1week",0)) {
1757 SMSC->Validity.Relative = SMS_VALID_1_Week;
1758 }
1759 }
1760}
1761
1762static void ReadWAPSettingsEntry(INI_Section *file_info, char *section, GSM_MultiWAPSettings *settings, bool UseUnicode)
1763{
1764 unsigned char buffer[10000], *readvalue;
1765 int num;
1766 INI_Entry *e;
1767
1768 settings->ActiveBearer = WAPSETTINGS_BEARER_DATA;
1769 sprintf(buffer,"Bearer");
1770 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1771 if (readvalue!=NULL) {
1772 if (mystrncasecmp(readvalue,"SMS",0)) {
1773 settings->ActiveBearer = WAPSETTINGS_BEARER_SMS;
1774 } else if (mystrncasecmp(readvalue,"GPRS",0)) {
1775 settings->ActiveBearer = WAPSETTINGS_BEARER_GPRS;
1776 } else if (mystrncasecmp(readvalue,"USSD",0)) {
1777 settings->ActiveBearer = WAPSETTINGS_BEARER_USSD;
1778 }
1779 }
1780
1781 settings->Active = false;
1782 sprintf(buffer,"Active");
1783 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1784 if (readvalue!=NULL) {
1785 if (mystrncasecmp(readvalue,"Yes",0)) settings->Active = true;
1786 }
1787
1788 settings->ReadOnly = false;
1789 sprintf(buffer,"ReadOnly");
1790 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1791 if (readvalue!=NULL) {
1792 if (mystrncasecmp(readvalue,"Yes",0)) settings->ReadOnly = true;
1793 }
1794
1795 sprintf(buffer,"Proxy");
1796 ReadBackupText(file_info, section, buffer, settings->Proxy,UseUnicode);
1797 sprintf(buffer,"ProxyPort");
1798 settings->ProxyPort = 8080;
1799 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1800 if (readvalue!=NULL) settings->ProxyPort = atoi(readvalue);
1801 sprintf(buffer,"Proxy2");
1802 ReadBackupText(file_info, section, buffer, settings->Proxy2,UseUnicode);
1803 sprintf(buffer,"Proxy2Port");
1804 settings->Proxy2Port = 8080;
1805 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1806 if (readvalue!=NULL) settings->Proxy2Port = atoi(readvalue);
1807
1808 settings->Number = 0;
1809 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1810 while (e != NULL) {
1811 num = -1;
1812 if (UseUnicode) {
1813 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1814 } else {
1815 sprintf(buffer,"%s",e->EntryName);
1816 }
1817 if (strlen(buffer) == 7) {
1818 if (mystrncasecmp("Title", buffer,5)) num = atoi(buffer+5);
1819 }
1820 e = e->Prev;
1821 if (num != -1) {
1822 sprintf(buffer,"Title%02i",num);
1823 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Title,UseUnicode);
1824 sprintf(buffer,"HomePage%02i",num);
1825 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].HomePage,UseUnicode);
1826 sprintf(buffer,"Type%02i",num);
1827 settings->Settings[settings->Number].IsContinuous = true;
1828 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1829 if (readvalue!=NULL) {
1830 if (mystrncasecmp(readvalue,"Temporary",0)) settings->Settings[settings->Number].IsContinuous = false;
1831 }
1832 sprintf(buffer,"Security%02i",num);
1833 settings->Settings[settings->Number].IsSecurity = true;
1834 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1835 if (readvalue!=NULL)
1836 {
1837 if (mystrncasecmp(readvalue,"Off",0)) settings->Settings[settings->Number].IsSecurity = false;
1838 }
1839 sprintf(buffer,"Bearer%02i",num);
1840 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1841 if (readvalue!=NULL)
1842 {
1843 if (mystrncasecmp(readvalue,"SMS",0)) {
1844 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_SMS;
1845 sprintf(buffer,"Server%02i",num);
1846 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Server,UseUnicode);
1847 sprintf(buffer,"Service%02i",num);
1848 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Service,UseUnicode);
1849 } else if ((mystrncasecmp(readvalue,"Data",0) || mystrncasecmp(readvalue,"GPRS",0))) {
1850 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_DATA;
1851 if (mystrncasecmp(readvalue,"GPRS",0)) settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_GPRS;
1852 sprintf(buffer,"Number%02i",num);
1853 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].DialUp,UseUnicode);
1854 sprintf(buffer,"IP%02i",num);
1855 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].IPAddress,UseUnicode);
1856 sprintf(buffer,"User%02i",num);
1857 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].User,UseUnicode);
1858 sprintf(buffer,"Password%02i",num);
1859 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Password,UseUnicode);
1860 sprintf(buffer,"Authentication%02i",num);
1861 settings->Settings[settings->Number].IsNormalAuthentication = true;
1862 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1863 if (readvalue!=NULL)
1864 {
1865 if (mystrncasecmp(readvalue,"Secure",0)) settings->Settings[settings->Number].IsNormalAuthentication = false;
1866 }
1867 sprintf(buffer,"CallSpeed%02i",num);
1868 settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_14400;
1869 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1870 if (readvalue!=NULL)
1871 {
1872 if (mystrncasecmp(readvalue,"9600",0)) settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_9600;
1873 if (mystrncasecmp(readvalue,"auto",0)) settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_AUTO;
1874 }
1875 sprintf(buffer,"Login%02i",num);
1876 settings->Settings[settings->Number].ManualLogin = false;
1877 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1878 if (readvalue!=NULL)
1879 {
1880 if (mystrncasecmp(readvalue,"Manual",0)) settings->Settings[settings->Number].ManualLogin = true;
1881 }
1882 sprintf(buffer,"CallType%02i",num);
1883 settings->Settings[settings->Number].IsISDNCall = true;
1884 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1885 if (readvalue!=NULL)
1886 {
1887 if (mystrncasecmp(readvalue,"Analogue",0)) settings->Settings[settings->Number].IsISDNCall = false;
1888 }
1889 } else if (mystrncasecmp(readvalue,"USSD",0)) {
1890 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_USSD;
1891 sprintf(buffer,"ServiceCode%02i",num);
1892 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Code,UseUnicode);
1893 sprintf(buffer,"IP%02i",num);
1894 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1895 if (readvalue!=NULL) {
1896 settings->Settings[settings->Number].IsIP = true;
1897 sprintf(buffer,"IP%02i",num);
1898 } else {
1899 settings->Settings[settings->Number].IsIP = false;
1900 sprintf(buffer,"Number%02i",num);
1901 }
1902 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Service,UseUnicode);
1903 }
1904 }
1905 settings->Number++;
1906 }
1907 }
1908}
1909
1910static void ReadRingtoneEntry(INI_Section *file_info, char *section, GSM_Ringtone *ringtone, bool UseUnicode)
1911{
1912 unsigned char buffer[10000], buffer2[10000], *readvalue;
1913
1914 sprintf(buffer,"Name");
1915 ReadBackupText(file_info, section, buffer, ringtone->Name,UseUnicode);
1916 ringtone->Location = 0;
1917 sprintf(buffer,"Location");
1918 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1919 if (readvalue!=NULL) ringtone->Location = atoi(readvalue);
1920 sprintf(buffer,"NokiaBinary00");
1921 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1922 if (readvalue!=NULL) {
1923 ringtone->Format = RING_NOKIABINARY;
1924 ReadLinkedBackupText(file_info, section, "NokiaBinary", buffer2, UseUnicode);
1925 DecodeHexBin (ringtone->NokiaBinary.Frame, buffer2, strlen(buffer2));
1926 ringtone->NokiaBinary.Length = strlen(buffer2)/2;
1927 }
1928 sprintf(buffer,"Pure Midi00");
1929 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1930 if (readvalue!=NULL) {
1931 ringtone->Format = RING_MIDI;
1932 ReadLinkedBackupText(file_info, section, "Pure Midi", buffer2, UseUnicode);
1933 DecodeHexBin (ringtone->NokiaBinary.Frame, buffer2, strlen(buffer2));
1934 ringtone->NokiaBinary.Length = strlen(buffer2)/2;
1935 }
1936
1937}
1938
1939static void ReadProfileEntry(INI_Section *file_info, char *section, GSM_Profile *Profile, bool UseUnicode)
1940{
1941 unsigned char buffer[10000];
1942 char *readvalue;
1943 bool unknown;
1944 int num,j;
1945 INI_Entry *e;
1946
1947 sprintf(buffer,"Name");
1948 ReadBackupText(file_info, section, buffer, Profile->Name,UseUnicode);
1949
1950 sprintf(buffer,"Location");
1951 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1952 Profile->Location = atoi(readvalue);
1953
1954 Profile->DefaultName = false;
1955 sprintf(buffer,"DefaultName");
1956 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1957 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->DefaultName = true;
1958
1959 Profile->HeadSetProfile = false;
1960 sprintf(buffer,"HeadSetProfile");
1961 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1962 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->HeadSetProfile = true;
1963
1964 Profile->CarKitProfile = false;
1965 sprintf(buffer,"CarKitProfile");
1966 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1967 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->CarKitProfile = true;
1968
1969 Profile->FeaturesNumber = 0;
1970 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1971 while (e != NULL) {
1972 num = -1;
1973 if (UseUnicode) {
1974 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1975 } else {
1976 sprintf(buffer,"%s",e->EntryName);
1977 }
1978 if (strlen(buffer) == 9) {
1979 if (mystrncasecmp("Feature", buffer, 7)) num = atoi(buffer+7);
1980 }
1981 e = e->Prev;
1982 if (num != -1) {
1983 sprintf(buffer,"Feature%02i",num);
1984 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1985 if (readvalue==NULL) break;
1986 unknown = true;
1987 if (mystrncasecmp(readvalue,"RingtoneID",0)) {
1988 Profile->FeatureID[Profile->FeaturesNumber]=Profile_RingtoneID;
1989 sprintf(buffer,"Value%02i",num);
1990 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1991 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
1992 Profile->FeaturesNumber++;
1993 } else if (mystrncasecmp(readvalue,"MessageToneID",0)) {
1994 Profile->FeatureID[Profile->FeaturesNumber]=Profile_MessageToneID;
1995 sprintf(buffer,"Value%02i",num);
1996 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1997 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
1998 Profile->FeaturesNumber++;
1999 } else if (mystrncasecmp(readvalue,"ScreenSaverNumber",0)) {
2000 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaverNumber;
2001 sprintf(buffer,"Value%02i",num);
2002 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2003 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
2004 Profile->FeaturesNumber++;
2005 } else if (mystrncasecmp(readvalue,"CallerGroups",0)) {
2006 Profile->FeatureID[Profile->FeaturesNumber]=Profile_CallerGroups;
2007 sprintf(buffer,"Value%02i",num);
2008 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2009 for (j=0;j<5;j++) {
2010 Profile->CallerGroups[j]=false;
2011 if (strstr(readvalue,"1"+j)!=NULL) Profile->CallerGroups[j]=true;
2012 }
2013 Profile->FeaturesNumber++;
2014 } else if (mystrncasecmp(readvalue,"IncomingCallAlert",0)) {
2015 Profile->FeatureID[Profile->FeaturesNumber]=Profile_CallAlert;
2016 unknown = false;
2017 } else if (mystrncasecmp(readvalue,"RingtoneVolume",0)) {
2018 Profile->FeatureID[Profile->FeaturesNumber]=Profile_RingtoneVolume;
2019 unknown = false;
2020 } else if (mystrncasecmp(readvalue,"Vibrating",0)) {
2021 Profile->FeatureID[Profile->FeaturesNumber]=Profile_Vibration;
2022 unknown = false;
2023 } else if (mystrncasecmp(readvalue,"MessageTone",0)) {
2024 Profile->FeatureID[Profile->FeaturesNumber]=Profile_MessageTone;
2025 unknown = false;
2026 } else if (mystrncasecmp(readvalue,"KeypadTones",0)) {
2027 Profile->FeatureID[Profile->FeaturesNumber]=Profile_KeypadTone;
2028 unknown = false;
2029 } else if (mystrncasecmp(readvalue,"WarningTones",0)) {
2030 Profile->FeatureID[Profile->FeaturesNumber]=Profile_WarningTone;
2031 unknown = false;
2032 } else if (mystrncasecmp(readvalue,"ScreenSaver",0)) {
2033 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaver;
2034 unknown = false;
2035 } else if (mystrncasecmp(readvalue,"ScreenSaverTimeout",0)) {
2036 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaverTime;
2037 unknown = false;
2038 } else if (mystrncasecmp(readvalue,"AutomaticAnswer",0)) {
2039 Profile->FeatureID[Profile->FeaturesNumber]=Profile_AutoAnswer;
2040 unknown = false;
2041 } else if (mystrncasecmp(readvalue,"Lights",0)) {
2042 Profile->FeatureID[Profile->FeaturesNumber]=Profile_Lights;
2043 unknown = false;
2044 }
2045 if (!unknown) {
2046 sprintf(buffer,"Value%02i",num);
2047 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2048 if (mystrncasecmp(readvalue,"Level1",0)) {
2049 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL1;
2050 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2051 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL1;
2052 }
2053 } else if (mystrncasecmp(readvalue,"Level2",0)) {
2054 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL2;
2055 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2056 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL2;
2057 }
2058 } else if (mystrncasecmp(readvalue,"Level3",0)) {
2059 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL3;
2060 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2061 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL3;
2062 }
2063 } else if (mystrncasecmp(readvalue,"Level4",0)) {
2064 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL4;
2065 } else if (mystrncasecmp(readvalue,"Level5",0)) {
2066 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL5;
2067 } else if (mystrncasecmp(readvalue,"Off",0)) {
2068 switch (Profile->FeatureID[Profile->FeaturesNumber]) {
2069 case Profile_MessageTone:
2070 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_NOTONE;
2071 break;
2072 case Profile_AutoAnswer:
2073 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_AUTOANSWER_OFF;
2074 break;
2075 case Profile_Lights:
2076 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_LIGHTS_OFF;
2077 break;
2078 case Profile_ScreenSaver:
2079 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_OFF;
2080 break;
2081 case Profile_WarningTone:
2082 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_WARNING_OFF;
2083 break;
2084 case Profile_CallAlert:
2085 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_OFF;
2086 break;
2087 case Profile_Vibration:
2088 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_OFF;
2089 break;
2090 default:
2091 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_OFF;
2092 break;
2093 }
2094 } else if (mystrncasecmp(readvalue,"Ringing",0)) {
2095 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_RINGING;
2096 } else if (mystrncasecmp(readvalue,"BeepOnce",0)) {
2097 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_BEEPONCE;
2098 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_MessageTone) {
2099 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_BEEPONCE;
2100 }
2101 } else if (mystrncasecmp(readvalue,"RingOnce",0)) {
2102 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_RINGONCE;
2103 } else if (mystrncasecmp(readvalue,"Ascending",0)) {
2104 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_ASCENDING;
2105 } else if (mystrncasecmp(readvalue,"CallerGroups",0)) {
2106 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_CALLERGROUPS;
2107 } else if (mystrncasecmp(readvalue,"Standard",0)) {
2108 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_STANDARD;
2109 } else if (mystrncasecmp(readvalue,"Special",0)) {
2110 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_SPECIAL;
2111 } else if (mystrncasecmp(readvalue,"Ascending",0)) {
2112 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_ASCENDING;
2113 } else if (mystrncasecmp(readvalue,"Personal",0)) {
2114 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_PERSONAL;
2115 } else if (mystrncasecmp(readvalue,"VibrateFirst",0)) {
2116 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_FIRST;
2117 } else if (mystrncasecmp(readvalue,"Auto",0)) {
2118 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_LIGHTS_AUTO;
2119 } else if (mystrncasecmp(readvalue,"5Seconds",0)) {
2120 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_5SEC;
2121 } else if (mystrncasecmp(readvalue,"20Seconds",0)) {
2122 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_20SEC;
2123 } else if (mystrncasecmp(readvalue,"1Minute",0)) {
2124 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_1MIN;
2125 } else if (mystrncasecmp(readvalue,"2Minutes",0)) {
2126 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_2MIN;
2127 } else if (mystrncasecmp(readvalue,"5Minutes",0)) {
2128 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_5MIN;
2129 } else if (mystrncasecmp(readvalue,"10Minutes",0)) {
2130 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_10MIN;
2131 } else if (mystrncasecmp(readvalue,"On",0)) {
2132 switch (Profile->FeatureID[Profile->FeaturesNumber]) {
2133 case Profile_AutoAnswer:
2134 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_AUTOANSWER_ON;
2135 break;
2136 case Profile_WarningTone:
2137 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_WARNING_ON;
2138 break;
2139 case Profile_ScreenSaver:
2140 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_ON;
2141 break;
2142 default:
2143 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_ON;
2144 break;
2145 }
2146 } else unknown = true;
2147 }
2148 if (!unknown) Profile->FeaturesNumber++;
2149 }
2150 }
2151}
2152
2153static void ReadFMStationEntry(INI_Section *file_info, char *section, GSM_FMStation *FMStation, bool UseUnicode)
2154{
2155 unsigned char buffer[10000], *readvalue;
2156
2157 FMStation->Location = 0;
2158 FMStation->Frequency = 0;
2159
2160 sprintf(buffer,"Location");
2161 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2162 if (readvalue!=NULL) FMStation->Location = atoi(readvalue);
2163
2164 sprintf(buffer,"StationName");
2165 ReadBackupText(file_info, section, buffer, FMStation->StationName,UseUnicode);
2166
2167 sprintf(buffer,"Frequency");
2168 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2169 if (readvalue!=NULL) StringToDouble(readvalue, &FMStation->Frequency);
2170}
2171
2172static void ReadGPRSPointEntry(INI_Section *file_info, char *section, GSM_GPRSAccessPoint *GPRSPoint, bool UseUnicode)
2173{
2174 unsigned char buffer[10000], *readvalue;
2175
2176 GPRSPoint->Name[0] = 0;
2177 GPRSPoint->Name[1] = 0;
2178 GPRSPoint->URL[0] = 0;
2179 GPRSPoint->URL[1] = 0;
2180 GPRSPoint->Location = 0;
2181
2182 GPRSPoint->Active = false;
2183 sprintf(buffer,"Active");
2184 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2185 if (readvalue!=NULL) {
2186 if (mystrncasecmp(readvalue,"Yes",0)) GPRSPoint->Active = true;
2187 }
2188
2189 sprintf(buffer,"Location");
2190 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2191 if (readvalue!=NULL) GPRSPoint->Location = atoi(readvalue);
2192
2193 sprintf(buffer,"Name");
2194 ReadBackupText(file_info, section, buffer, GPRSPoint->Name,UseUnicode);
2195
2196 sprintf(buffer,"URL");
2197 ReadBackupText(file_info, section, buffer, GPRSPoint->URL,UseUnicode);
2198}
2199
2200static void ReadNoteEntry(INI_Section *file_info, char *section, GSM_NoteEntry *Note, bool UseUnicode)
2201{
2202 unsigned char buffer[100];
2203
2204 sprintf(buffer,"Text");
2205 ReadBackupText(file_info, section, buffer, Note->Text,UseUnicode);
2206}
2207
2208GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
2209{
2210 INI_Section *file_info, *h;
2211 char buffer[100], *readvalue;
2212 int num;
2213 GSM_MemoryEntry PBK;
2214 bool found;
2215
2216 file_info = INI_ReadFile(FileName, UseUnicode);
2217
2218 sprintf(buffer,"Backup");
2219 if (UseUnicode) EncodeUnicode(buffer,"Backup",6);
2220
2221 readvalue = ReadCFGText(file_info, buffer, "Format", UseUnicode);
2222 /* Did we read anything? */
2223 if (readvalue == NULL) return ERR_FILENOTSUPPORTED;
2224 /* Is this format version supported ? */
2225 if (strcmp(readvalue,"1.01")!=0 && strcmp(readvalue,"1.02")!=0 &&
2226 strcmp(readvalue,"1.03")!=0) return ERR_FILENOTSUPPORTED;
2227
2228 readvalue = ReadCFGText(file_info, buffer, "IMEI", UseUnicode);
2229 if (readvalue!=NULL) strcpy(backup->IMEI,readvalue);
2230 readvalue = ReadCFGText(file_info, buffer, "Phone", UseUnicode);
2231 if (readvalue!=NULL) strcpy(backup->Model,readvalue);
2232 readvalue = ReadCFGText(file_info, buffer, "Creator", UseUnicode);
2233 if (readvalue!=NULL) strcpy(backup->Creator,readvalue);
2234 readvalue = ReadCFGText(file_info, buffer, "DateTime", UseUnicode);
2235 if (readvalue!=NULL) {
2236 ReadVCALDateTime(readvalue, &backup->DateTime);
2237 backup->DateTimeAvailable = true;
2238 }
2239
2240 sprintf(buffer,"Checksum");
2241 if (UseUnicode) EncodeUnicode(buffer,"Checksum",8);
2242 readvalue = ReadCFGText(file_info, buffer, "MD5", UseUnicode);
2243 if (readvalue!=NULL) strcpy(backup->MD5Original,readvalue);
2244
2245 num = 0;
2246 for (h = file_info; h != NULL; h = h->Next) {
2247 found = false;
2248 if (UseUnicode) {
2249 EncodeUnicode(buffer,"Profile",7);
2250 if (mywstrncasecmp(buffer, h->SectionName, 7)) found = true;
2251 } else {
2252 if (mystrncasecmp("Profile", h->SectionName, 7)) found = true;
2253 }
2254 if (found) {
2255 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2256 if (readvalue==NULL) break;
2257 if (num < GSM_BACKUP_MAX_PROFILES) {
2258 backup->Profiles[num] = malloc(sizeof(GSM_Profile));
2259 if (backup->Profiles[num] == NULL) return ERR_MOREMEMORY;
2260 backup->Profiles[num + 1] = NULL;
2261 } else {
2262 dbgprintf("Increase GSM_BACKUP_MAX_PROFILES\n");
2263 return ERR_MOREMEMORY;
2264 }
2265 ReadProfileEntry(file_info, h->SectionName, backup->Profiles[num], UseUnicode);
2266 num++;
2267 }
2268 }
2269 num = 0;
2270 for (h = file_info; h != NULL; h = h->Next) {
2271 found = false;
2272 if (UseUnicode) {
2273 EncodeUnicode(buffer,"PhonePBK",8);
2274 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2275 } else {
2276 if (mystrncasecmp("PhonePBK", h->SectionName, 8)) found = true;
2277 }
2278 if (found) {
2279 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2280 if (readvalue==NULL) break;
2281 if (num < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
2282 backup->PhonePhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
2283 if (backup->PhonePhonebook[num] == NULL) return ERR_MOREMEMORY;
2284 backup->PhonePhonebook[num + 1] = NULL;
2285 } else {
2286 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
2287 return ERR_MOREMEMORY;
2288 }
2289 backup->PhonePhonebook[num]->Location= atoi (readvalue);
2290 backup->PhonePhonebook[num]->MemoryType= MEM_ME;
2291 ReadPbkEntry(file_info, h->SectionName, backup->PhonePhonebook[num],UseUnicode);
2292 dbgprintf("number of entries = %i\n",backup->PhonePhonebook[num]->EntriesNum);
2293 num++;
2294 }
2295 }
2296 num = 0;
2297 while (0) {
2298 if (backup->PhonePhonebook[num] == NULL) break;
2299 if (backup->PhonePhonebook[num+1] != NULL) {
2300 if (backup->PhonePhonebook[num+1]->Location < backup->PhonePhonebook[num]->Location) {
2301 memcpy(&PBK,backup->PhonePhonebook[num+1],sizeof(GSM_MemoryEntry));
2302 memcpy(backup->PhonePhonebook[num+1],backup->PhonePhonebook[num],sizeof(GSM_MemoryEntry));
2303 memcpy(backup->PhonePhonebook[num],&PBK,sizeof(GSM_MemoryEntry));
2304 num = 0;
2305 continue;
2306 }
2307 }
2308 num++;
2309 }
2310 num = 0;
2311 for (h = file_info; h != NULL; h = h->Next) {
2312 found = false;
2313 if (UseUnicode) {
2314 EncodeUnicode(buffer,"SIMPBK",6);
2315 if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
2316 } else {
2317 if (mystrncasecmp("SIMPBK", h->SectionName, 6)) found = true;
2318 }
2319 if (found) {
2320 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2321 if (readvalue==NULL) break;
2322 if (num < GSM_BACKUP_MAX_SIMPHONEBOOK) {
2323 backup->SIMPhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
2324 if (backup->SIMPhonebook[num] == NULL) return ERR_MOREMEMORY;
2325 backup->SIMPhonebook[num + 1] = NULL;
2326 } else {
2327 dbgprintf("Increase GSM_BACKUP_MAX_SIMPHONEBOOK\n");
2328 return ERR_MOREMEMORY;
2329 }
2330 backup->SIMPhonebook[num]->Location= atoi (readvalue);
2331 backup->SIMPhonebook[num]->MemoryType= MEM_SM;
2332 ReadPbkEntry(file_info, h->SectionName, backup->SIMPhonebook[num],UseUnicode);
2333 num++;
2334 }
2335 }
2336 num = 0;
2337 while (0) {
2338 if (backup->SIMPhonebook[num] == NULL) break;
2339 if (backup->SIMPhonebook[num+1] != NULL) {
2340 if (backup->SIMPhonebook[num+1]->Location < backup->SIMPhonebook[num]->Location) {
2341 memcpy(&PBK,backup->SIMPhonebook[num+1],sizeof(GSM_MemoryEntry));
2342 memcpy(backup->SIMPhonebook[num+1],backup->SIMPhonebook[num],sizeof(GSM_MemoryEntry));
2343 memcpy(backup->SIMPhonebook[num],&PBK,sizeof(GSM_MemoryEntry));
2344 num = 0;
2345 continue;
2346 }
2347 }
2348 num++;
2349 }
2350 num = 0;
2351 for (h = file_info; h != NULL; h = h->Next) {
2352 found = false;
2353 if (UseUnicode) {
2354 EncodeUnicode(buffer,"Calendar",8);
2355 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2356 } else {
2357 if (mystrncasecmp("Calendar", h->SectionName, 8)) found = true;
2358 }
2359 if (found) {
2360 readvalue = ReadCFGText(file_info, h->SectionName, "Type", UseUnicode);
2361 if (readvalue==NULL) break;
2362 if (num < GSM_MAXCALENDARTODONOTES) {
2363 backup->Calendar[num] = malloc(sizeof(GSM_CalendarEntry));
2364 if (backup->Calendar[num] == NULL) return ERR_MOREMEMORY;
2365 backup->Calendar[num + 1] = NULL;
2366 } else {
2367 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
2368 return ERR_MOREMEMORY;
2369 }
2370 backup->Calendar[num]->Location = num + 1;
2371 ReadCalendarEntry(file_info, h->SectionName, backup->Calendar[num],UseUnicode);
2372 num++;
2373 }
2374 }
2375 num = 0;
2376 for (h = file_info; h != NULL; h = h->Next) {
2377 found = false;
2378 if (UseUnicode) {
2379 EncodeUnicode(buffer,"Caller",6);
2380 if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
2381 } else {
2382 if (mystrncasecmp("Caller", h->SectionName, 6)) found = true;
2383 }
2384 if (found) {
2385 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2386 if (readvalue==NULL) break;
2387 if (num < GSM_BACKUP_MAX_CALLER) {
2388 backup->CallerLogos[num] = malloc(sizeof(GSM_Bitmap));
2389 if (backup->CallerLogos[num] == NULL) return ERR_MOREMEMORY;
2390 backup->CallerLogos[num + 1] = NULL;
2391 } else {
2392 dbgprintf("Increase GSM_BACKUP_MAX_CALLER\n");
2393 return ERR_MOREMEMORY;
2394 }
2395 backup->CallerLogos[num]->Location = atoi (readvalue);
2396 ReadCallerEntry(file_info, h->SectionName, backup->CallerLogos[num],UseUnicode);
2397 num++;
2398 }
2399 }
2400 num = 0;
2401 for (h = file_info; h != NULL; h = h->Next) {
2402 found = false;
2403 if (UseUnicode) {
2404 EncodeUnicode(buffer,"SMSC",4);
2405 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2406 } else {
2407 if (mystrncasecmp("SMSC", h->SectionName, 4)) found = true;
2408 }
2409 if (found) {
2410 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2411 if (readvalue==NULL) break;
2412 if (num < GSM_BACKUP_MAX_SMSC) {
2413 backup->SMSC[num] = malloc(sizeof(GSM_SMSC));
2414 if (backup->SMSC[num] == NULL) return ERR_MOREMEMORY;
2415 backup->SMSC[num + 1] = NULL;
2416 } else {
2417 dbgprintf("Increase GSM_BACKUP_MAX_SMSC\n");
2418 return ERR_MOREMEMORY;
2419 }
2420 backup->SMSC[num]->Location = atoi (readvalue);
2421 ReadSMSCEntry(file_info, h->SectionName, backup->SMSC[num],UseUnicode);
2422 num++;
2423 }
2424 }
2425 num = 0;
2426 for (h = file_info; h != NULL; h = h->Next) {
2427 found = false;
2428 if (UseUnicode) {
2429 EncodeUnicode(buffer,"WAPBookmark",11);
2430 if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
2431 if (!found) {
2432 EncodeUnicode(buffer,"Bookmark",8);
2433 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2434 }
2435 } else {
2436 if (mystrncasecmp("WAPBookmark", h->SectionName, 11)) found = true;
2437 if (!found) {
2438 if (mystrncasecmp("Bookmark", h->SectionName, 8)) found = true;
2439 }
2440 }
2441 if (found) {
2442 readvalue = ReadCFGText(file_info, h->SectionName, "URL", UseUnicode);
2443 if (readvalue==NULL) break;
2444 if (num < GSM_BACKUP_MAX_WAPBOOKMARK) {
2445 backup->WAPBookmark[num] = malloc(sizeof(GSM_WAPBookmark));
2446 if (backup->WAPBookmark[num] == NULL) return ERR_MOREMEMORY;
2447 backup->WAPBookmark[num + 1] = NULL;
2448 } else {
2449 dbgprintf("Increase GSM_BACKUP_MAX_WAPBOOKMARK\n");
2450 return ERR_MOREMEMORY;
2451 }
2452 backup->WAPBookmark[num]->Location = num + 1;
2453 ReadWAPBookmarkEntry(file_info, h->SectionName, backup->WAPBookmark[num],UseUnicode);
2454 num++;
2455 }
2456 }
2457 num = 0;
2458 for (h = file_info; h != NULL; h = h->Next) {
2459 found = false;
2460 if (UseUnicode) {
2461 EncodeUnicode(buffer,"WAPSettings",11);
2462 if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
2463 if (!found) {
2464 EncodeUnicode(buffer,"Settings",8);
2465 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2466 }
2467 } else {
2468 if (mystrncasecmp("WAPSettings", h->SectionName, 11)) found = true;
2469 if (!found) {
2470 if (mystrncasecmp("Settings", h->SectionName, 8)) found = true;
2471 }
2472 }
2473 if (found) {
2474 readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
2475 if (readvalue==NULL) break;
2476 if (num < GSM_BACKUP_MAX_WAPSETTINGS) {
2477 backup->WAPSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
2478 if (backup->WAPSettings[num] == NULL) return ERR_MOREMEMORY;
2479 backup->WAPSettings[num + 1] = NULL;
2480 } else {
2481 dbgprintf("Increase GSM_BACKUP_MAX_WAPSETTINGS\n");
2482 return ERR_MOREMEMORY;
2483 }
2484 backup->WAPSettings[num]->Location = num + 1;
2485 dbgprintf("reading wap settings\n");
2486 ReadWAPSettingsEntry(file_info, h->SectionName, backup->WAPSettings[num],UseUnicode);
2487 num++;
2488 }
2489 }
2490 num = 0;
2491 for (h = file_info; h != NULL; h = h->Next) {
2492 found = false;
2493 if (UseUnicode) {
2494 EncodeUnicode(buffer,"MMSSettings",8);
2495 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2496 } else {
2497 if (mystrncasecmp("MMSSettings", h->SectionName, 8)) found = true;
2498 }
2499 if (found) {
2500 readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
2501 if (readvalue==NULL) break;
2502 if (num < GSM_BACKUP_MAX_MMSSETTINGS) {
2503 backup->MMSSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
2504 if (backup->MMSSettings[num] == NULL) return ERR_MOREMEMORY;
2505 backup->MMSSettings[num + 1] = NULL;
2506 } else {
2507 dbgprintf("Increase GSM_BACKUP_MAX_MMSSETTINGS\n");
2508 return ERR_MOREMEMORY;
2509 }
2510 backup->MMSSettings[num]->Location = num + 1;
2511 dbgprintf("reading mms settings\n");
2512 ReadWAPSettingsEntry(file_info, h->SectionName, backup->MMSSettings[num],UseUnicode);
2513 num++;
2514 }
2515 }
2516 num = 0;
2517 for (h = file_info; h != NULL; h = h->Next) {
2518 found = false;
2519 if (UseUnicode) {
2520 EncodeUnicode(buffer,"Ringtone",8);
2521 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2522 } else {
2523 if (mystrncasecmp("Ringtone", h->SectionName, 8)) found = true;
2524 }
2525 if (found) {
2526 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2527 if (readvalue==NULL) break;
2528 if (num < GSM_BACKUP_MAX_RINGTONES) {
2529 backup->Ringtone[num] = malloc(sizeof(GSM_Ringtone));
2530 if (backup->Ringtone[num] == NULL) return ERR_MOREMEMORY;
2531 backup->Ringtone[num + 1] = NULL;
2532 } else {
2533 dbgprintf("Increase GSM_BACKUP_MAX_RINGTONES\n");
2534 return ERR_MOREMEMORY;
2535 }
2536 ReadRingtoneEntry(file_info, h->SectionName, backup->Ringtone[num],UseUnicode);
2537 num++;
2538 }
2539 }
2540 num = 0;
2541 for (h = file_info; h != NULL; h = h->Next) {
2542 found = false;
2543 if (UseUnicode) {
2544 EncodeUnicode(buffer,"TODO",4);
2545 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2546 } else {
2547 if (mystrncasecmp("TODO", h->SectionName, 4)) found = true;
2548 }
2549 if (found) {
2550 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2551 if (readvalue==NULL) break;
2552 if (num < GSM_MAXCALENDARTODONOTES) {
2553 backup->ToDo[num] = malloc(sizeof(GSM_ToDoEntry));
2554 if (backup->ToDo[num] == NULL) return ERR_MOREMEMORY;
2555 backup->ToDo[num + 1] = NULL;
2556 } else {
2557 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
2558 return ERR_MOREMEMORY;
2559 }
2560 backup->ToDo[num]->Location = num + 1;
2561 ReadToDoEntry(file_info, h->SectionName, backup->ToDo[num],UseUnicode);
2562 num++;
2563 }
2564 }
2565 sprintf(buffer,"Startup");
2566 readvalue = ReadCFGText(file_info, buffer, "Text", UseUnicode);
2567 if (readvalue==NULL) {
2568 readvalue = ReadCFGText(file_info, buffer, "Width", UseUnicode);
2569 }
2570 if (readvalue!=NULL) {
2571 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
2572 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
2573 ReadStartupEntry(file_info, buffer, backup->StartupLogo,UseUnicode);
2574 }
2575 sprintf(buffer,"Operator");
2576 readvalue = ReadCFGText(file_info, buffer, "Network", UseUnicode);
2577 if (readvalue!=NULL) {
2578 backup->OperatorLogo = malloc(sizeof(GSM_Bitmap));
2579 if (backup->OperatorLogo == NULL) return ERR_MOREMEMORY;
2580 ReadOperatorEntry(file_info, buffer, backup->OperatorLogo,UseUnicode);
2581 }
2582 num = 0;
2583 for (h = file_info; h != NULL; h = h->Next) {
2584 found = false;
2585 if (UseUnicode) {
2586 EncodeUnicode(buffer,"FMStation",9);
2587 if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
2588 } else {
2589 if (mystrncasecmp("FMStation", h->SectionName, 9)) found = true;
2590 }
2591 if (found) {
2592 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2593 if (readvalue==NULL) break;
2594 if (num < GSM_BACKUP_MAX_FMSTATIONS) {
2595 backup->FMStation[num] = malloc(sizeof(GSM_FMStation));
2596 if (backup->FMStation[num] == NULL) return ERR_MOREMEMORY;
2597 backup->FMStation[num + 1] = NULL;
2598 } else {
2599 dbgprintf("Increase GSM_BACKUP_MAX_FMSTATIONS\n");
2600 return ERR_MOREMEMORY;
2601 }
2602 backup->FMStation[num]->Location = num + 1;
2603 ReadFMStationEntry(file_info, h->SectionName, backup->FMStation[num],UseUnicode);
2604 num++;
2605 }
2606 }
2607 num = 0;
2608 for (h = file_info; h != NULL; h = h->Next) {
2609 found = false;
2610 if (UseUnicode) {
2611 EncodeUnicode(buffer,"GPRSPoint",9);
2612 if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
2613 } else {
2614 if (mystrncasecmp("GPRSPoint", h->SectionName, 9)) found = true;
2615 }
2616 if (found) {
2617 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2618 if (readvalue==NULL) break;
2619 if (num < GSM_BACKUP_MAX_GPRSPOINT) {
2620 backup->GPRSPoint[num] = malloc(sizeof(GSM_GPRSAccessPoint));
2621 if (backup->GPRSPoint[num] == NULL) return ERR_MOREMEMORY;
2622 backup->GPRSPoint[num + 1] = NULL;
2623 } else {
2624 dbgprintf("Increase GSM_BACKUP_MAX_GPRSPOINT\n");
2625 return ERR_MOREMEMORY;
2626 }
2627 backup->GPRSPoint[num]->Location = num + 1;
2628 ReadGPRSPointEntry(file_info, h->SectionName, backup->GPRSPoint[num],UseUnicode);
2629 num++;
2630 }
2631 }
2632 num = 0;
2633 for (h = file_info; h != NULL; h = h->Next) {
2634 found = false;
2635 if (UseUnicode) {
2636 EncodeUnicode(buffer,"Note",4);
2637 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2638 } else {
2639 if (mystrncasecmp("Note", h->SectionName, 4)) found = true;
2640 }
2641 if (found) {
2642 readvalue = ReadCFGText(file_info, h->SectionName, "Text", UseUnicode);
2643 if (readvalue==NULL) break;
2644 if (num < GSM_BACKUP_MAX_NOTE) {
2645 backup->Note[num] = malloc(sizeof(GSM_NoteEntry));
2646 if (backup->Note[num] == NULL) return ERR_MOREMEMORY;
2647 backup->Note[num + 1] = NULL;
2648 } else {
2649 dbgprintf("Increase GSM_BACKUP_MAX_NOTE\n");
2650 return ERR_MOREMEMORY;
2651 }
2652 ReadNoteEntry(file_info, h->SectionName, backup->Note[num],UseUnicode);
2653 num++;
2654 }
2655 }
2656 if (backup->MD5Original[0]!=0) {
2657 FindBackupChecksum(FileName, UseUnicode, backup->MD5Calculated);
2658 }
2659
2660 return ERR_NONE;
2661}
2662
2663/* ---------------------- backup files for SMS ----------------------------- */
2664
2665static void ReadSMSBackupEntry(INI_Section *file_info, char *section, GSM_SMSMessage *SMS)
2666{
2667 unsigned char buffer[10000], *readvalue;
2668
2669 GSM_SetDefaultSMSData(SMS);
2670
2671 SMS->PDU = SMS_Submit;
2672 SMS->SMSC.Location = 0;
2673 sprintf(buffer,"SMSC");
2674 ReadBackupText(file_info, section, buffer, SMS->SMSC.Number, false);
2675 sprintf(buffer,"ReplySMSC");
2676 SMS->ReplyViaSameSMSC = false;
2677 readvalue = ReadCFGText(file_info, section, buffer, false);
2678 if (readvalue!=NULL) {
2679 if (mystrncasecmp(readvalue,"True",0)) SMS->ReplyViaSameSMSC = true;
2680 }
2681 sprintf(buffer,"Class");
2682 SMS->Class = -1;
2683 readvalue = ReadCFGText(file_info, section, buffer, false);
2684 if (readvalue!=NULL) SMS->Class = atoi(readvalue);
2685 sprintf(buffer,"Sent");
2686 readvalue = ReadCFGText(file_info, section, buffer, false);
2687 if (readvalue!=NULL) {
2688 ReadVCALDateTime(readvalue, &SMS->DateTime);
2689 SMS->PDU = SMS_Deliver;
2690 }
2691 sprintf(buffer,"RejectDuplicates");
2692 SMS->RejectDuplicates = false;
2693 readvalue = ReadCFGText(file_info, section, buffer, false);
2694 if (readvalue!=NULL) {
2695 if (mystrncasecmp(readvalue,"True",0)) SMS->RejectDuplicates = true;
2696 }
2697 sprintf(buffer,"ReplaceMessage");
2698 SMS->ReplaceMessage = 0;
2699 readvalue = ReadCFGText(file_info, section, buffer, false);
2700 if (readvalue!=NULL) SMS->ReplaceMessage = atoi(readvalue);
2701 sprintf(buffer,"MessageReference");
2702 SMS->MessageReference = 0;
2703 readvalue = ReadCFGText(file_info, section, buffer, false);
2704 if (readvalue!=NULL) SMS->MessageReference = atoi(readvalue);
2705 sprintf(buffer,"State");
2706 SMS->State = SMS_UnRead;
2707 readvalue = ReadCFGText(file_info, section, buffer, false);
2708 if (readvalue!=NULL) {
2709 if (mystrncasecmp(readvalue,"Read",0)) SMS->State = SMS_Read;
2710 else if (mystrncasecmp(readvalue,"Sent",0))SMS->State = SMS_Sent;
2711 else if (mystrncasecmp(readvalue,"UnSent",0))SMS->State = SMS_UnSent;
2712 }
2713 sprintf(buffer,"Number");
2714 ReadBackupText(file_info, section, buffer, SMS->Number, false);
2715 sprintf(buffer,"Name");
2716 ReadBackupText(file_info, section, buffer, SMS->Name, false);
2717 sprintf(buffer,"Length");
2718 SMS->Length = 0;
2719 readvalue = ReadCFGText(file_info, section, buffer, false);
2720 if (readvalue!=NULL) SMS->Length = atoi(readvalue);
2721 sprintf(buffer,"Coding");
2722 SMS->Coding = SMS_Coding_Default;
2723 readvalue = ReadCFGText(file_info, section, buffer, false);
2724 if (readvalue!=NULL) {
2725 if (mystrncasecmp(readvalue,"Unicode",0)) {
2726 SMS->Coding = SMS_Coding_Unicode;
2727 } else if (mystrncasecmp(readvalue,"8bit",0)) {
2728 SMS->Coding = SMS_Coding_8bit;
2729 }
2730 }
2731 ReadLinkedBackupText(file_info, section, "Text", buffer, false);
2732 DecodeHexBin (SMS->Text, buffer, strlen(buffer));
2733 SMS->Text[strlen(buffer)/2]= 0;
2734 SMS->Text[strlen(buffer)/2+1] = 0;
2735 sprintf(buffer,"Folder");
2736 readvalue = ReadCFGText(file_info, section, buffer, false);
2737 if (readvalue!=NULL) SMS->Folder = atoi(readvalue);
2738 SMS->UDH.Type = UDH_NoUDH;
2739 SMS->UDH.Length = 0;
2740 SMS->UDH.ID8bit = -1;
2741 SMS->UDH.ID16bit= -1;
2742 SMS->UDH.PartNumber= -1;
2743 SMS->UDH.AllParts= -1;
2744 sprintf(buffer,"UDH");
2745 readvalue = ReadCFGText(file_info, section, buffer, false);
2746 if (readvalue!=NULL) {
2747 DecodeHexBin (SMS->UDH.Text, readvalue, strlen(readvalue));
2748 SMS->UDH.Length = strlen(readvalue)/2;
2749 GSM_DecodeUDHHeader(&SMS->UDH);
2750 }
2751}
2752
2753static GSM_Error GSM_ReadSMSBackupTextFile(char *FileName, GSM_SMS_Backup *backup)
2754{
2755 INI_Section*file_info, *h;
2756 char *readvalue;
2757 int num;
2758
2759 backup->SMS[0] = NULL;
2760
2761 file_info = INI_ReadFile(FileName, false);
2762
2763 num = 0;
2764 for (h = file_info; h != NULL; h = h->Next) {
2765 if (mystrncasecmp("SMSBackup", h->SectionName, 9)) {
2766 readvalue = ReadCFGText(file_info, h->SectionName, "Number", false);
2767 if (readvalue==NULL) break;
2768 if (num < GSM_BACKUP_MAX_SMS) {
2769 backup->SMS[num] = malloc(sizeof(GSM_SMSMessage));
2770 if (backup->SMS[num] == NULL) return ERR_MOREMEMORY;
2771 backup->SMS[num + 1] = NULL;
2772 } else {
2773 dbgprintf("Increase GSM_BACKUP_MAX_SMS\n");
2774 return ERR_MOREMEMORY;
2775 }
2776 backup->SMS[num]->Location = num + 1;
2777 ReadSMSBackupEntry(file_info, h->SectionName, backup->SMS[num]);
2778 num++;
2779 }
2780 }
2781 return ERR_NONE;
2782}
2783
2784GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup)
2785{
2786 FILE *file;
2787
2788 backup->SMS[0] = NULL;
2789
2790 file = fopen(FileName, "rb");
2791 if (file == NULL) return(ERR_CANTOPENFILE);
2792
2793 fclose(file);
2794
2795 return GSM_ReadSMSBackupTextFile(FileName, backup);
2796}
2797
2798GSM_Error SaveSMSBackupTextFile(FILE *file, GSM_SMS_Backup *backup)
2799{
2800 int i,w,current;
2801 unsigned char buffer[10000];
2802 GSM_DateTimeDT;
2803
2804 fprintf(file,"\n# File created by Gammu (www.mwiacek.com) version %s\n",VERSION);
2805 GSM_GetCurrentDateTime (&DT);
2806 fprintf(file,"# Saved %s\n\n",OSDateTime(DT,false));
2807
2808 i=0;
2809 while (backup->SMS[i]!=NULL) {
2810 fprintf(file,"[SMSBackup%03i]\n",i);
2811 switch (backup->SMS[i]->Coding) {
2812 case SMS_Coding_Unicode:
2813 case SMS_Coding_Default:
2814 sprintf(buffer,"%s",DecodeUnicodeString(backup->SMS[i]->Text));
2815 fprintf(file,"#");
2816 current = 0;
2817 for (w=0;w<(int)(strlen(buffer));w++) {
2818 switch (buffer[w]) {
2819 case 10:
2820 fprintf(file,"\n#");
2821 current = 0;
2822 break;
2823 case 13:
2824 break;
2825 default:
2826 if (isprint(buffer[w])) {
2827 fprintf(file,"%c",buffer[w]);
2828 current ++;
2829 }
2830 if (current == 75) {
2831 fprintf(file,"\n#");
2832 current = 0;
2833 }
2834 }
2835 }
2836 fprintf(file,"\n");
2837 break;
2838 default:
2839 break;
2840 }
2841 if (backup->SMS[i]->PDU == SMS_Deliver) {
2842 SaveBackupText(file, "SMSC", backup->SMS[i]->SMSC.Number, false);
2843 if (backup->SMS[i]->ReplyViaSameSMSC) fprintf(file,"SMSCReply = true\n");
2844 fprintf(file,"Sent");
2845 SaveVCalDateTime(file,&backup->SMS[i]->DateTime, false);
2846 }
2847 fprintf(file,"State = ");
2848 switch (backup->SMS[i]->State) {
2849 case SMS_UnRead : fprintf(file,"UnRead\n");break;
2850 case SMS_Read : fprintf(file,"Read\n");break;
2851 case SMS_Sent : fprintf(file,"Sent\n");break;
2852 case SMS_UnSent : fprintf(file,"UnSent\n");break;
2853 }
2854 SaveBackupText(file, "Number", backup->SMS[i]->Number, false);
2855 SaveBackupText(file, "Name", backup->SMS[i]->Name, false);
2856 if (backup->SMS[i]->UDH.Type != UDH_NoUDH) {
2857 EncodeHexBin(buffer,backup->SMS[i]->UDH.Text,backup->SMS[i]->UDH.Length);
2858 fprintf(file,"UDH = %s\n",buffer);
2859 }
2860 switch (backup->SMS[i]->Coding) {
2861 case SMS_Coding_Unicode:
2862 case SMS_Coding_Default:
2863 EncodeHexBin(buffer,backup->SMS[i]->Text,backup->SMS[i]->Length*2);
2864 break;
2865 default:
2866 EncodeHexBin(buffer,backup->SMS[i]->Text,backup->SMS[i]->Length);
2867 break;
2868 }
2869 SaveLinkedBackupText(file, "Text", buffer, false);
2870 switch (backup->SMS[i]->Coding) {
2871 case SMS_Coding_Unicode : fprintf(file,"Coding = Unicode\n"); break;
2872 case SMS_Coding_Default : fprintf(file,"Coding = Default\n"); break;
2873 case SMS_Coding_8bit : fprintf(file,"Coding = 8bit\n"); break;
2874 }
2875 fprintf(file,"Folder = %i\n",backup->SMS[i]->Folder);
2876 fprintf(file,"Length = %i\n",backup->SMS[i]->Length);
2877 fprintf(file,"Class = %i\n",backup->SMS[i]->Class);
2878 fprintf(file,"ReplySMSC = ");
2879 if (backup->SMS[i]->ReplyViaSameSMSC) fprintf(file,"True\n"); else fprintf(file,"False\n");
2880 fprintf(file,"RejectDuplicates = ");
2881 if (backup->SMS[i]->RejectDuplicates) fprintf(file,"True\n"); else fprintf(file,"False\n");
2882 fprintf(file,"ReplaceMessage = %i\n",backup->SMS[i]->ReplaceMessage);
2883 fprintf(file,"MessageReference = %i\n",backup->SMS[i]->MessageReference);
2884 fprintf(file,"\n");
2885 i++;
2886 }
2887 return ERR_NONE;
2888}
2889
2890GSM_Error GSM_SaveSMSBackupFile(char *FileName, GSM_SMS_Backup *backup)
2891{
2892 FILE *file;
2893
2894 file = fopen(FileName, "wb");
2895 if (file == NULL) return(ERR_CANTOPENFILE);
2896
2897 SaveSMSBackupTextFile(file,backup);
2898
2899 fclose(file);
2900
2901 return ERR_NONE;
2902}
2903
2904#endif
2905
2906/* How should editor hadle tabs in this file? Add editor commands here.
2907 * vim: noexpandtab sw=8 ts=8 sts=8:
2908 */
diff --git a/gammu/emb/common/service/backup/backtext.h b/gammu/emb/common/service/backup/backtext.h
new file mode 100644
index 0000000..a95bd89
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backtext.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backtext_h
4#define __gsm_backtext_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode);
10GSM_Error SaveBackup(char *FileName, GSM_Backup *backup, bool UseUnicode);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backvcf.c b/gammu/emb/common/service/backup/backvcf.c
new file mode 100644
index 0000000..761a81b
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcf.c
@@ -0,0 +1,75 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backvcf.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveVCard(char *FileName, GSM_Backup *backup)
16{
17 int i, Length = 0;
18 unsigned char Buffer[1000];
19 FILE *file;
20
21 file = fopen(FileName, "wb");
22 if (file == NULL) return ERR_CANTOPENFILE;
23
24 i=0;
25 while (backup->PhonePhonebook[i]!=NULL) {
26 sprintf(Buffer, "%c%c",13,10);
27 fwrite(Buffer,1,2,file);
28 Length = 0;
29 GSM_EncodeVCARD(Buffer,&Length,backup->PhonePhonebook[i],true,Nokia_VCard21);
30 fwrite(Buffer,1,Length,file);
31 i++;
32 }
33
34 fclose(file);
35 return ERR_NONE;
36}
37
38GSM_Error LoadVCard(char *FileName, GSM_Backup *backup)
39{
40 GSM_File File;
41 GSM_Error error;
42 GSM_MemoryEntry Pbk;
43 int numPbk = 0, Pos;
44
45 File.Buffer = NULL;
46 error = GSM_ReadFile(FileName, &File);
47 if (error != ERR_NONE) return error;
48
49 Pos = 0;
50 while (1) {
51 error = GSM_DecodeVCARD(File.Buffer, &Pos, &Pbk, Nokia_VCard21);
52 if (error == ERR_EMPTY) break;
53 if (error != ERR_NONE) return error;
54 if (numPbk < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
55 backup->PhonePhonebook[numPbk] = malloc(sizeof(GSM_MemoryEntry));
56 if (backup->PhonePhonebook[numPbk] == NULL) return ERR_MOREMEMORY;
57 backup->PhonePhonebook[numPbk + 1] = NULL;
58 } else {
59 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
60 return ERR_MOREMEMORY;
61 }
62 memcpy(backup->PhonePhonebook[numPbk],&Pbk,sizeof(GSM_MemoryEntry));
63 backup->PhonePhonebook[numPbk]->Location = numPbk + 1;
64 backup->PhonePhonebook[numPbk]->MemoryType = MEM_ME;
65 numPbk++;
66 }
67
68 return ERR_NONE;
69}
70
71#endif
72
73/* How should editor hadle tabs in this file? Add editor commands here.
74 * vim: noexpandtab sw=8 ts=8 sts=8:
75 */
diff --git a/gammu/emb/common/service/backup/backvcf.h b/gammu/emb/common/service/backup/backvcf.h
new file mode 100644
index 0000000..8cbb6cf
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcf.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backvcf_h
4#define __gsm_backvcf_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveVCard(char *FileName, GSM_Backup *backup);
10GSM_Error LoadVCard(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backvcs.c b/gammu/emb/common/service/backup/backvcs.c
new file mode 100644
index 0000000..332e718
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcs.c
@@ -0,0 +1,106 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backvcs.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveVCalendar(char *FileName, GSM_Backup *backup)
16{
17 int i, Length = 0;
18 unsigned char Buffer[1000];
19 FILE *file;
20
21 file = fopen(FileName, "wb");
22 if (file == NULL) return ERR_CANTOPENFILE;
23
24 Length=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
25 Length+=sprintf(Buffer+Length, "VERSION:1.0%c%c",13,10);
26 fwrite(Buffer,1,Length,file);
27
28 i=0;
29 while (backup->Calendar[i]!=NULL) {
30 sprintf(Buffer, "%c%c",13,10);
31 fwrite(Buffer,1,2,file);
32 Length = 0;
33 GSM_EncodeVCALENDAR(Buffer,&Length,backup->Calendar[i],false,Nokia_VCalendar);
34 fwrite(Buffer,1,Length,file);
35 i++;
36 }
37 i=0;
38 while (backup->ToDo[i]!=NULL) {
39 sprintf(Buffer, "%c%c",13,10);
40 fwrite(Buffer,1,2,file);
41 Length = 0;
42 GSM_EncodeVTODO(Buffer,&Length,backup->ToDo[i],false,Nokia_VToDo);
43 fwrite(Buffer,1,Length,file);
44 i++;
45 }
46
47 Length=sprintf(Buffer, "%c%cEND:VCALENDAR%c%c",13,10,13,10);
48 fwrite(Buffer,1,Length,file);
49
50 fclose(file);
51 return ERR_NONE;
52}
53
54GSM_Error LoadVCalendar(char *FileName, GSM_Backup *backup)
55{
56 GSM_File File;
57 GSM_Error error;
58 GSM_CalendarEntryCalendar;
59 GSM_ToDoEntry ToDo;
60 int numCal = 0, numToDo = 0, Pos;
61
62 File.Buffer = NULL;
63 error = GSM_ReadFile(FileName, &File);
64 if (error != ERR_NONE) return error;
65
66 Pos = 0;
67 while (1) {
68 error = GSM_DecodeVCALENDAR_VTODO(File.Buffer, &Pos, &Calendar, &ToDo, Nokia_VCalendar, Nokia_VToDo);
69 if (error == ERR_EMPTY) break;
70 if (error != ERR_NONE) return error;
71 if (Calendar.EntriesNum != 0) {
72 if (numCal < GSM_MAXCALENDARTODONOTES) {
73 backup->Calendar[numCal] = malloc(sizeof(GSM_CalendarEntry));
74 if (backup->Calendar[numCal] == NULL) return ERR_MOREMEMORY;
75 backup->Calendar[numCal + 1] = NULL;
76 } else {
77 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
78 return ERR_MOREMEMORY;
79 }
80 memcpy(backup->Calendar[numCal],&Calendar,sizeof(GSM_CalendarEntry));
81 backup->Calendar[numCal]->Location = numCal + 1;
82 numCal++;
83 }
84 if (ToDo.EntriesNum != 0) {
85 if (numToDo < GSM_MAXCALENDARTODONOTES) {
86 backup->ToDo[numToDo] = malloc(sizeof(GSM_ToDoEntry));
87 if (backup->ToDo[numToDo] == NULL) return ERR_MOREMEMORY;
88 backup->ToDo[numToDo + 1] = NULL;
89 } else {
90 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
91 return ERR_MOREMEMORY;
92 }
93 memcpy(backup->ToDo[numToDo],&ToDo,sizeof(GSM_ToDoEntry));
94 backup->ToDo[numToDo]->Location = numToDo + 1;
95 numToDo++;
96 }
97 }
98
99 return ERR_NONE;
100}
101
102#endif
103
104/* How should editor hadle tabs in this file? Add editor commands here.
105 * vim: noexpandtab sw=8 ts=8 sts=8:
106 */
diff --git a/gammu/emb/common/service/backup/backvcs.h b/gammu/emb/common/service/backup/backvcs.h
new file mode 100644
index 0000000..f3331b5
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcs.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backvcs_h
4#define __gsm_backvcs_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveVCalendar(char *FileName, GSM_Backup *backup);
10GSM_Error LoadVCalendar(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/gsmback.c b/gammu/emb/common/service/backup/gsmback.c
new file mode 100644
index 0000000..91ac745
--- a/dev/null
+++ b/gammu/emb/common/service/backup/gsmback.c
@@ -0,0 +1,280 @@
1/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../../misc/cfg.h"
10#include "../gsmlogo.h"
11#include "../gsmmisc.h"
12#include "../gsmcal.h"
13#include "gsmback.h"
14#include "backtext.h"
15#include "backldif.h"
16#include "backlmb.h"
17#include "backvcs.h"
18#include "backvcf.h"
19#include "backics.h"
20
21#ifdef GSM_ENABLE_BACKUP
22
23void GSM_FreeBackup(GSM_Backup *backup)
24{
25 int i;
26
27 i=0;
28 while (backup->PhonePhonebook[i]!=NULL) {
29 free(backup->PhonePhonebook[i]);
30 backup->PhonePhonebook[i] = NULL;
31 i++;
32 }
33 i=0;
34 while (backup->SIMPhonebook[i]!=NULL) {
35 free(backup->SIMPhonebook[i]);
36 backup->SIMPhonebook[i] = NULL;
37 i++;
38 }
39 i=0;
40 while (backup->Calendar[i]!=NULL) {
41 free(backup->Calendar[i]);
42 backup->Calendar[i] = NULL;
43 i++;
44 }
45 i=0;
46 while (backup->CallerLogos[i]!=NULL) {
47 free(backup->CallerLogos[i]);
48 backup->CallerLogos[i] = NULL;
49 i++;
50 }
51 i=0;
52 while (backup->SMSC[i]!=NULL) {
53 free(backup->SMSC[i]);
54 backup->SMSC[i] = NULL;
55 i++;
56 }
57 i=0;
58 while (backup->WAPBookmark[i]!=NULL) {
59 free(backup->WAPBookmark[i]);
60 backup->WAPBookmark[i] = NULL;
61 i++;
62 }
63 i=0;
64 while (backup->WAPSettings[i]!=NULL) {
65 free(backup->WAPSettings[i]);
66 backup->WAPSettings[i] = NULL;
67 i++;
68 }
69 i=0;
70 while (backup->MMSSettings[i]!=NULL) {
71 free(backup->MMSSettings[i]);
72 backup->MMSSettings[i] = NULL;
73 i++;
74 }
75 i=0;
76 while (backup->Ringtone[i]!=NULL) {
77 free(backup->Ringtone[i]);
78 backup->Ringtone[i] = NULL;
79 i++;
80 }
81 i=0;
82 while (backup->ToDo[i]!=NULL) {
83 free(backup->ToDo[i]);
84 backup->ToDo[i] = NULL;
85 i++;
86 }
87 i=0;
88 while (backup->Profiles[i]!=NULL) {
89 free(backup->Profiles[i]);
90 backup->Profiles[i] = NULL;
91 i++;
92 }
93 i=0;
94 while (backup->FMStation[i]!=NULL) {
95 free(backup->FMStation[i]);
96 backup->FMStation[i] = NULL;
97 i++;
98 }
99 if (backup->StartupLogo!=NULL) {
100 free(backup->StartupLogo);
101 backup->StartupLogo = NULL;
102 }
103 if (backup->OperatorLogo!=NULL) {
104 free(backup->OperatorLogo);
105 backup->OperatorLogo = NULL;
106 }
107 i=0;
108 while (backup->GPRSPoint[i]!=NULL) {
109 free(backup->GPRSPoint[i]);
110 backup->GPRSPoint[i] = NULL;
111 i++;
112 }
113 i=0;
114 while (backup->Note[i]!=NULL) {
115 free(backup->Note[i]);
116 backup->Note[i] = NULL;
117 i++;
118 }
119}
120
121GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode)
122{
123 if (strstr(FileName,".lmb")) {
124 return SaveLMB(FileName,backup);
125 } else if (strstr(FileName,".vcs")) {
126 return SaveVCalendar(FileName,backup);
127 } else if (strstr(FileName,".vcf")) {
128 return SaveVCard(FileName,backup);
129 } else if (strstr(FileName,".ldif")) {
130 return SaveLDIF(FileName,backup);
131 } else if (strstr(FileName,".ics")) {
132 return SaveICS(FileName,backup);
133 } else {
134 return SaveBackup(FileName,backup, UseUnicode);
135 }
136}
137
138GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup)
139{
140 FILE *file;
141 unsigned charbuffer[300];
142
143 file = fopen(FileName, "rb");
144 if (file == NULL) return ERR_CANTOPENFILE;
145 fread(buffer, 1, 9, file); /* Read the header of the file. */
146 fclose(file);
147
148 GSM_ClearBackup(backup);
149
150 /* Attempt to identify filetype */
151 if (strstr(FileName,".vcs")) {
152 return LoadVCalendar(FileName,backup);
153 } else if (strstr(FileName,".vcf")) {
154 return LoadVCard(FileName,backup);
155 } else if (strstr(FileName,".ldif")) {
156 return LoadLDIF(FileName,backup);
157 } else if (strstr(FileName,".ics")) {
158 return LoadICS(FileName,backup);
159 } else if (memcmp(buffer, "LMB ",4)==0) {
160 return LoadLMB(FileName,backup);
161 } else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
162 return LoadBackup(FileName,backup,true);
163 } else if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
164 return LoadBackup(FileName,backup,true);
165 } else {
166 return LoadBackup(FileName,backup,false);
167 }
168}
169
170void GSM_ClearBackup(GSM_Backup *backup)
171{
172 backup->PhonePhonebook[0] = NULL;
173 backup->SIMPhonebook[0] = NULL;
174 backup->Calendar[0] = NULL;
175 backup->CallerLogos[0] = NULL;
176 backup->SMSC [0] = NULL;
177 backup->WAPBookmark[0] = NULL;
178 backup->WAPSettings[0] = NULL;
179 backup->MMSSettings[0] = NULL;
180 backup->Ringtone[0] = NULL;
181 backup->Profiles[0] = NULL;
182 backup->ToDo [0] = NULL;
183 backup->GPRSPoint[0] = NULL;
184 backup->FMStation[0] = NULL;
185 backup->Note [0] = NULL;
186 backup->StartupLogo = NULL;
187 backup->OperatorLogo = NULL;
188
189 backup->Creator [0] = 0;
190 backup->IMEI [0] = 0;
191 backup->Model [0] = 0;
192 backup->DateTimeAvailable = false;
193 backup->MD5Original[0] = 0;
194 backup->MD5Calculated[0] = 0;
195}
196
197void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info)
198{
199 info->UseUnicode= false;
200 info->IMEI = false;
201 info->Model = false;
202 info->DateTime = false;
203 info->PhonePhonebook = false;
204 info->SIMPhonebook = false;
205 info->ToDo = false;
206 info->Calendar = false;
207 info->CallerLogos = false;
208 info->SMSC = false;
209 info->WAPBookmark = false;
210 info->WAPSettings = false;
211 info->MMSSettings = false;
212 info->Ringtone = false;
213 info->StartupLogo = false;
214 info->OperatorLogo = false;
215 info->Profiles = false;
216 info->FMStation = false;
217 info->GPRSPoint = false;
218 info->Note = false;
219
220 if (strstr(FileName,".lmb")) {
221 info->PhonePhonebook = true;
222 info->SIMPhonebook = true;
223 info->CallerLogos = true;
224 info->StartupLogo = true;
225 } else if (strstr(FileName,".vcs")) {
226 info->ToDo = true;
227 info->Calendar = true;
228 } else if (strstr(FileName,".vcf")) {
229 info->PhonePhonebook= true;
230 } else if (strstr(FileName,".ics")) {
231 info->ToDo = true;
232 info->Calendar = true;
233 } else if (strstr(FileName,".ldif")) {
234 info->PhonePhonebook= true;
235 } else {
236 info->UseUnicode= true;
237 info->IMEI = true;
238 info->Model = true;
239 info->DateTime = true;
240 info->PhonePhonebook = true;
241 info->SIMPhonebook = true;
242 info->ToDo = true;
243 info->Calendar = true;
244 info->CallerLogos = true;
245 info->SMSC = true;
246 info->WAPBookmark = true;
247 info->WAPSettings = true;
248 info->MMSSettings = true;
249 info->Ringtone = true;
250 info->StartupLogo = true;
251 info->OperatorLogo = true;
252 info->Profiles = true;
253 info->FMStation = true;
254 info->GPRSPoint = true;
255 info->Note = true;
256 }
257}
258
259void GSM_GetBackupFileFeatures(char *FileName, GSM_Backup_Info *info, GSM_Backup *backup)
260{
261 GSM_GetBackupFormatFeatures(FileName, info);
262
263 if (info->PhonePhonebook && backup->PhonePhonebook[0] == NULL) info->PhonePhonebook = false;
264 if (info->SIMPhonebook && backup->SIMPhonebook[0] == NULL) info->SIMPhonebook = false;
265 if (info->Calendar && backup->Calendar[0] == NULL) info->Calendar = false;
266 if (info->ToDo && backup->ToDo[0] == NULL) info->ToDo = false;
267 if (info->WAPBookmark && backup->WAPBookmark[0] == NULL) info->WAPBookmark = false;
268 if (info->WAPSettings && backup->WAPSettings[0] == NULL) info->WAPSettings = false;
269 if (info->MMSSettings && backup->MMSSettings[0] == NULL) info->MMSSettings = false;
270 if (info->FMStation && backup->FMStation[0] == NULL) info->FMStation = false;
271 if (info->GPRSPoint && backup->GPRSPoint[0] == NULL) info->GPRSPoint = false;
272 if (info->Profiles && backup->Profiles[0] == NULL) info->Profiles = false;
273 /* .... */
274}
275
276#endif
277
278/* How should editor hadle tabs in this file? Add editor commands here.
279 * vim: noexpandtab sw=8 ts=8 sts=8:
280 */
diff --git a/gammu/emb/common/service/backup/gsmback.h b/gammu/emb/common/service/backup/gsmback.h
new file mode 100644
index 0000000..1fd99b0
--- a/dev/null
+++ b/gammu/emb/common/service/backup/gsmback.h
@@ -0,0 +1,48 @@
1/* (c) 2003-2004 by Marcin Wiacek */
2
3#ifndef __gsm_back_h
4#define __gsm_back_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9
10GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode);
11GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup);
12
13void GSM_ClearBackup (GSM_Backup *backup);
14void GSM_FreeBackup (GSM_Backup *backup);
15
16typedef struct {
17 bool UseUnicode;
18
19 bool IMEI;
20 bool Model;
21 bool DateTime;
22 bool ToDo;
23 bool PhonePhonebook;
24 bool SIMPhonebook;
25 bool Calendar;
26 bool CallerLogos;
27 bool SMSC;
28 bool WAPBookmark;
29 bool Profiles;
30 bool WAPSettings;
31 bool MMSSettings;
32 bool Ringtone;
33 bool StartupLogo;
34 bool OperatorLogo;
35 bool FMStation;
36 bool GPRSPoint;
37 bool Note;
38} GSM_Backup_Info;
39
40void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info);
41void GSM_GetBackupFileFeatures (char *FileName, GSM_Backup_Info *info, GSM_Backup *backup);
42
43#endif
44#endif
45
46/* How should editor hadle tabs in this file? Add editor commands here.
47 * vim: noexpandtab sw=8 ts=8 sts=8:
48 */
diff --git a/gammu/emb/common/service/gsmcal.c b/gammu/emb/common/service/gsmcal.c
new file mode 100644
index 0000000..950e35e
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcal.c
@@ -0,0 +1,509 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmcal.h"
6#include "gsmmisc.h"
7#include "../misc/coding/coding.h"
8
9bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note)
10{
11 bool Past = true;
12 int i;
13 GSM_DateTimeDT;
14
15 GSM_GetCurrentDateTime (&DT);
16 for (i = 0; i < note->EntriesNum; i++) {
17 switch (note->Entries[i].EntryType) {
18 case CAL_RECURRANCE:
19 Past = false;
20 break;
21 case CAL_START_DATETIME :
22 if (note->Entries[i].Date.Year > DT.Year) Past = false;
23 if (note->Entries[i].Date.Year == DT.Year &&
24 note->Entries[i].Date.Month > DT.Month) Past = false;
25 if (note->Entries[i].Date.Year == DT.Year &&
26 note->Entries[i].Date.Month == DT.Month &&
27 note->Entries[i].Date.Day > DT.Day) Past = false;
28 break;
29 default:
30 break;
31 }
32 if (!Past) break;
33 }
34 switch (note->Type) {
35 case GSM_CAL_BIRTHDAY:
36 Past = false;
37 break;
38 default:
39 break;
40 }
41 return Past;
42}
43
44void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location)
45{
46 int i;
47
48 *Text = -1;
49 *Time = -1;
50 *Alarm = -1;
51 *Phone = -1;
52 *Recurrance= -1;
53 *EndTime= -1;
54 *Location= -1;
55 for (i = 0; i < entry->EntriesNum; i++) {
56 switch (entry->Entries[i].EntryType) {
57 case CAL_START_DATETIME :
58 if (*Time == -1) *Time = i;
59 break;
60 case CAL_END_DATETIME :
61 if (*EndTime == -1) *EndTime = i;
62 break;
63 case CAL_ALARM_DATETIME :
64 case CAL_SILENT_ALARM_DATETIME:
65 if (*Alarm == -1) *Alarm = i;
66 break;
67 case CAL_RECURRANCE:
68 if (*Recurrance == -1) *Recurrance = i;
69 break;
70 case CAL_TEXT:
71 if (*Text == -1) *Text = i;
72 break;
73 case CAL_PHONE:
74 if (*Phone == -1) *Phone = i;
75 break;
76 case CAL_LOCATION:
77 if (*Location == -1) *Location = i;
78 break;
79 default:
80 break;
81 }
82 }
83}
84
85GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version)
86{
87 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location;
88 char buffer[2000];
89
90 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
91
92 if (header) {
93 *Length+=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
94 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
95 }
96 *Length+=sprintf(Buffer+(*Length), "BEGIN:VEVENT%c%c",13,10);
97
98 if (Version == Nokia_VCalendar) {
99 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
100 switch (note->Type) {
101 case GSM_CAL_REMINDER:
102 *Length+=sprintf(Buffer+(*Length), "REMINDER%c%c",13,10);
103 break;
104 case GSM_CAL_MEMO:
105 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
106 break;
107 case GSM_CAL_CALL:
108 *Length+=sprintf(Buffer+(*Length), "PHONE CALL%c%c",13,10);
109 break;
110 case GSM_CAL_BIRTHDAY:
111 *Length+=sprintf(Buffer+(*Length), "SPECIAL OCCASION%c%c",13,10);
112 break;
113 case GSM_CAL_MEETING:
114 default:
115 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
116 break;
117 }
118 if (note->Type == GSM_CAL_CALL) {
119 buffer[0] = 0;
120 buffer[1] = 0;
121 if (Phone != -1) CopyUnicodeString(buffer,note->Entries[Phone].Text);
122 if (Text != -1) {
123 if (Phone != -1) EncodeUnicode(buffer+UnicodeLength(buffer)*2," ",1);
124 CopyUnicodeString(buffer+UnicodeLength(buffer)*2,note->Entries[Text].Text);
125 }
126 SaveVCALText(Buffer, Length, buffer, "SUMMARY");
127 } else {
128 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
129 }
130 if (note->Type == GSM_CAL_MEETING && Location != -1) {
131 SaveVCALText(Buffer, Length, note->Entries[Location].Text, "LOCATION");
132 }
133
134 if (Time == -1) return ERR_UNKNOWN;
135 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
136
137 if (EndTime != -1) {
138 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DTEND");
139 }
140
141 if (Alarm != -1) {
142 if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
143 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
144 } else {
145 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
146 }
147 }
148
149 /* Birthday is known to be recurranced */
150 if (Recurrance != -1 && note->Type != GSM_CAL_BIRTHDAY) {
151 switch(note->Entries[Recurrance].Number/24) {
152 case 1 : *Length+=sprintf(Buffer+(*Length), "RRULE:D1 #0%c%c",13,10); break;
153 case 7 : *Length+=sprintf(Buffer+(*Length), "RRULE:W1 #0%c%c",13,10); break;
154 case 14 : *Length+=sprintf(Buffer+(*Length), "RRULE:W2 #0%c%c",13,10); break;
155 case 365 : *Length+=sprintf(Buffer+(*Length), "RRULE:YD1 #0%c%c",13,10); break;
156 }
157 }
158 } else if (Version == Siemens_VCalendar) {
159 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
160 switch (note->Type) {
161 case GSM_CAL_MEETING:
162 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
163 break;
164 case GSM_CAL_CALL:
165 *Length+=sprintf(Buffer+(*Length), "PHONE CALL%c%c",13,10);
166 break;
167 case GSM_CAL_BIRTHDAY:
168 *Length+=sprintf(Buffer+(*Length), "ANNIVERSARY%c%c",13,10);
169 break;
170 case GSM_CAL_MEMO:
171 default:
172 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
173 break;
174 }
175
176 if (Time == -1) return ERR_UNKNOWN;
177 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
178
179 if (Alarm != -1) {
180 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
181 }
182
183 if (Recurrance != -1) {
184 switch(note->Entries[Recurrance].Number/24) {
185 case 1 : *Length+=sprintf(Buffer+(*Length), "RRULE:D1%c%c",13,10);break;
186 case 7 : *Length+=sprintf(Buffer+(*Length), "RRULE:D7%c%c",13,10);break;
187 case 30 : *Length+=sprintf(Buffer+(*Length), "RRULE:MD1%c%c",13,10);break;
188 case 365 : *Length+=sprintf(Buffer+(*Length), "RRULE:YD1%c%c",13,10);break;
189 }
190 }
191
192 if (note->Type == GSM_CAL_CALL) {
193 buffer[0] = 0;
194 buffer[1] = 0;
195 if (Phone != -1) CopyUnicodeString(buffer,note->Entries[Phone].Text);
196 if (Text != -1) {
197 if (Phone != -1) EncodeUnicode(buffer+UnicodeLength(buffer)*2," ",1);
198 CopyUnicodeString(buffer+UnicodeLength(buffer)*2,note->Entries[Text].Text);
199 }
200 SaveVCALText(Buffer, Length, buffer, "DESCRIPTION");
201 } else {
202 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "DESCRIPTION");
203 }
204 } else if (Version == SonyEricsson_VCalendar) {
205 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
206 switch (note->Type) {
207 case GSM_CAL_MEETING:
208 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
209 break;
210 case GSM_CAL_REMINDER:
211 *Length+=sprintf(Buffer+(*Length), "DATE%c%c",13,10);
212 break;
213 case GSM_CAL_TRAVEL:
214 *Length+=sprintf(Buffer+(*Length), "TRAVEL%c%c",13,10);
215 break;
216 case GSM_CAL_VACATION:
217 *Length+=sprintf(Buffer+(*Length), "VACATION%c%c",13,10);
218 break;
219 case GSM_CAL_BIRTHDAY:
220 *Length+=sprintf(Buffer+(*Length), "ANNIVERSARY%c%c",13,10);
221 break;
222 case GSM_CAL_MEMO:
223 default:
224 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
225 break;
226 }
227
228 if (Time == -1) return ERR_UNKNOWN;
229 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
230
231 if (EndTime != -1) {
232 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DTEND");
233 }
234
235 if (Alarm != -1) {
236 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
237 }
238
239 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
240
241 if (Location != -1) {
242 SaveVCALText(Buffer, Length, note->Entries[Location].Text, "LOCATION");
243 }
244 }
245
246 *Length+=sprintf(Buffer+(*Length), "END:VEVENT%c%c",13,10);
247 if (header) *Length+=sprintf(Buffer+(*Length), "END:VCALENDAR%c%c",13,10);
248
249 return ERR_NONE;
250}
251
252void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone)
253{
254 int i;
255
256 *Text = -1;
257 *EndTime= -1;
258 *Alarm = -1;
259 *Completed= -1;
260 *Phone = -1;
261 for (i = 0; i < entry->EntriesNum; i++) {
262 switch (entry->Entries[i].EntryType) {
263 case TODO_END_DATETIME :
264 if (*EndTime == -1) *EndTime = i;
265 break;
266 case TODO_ALARM_DATETIME :
267 case TODO_SILENT_ALARM_DATETIME:
268 if (*Alarm == -1) *Alarm = i;
269 break;
270 case TODO_TEXT:
271 if (*Text == -1) *Text = i;
272 break;
273 case TODO_COMPLETED:
274 if (*Completed == -1) *Completed = i;
275 break;
276 case TODO_PHONE:
277 if (*Phone == -1) *Phone = i;
278 break;
279 default:
280 break;
281 }
282 }
283}
284
285GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version)
286{
287 int Text, Alarm, Completed, EndTime, Phone;
288
289 GSM_ToDoFindDefaultTextTimeAlarmCompleted(note, &Text, &Alarm, &Completed, &EndTime, &Phone);
290
291 if (header) {
292 *Length+=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
293 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
294 }
295
296 *Length+=sprintf(Buffer+(*Length), "BEGIN:VTODO%c%c",13,10);
297
298 if (Version == Nokia_VToDo) {
299 if (Text == -1) return ERR_UNKNOWN;
300 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
301
302 if (Completed == -1) {
303 *Length+=sprintf(Buffer+(*Length), "STATUS:NEEDS ACTION%c%c",13,10);
304 } else {
305 *Length+=sprintf(Buffer+(*Length), "STATUS:COMPLETED%c%c",13,10);
306 }
307
308 switch (note->Priority) {
309 case GSM_Priority_Low: *Length+=sprintf(Buffer+(*Length), "PRIORITY:1%c%c",13,10); break;
310 case GSM_Priority_Medium: *Length+=sprintf(Buffer+(*Length), "PRIORITY:2%c%c",13,10); break;
311 case GSM_Priority_High: *Length+=sprintf(Buffer+(*Length), "PRIORITY:3%c%c",13,10); break;
312 }
313
314 if (EndTime != -1) {
315 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DUE");
316 }
317
318 if (Alarm != -1) {
319 if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
320 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
321 } else {
322 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
323 }
324 }
325 } else if (Version == SonyEricsson_VToDo) {
326 if (Text == -1) return ERR_UNKNOWN;
327 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
328
329 if (Completed == -1) {
330 *Length+=sprintf(Buffer+(*Length), "STATUS:NEEDS ACTION%c%c",13,10);
331 } else {
332 *Length+=sprintf(Buffer+(*Length), "STATUS:COMPLETED%c%c",13,10);
333 }
334
335 switch (note->Priority) {
336 case GSM_Priority_Low: *Length+=sprintf(Buffer+(*Length), "PRIORITY:3%c%c",13,10); break;
337 case GSM_Priority_Medium: *Length+=sprintf(Buffer+(*Length), "PRIORITY:2%c%c",13,10); break;
338 case GSM_Priority_High: *Length+=sprintf(Buffer+(*Length), "PRIORITY:1%c%c",13,10); break;
339 }
340
341 if (Alarm != -1) {
342 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
343 }
344 }
345
346 *Length+=sprintf(Buffer+(*Length), "END:VTODO%c%c",13,10);
347
348 if (header) {
349 *Length+=sprintf(Buffer+(*Length), "END:VCALENDAR%c%c",13,10);
350 }
351 return ERR_NONE;
352}
353
354GSM_Error GSM_DecodeVCALENDAR_VTODO(unsigned char *Buffer, int *Pos, GSM_CalendarEntry *Calendar, GSM_ToDoEntry *ToDo, GSM_VCalendarVersion CalVer, GSM_VToDoVersion ToDoVer)
355{
356 unsigned char Line[2000],Buff[2000];
357 int Level = 0;
358
359 Calendar->EntriesNum = 0;
360 ToDo->EntriesNum = 0;
361
362 while (1) {
363 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
364 if (strlen(Line) == 0) break;
365 switch (Level) {
366 case 0:
367 if (strstr(Line,"BEGIN:VEVENT")) {
368 Calendar->Type = GSM_CAL_MEMO;
369 Level = 1;
370 }
371 if (strstr(Line,"BEGIN:VTODO")) {
372 ToDo->Priority = GSM_Priority_Low;
373 Level = 2;
374 }
375 break;
376 case 1: /* Calendar note */
377 if (strstr(Line,"END:VEVENT")) {
378 if (Calendar->EntriesNum == 0) return ERR_EMPTY;
379 return ERR_NONE;
380 }
381 if (strstr(Line,"CATEGORIES:REMINDER")) Calendar->Type = GSM_CAL_REMINDER;
382 if (strstr(Line,"CATEGORIES:DATE")) Calendar->Type = GSM_CAL_REMINDER;//SE
383 if (strstr(Line,"CATEGORIES:TRAVEL")) Calendar->Type = GSM_CAL_TRAVEL; //SE
384 if (strstr(Line,"CATEGORIES:VACATION")) Calendar->Type = GSM_CAL_VACATION;//SE
385 if (strstr(Line,"CATEGORIES:MISCELLANEOUS")) Calendar->Type = GSM_CAL_MEMO;
386 if (strstr(Line,"CATEGORIES:PHONE CALL")) Calendar->Type = GSM_CAL_CALL;
387 if (strstr(Line,"CATEGORIES:SPECIAL OCCASION")) Calendar->Type = GSM_CAL_BIRTHDAY;
388 if (strstr(Line,"CATEGORIES:ANNIVERSARY")) Calendar->Type = GSM_CAL_BIRTHDAY;
389 if (strstr(Line,"CATEGORIES:MEETING")) Calendar->Type = GSM_CAL_MEETING;
390 if (strstr(Line,"CATEGORIES:APPOINTMENT")) Calendar->Type = GSM_CAL_MEETING;
391 if (strstr(Line,"RRULE:D1")) {
392 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
393 Calendar->Entries[Calendar->EntriesNum].Number = 1*24;
394 Calendar->EntriesNum++;
395 }
396 if ((strstr(Line,"RRULE:W1")) || (strstr(Line,"RRULE:D7"))) {
397 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
398 Calendar->Entries[Calendar->EntriesNum].Number = 7*24;
399 Calendar->EntriesNum++;
400 }
401 if (strstr(Line,"RRULE:W2")) {
402 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
403 Calendar->Entries[Calendar->EntriesNum].Number = 14*24;
404 Calendar->EntriesNum++;
405 }
406 if (strstr(Line,"RRULE:MD1")) {
407 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
408 Calendar->Entries[Calendar->EntriesNum].Number = 30*24;
409 Calendar->EntriesNum++;
410 }
411 if (strstr(Line,"RRULE:YD1")) {
412 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
413 Calendar->Entries[Calendar->EntriesNum].Number = 365*24;
414 Calendar->EntriesNum++;
415 }
416 if ((ReadVCALText(Line, "SUMMARY", Buff)) || (ReadVCALText(Line, "DESCRIPTION", Buff))) {
417 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_TEXT;
418 CopyUnicodeString(Calendar->Entries[Calendar->EntriesNum].Text,Buff);
419 Calendar->EntriesNum++;
420 }
421 if (ReadVCALText(Line, "LOCATION", Buff)) {
422 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_LOCATION;
423 CopyUnicodeString(Calendar->Entries[Calendar->EntriesNum].Text,Buff);
424 Calendar->EntriesNum++;
425 }
426 if (ReadVCALText(Line, "DTSTART", Buff)) {
427 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_START_DATETIME;
428 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
429 Calendar->EntriesNum++;
430 }
431 if (ReadVCALText(Line, "DTEND", Buff)) {
432 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_END_DATETIME;
433 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
434 Calendar->EntriesNum++;
435 }
436 if (ReadVCALText(Line, "DALARM", Buff)) {
437 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
438 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
439 Calendar->EntriesNum++;
440 }
441 if (ReadVCALText(Line, "AALARM", Buff)) {
442 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_ALARM_DATETIME;
443 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
444 Calendar->EntriesNum++;
445 }
446 break;
447 case 2: /* ToDo note */
448 if (strstr(Line,"END:VTODO")) {
449 if (ToDo->EntriesNum == 0) return ERR_EMPTY;
450 return ERR_NONE;
451 }
452 if (ReadVCALText(Line, "DUE", Buff)) {
453 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_END_DATETIME;
454 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
455 ToDo->EntriesNum++;
456 }
457 if (ReadVCALText(Line, "DALARM", Buff)) {
458 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
459 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
460 ToDo->EntriesNum++;
461 }
462 if (ReadVCALText(Line, "AALARM", Buff)) {
463 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_ALARM_DATETIME;
464 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
465 ToDo->EntriesNum++;
466 }
467 if (ReadVCALText(Line, "SUMMARY", Buff)) {
468 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_TEXT;
469 CopyUnicodeString(ToDo->Entries[ToDo->EntriesNum].Text,Buff);
470 ToDo->EntriesNum++;
471 }
472 if (ReadVCALText(Line, "PRIORITY", Buff)) {
473 if (ToDoVer == SonyEricsson_VToDo) {
474 ToDo->Priority = GSM_Priority_Low;
475 if (atoi(DecodeUnicodeString(Buff))==2) ToDo->Priority = GSM_Priority_Medium;
476 if (atoi(DecodeUnicodeString(Buff))==1) ToDo->Priority = GSM_Priority_High;
477 dbgprintf("atoi is %i %s\n",atoi(DecodeUnicodeString(Buff)),DecodeUnicodeString(Buff));
478 } else if (ToDoVer == Nokia_VToDo) {
479 ToDo->Priority = GSM_Priority_Low;
480 if (atoi(DecodeUnicodeString(Buff))==2) ToDo->Priority = GSM_Priority_Medium;
481 if (atoi(DecodeUnicodeString(Buff))==3) ToDo->Priority = GSM_Priority_High;
482 }
483 }
484 if (strstr(Line,"STATUS:COMPLETED")) {
485 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_COMPLETED;
486 ToDo->Entries[ToDo->EntriesNum].Number = 1;
487 ToDo->EntriesNum++;
488 }
489 break;
490 }
491 }
492
493 if (Calendar->EntriesNum == 0 && ToDo->EntriesNum == 0) return ERR_EMPTY;
494 return ERR_NONE;
495}
496
497GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note)
498{
499 *Length+=sprintf(Buffer+(*Length), "BEGIN:VNOTE%c%c",13,10);
500 *Length+=sprintf(Buffer+(*Length), "VERSION:1.1%c%c",13,10);
501 SaveVCALText(Buffer, Length, Note->Text, "BODY");
502 *Length+=sprintf(Buffer+(*Length), "END:VNOTE%c%c",13,10);
503
504 return ERR_NONE;
505}
506
507/* How should editor hadle tabs in this file? Add editor commands here.
508 * vim: noexpandtab sw=8 ts=8 sts=8:
509 */
diff --git a/gammu/emb/common/service/gsmcal.h b/gammu/emb/common/service/gsmcal.h
new file mode 100644
index 0000000..067a4a4
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcal.h
@@ -0,0 +1,445 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* 5210 calendar IDs by Frederick Ros */
3
4#ifndef __gsm_cal_h
5#define __gsm_cal_h
6
7#include "../gsmcomon.h"
8
9/* ---------------------------- calendar ----------------------------------- */
10
11 #define GSM_CALENDAR_ENTRIES 16
12 #define MAX_CALENDAR_TEXT_LENGTH256 /* In 6310 max. 256 chars */
13
14/**
15 * Enum defines types of calendar notes
16 */
17typedef enum {
18 /**
19 * Reminder or Date
20 */
21 GSM_CAL_REMINDER=1,
22 /**
23 * Call
24 */
25 GSM_CAL_CALL,
26 /**
27 * Meeting
28 */
29 GSM_CAL_MEETING,
30 /**
31 * Birthday or Anniversary or Special Occasion
32 */
33 GSM_CAL_BIRTHDAY,
34 /**
35 * Memo or Miscellaneous
36 */
37 GSM_CAL_MEMO,
38 /**
39 * Travel
40 */
41 GSM_CAL_TRAVEL,
42 /**
43 * Vacation
44 */
45 GSM_CAL_VACATION,
46 /**
47 * Training - Athletism
48 */
49 GSM_CAL_T_ATHL,
50 /**
51 * Training - Ball Games
52 */
53 GSM_CAL_T_BALL,
54 /**
55 * Training - Cycling
56 */
57 GSM_CAL_T_CYCL,
58 /**
59 * Training - Budo
60 */
61 GSM_CAL_T_BUDO,
62 /**
63 * Training - Dance
64 */
65 GSM_CAL_T_DANC,
66 /**
67 * Training - Extreme Sports
68 */
69 GSM_CAL_T_EXTR,
70 /**
71 * Training - Football
72 */
73 GSM_CAL_T_FOOT,
74 /**
75 * Training - Golf
76 */
77 GSM_CAL_T_GOLF,
78 /**
79 * Training - Gym
80 */
81 GSM_CAL_T_GYM,
82 /**
83 * Training - Horse Race
84 */
85 GSM_CAL_T_HORS,
86 /**
87 * Training - Hockey
88 */
89 GSM_CAL_T_HOCK,
90 /**
91 * Training - Races
92 */
93 GSM_CAL_T_RACE,
94 /**
95 * Training - Rugby
96 */
97 GSM_CAL_T_RUGB,
98 /**
99 * Training - Sailing
100 */
101 GSM_CAL_T_SAIL,
102 /**
103 * Training - Street Games
104 */
105 GSM_CAL_T_STRE,
106 /**
107 * Training - Swimming
108 */
109 GSM_CAL_T_SWIM,
110 /**
111 * Training - Tennis
112 */
113 GSM_CAL_T_TENN,
114 /**
115 * Training - Travels
116 */
117 GSM_CAL_T_TRAV,
118 /**
119 * Training - Winter Games
120 */
121 GSM_CAL_T_WINT,
122 /**
123 * Alarm
124 */
125 GSM_CAL_ALARM,
126 /**
127 * Alarm repeating each day.
128 */
129 GSM_CAL_DAILY_ALARM
130} GSM_CalendarNoteType;
131
132/**
133 * One value of calendar event.
134 */
135typedef enum {
136 /**
137 * Date and time of event start.
138 */
139 CAL_START_DATETIME = 1,
140 /**
141 * Date and time of event end.
142 */
143 CAL_END_DATETIME,
144 /**
145 * Alarm date and time.
146 */
147 CAL_ALARM_DATETIME,
148 /**
149 * Date and time of silent alarm.
150 */
151 CAL_SILENT_ALARM_DATETIME,
152 /**
153 * Recurrance.
154 */
155 CAL_RECURRANCE,
156 /**
157 * Text.
158 */
159 CAL_TEXT,
160 /**
161 * Location.
162 */
163 CAL_LOCATION,
164 /**
165 * Phone number.
166 */
167 CAL_PHONE,
168 /**
169 * Whether this entry is private.
170 */
171 CAL_PRIVATE,
172 /**
173 * Related contact id.
174 */
175 CAL_CONTACTID,
176 /**
177 * Repeat each x'th day of week.
178 */
179 CAL_REPEAT_DAYOFWEEK,
180 /**
181 * Repeat each x'th day of month.
182 */
183 CAL_REPEAT_DAY,
184 /**
185 * Repeat x'th week of month.
186 */
187 CAL_REPEAT_WEEKOFMONTH,
188 /**
189 * Repeat x'th month.
190 */
191 CAL_REPEAT_MONTH,
192 /**
193 * Repeating frequency.
194 */
195 CAL_REPEAT_FREQUENCY,
196 /**
197 * Repeating start.
198 */
199 CAL_REPEAT_STARTDATE,
200 /**
201 * Repeating end.
202 */
203 CAL_REPEAT_STOPDATE
204} GSM_CalendarType;
205
206/**
207 * One value of calendar event.
208 */
209typedef struct {
210 /**
211 * Type of value.
212 */
213 GSM_CalendarTypeEntryType;
214 /**
215 * Text of value, if applicable.
216 */
217 unsigned char Text[(MAX_CALENDAR_TEXT_LENGTH + 1)*2];
218 /**
219 * Date and time of value, if applicable.
220 */
221 GSM_DateTime Date;
222 /**
223 * Number of value, if applicable.
224 */
225 unsigned int Number;
226} GSM_SubCalendarEntry;
227
228/**
229 * Calendar note values.
230 */
231typedef struct {
232 /**
233 * Type of calendar note.
234 */
235 GSM_CalendarNoteType Type;
236 /**
237 * Location in memory.
238 */
239 int Location;
240 /**
241 * Number of entries.
242 */
243 int EntriesNum;
244 /**
245 * Values of entries.
246 */
247 GSM_SubCalendarEntry Entries[GSM_CALENDAR_ENTRIES];
248} GSM_CalendarEntry;
249
250void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location);
251
252typedef enum {
253 Nokia_VCalendar = 1,
254 Siemens_VCalendar,
255 SonyEricsson_VCalendar
256} GSM_VCalendarVersion;
257
258GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version);
259
260bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note);
261
262typedef struct {
263 /**
264 * Monday = 1, Tuesday = 2,...
265 */
266 int StartDay;
267 /**
268 * 0 = no delete, 1 = after day,...
269 */
270 int AutoDelete;
271} GSM_CalendarSettings;
272
273/**
274 * Structure used for returning calendar status.
275 */
276typedef struct {
277 /**
278 * Number of used positions.
279 */
280 int Used;
281} GSM_CalendarStatus;
282
283
284/* ------------------------------ to-do ------------------------------------ */
285
286 #define GSM_TODO_ENTRIES 7
287 #define MAX_TODO_TEXT_LENGTH 50 /* Alcatel BE5 50 chars */
288
289/**
290 * Types of to do values. In parenthesis is member of @ref GSM_SubToDoEntry,
291 * where value is stored.
292 */
293typedef enum {
294 /**
295 * Due date. (Date)
296 */
297 TODO_END_DATETIME = 1,
298 /**
299 * Whether is completed. (Number)
300 */
301 TODO_COMPLETED,
302 /**
303 * When should alarm be fired (Date).
304 */
305 TODO_ALARM_DATETIME,
306 /**
307 * When should silent alarm be fired (Date).
308 */
309 TODO_SILENT_ALARM_DATETIME,
310 /**
311 * Text of to do (Text).
312 */
313 TODO_TEXT,
314 /**
315 * Whether entry is private (Number).
316 */
317 TODO_PRIVATE,
318 /**
319 * Category of entry (Number).
320 */
321 TODO_CATEGORY,
322 /**
323 * Related contact ID (Number).
324 */
325 TODO_CONTACTID,
326 /**
327 * Number to call (Text).
328 */
329 TODO_PHONE
330} GSM_ToDoType;
331
332/**
333 * Priority of to do.
334 */
335typedef enum {
336 GSM_Priority_High = 1,
337 GSM_Priority_Medium,
338 GSM_Priority_Low
339} GSM_ToDo_Priority;
340
341/**
342 * Value of to do entry.
343 */
344typedef struct {
345 /**
346 * Type of entry.
347 */
348 GSM_ToDoType EntryType;
349 /**
350 * Text of value, if appropriate, see @ref GSM_ToDoType.
351 */
352 unsigned char Text[(MAX_TODO_TEXT_LENGTH + 1)*2];
353 /**
354 * Date of value, if appropriate, see @ref GSM_ToDoType.
355 */
356 GSM_DateTime Date;
357 /**
358 * Number of value, if appropriate, see @ref GSM_ToDoType.
359 */
360 unsigned int Number;
361} GSM_SubToDoEntry;
362
363/**
364 * To do entry.
365 */
366typedef struct {
367 /**
368 * Priority of entry.
369 */
370 GSM_ToDo_Priority Priority;
371 /**
372 * Location in memory.
373 */
374 int Location;
375 /**
376 * Number of entries.
377 */
378 int EntriesNum;
379 /**
380 * Values of current entry.
381 */
382 GSM_SubToDoEntryEntries[GSM_TODO_ENTRIES];
383} GSM_ToDoEntry;
384
385void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone);
386
387typedef enum {
388 Nokia_VToDo = 1,
389 SonyEricsson_VToDo
390} GSM_VToDoVersion;
391
392GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version);
393
394/**
395 * Status of to do entries.
396 */
397typedef struct {
398 /**
399 * Number of used positions.
400 */
401 int Used;
402} GSM_ToDoStatus;
403
404/* --------------------------- note ---------------------------------------- */
405
406typedef struct {
407 int Location;
408 char Text[100];
409} GSM_NoteEntry;
410
411GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note);
412
413/* --------------------------- alarm --------------------------------------- */
414
415/**
416 * Alarm values.
417 */
418typedef struct {
419 /**
420 * Location where it is stored.
421 */
422 int Location;
423 /**
424 * Date and time of alarm.
425 */
426 GSM_DateTime DateTime;
427 /**
428 * Whether it repeats each day.
429 */
430 bool Repeating;
431 /**
432 * Text that is shown on display.
433 */
434 char Text[(MAX_CALENDAR_TEXT_LENGTH + 1) * 2];
435} GSM_Alarm;
436
437/* --------------------------- calendar & todo ----------------------------- */
438
439GSM_Error GSM_DecodeVCALENDAR_VTODO(unsigned char *Buffer, int *Pos, GSM_CalendarEntry *Calendar, GSM_ToDoEntry *ToDo, GSM_VCalendarVersion CalVer, GSM_VToDoVersion ToDoVer);
440
441#endif
442
443/* How should editor hadle tabs in this file? Add editor commands here.
444 * vim: noexpandtab sw=8 ts=8 sts=8:
445 */
diff --git a/gammu/emb/common/service/gsmcall.h b/gammu/emb/common/service/gsmcall.h
new file mode 100644
index 0000000..c5032a5
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcall.h
@@ -0,0 +1,185 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef _gsm_call_h
4#define _gsm_call_h
5
6#include "../misc/misc.h"
7
8/* ------------------ call info -------------------------------------------- */
9
10/**
11 * Enum with status of call.
12 */
13typedef enum {
14 /**
15 * Somebody calls to us
16 */
17 GSM_CALL_IncomingCall=1,
18 /**
19 * We call somewhere
20 */
21 GSM_CALL_OutgoingCall,
22 /**
23 * Call started
24 */
25 GSM_CALL_CallStart,
26 /**
27 * End of call from unknown side
28 */
29 GSM_CALL_CallEnd,
30 /**
31 * End of call from remote side
32 */
33 GSM_CALL_CallRemoteEnd,
34 /**
35 * End of call from our side
36 */
37 GSM_CALL_CallLocalEnd,
38 /**
39 * Call established. Waiting for answer or dropping
40 */
41 GSM_CALL_CallEstablished,
42 /**
43 * Call held
44 */
45 GSM_CALL_CallHeld,
46 /**
47 * Call resumed
48 */
49 GSM_CALL_CallResumed,
50 /**
51 * We switch to call
52 */
53 GSM_CALL_CallSwitched
54} GSM_CallStatus;
55
56/**
57 * Call information.
58 */
59typedef struct {
60 /**
61 * Call status.
62 */
63 GSM_CallStatus Status;
64 /**
65 * Remote phone number.
66 */
67 char PhoneNumber [(GSM_MAX_NUMBER_LENGTH+1)*2];
68 /**
69 * Call ID
70 */
71 int CallID;
72 /**
73 * Whether Call ID is available.
74 */
75 bool CallIDAvailable;
76 /**
77 * Status code.
78 */
79 int StatusCode;
80} GSM_Call;
81
82/* --------------- Data structures for the call divert -------------------- */
83
84/**
85 * Defines when diversion is active.
86 */
87typedef enum {
88 /**
89 * Divert when busy.
90 */
91 GSM_DIVERT_Busy = 0x01,
92 /**
93 * Divert when not answered.
94 */
95 GSM_DIVERT_NoAnswer,
96 /**
97 * Divert when phone off or no coverage.
98 */
99 GSM_DIVERT_OutOfReach,
100 /**
101 * Divert all calls without ringing.
102 */
103 GSM_DIVERT_AllTypes
104} GSM_Divert_DivertTypes;
105
106/**
107 * Which type of calls should be diverted.
108 */
109typedef enum {
110 /**
111 * Voice calls.
112 */
113 GSM_DIVERT_VoiceCalls = 0x01,
114 /**
115 * Fax calls.
116 */
117 GSM_DIVERT_FaxCalls,
118 /**
119 * Data calls.
120 */
121 GSM_DIVERT_DataCalls,
122 /**
123 * All calls.
124 */
125 GSM_DIVERT_AllCalls
126} GSM_Divert_CallTypes;
127
128/**
129 * Call diversion definition.
130 */
131typedef struct {
132 /**
133 * When diversion is active.
134 */
135 GSM_Divert_DivertTypes DivertType;
136 /**
137 * Type of call to divert.
138 */
139 GSM_Divert_CallTypes CallType;
140 /**
141 * Number where to divert.
142 */
143 char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
144 /**
145 * Timeout for diversion.
146 */
147 unsigned int Timeout;
148} GSM_CallDivert;
149
150/**
151 * Multiple call diversions.
152 */
153typedef struct {
154 GSM_CallDivert Request;
155 struct {
156 int EntriesNum;
157 GSM_CallDivertEntries[10];
158 } Response;
159} GSM_MultiCallDivert;
160
161/* -------------------------------- dial voice ---------------------------- */
162
163/**
164 * How to handle number when initiating voice call.
165 */
166typedef enum {
167 /**
168 * Show number.
169 */
170 GSM_CALL_ShowNumber = 1,
171 /**
172 * Hide number.
173 */
174 GSM_CALL_HideNumber,
175 /**
176 * Keep phone default settings.
177 */
178 GSM_CALL_DefaultNumberPresence
179} GSM_CallShowNumber;
180
181#endif
182
183/* How should editor hadle tabs in this file? Add editor commands here.
184 * vim: noexpandtab sw=8 ts=8 sts=8:
185 */
diff --git a/gammu/emb/common/service/gsmdata.c b/gammu/emb/common/service/gsmdata.c
new file mode 100644
index 0000000..94e9b7b
--- a/dev/null
+++ b/gammu/emb/common/service/gsmdata.c
@@ -0,0 +1,366 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmdata.h"
6#include "../misc/coding/coding.h"
7
8/* SNIFFS, specs somewhere in http://www.wapforum.org */
9void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator)
10{
11 unsigned char buffer[200];
12 int i;
13
14 strcpy(Buffer+(*Length),"\xE6\x06\"");
15 (*Length)=(*Length)+3;
16 strcpy(Buffer+(*Length),"application/vnd.wap.mms-message");
17 (*Length)=(*Length)+31;
18 Buffer[(*Length)++] = 0x00;
19
20 strcpy(Buffer+(*Length),"\xAF\x84\x8C\x82\x98");
21 (*Length)=(*Length)+5;
22
23 i = strlen(Indicator.Address);
24 while (Indicator.Address[i] != '/' && i!=0) i--;
25 strcpy(Buffer+(*Length),Indicator.Address+i+1);
26 (*Length)=(*Length)+strlen(Indicator.Address+i+1);
27 Buffer[(*Length)++] = 0x00;
28
29 strcpy(Buffer+(*Length),"\x8D\x90\x89");
30 (*Length)=(*Length)+3;
31
32 sprintf(buffer,"%s/TYPE=PLMN",Indicator.Sender);
33 Buffer[(*Length)++] = strlen(buffer);
34 Buffer[(*Length)++] = 0x80;
35 strcpy(Buffer+(*Length),buffer);
36 (*Length)=(*Length)+strlen(buffer);
37 Buffer[(*Length)++] = 0x00;
38
39 Buffer[(*Length)++] = 0x96;
40 strcpy(Buffer+(*Length),Indicator.Title);
41 (*Length)=(*Length)+strlen(Indicator.Title);
42 Buffer[(*Length)++] = 0x00;
43
44 strcpy(Buffer+(*Length),"\x8A\x80\x8E\x02\x47\xBB\x88\x05\x81\x03\x02\xA3");
45 (*Length)=(*Length)+12;
46 Buffer[(*Length)++] = 0x00;
47
48 Buffer[(*Length)++] = 0x83;
49 strcpy(Buffer+(*Length),Indicator.Address);
50 (*Length)=(*Length)+strlen(Indicator.Address);
51 Buffer[(*Length)++] = 0x00;
52}
53
54/* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
55static void AddWAPSMSParameterText(unsigned char *Buffer, int *Length, unsigned char ID, char *Text, int Len)
56{
57 int i;
58
59 Buffer[(*Length)++] = 0x87; //PARM with attributes
60 Buffer[(*Length)++] = ID;
61 Buffer[(*Length)++] = 0x11; //VALUE
62 Buffer[(*Length)++] = 0x03; //Inline string
63 for (i=0;i<Len;i++) {
64 Buffer[(*Length)++] = Text[i]; //Text
65 }
66 Buffer[(*Length)++] = 0x00; //END Inline string
67 Buffer[(*Length)++] = 0x01; //END PARMeter
68}
69
70/* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
71static void AddWAPSMSParameterInt(unsigned char *Buffer, int *Length, unsigned char ID, unsigned char Value)
72{
73 Buffer[(*Length)++] = 0x87; //PARM with attributes
74 Buffer[(*Length)++] = ID;
75 Buffer[(*Length)++] = Value;
76 Buffer[(*Length)++] = 0x01; //END PARMeter
77}
78
79/* http://forum.nokia.com : OTA MMS Settings 1.0, OTA Settings 7.0
80 * http://www.wapforum.org : Wireless Datagram Protocol
81 */
82void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS)
83{
84 int i;
85 unsigned char buffer[400];
86
87 Buffer[(*Length)++] = 0x01; //Push ID
88 Buffer[(*Length)++] = 0x06; //PDU Type (push)
89 Buffer[(*Length)++] = 0x2C; //Headers length (content type + headers)
90 strcpy(Buffer+(*Length),"\x1F\x2A");
91 (*Length)=(*Length)+2; //Value length
92 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-settings");
93 (*Length)=(*Length)+39; //MIME-Type
94 Buffer[(*Length)++] = 0x00; //end inline string
95 strcpy(Buffer+(*Length),"\x81\xEA");
96 (*Length)=(*Length)+2; //charset UTF-8 short int.
97 strcpy(Buffer+(*Length),"\x01\x01");
98 (*Length)=(*Length)+2; //version WBXML 1.1
99 Buffer[(*Length)++] = 0x6A; //charset UTF-8
100 Buffer[(*Length)++] = 0x00; //string table length
101
102 Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
103 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
104 Buffer[(*Length)++] = 0x06; //TYPE=ADDRESS
105 Buffer[(*Length)++] = 0x01; //END PARMeter
106 switch (settings->Bearer) {
107 case WAPSETTINGS_BEARER_GPRS:
108 /* Bearer */
109 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x49);
110 /* PPP_LOGINTYPE (manual login or not) */
111 if (settings->ManualLogin) {
112 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
113 } else {
114 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
115 }
116 /* PPP_AUTHTYPE*/
117 if (settings->IsNormalAuthentication) {
118 /* OTA_CSD_AUTHTYPE_PAP */
119 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
120 } else {
121 /* OTA_CSD_AUTHTYPE_CHAP */
122 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
123 }
124 /* GPRS_ACCESSPOINTNAME */
125 AddWAPSMSParameterText(Buffer, Length, 0x1C, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
126 /* PROXY */
127 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
128 /* PPP_AUTHNAME (user) */
129 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
130 /* PPP_AUTHSECRET (password) */
131 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
132 break;
133 case WAPSETTINGS_BEARER_DATA:
134 /* Bearer */
135 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x45);
136 /* CSD_DIALSTRING */
137 AddWAPSMSParameterText(Buffer, Length, 0x21, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
138 /* PROXY */
139 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
140 /* PPP_LOGINTYPE (manual login or not) */
141 if (settings->ManualLogin) {
142 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
143 } else {
144 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
145 }
146 /* PPP_AUTHTYPE*/
147 if (settings->IsNormalAuthentication) {
148 /* OTA_CSD_AUTHTYPE_PAP */
149 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
150 } else {
151 /* OTA_CSD_AUTHTYPE_CHAP */
152 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
153 }
154 /* CSD_CALLTYPE (type of call) */
155 if (settings->IsISDNCall) {
156 /* ISDN */
157 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x73);
158 } else {
159 /* analogue */
160 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x72);
161 }
162 /* CSD_CALLSPEED (speed of call) */
163 switch (settings->Speed) {
164 case WAPSETTINGS_SPEED_AUTO:
165 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6A);
166 break;
167 case WAPSETTINGS_SPEED_9600:
168 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6B);
169 break;
170 case WAPSETTINGS_SPEED_14400:
171 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6C);
172 }
173 /* PPP_AUTHNAME (user) */
174 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
175 /* PPP_AUTHSECRET (password) */
176 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
177 break;
178#ifdef DEVELOP
179 case WAPSETTINGS_BEARER_SMS:
180 /* Bearer */
181 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
182 /* PROXY */
183 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Server), UnicodeLength(settings->Server));
184 /* SMS_SMSC_ADDRESS */
185 // .....
186 break;
187 case WAPSETTINGS_BEARER_USSD:
188 /* FIXME */
189 /* Bearer */
190 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
191 /* PROXY */
192 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Service), UnicodeLength(settings->Service));
193 /* USSD_SERVICE_CODE */
194 /* FIXME */
195 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Code), UnicodeLength(settings->Code));
196#else
197 case WAPSETTINGS_BEARER_SMS:
198 case WAPSETTINGS_BEARER_USSD:
199 break;
200#endif
201 }
202 /* PORT */
203 if (settings->IsSecurity) {
204 if (settings->IsContinuous) {
205 /* Port = 9203. Continuous */
206 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x63);
207 } else {
208 /* Port = 9202. Temporary */
209 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x62);
210 }
211 } else {
212 if (settings->IsContinuous) {
213 /* Port = 9201. Continuous */
214 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x61);
215 } else {
216 /* Port = 9200. Temporary */
217 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x60);
218 }
219 }
220 Buffer[(*Length)++] = 0x01; //END PARMeter
221
222 /* URL */
223 Buffer[(*Length)++] = 0x86; //CHARACTERISTIC-LIST with attributes
224 if (MMS) {
225 Buffer[(*Length)++] = 0x7C; //TYPE = MMSURL
226 } else {
227 Buffer[(*Length)++] = 0x07; //TYPE = URL
228 }
229 Buffer[(*Length)++] = 0x11; //VALUE
230 Buffer[(*Length)++] = 0x03; //Inline string
231 sprintf(buffer,"%s",DecodeUnicodeString(settings->HomePage));
232 for (i=0;i<(int)strlen(buffer);i++) {
233 Buffer[(*Length)++] = buffer[i];//Text
234 }
235 Buffer[(*Length)++] = 0x00; //END Inline string
236 Buffer[(*Length)++] = 0x01; //END PARMeter
237
238 /* ISP_NAME (name) */
239 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
240 Buffer[(*Length)++] = 0x08; //TYPE=NAME
241 Buffer[(*Length)++] = 0x01; //END PARMeter
242 /* Settings name */
243 AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(settings->Title), UnicodeLength(settings->Title));
244 Buffer[(*Length)++] = 0x01; //END PARMeter
245 Buffer[(*Length)++] = 0x01; //END PARMeter
246}
247
248/* http://forum.nokia.com: OTA Settings 7.0 */
249void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
250{
251 unsigned charbuffer[100];
252 bool UnicodeCoding = false;
253
254 EncodeUTF8QuotedPrintable(buffer,bookmark->Title);
255 if (UnicodeLength(bookmark->Title)!=strlen(buffer)) UnicodeCoding = true;
256
257 Buffer[(*Length)++] = 0x01; //Push ID
258 Buffer[(*Length)++] = 0x06; //PDU Type (push)
259 Buffer[(*Length)++] = 0x2D; //Headers length (content type + headers)
260 strcpy(Buffer+(*Length),"\x1F\x2B");
261 (*Length)=(*Length)+2; //Value length
262 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-bookmarks");
263 (*Length)=(*Length)+40; //MIME-Type
264 Buffer[(*Length)++] = 0x00; //end inline string
265 strcpy(Buffer+(*Length),"\x81\xEA");
266 (*Length)=(*Length)+2; //charset UTF-8 short int.
267
268 /* Block from sniffs. UNKNOWN */
269 if (!UnicodeCoding) {
270 Buffer[(*Length)++] = 0x00;
271 Buffer[(*Length)++] = 0x01;
272 } else {
273 strcpy(Buffer+(*Length),"\x01\x01\x87\x68");
274 (*Length)=(*Length)+4;
275 }
276 Buffer[(*Length)++] = 0x00;
277
278 Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
279 /* URL */
280 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
281 Buffer[(*Length)++] = 0x7F; //TYPE = BOOKMARK
282 Buffer[(*Length)++] = 0x01; //END PARMeter
283 if (!UnicodeCoding) {
284 /* TITLE */
285 AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(bookmark->Title), UnicodeLength(bookmark->Title));
286 /* URL */
287 AddWAPSMSParameterText(Buffer, Length, 0x17, DecodeUnicodeString(bookmark->Address), UnicodeLength(bookmark->Address));
288 } else {
289 /* TITLE */
290 AddWAPSMSParameterText(Buffer, Length, 0x15, bookmark->Title, UnicodeLength(bookmark->Title)*2+1);
291 /* URL */
292 AddWAPSMSParameterText(Buffer, Length, 0x17, bookmark->Address, UnicodeLength(bookmark->Address)*2+1);
293 }
294 Buffer[(*Length)++] = 0x01; //END PARMeter
295 Buffer[(*Length)++] = 0x01; //END PARMeter
296}
297
298void GSM_EncodeMMSFile(GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length)
299{
300 int i;
301
302 strcpy(Buffer+(*Length),"\x8C\x80\x98\x4F");
303 (*Length)=(*Length)+4;
304
305 /* Unique MMS ID ? */
306 strcpy(Buffer+(*Length),"123456789");
307 (*Length)=(*Length)+9;
308 Buffer[(*Length)++] = 0x00;
309
310 strcpy(Buffer+(*Length),"\x8D\x90\x89");
311 (*Length)=(*Length)+3;
312
313 strcpy(Buffer+(*Length),"\x01\x81\x86\x81\x96");
314 (*Length)=(*Length)+5;
315
316 if (UnicodeLength(Info->Subject) != 0) {
317 sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Subject));
318 (*Length)=(*Length)+UnicodeLength(Info->Subject);
319 Buffer[(*Length)++] = 0x00;
320 }
321
322 for (i=0;i<Info->EntriesNum;i++) {
323 switch(Info->Entries[i].ID) {
324 case MMS_Text:
325 strcpy(Buffer+(*Length),"\x84\xA3\x01\x04\x04\x03\x83\x81\xEA");
326 (*Length)=(*Length)+9;
327
328 sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Entries[i].Buffer));
329 (*Length)=(*Length)+UnicodeLength(Info->Entries[i].Buffer);
330 break;
331 default:
332 break;
333 }
334 }
335}
336
337void GSM_ClearMultiPartMMSInfo(GSM_EncodeMultiPartMMSInfo *Info)
338{
339 Info->EntriesNum= 0;
340 Info->Subject[0]= 0x00;
341 Info->Subject[1]= 0x00;
342 Info->Source[0] = 0x00;
343 Info->Source[1] = 0x00;
344 Info->Destination[0] = 0x00;
345 Info->Destination[1] = 0x00;
346}
347
348GSM_Error GSM_EncodeURLFile(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
349{
350 *Length+=sprintf(Buffer+(*Length), "BEGIN:VBKM%c%c",13,10);
351 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
352 *Length+=sprintf(Buffer+(*Length), "TITLE:%s%c%c",DecodeUnicodeString(bookmark->Title),13,10);
353 *Length+=sprintf(Buffer+(*Length), "URL:%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
354 *Length+=sprintf(Buffer+(*Length), "BEGIN:ENV%c%c",13,10);
355 *Length+=sprintf(Buffer+(*Length), "X-IRMC-URL;QUOTED-PRINTABLE:=%c%c",13,10);
356 *Length+=sprintf(Buffer+(*Length), "[InternetShortcut] =%c%c",13,10);
357 *Length+=sprintf(Buffer+(*Length), "URL=%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
358 *Length+=sprintf(Buffer+(*Length), "END:ENV%c%c",13,10);
359 *Length+=sprintf(Buffer+(*Length), "END:VBKM%c%c",13,10);
360
361 return ERR_NONE;
362}
363
364/* How should editor hadle tabs in this file? Add editor commands here.
365 * vim: noexpandtab sw=8 ts=8 sts=8:
366 */
diff --git a/gammu/emb/common/service/gsmdata.h b/gammu/emb/common/service/gsmdata.h
new file mode 100644
index 0000000..f5f8e07
--- a/dev/null
+++ b/gammu/emb/common/service/gsmdata.h
@@ -0,0 +1,152 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#ifndef __gsm_wap_h
4#define __gsm_wap_h
5
6#include "gsmmisc.h"
7#include "../misc/misc.h"
8
9/* --------------------------- WAP or MMS settings ------------------------- */
10
11typedef enum {
12 WAPSETTINGS_SPEED_9600,
13 WAPSETTINGS_SPEED_14400,
14 WAPSETTINGS_SPEED_AUTO
15} WAPSettings_Speed;
16
17typedef enum {
18 WAPSETTINGS_BEARER_SMS = 1,
19 WAPSETTINGS_BEARER_DATA,
20 WAPSETTINGS_BEARER_USSD,
21 WAPSETTINGS_BEARER_GPRS
22} WAPSettings_Bearer;
23
24typedef struct {
25 char Title [(20+1)*2];
26 char HomePage[(100+1)*2];
27 WAPSettings_BearerBearer;
28 bool IsSecurity;
29 bool IsContinuous;
30
31 /* for data bearer */
32 bool IsISDNCall;
33 bool IsNormalAuthentication;
34
35 /* for sms bearer */
36 char Server [(21+1)*2];
37
38 /* for sms or ussd bearer */
39 char Service [(20+1)*2];
40 bool IsIP;
41
42 /* for ussd bearer */
43 char Code [(10+1)*2];
44
45 /* for data or gprs */
46 char IPAddress[(20+1)*2];
47 bool ManualLogin;
48 char DialUp [(20+1)*2];
49 char User [(50+1)*2]; /*is length OK ?*/
50 char Password[(50+1)*2]; /*is length OK ?*/
51 WAPSettings_SpeedSpeed;
52} GSM_WAPSettings;
53
54typedef struct {
55 int Location;
56 unsigned char Number;
57 GSM_WAPSettings Settings[4];
58 bool Active;
59 bool ReadOnly;
60 char Proxy [(100+1)*2];
61 int ProxyPort;
62 char Proxy2 [(100+1)*2];
63 int Proxy2Port;
64
65 WAPSettings_BearerActiveBearer;
66} GSM_MultiWAPSettings;
67
68void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS);
69
70/* -------------------------------- WAP Bookmark --------------------------- */
71
72typedef struct {
73 char Address [(255+1)*2];
74 char Title [(50+1)*2];
75 int Location;
76} GSM_WAPBookmark;
77
78 void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
79 GSM_Error GSM_EncodeURLFile (unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
80
81/* ------------------------------ MMS Indicator ---------------------------- */
82
83typedef struct {
84 unsigned char Address[500];
85 unsigned char Title[200];
86 unsigned char Sender[200];
87} GSM_MMSIndicator;
88
89void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator);
90
91/* ------------------------------ MMS file --------------------------------- */
92
93#define MAX_MULTI_MMS 20
94
95typedef enum {
96 MMS_Text = 1,
97 MMS_Bitmap_JPG
98} EncodeMultiPartMMSID;
99
100typedef struct {
101 EncodeMultiPartMMSID ID;
102
103 GSM_File File;
104 unsigned char *Buffer;
105} EncodeMultiPartMMSEntry;
106
107typedef struct {
108 /* Input values */
109 EncodeMultiPartMMSEntry Entries[MAX_MULTI_MMS];
110 int EntriesNum;
111
112 unsigned char Source[200];
113 unsigned char Destination[200];
114 unsigned char Subject[200];
115} GSM_EncodeMultiPartMMSInfo;
116
117 void GSM_EncodeMMSFile (GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length);
118 void GSM_ClearMultiPartMMSInfo(GSM_EncodeMultiPartMMSInfo *Info);
119
120/* ------------------------------------------------------------------------ */
121
122typedef struct {
123 int Location;
124 bool Active;
125 bool SyncPhonebook;
126 bool SyncCalendar;
127 char Name[(20+1)*2];
128 char PhonebookDataBase[(50+1)*2];
129 char CalendarDataBase[(50+1)*2];
130 char User[(30+1)*2];
131 char Password[(20+1)*2];
132 char Server[(128+1)*2];
133 GSM_MultiWAPSettingsConnection;
134} GSM_SyncMLSettings;
135
136/* ------------------------------------------------------------------------ */
137
138typedef struct {
139 char Name[(50+1)*2];
140 char HomePage[(200+1)*2];
141 char User[(50+1)*2];
142 char Password[(50+1)*2];
143 int Location;
144 bool Active;
145 GSM_MultiWAPSettingsConnection;
146} GSM_ChatSettings;
147
148#endif
149
150/* How should editor hadle tabs in this file? Add editor commands here.
151 * vim: noexpandtab sw=8 ts=8 sts=8:
152 */
diff --git a/gammu/emb/common/service/gsmlogo.c b/gammu/emb/common/service/gsmlogo.c
new file mode 100644
index 0000000..c992915
--- a/dev/null
+++ b/gammu/emb/common/service/gsmlogo.c
@@ -0,0 +1,1003 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <stdlib.h>
5
6#include "../misc/misc.h"
7#include "../misc/coding/coding.h"
8#include "gsmlogo.h"
9#include "gsmnet.h"
10
11void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
12{
13 *width = 0;
14 *height= 0;
15 switch (Type) {
16 case GSM_EMSSmallPicture: *width=8; *height=8; break;
17 case GSM_EMSMediumPicture: *width=16; *height=16; break;
18 case GSM_EMSBigPicture : *width=32; *height=32; break;
19 case GSM_NokiaOperatorLogo:
20 case GSM_NokiaCallerLogo: *width=72; *height=14; break;
21 case GSM_NokiaPictureImage: *width=72; *height=28; break;
22 case GSM_Nokia7110OperatorLogo:
23 case GSM_Nokia6510OperatorLogo: *width=78; *height=21; break;
24 case GSM_NokiaStartupLogo: *width=84; *height=48; break;
25 case GSM_Nokia6210StartupLogo: *width=96; *height=60; break;
26 case GSM_Nokia7110StartupLogo: *width=96; *height=65; break;
27 case GSM_EMSVariablePicture : break;
28 case GSM_AlcatelBMMIPicture : break;
29 }
30}
31
32int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
33{
34 int width, height, x;
35
36 PHONE_GetBitmapWidthHeight(Type, &width, &height);
37 if (width == 0 && height == 0) {
38 width = Width;
39 height = Height;
40 }
41 switch (Type) {
42 case GSM_Nokia6510OperatorLogo:
43 x = width * height;
44 return x/8 + (x%8 > 0);
45 case GSM_Nokia7110OperatorLogo:
46 return (width*height + 7)/8;
47 case GSM_NokiaStartupLogo:
48 case GSM_NokiaOperatorLogo:
49 case GSM_NokiaCallerLogo:
50 case GSM_NokiaPictureImage:
51 case GSM_EMSSmallPicture:
52 case GSM_EMSMediumPicture:
53 case GSM_EMSBigPicture:
54 case GSM_EMSVariablePicture:
55 return height*width/8;
56 case GSM_Nokia7110StartupLogo:
57 case GSM_Nokia6210StartupLogo:
58 return (height+7)/8*width;
59 case GSM_AlcatelBMMIPicture:
60 return width*((height+7)/8);
61 }
62 return 0;
63}
64
65static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
66{
67 int i=0, pixel;
68
69 switch (Type) {
70 case GSM_NokiaStartupLogo:
71 case GSM_Nokia6210StartupLogo:
72 case GSM_Nokia7110StartupLogo:
73 case GSM_Nokia6510OperatorLogo:
74 i=(buffer[(y/8*width) + x] & 1<<(y%8));
75 break;
76 case GSM_NokiaOperatorLogo:
77 case GSM_Nokia7110OperatorLogo:
78 case GSM_NokiaCallerLogo:
79 case GSM_EMSVariablePicture:
80 case GSM_EMSSmallPicture:
81 case GSM_EMSMediumPicture:
82 case GSM_EMSBigPicture:
83 pixel=width*y + x;
84 i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
85 break;
86 case GSM_NokiaPictureImage:
87 i=(buffer[9*y + x/8] & 1<<(7-(x%8)));
88 break;
89 case GSM_AlcatelBMMIPicture:
90 break;
91 }
92 if (i) return true; else return false;
93}
94
95static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
96{
97 int pixel;
98
99 switch (Type) {
100 case GSM_NokiaStartupLogo:
101 case GSM_Nokia6210StartupLogo:
102 case GSM_Nokia7110StartupLogo:
103 case GSM_Nokia6510OperatorLogo:
104 buffer[(y/8*width)+x] |= 1 << (y%8);
105 break;
106 case GSM_NokiaOperatorLogo:
107 case GSM_Nokia7110OperatorLogo:
108 case GSM_NokiaCallerLogo:
109 case GSM_EMSSmallPicture:
110 case GSM_EMSMediumPicture:
111 case GSM_EMSBigPicture:
112 case GSM_EMSVariablePicture:
113 pixel = width*y + x;
114 buffer[pixel/8] |= 1 << (7-(pixel%8));
115 break;
116 case GSM_NokiaPictureImage:
117 buffer[9*y + x/8] |= 1 << (7-(x%8));
118 break;
119 case GSM_AlcatelBMMIPicture:
120 pixel = height / 8;
121 if ((height % 8) != 0) pixel++;
122 buffer[pixel*x + y/8] |= 1 << (7 - (y%8));
123 break;
124 }
125}
126
127void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
128{
129 int width, height, x,y;
130
131 PHONE_GetBitmapWidthHeight(Type, &width, &height);
132 if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
133 Bitmap->BitmapHeight= height;
134 Bitmap->BitmapWidth= width;
135 }
136 switch (Type) {
137 case GSM_NokiaOperatorLogo:
138 case GSM_Nokia7110OperatorLogo:
139 case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo;break;
140 case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerGroupLogo;break;
141 case GSM_AlcatelBMMIPicture :
142 case GSM_NokiaStartupLogo:
143 case GSM_Nokia7110StartupLogo:
144 case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
145 case GSM_NokiaPictureImage:
146 case GSM_EMSVariablePicture:
147 case GSM_EMSSmallPicture:
148 case GSM_EMSMediumPicture:
149 case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage;break;
150 }
151
152 Bitmap->Location = 0;
153 Bitmap->Text[0] = 0;
154 Bitmap->Text[1] = 0;
155 Bitmap->BitmapEnabled = false;
156 Bitmap->DefaultName = false;
157 Bitmap->DefaultBitmap = false;
158 Bitmap->DefaultRingtone = false;
159 Bitmap->RingtoneID = 0;
160 Bitmap->NetworkCode[0] = 0;
161 Bitmap->Sender[0] = 0;
162 Bitmap->Sender[1] = 0;
163 Bitmap->ID = 0;
164
165 GSM_ClearBitmap(Bitmap);
166 for (x=0;x<Bitmap->BitmapWidth;x++) {
167 for (y=0;y<Bitmap->BitmapHeight;y++) {
168 if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->BitmapWidth, Bitmap->BitmapHeight)) {
169 GSM_SetPointBitmap(Bitmap,x,y);
170 }
171 }
172 }
173}
174
175void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
176{
177 memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
178}
179
180void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
181{
182 int width, height, x, y;
183 GSM_Bitmapdest;
184
185 PHONE_GetBitmapWidthHeight(Type, &width, &height);
186 if (width == 0 && height == 0) {
187 width = Bitmap->BitmapWidth;
188 height = Bitmap->BitmapHeight;
189 }
190 GSM_ResizeBitmap(&dest, Bitmap, width, height);
191 PHONE_ClearBitmap(Type, buffer, width, height);
192
193 for (x=0;x<width;x++) {
194 for (y=0;y<height;y++) {
195 if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
196 }
197 }
198}
199
200void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
201{
202 switch (Type) {
203 case GSM_CallerGroupLogo: *width=72; *height=14; break;
204 case GSM_OperatorLogo: *width=101;*height=21; break;
205 case GSM_StartupLogo: *width=96; *height=65; break;
206 case GSM_PictureImage: *width=72; *height=28; break;
207 default : break;
208 }
209}
210
211void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
212{
213 SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
214}
215
216void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
217{
218 ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
219}
220
221bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
222{
223 if (GetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x)) return true; else return false;
224}
225
226void GSM_ClearBitmap(GSM_Bitmap *bmp)
227{
228 memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp));
229}
230
231int GSM_GetBitmapSize(GSM_Bitmap *bmp)
232{
233 return bmp->BitmapWidth*bmp->BitmapHeight/8+1;
234}
235
236void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
237{
238 int x,y;
239
240 for (y=0;y<bitmap->BitmapHeight;y++) {
241 for (x=0;x<bitmap->BitmapWidth;x++) {
242 if (GSM_IsPointBitmap(bitmap,x,y)) {
243 fprintf(file,"#");
244 } else {
245 fprintf(file," ");
246 }
247 }
248 fprintf(file,"\n");
249 }
250}
251
252void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
253{
254 int x, y;
255
256 for (x=0;x<Bitmap->BitmapWidth;x++) {
257 for (y=0;y<Bitmap->BitmapHeight;y++) {
258 if (GSM_IsPointBitmap(Bitmap,x,y)) {
259 GSM_ClearPointBitmap(Bitmap, x, y);
260 } else {
261 GSM_SetPointBitmap(Bitmap, x, y);
262 }
263 }
264 }
265}
266
267void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
268{
269 int startx=0,endx=0,setx=0, starty=0,endy=0,sety=0, x, y;
270
271 if (src->BitmapWidth<=width) {
272 startx= 0;
273 endx= src->BitmapWidth;
274 setx= (width-src->BitmapWidth)/2;
275 } else {
276 startx= (src->BitmapWidth-width)/2;
277 endx= startx + width;
278 setx= 0;
279 }
280 if (src->BitmapHeight<=height) {
281 starty= 0;
282 endy= src->BitmapHeight;
283 sety= (height-src->BitmapHeight)/2;
284 } else {
285 starty= (src->BitmapHeight-height)/2;
286 endy= starty + height;
287 sety= 0;
288 }
289 dest->BitmapHeight= height;
290 dest->BitmapWidth= width;
291 GSM_ClearBitmap(dest);
292 for (x=startx;x<endx;x++) {
293 for (y=starty;y<endy;y++) {
294 if (GSM_IsPointBitmap(src,x,y))
295 GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
296 }
297 }
298}
299
300GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
301{
302 int x,y,pos,i,sizeimage,buffpos=0;
303 unsigned charbuff[1];
304 div_t division;
305 bool isfile=false;
306
307 unsigned char header[]={
308/*1'st header*/ 'B','M', /* BMP file ID */
309 0x00,0x00,0x00,0x00, /* Size of file */
310 0x00,0x00, /* Reserved for future use */
311 0x00,0x00, /* Reserved for future use */
312 62,0x00,0x00,0x00, /* Offset for image data */
313
314/*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
315 0x00,0x00,0x00,0x00, /* Width of image */
316 0x00,0x00,0x00,0x00, /* Height of image */
317 1,0x00, /* How many planes in target device */
318 1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
319 0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
320/*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
321/*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
322 /*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
323/*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
324/*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
325
326/*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
327 0x00, /* Each color in palette is end by 4'th byte */
328 102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
329 0x00}; /* Each color in palette is end by 4'th byte */
330
331 if (file!=NULL) isfile=true;
332
333 header[22]=bitmap->BitmapHeight;
334 header[18]=bitmap->BitmapWidth;
335
336 pos = 7;
337 sizeimage = 0;
338 /*lines are written from the last to the first*/
339 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
340 i=1;
341 for (x=0;x<bitmap->BitmapWidth;x++) {
342 /*new byte !*/
343 if (pos==7) {
344 if (x!=0) sizeimage++;
345 i++;
346 /*each line is written in multiply of 4 bytes*/
347 if(i==5) i=1;
348 }
349 pos--;
350 /*going to new byte*/
351 if (pos<0) pos=7;
352 }
353 /*going to new byte*/
354 pos=7;
355 sizeimage++;
356 if (i!=1) {
357 /*each line is written in multiply of 4 bytes*/
358 while (i!=5) {
359 sizeimage++;
360 i++;
361 }
362 }
363 }
364 dbgprintf("Data size in BMP file: %i\n",sizeimage);
365 division=div(sizeimage,256);
366 header[35]=division.quot;
367 header[34]=sizeimage-(division.quot*256);
368 sizeimage=sizeimage+sizeof(header);
369 dbgprintf("Size of BMP file: %i\n",sizeimage);
370 division=div(sizeimage,256);
371 header[3]=division.quot;
372 header[2]=sizeimage-(division.quot*256);
373
374 if (isfile) {
375 fwrite(header,1,sizeof(header),file);
376 } else {
377 memcpy(buffer,header,sizeof(header));
378 buffpos += sizeof(header);
379 }
380
381 pos=7;
382 /*lines are written from the last to the first*/
383 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
384 i=1;
385 for (x=0;x<bitmap->BitmapWidth;x++) {
386 /*new byte !*/
387 if (pos==7) {
388 if (x!=0) {
389 if (isfile) {
390 fwrite(buff, 1, sizeof(buff), file);
391 } else {
392 memcpy (buffer+buffpos,buff,1);
393 buffpos++;
394 }
395 }
396 i++;
397 /*each line is written in multiply of 4 bytes*/
398 if(i==5) i=1;
399 buff[0]=0;
400 }
401 if (!GSM_IsPointBitmap(bitmap,x,y)) buff[0]|=(1<<pos);
402 pos--;
403 /*going to new byte*/
404 if (pos<0) pos=7;
405 }
406 /*going to new byte*/
407 pos=7;
408 if (isfile) {
409 fwrite(buff, 1, sizeof(buff), file);
410 } else {
411 memcpy (buffer+buffpos,buff,1);
412 buffpos++;
413 }
414 if (i!=1) {
415 /*each line is written in multiply of 4 bytes*/
416 while (i!=5) {
417 buff[0]=0;
418 if (isfile) {
419 fwrite(buff, 1, sizeof(buff), file);
420 } else {
421 memcpy (buffer+buffpos,buff,1);
422 buffpos++;
423 }
424 i++;
425 }
426 }
427 }
428 return ERR_NONE;
429}
430
431static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
432{
433 GSM_Error error;
434
435 error=Bitmap2BMP(NULL,file,&bitmap->Bitmap[0]);
436 return error;
437}
438
439static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
440{
441 unsigned charbuffer[1000];
442 int x,y,pos,pos2;
443 div_t division;
444
445 pos=0;pos2=7;
446 for (y=0;y<Bitmap->BitmapHeight;y++) {
447 for (x=0;x<Bitmap->BitmapWidth;x++) {
448 if (pos2==7) buffer[pos]=0;
449 if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
450 pos2--;
451 /* going to new line */
452 if (pos2<0) {pos2=7;pos++;}
453 }
454 /* for startup logos - new line with new byte */
455 if (pos2!=7) {pos2=7;pos++;}
456 }
457
458 division=div(Bitmap->BitmapWidth,8);
459 /* For startup logos */
460 if (division.rem!=0) division.quot++;
461
462 fwrite(buffer,1,(division.quot*Bitmap->BitmapHeight),file);
463}
464
465static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
466{
467 int i;
468 char header[]={
469 'N','L','M',' ', /* Nokia Logo Manager file ID. */
470 0x01,
471 0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
472 0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
473 0x00, /* Width. */
474 0x00, /* Height. */
475 0x01};
476
477 switch (bitmap->Bitmap[0].Type) {
478 case GSM_OperatorLogo : header[5]=0x00; break;
479 case GSM_CallerGroupLogo : header[5]=0x01; break;
480 case GSM_StartupLogo : header[5]=0x02; break;
481 case GSM_PictureImage : header[5]=0x03; break;
482 default : return ERR_UNKNOWN;
483 }
484 header[6] = bitmap->Number - 1;
485 header[7] = bitmap->Bitmap[0].BitmapWidth;
486 header[8] = bitmap->Bitmap[0].BitmapHeight;
487 fwrite(header,1,sizeof(header),file);
488
489 for (i=0;i<bitmap->Number;i++) {
490 PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
491 }
492
493 return ERR_NONE;
494}
495
496static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
497{
498 char buffer[GSM_BITMAP_SIZE];
499 intx,y,current=0;
500
501 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
502 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++) {
503 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
504 buffer[current++] = '1';
505 } else {
506 buffer[current++] = '0';
507 }
508 }
509 }
510 fwrite(buffer,1,current,file);
511}
512
513static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
514{
515 char header[]={
516 'N','G','G',0x00,0x01,0x00,
517 0x00,0x00,/* Width */
518 0x00,0x00,/* Height */
519 0x01,0x00,0x01,0x00,
520 0x00, /* Unknown.Can't be checksum - for */
521 /* the same logo files can be different */
522 0x00};
523
524 header[6] = bitmap->Bitmap[0].BitmapWidth;
525 header[8] = bitmap->Bitmap[0].BitmapHeight;
526 fwrite(header,1,sizeof(header),file);
527
528 PrivSaveNGGNOL(file,bitmap);
529
530 return ERR_NONE;
531}
532
533static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
534{
535 int country,net;
536 char header[]={
537 'N','O','L',0x00,0x01,0x00,
538 0x00,0x00, /* MCC */
539 0x00,0x00, /* MNC */
540 0x00,0x00, /* Width */
541 0x00,0x00, /* Height */
542 0x01,0x00,0x01,0x00,
543 0x00, /* Unknown.Can't be checksum - for */
544 /* the same logo files can be different */
545 0x00};
546
547 if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
548
549 header[6]= country%256;
550 header[7]= country/256;
551 header[8]= net%256;
552 header[9]= net/256;
553 header[10]= bitmap->Bitmap[0].BitmapWidth;
554 header[12]= bitmap->Bitmap[0].BitmapHeight;
555 fwrite(header,1,sizeof(header),file);
556
557 PrivSaveNGGNOL(file,bitmap);
558
559 return ERR_NONE;
560}
561
562static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
563{
564 int x,y;
565
566 fprintf(file,"/* XPM */\n");
567 fprintf(file,"static char * ala_xpm[] = {\n");
568 fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].BitmapWidth,bitmap->Bitmap[0].BitmapHeight);
569 fprintf(file,"\". s c m #000000 g4 #000000 g #000000c #000000\",\n");
570 fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffffc #ffffff\",\n");
571
572 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
573 fprintf(file,"\"");
574 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++)
575 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
576 fprintf(file,".");
577 } else {
578 fprintf(file,"#");
579 }
580 fprintf(file,"\"");
581 if (y==bitmap->Bitmap[0].BitmapHeight-1) {
582 fprintf(file,"};\n");
583 } else {
584 fprintf(file,",\n");
585 }
586 }
587
588 return ERR_NONE;
589}
590
591static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
592{
593 char buffer[GSM_BITMAP_SIZE];
594 unsigned char header[]={
595 'F','O','R','M', 0x01,0xFE,/* File ID block, size 1*256+0xFE=510*/
596 'N','S','L','D', 0x01,0xF8};/* Startup Logo block, size 1*256+0xF8=504*/
597
598 fwrite(header,1,sizeof(header),file);
599 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
600 fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
601
602 return ERR_NONE;
603}
604
605static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
606{
607 unsigned char buffer[4];
608
609 buffer[0] = 0x00;
610 buffer[1] = 0x00;
611 buffer[2] = bitmap->Bitmap[0].BitmapWidth;
612 buffer[3] = bitmap->Bitmap[0].BitmapHeight;
613 fwrite(buffer,1,4,file);
614
615 PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
616
617 return ERR_NONE;
618}
619
620GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
621{
622 FILE *file;
623 GSM_Error error=ERR_NONE;
624
625 file = fopen(FileName, "wb");
626 if (file == NULL) return ERR_CANTOPENFILE;
627
628 /* Attempt to identify filetype */
629 if (strstr(FileName,".nlm")) {
630 error=savenlm(file,bitmap);
631 } else if (strstr(FileName,".ngg")) {
632 error=savengg(file,bitmap);
633 } else if (strstr(FileName,".nol")) {
634 error=savenol(file,bitmap);
635 } else if (strstr(FileName,".xpm")) {
636 error=savexpm(file,bitmap);
637 } else if (strstr(FileName,".nsl")) {
638 error=savensl(file,bitmap);
639 } else if (strstr(FileName,".wbmp")) {
640 error=savewbmp(file,bitmap);
641 } else {
642 error=savebmp(file,bitmap);
643 }
644 fclose(file);
645
646 return error;
647}
648
649GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
650{
651 bool first_white,isfile=false;
652 unsigned char buff[34];
653 int w,h,pos,y,x,i,buffpos=0;
654#ifdef DEBUG
655 int sizeimage=0;
656#endif
657
658 if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
659 if (file!=NULL) isfile=true;
660 if (isfile) {
661 fread(buff, 1, 34, file);
662 } else {
663 memcpy(buff,buffer,34);
664 }
665
666 /* height and width of image in the file */
667 h=buff[22]+256*buff[21];
668 w=buff[18]+256*buff[17];
669 dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
670
671 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->BitmapWidth, &bitmap->BitmapHeight);
672 if (h<bitmap->BitmapHeight)bitmap->BitmapHeight=h;
673 if (w<bitmap->BitmapWidth)bitmap->BitmapWidth=w;
674 dbgprintf("Height %i %i, width %i %i\n",h,bitmap->BitmapHeight,w,bitmap->BitmapWidth);
675
676 GSM_ClearBitmap(bitmap);
677
678#ifdef DEBUG
679 dbgprintf("Number of colors in BMP file: ");
680 switch (buff[28]) {
681 case 1 : dbgprintf("2 (supported)\n"); break;
682 case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
683 case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
684 case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
685 default : dbgprintf("unknown\n"); break;
686 }
687#endif
688 if (buff[28]!=1) {
689 dbgprintf("Wrong number of colors\n");
690 return ERR_FILENOTSUPPORTED;
691 }
692
693#ifdef DEBUG
694 dbgprintf("Compression in BMP file: ");
695 switch (buff[30]) {
696 case 0 :dbgprintf("no compression (supported)\n"); break;
697 case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
698 case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
699 default :dbgprintf("unknown\n"); break;
700 }
701#endif
702 if (buff[30]!=0) {
703 dbgprintf("Compression type not supported\n");
704 return ERR_FILENOTSUPPORTED;
705 }
706
707 /* read rest of header (if exists) and color palette */
708 if (isfile) {
709 pos=buff[10]-34;
710 fread(buff, 1, pos, file);
711 } else {
712 pos=buff[10]-34;
713 buffpos=buff[10];
714 memcpy (buff,buffer+34,pos);
715 }
716
717#ifdef DEBUG
718 dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
719 if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
720 if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
721 if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
722 dbgprintf("\n");
723 dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
724 if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
725 if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
726 dbgprintf("\n");
727#endif
728 first_white=true;
729 if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
730
731 pos=7;
732 /* lines are written from the last to the first */
733 for (y=h-1;y>=0;y--) { i=1;
734 for (x=0;x<w;x++) { /* new byte ! */
735 if (pos==7) { if (isfile) {
736 fread(buff, 1, 1, file);
737 } else {
738 memcpy (buff,buffer+buffpos,1);
739 buffpos++;
740 }
741#ifdef DEBUG
742 sizeimage++;
743#endif
744 i++;
745 /* each line is written in multiply of 4 bytes */
746 if(i==5) i=1;
747 }
748 /* we have top left corner ! */
749 if (x<=bitmap->BitmapWidth && y<=bitmap->BitmapHeight) { if (first_white) {
750 if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
751 } else {
752 if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
753 }
754 }
755 pos--;
756 /* going to new byte */
757 if (pos<0) pos=7;
758 }
759 /* going to new byte */
760 pos=7;
761 if (i!=1) {
762 /* each line is written in multiply of 4 bytes */
763 while (i!=5) {
764 if (isfile) {
765 fread(buff, 1, 1, file);
766 } else {
767 memcpy (buff,buffer+buffpos,1);
768 buffpos++;
769 }
770#ifdef DEBUG
771 sizeimage++;
772#endif
773 i++;
774 }
775 }
776 }
777#ifdef DEBUG
778 dbgprintf("Data size in BMP file: %i\n",sizeimage);
779#endif
780 return(ERR_NONE);
781}
782
783static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
784{
785 GSM_Error error;
786
787 error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
788 bitmap->Number = 1;
789 return error;
790}
791
792static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
793{
794 unsigned char buffer[1000];
795 int pos,pos2,x,y,h,w,i,number;
796 div_t division;
797
798 fread(buffer,1,5,file);
799
800 fread(buffer,1,1,file);
801 switch (buffer[0]) {
802 case 0x00:
803 dbgprintf("Operator logo\n");
804 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
805 break;
806 case 0x01:
807 dbgprintf("Caller logo\n");
808 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
809 break;
810 case 0x02:
811 dbgprintf("Startup logo\n");
812 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
813 break;
814 case 0x03:
815 dbgprintf("Picture Image logo\n");
816 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
817 break;
818 }
819
820 bitmap->Number = 0;
821 fread(buffer,1,4,file);
822 number = buffer[0] + 1;
823 w = buffer[1];
824 h = buffer[2];
825 for (i=0;i<number;i++) {
826 bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
827 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].BitmapWidth, &bitmap->Bitmap[i].BitmapHeight);
828 if (h < bitmap->Bitmap[i].BitmapHeight) bitmap->Bitmap[i].BitmapHeight= h;
829 if (w < bitmap->Bitmap[i].BitmapWidth) bitmap->Bitmap[i].BitmapWidth = w;
830
831 division=div(w,8);
832 /* For startup logos */
833 if (division.rem!=0) division.quot++;
834 if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return ERR_UNKNOWN;
835
836 GSM_ClearBitmap(&bitmap->Bitmap[i]);
837
838 pos=0;pos2=7;
839 for (y=0;y<h;y++) {
840 for (x=0;x<w;x++) {
841 if ((buffer[pos]&(1<<pos2))>0) {
842 if (y<bitmap->Bitmap[i].BitmapHeight && x<bitmap->Bitmap[i].BitmapWidth) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
843 }
844 pos2--;
845 /* going to new byte */
846 if (pos2<0) {pos2=7;pos++;}
847 }
848 /* for startup logos-new line means new byte */
849 if (pos2!=7) {pos2=7;pos++;}
850 }
851 bitmap->Number++;
852 if (bitmap->Number == MAX_MULTI_BITMAP) break;
853 }
854 return (ERR_NONE);
855}
856
857static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
858{
859 unsigned char buffer[2000];
860 int i,h,w,x,y;
861
862 fread(buffer, 1, 6, file);
863
864 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
865 if (nolformat) {
866 fread(buffer, 1, 4, file);
867 sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
868 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
869 }
870
871 fread(buffer, 1, 4, file);
872 w = buffer[0];
873 h = buffer[2];
874 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].BitmapWidth, &bitmap->Bitmap[0].BitmapHeight);
875 if (h < bitmap->Bitmap[0].BitmapHeight) bitmap->Bitmap[0].BitmapHeight= h;
876 if (w < bitmap->Bitmap[0].BitmapWidth) bitmap->Bitmap[0].BitmapWidth= w;
877
878 /* Unknown bytes. */
879 fread(buffer, 1, 6, file);
880
881 GSM_ClearBitmap(&bitmap->Bitmap[0]);
882
883 x=0; y=0;
884 for (i=0; i<w*h; i++) {
885 if (fread(buffer, 1, 1, file)!=1) return ERR_UNKNOWN;
886 if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
887 x++;
888 if (x==w) {x=0; y++;}
889 }
890
891#ifdef DEBUG
892 /* Some programs writes here fileinfo */
893 if (fread(buffer, 1, 1, file)==1) {
894 dbgprintf("Fileinfo: %c",buffer[0]);
895 while (fread(buffer, 1, 1, file)==1) {
896 if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
897 }
898 dbgprintf("\n");
899 }
900#endif
901 bitmap->Number = 1;
902 return(ERR_NONE);
903}
904
905static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
906{
907 unsigned char block[6],buffer[505];
908 int block_size;
909 GSM_Bitmap_TypesOldType;
910
911 while (fread(block,1,6,file)==6) {
912 block_size = block[4]*256 + block[5];
913 dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
914 if (!strncmp(block, "FORM", 4)) {
915 dbgprintf("File ID\n");
916 } else {
917 if (block_size>504) return ERR_UNKNOWN;
918 if (block_size!=0) {
919 fread(buffer,1,block_size,file);
920 /* if it's string, we end it with 0 */
921 buffer[block_size]=0;
922#ifdef DEBUG
923 if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
924 if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
925 if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
926#endif
927 if (!strncmp(block, "NSLD", 4)) {
928 bitmap->Bitmap[0].BitmapHeight = 48;
929 bitmap->Bitmap[0].BitmapWidth = 84;
930 OldType = bitmap->Bitmap[0].Type;
931 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
932 if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
933 dbgprintf("Startup logo (size %i)\n",block_size);
934 }
935 }
936 }
937 }
938 bitmap->Number = 1;
939 return(ERR_NONE);
940}
941
942static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
943{
944 unsigned char buffer[10000];
945
946 fread(buffer,1,4,file);
947 bitmap->Bitmap[0].BitmapWidth = buffer[2];
948 bitmap->Bitmap[0].BitmapHeight = buffer[3];
949 bitmap->Number = 1;
950
951 fread(buffer,1,10000,file);
952 PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
953 GSM_ReverseBitmap(&bitmap->Bitmap[0]);
954
955 return ERR_NONE;
956}
957
958GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
959{
960 FILE *file;
961 unsigned charbuffer[300];
962
963 file = fopen(FileName, "rb");
964 if (file == NULL) return ERR_CANTOPENFILE;
965
966 fread(buffer, 1, 9, file); /* Read the header of the file. */
967 rewind(file);
968
969 bitmap->Bitmap[0].DefaultBitmap = false;
970
971 /* Attempt to identify filetype */
972 if (memcmp(buffer, "BM",2)==0) {
973 return loadbmp(file,bitmap);
974 } else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
975 return loadwbmp(file,bitmap);
976 } else if (memcmp(buffer, "NLM",3)==0) {
977 return loadnlm(file,bitmap);
978 } else if (memcmp(buffer, "NOL",3)==0) {
979 return loadnolngg(file,bitmap,true);
980 } else if (memcmp(buffer, "NGG",3)==0) {
981 return loadnolngg(file,bitmap,false);
982 } else if (memcmp(buffer, "FORM",4)==0) {
983 return loadnsl(file,bitmap);
984 }
985 return ERR_UNKNOWN;
986}
987
988void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
989{
990 int Width, Height;
991
992 Buffer[(*Length)++] = 0x00;
993 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
994 Buffer[(*Length)++] = Width;
995 Buffer[(*Length)++] = Height;
996 Buffer[(*Length)++] = 0x01;
997 PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
998 (*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
999}
1000
1001/* How should editor hadle tabs in this file? Add editor commands here.
1002 * vim: noexpandtab sw=8 ts=8 sts=8:
1003 */
diff --git a/gammu/emb/common/service/gsmlogo.h b/gammu/emb/common/service/gsmlogo.h
new file mode 100644
index 0000000..b1b579d
--- a/dev/null
+++ b/gammu/emb/common/service/gsmlogo.h
@@ -0,0 +1,180 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_bitmaps_h
4#define __gsm_bitmaps_h
5
6#include "../gsmcomon.h"
7
8/**
9 * Enum to handle all possible bitmaps, which are not saved in various filesystems.
10 */
11typedef enum {
12 GSM_None = 1,
13 /**
14 * ID of static file in filesystem displayed during startup
15 */
16 GSM_ColourStartupLogo_ID,
17 /**
18 * Static mono bitmap/ID of animated mono bitmap displayed during startup
19 */
20 GSM_StartupLogo,
21 /**
22 * ID of static file in filesystem displayed instead of operator name
23 */
24 GSM_ColourOperatorLogo_ID,
25 /**
26 * Mono bitmap displayed instead of operator name
27 */
28 GSM_OperatorLogo,
29 /**
30 * ID of static file in filesystem displayed as wallpaper
31 */
32 GSM_ColourWallPaper_ID,
33 /**
34 * Mono bitmap assigned to caller group
35 */
36 GSM_CallerGroupLogo,
37 /**
38 * Text displayed during startup, which can't be removed from phone menu
39 */
40 GSM_DealerNote_Text,
41 /**
42 * Text displayed during startup
43 */
44 GSM_WelcomeNote_Text,
45 /**
46 * Image defined in Smart Messaging specification
47 */
48 GSM_PictureImage
49} GSM_Bitmap_Types;
50
51 #define GSM_BITMAP_SIZE(65+7)/8*96
52#define GSM_BITMAP_TEXT_LENGTH 128
53
54/**
55 * Structure for all possible bitmaps, which are not saved in various filesystems
56 */
57typedef struct {
58 /**
59 * For all: bitmap type
60 */
61 GSM_Bitmap_Types Type;
62 /**
63 * For caller group logos: number of group
64 * For startup logos: number of animated bitmap
65 */
66 unsigned char Location;
67 /**
68 * For dealer/welcome note text: text
69 * For caller group logo: name of group
70 * For picture images: text assigned to it
71 */
72 unsigned char Text[2 * (GSM_BITMAP_TEXT_LENGTH + 1)];
73 /**
74 * For caller group logo: true, when logo is enabled in group
75 */
76 bool BitmapEnabled;
77 /**
78 * For caller group logo: true, when group has default name
79 */
80 bool DefaultName;
81 /**
82 * For caller group logo: true, when group has default bitmap
83 */
84 bool DefaultBitmap;
85 /**
86 * For caller group logo: true, when group has default ringtone
87 */
88 bool DefaultRingtone;
89 /**
90 * For caller group logo: ringtone ID. Phone model specific
91 */
92 unsigned char RingtoneID;
93 bool FileSystemRingtone;
94 /**
95 * For mono bitmaps: body of bitmap
96 */
97 unsigned char BitmapPoints[GSM_BITMAP_SIZE];
98 /**
99 * For mono bitmaps: height specified in pixels
100 */
101 unsigned char BitmapHeight;
102 /**
103 * For mono bitmaps: width specified in pixels
104 */
105 unsigned char BitmapWidth;
106 /**
107 * For operator logos: Network operator code
108 */
109 char NetworkCode[7];
110 /**
111 * For picture images: number of sender
112 */
113 unsigned char Sender[2 * (GSM_MAX_NUMBER_LENGTH + 1)];
114 /**
115 * For colour bitmaps: ID
116 */
117 unsigned char ID;
118} GSM_Bitmap;
119
120#define MAX_MULTI_BITMAP 6
121
122/**
123 * Structure to handle more than one bitmap
124 */
125typedef struct {
126 /**
127 * Number of bitmaps
128 */
129 unsigned char Number;
130 /**
131 * All bitmaps
132 */
133 GSM_Bitmap Bitmap[MAX_MULTI_BITMAP];
134} GSM_MultiBitmap;
135
136typedef enum {
137 GSM_NokiaStartupLogo = 1,/*size 84*48*/
138 GSM_NokiaOperatorLogo, /*size 72*14*/
139 GSM_Nokia7110OperatorLogo,/*size 78*21*/
140 GSM_Nokia6510OperatorLogo,/*size 78*21*/
141 GSM_NokiaCallerLogo, /*size 72*14*/
142 GSM_NokiaPictureImage, /*size 72*28*/
143 GSM_Nokia7110StartupLogo,/*size 96*65*/
144 GSM_Nokia6210StartupLogo,/*size 96*60*/
145 GSM_AlcatelBMMIPicture,
146 GSM_EMSSmallPicture, /*size 8* 8*/
147 GSM_EMSMediumPicture, /*size 16*16*/
148 GSM_EMSBigPicture, /*size 32*32*/
149 GSM_EMSVariablePicture
150} GSM_Phone_Bitmap_Types;
151
152 bool GSM_IsPointBitmap (GSM_Bitmap *bmp, int x, int y);
153 void GSM_SetPointBitmap (GSM_Bitmap *bmp, int x, int y);
154 void GSM_ClearPointBitmap (GSM_Bitmap *bmp, int x, int y);
155 void GSM_ClearBitmap (GSM_Bitmap *bmp);
156 void GSM_ResizeBitmap (GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height);
157 void GSM_ReverseBitmap (GSM_Bitmap *Bitmap);
158 void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height);
159 int GSM_GetBitmapSize (GSM_Bitmap *bmp);
160 void GSM_PrintBitmap (FILE *file, GSM_Bitmap *bitmap);
161
162 GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap);
163 GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap);
164
165GSM_Error BMP2Bitmap (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
166GSM_Error Bitmap2BMP (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
167
168 void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height);
169 int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int width, int height);
170 void PHONE_ClearBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height);
171 void PHONE_DecodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
172 void PHONE_EncodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
173
174 void NOKIA_CopyBitmap (GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length);
175
176#endif
177
178/* How should editor hadle tabs in this file? Add editor commands here.
179 * vim: noexpandtab sw=8 ts=8 sts=8:
180 */
diff --git a/gammu/emb/common/service/gsmmisc.c b/gammu/emb/common/service/gsmmisc.c
new file mode 100644
index 0000000..6959a22
--- a/dev/null
+++ b/gammu/emb/common/service/gsmmisc.c
@@ -0,0 +1,262 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <stdlib.h>
5#include <sys/stat.h>
6#ifdef WIN32
7# include <io.h>
8# include <fcntl.h>
9#endif
10
11#include "../misc/coding/coding.h"
12#include "../gsmcomon.h"
13#include "gsmmisc.h"
14
15struct keys_table_position {
16 char whatchar;
17 int whatcode;
18};
19
20static struct keys_table_position Keys[] = {
21 {'m',GSM_KEY_MENU}, {'M',GSM_KEY_MENU},
22 {'n',GSM_KEY_NAMES}, {'N',GSM_KEY_NAMES},
23 {'p',GSM_KEY_POWER}, {'P',GSM_KEY_POWER},
24 {'u',GSM_KEY_UP}, {'U',GSM_KEY_UP},
25 {'d',GSM_KEY_DOWN}, {'D',GSM_KEY_DOWN},
26 {'+',GSM_KEY_INCREASEVOLUME},{'-',GSM_KEY_DECREASEVOLUME},
27 {'1',GSM_KEY_1}, {'2',GSM_KEY_2},{'3',GSM_KEY_3},
28 {'4',GSM_KEY_4}, {'5',GSM_KEY_5},{'6',GSM_KEY_6},
29 {'7',GSM_KEY_7}, {'8',GSM_KEY_8},{'9',GSM_KEY_9},
30 {'*',GSM_KEY_ASTERISK}, {'0',GSM_KEY_0},{'#',GSM_KEY_HASH},
31 {'g',GSM_KEY_GREEN}, {'G',GSM_KEY_GREEN},
32 {'r',GSM_KEY_RED}, {'R',GSM_KEY_RED},
33 {' ',0}
34};
35
36GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length)
37{
38 int i,j;
39 unsigned char key;
40
41 for (i=0;i<(int)(strlen(text));i++) {
42 key = text[i];
43 KeyCode[i] = GSM_KEY_NONE;
44 j = 0;
45 while (Keys[j].whatchar!=' ') {
46 if (Keys[j].whatchar==key) {
47 KeyCode[i]=Keys[j].whatcode;
48 break;
49 }
50 j++;
51 }
52 if (KeyCode[i] == GSM_KEY_NONE) {
53 *Length = i;
54 return ERR_NOTSUPPORTED;
55 }
56 }
57 *Length = i;
58 return ERR_NONE;
59}
60
61GSM_Error GSM_ReadFile(char *FileName, GSM_File *File)
62{
63 int i = 1000;
64 FILE *file;
65 struct statfileinfo;
66
67 if (FileName[0] == 0x00) return ERR_UNKNOWN;
68 file = fopen(FileName,"rb");
69 if (file == NULL) return ERR_CANTOPENFILE;
70
71 free(File->Buffer);
72 File->Buffer = NULL;
73 File->Used = 0;
74 while (i == 1000) {
75 File->Buffer = realloc(File->Buffer,File->Used + 1000);
76 i = fread(File->Buffer+File->Used,1,1000,file);
77 File->Used = File->Used + i;
78 }
79 File->Buffer = realloc(File->Buffer,File->Used);
80 fclose(file);
81
82 File->ModifiedEmpty = true;
83 if (stat(FileName,&fileinfo) == 0) {
84 File->ModifiedEmpty = false;
85 dbgprintf("File info read correctly\n");
86 //st_mtime is time of last modification of file
87 Fill_GSM_DateTime(&File->Modified, fileinfo.st_mtime);
88 File->Modified.Year = File->Modified.Year + 1900;
89 dbgprintf("FileTime: %02i-%02i-%04i %02i:%02i:%02i\n",
90 File->Modified.Day,File->Modified.Month,File->Modified.Year,
91 File->Modified.Hour,File->Modified.Minute,File->Modified.Second);
92 }
93
94 return ERR_NONE;
95}
96
97static void GSM_JADFindLine(GSM_File File, char *Name, char *Value)
98{
99 unsigned char Line[2000];
100 int Pos = 0;
101
102 Value[0] = 0;
103
104 while (1) {
105 MyGetLine(File.Buffer, &Pos, Line, File.Used);
106 if (strlen(Line) == 0) break;
107 if (!strncmp(Line,Name,strlen(Name))) {
108 Pos = strlen(Name);
109 while (Line[Pos] == 0x20) Pos++;
110 strcpy(Value,Line+Pos);
111 return;
112 }
113 }
114}
115
116GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size)
117{
118 char Size2[200];
119
120 GSM_JADFindLine(File, "MIDlet-Vendor:", Vendor);
121 if (Vendor[0] == 0x00) return ERR_FILENOTSUPPORTED;
122 dbgprintf("Vendor: \"%s\"\n",Vendor);
123
124 GSM_JADFindLine(File, "MIDlet-Name:", Name);
125 if (Name[0] == 0x00) return ERR_FILENOTSUPPORTED;
126 dbgprintf("Name: \"%s\"\n",Name);
127
128 GSM_JADFindLine(File, "MIDlet-Jar-URL:", JAR);
129 if (JAR[0] == 0x00) return ERR_FILENOTSUPPORTED;
130 dbgprintf("JAR file URL: \"%s\"\n",JAR);
131
132 GSM_JADFindLine(File, "MIDlet-Jar-Size:", Size2);
133 *Size = -1;
134 if (Size2[0] == 0x00) return ERR_FILENOTSUPPORTED;
135 dbgprintf("JAR size: \"%s\"\n",Size2);
136 (*Size) = atoi(Size2);
137
138 GSM_JADFindLine(File, "MIDlet-Version:", Version);
139 dbgprintf("Version: \"%s\"\n",Version);
140
141 return ERR_NONE;
142}
143
144void GSM_IdentifyFileFormat(GSM_File *File)
145{
146 File->Type = GSM_File_Other;
147 if (File->Used > 2) {
148 if (memcmp(File->Buffer, "BM",2)==0) {
149 File->Type = GSM_File_Image_BMP;
150 } else if (memcmp(File->Buffer, "GIF",3)==0) {
151 File->Type = GSM_File_Image_GIF;
152 } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x00) {
153 File->Type = GSM_File_Image_WBMP;
154 } else if (memcmp(File->Buffer+1, "PNG",3)==0) {
155 File->Type = GSM_File_Image_PNG;
156 } else if (File->Buffer[0] == 0xFF && File->Buffer[1] == 0xD8) {
157 File->Type = GSM_File_Image_JPG;
158 } else if (memcmp(File->Buffer, "MThd",4)==0) {
159 File->Type = GSM_File_Sound_MIDI;
160 } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x02) {
161 File->Type = GSM_File_Sound_NRT;
162 }
163 }
164}
165
166void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start)
167{
168 if (Start != NULL) {
169 *Length+=sprintf(Buffer+(*Length), "%s:",Start);
170 }
171 *Length+=sprintf(Buffer+(*Length), "%04d%02d%02dT%02d%02d%02d%c%c",
172 Date->Year, Date->Month, Date->Day,
173 Date->Hour, Date->Minute, Date->Second,13,10);
174}
175
176void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt)
177{
178 char year[5]="", month[3]="", day[3]="", hour[3]="", minute[3]="", second[3]="";
179
180 memset(dt,0,sizeof(dt));
181
182 strncpy(year, Buffer, 4);
183 strncpy(month, Buffer+4, 2);
184 strncpy(day, Buffer+6, 2);
185 strncpy(hour, Buffer+9,2);
186 strncpy(minute, Buffer+11,2);
187 strncpy(second, Buffer+13,2);
188
189 /* FIXME: Should check ranges... */
190 dt->Year= atoi(year);
191 dt->Month= atoi(month);
192 dt->Day = atoi(day);
193 dt->Hour= atoi(hour);
194 dt->Minute= atoi(minute);
195 dt->Second= atoi(second);
196 /* FIXME */
197 dt->Timezone= 0;
198}
199
200void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start)
201{
202 char buffer[1000];
203
204 if (UnicodeLength(Text) != 0) {
205 EncodeUTF8QuotedPrintable(buffer,Text);
206 if (UnicodeLength(Text)==strlen(buffer)) {
207 *Length+=sprintf(Buffer+(*Length), "%s:%s%c%c",Start,DecodeUnicodeString(Text),13,10);
208 } else {
209 *Length+=sprintf(Buffer+(*Length), "%s;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%s%c%c",Start,buffer,13,10);
210 }
211 }
212}
213
214bool ReadVCALText(char *Buffer, char *Start, char *Value)
215{
216 unsigned char buff[200];
217
218 Value[0] = 0x00;
219 Value[1] = 0x00;
220
221 strcpy(buff,Start);
222 strcat(buff,":");
223 if (!strncmp(Buffer,buff,strlen(buff))) {
224 EncodeUnicode(Value,Buffer+strlen(Start)+1,strlen(Buffer)-(strlen(Start)+1));
225 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
226 return true;
227 }
228 /* SE T68i */
229 strcpy(buff,Start);
230 strcat(buff,";ENCODING=QUOTED-PRINTABLE:");
231 if (!strncmp(Buffer,buff,strlen(buff))) {
232 DecodeUTF8QuotedPrintable(Value,Buffer+strlen(Start)+27,strlen(Buffer)-(strlen(Start)+27));
233 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
234 return true;
235 }
236 strcpy(buff,Start);
237 strcat(buff,";CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:");
238 if (!strncmp(Buffer,buff,strlen(buff))) {
239 DecodeUTF8QuotedPrintable(Value,Buffer+strlen(Start)+41,strlen(Buffer)-(strlen(Start)+41));
240 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
241 return true;
242 }
243 strcpy(buff,Start);
244 strcat(buff,";CHARSET=UTF-8:");
245 if (!strncmp(Buffer,buff,strlen(buff))) {
246 DecodeUTF8(Value,Buffer+strlen(Start)+15,strlen(Buffer)-(strlen(Start)+15));
247 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
248 return true;
249 }
250 strcpy(buff,Start);
251 strcat(buff,";CHARSET=UTF-7:");
252 if (!strncmp(Buffer,buff,strlen(buff))) {
253 DecodeUTF7(Value,Buffer+strlen(Start)+15,strlen(Buffer)-(strlen(Start)+15));
254 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
255 return true;
256 }
257 return false;
258}
259
260/* How should editor hadle tabs in this file? Add editor commands here.
261 * vim: noexpandtab sw=8 ts=8 sts=8:
262 */
diff --git a/gammu/emb/common/service/gsmmisc.h b/gammu/emb/common/service/gsmmisc.h
new file mode 100644
index 0000000..37501ad
--- a/dev/null
+++ b/gammu/emb/common/service/gsmmisc.h
@@ -0,0 +1,316 @@
1/* (c) 2001-2004 by Marcin Wiacek, Walek and Michal Cihar */
2
3#ifndef __gsm_misc_h
4#define __gsm_misc_h
5
6#include "../gsmcomon.h"
7
8/**
9 * Enum defines ID for various phone and SIM memories.
10 * Phone modules can translate them to values specific for concrete models
11 * Two letter codes (excluding VM) are from GSM 07.07
12 */
13typedef enum {
14 /**
15 * Internal memory of the mobile equipment
16 */
17 MEM_ME=1,
18 /**
19 * SIM card memory
20 */
21 MEM_SM,
22 /**
23 * Own numbers
24 */
25 MEM_ON,
26 /**
27 * Dialled calls
28 */
29 MEM_DC,
30 /**
31 * Received calls
32 */
33 MEM_RC,
34 /**
35 * Missed calls
36 */
37 MEM_MC,
38 /**
39 * Combined ME and SIM phonebook
40 */
41 MEM_MT,
42 /**
43 * Fixed dial
44 */
45 MEM_FD,
46
47 /**
48 * Voice mailbox
49 */
50 MEM_VM
51} GSM_MemoryType;
52
53/* --------------------------- resetting phone settings ------------------- */
54
55typedef enum {
56 GSM_RESET_PHONESETTINGS = 1,
57 GSM_RESET_USERINTERFACE,
58 GSM_RESET_USERINTERFACE_PHONESETTINGS,
59 GSM_RESET_DEVICE,
60 GSM_RESET_FULLFACTORY
61} GSM_ResetSettingsType;
62
63/* --------------------------- security codes ------------------------------ */
64
65/**
66 * Definition of security codes.
67 */
68typedef enum {
69 /**
70 * Security code.
71 */
72 SEC_SecurityCode = 0x01,
73 /**
74 * PIN.
75 */
76 SEC_Pin,
77 /**
78 * PIN 2.
79 */
80 SEC_Pin2,
81 /**
82 * PUK.
83 */
84 SEC_Puk,
85 /**
86 * PUK 2.
87 */
88 SEC_Puk2,
89 /**
90 * Code not needed.
91 */
92 SEC_None
93} GSM_SecurityCodeType;
94
95 #define GSM_SECURITY_CODE_LEN15
96
97/**
98 * Security code definition.
99 */
100typedef struct {
101 /**
102 * Actual code.
103 */
104 char Code[GSM_SECURITY_CODE_LEN+1];
105 /**
106 * Type of the code.
107 */
108 GSM_SecurityCodeType Type;
109} GSM_SecurityCode;
110
111/* ---------------------------- keyboard ----------------------------------- */
112
113typedef enum {
114 GSM_KEY_NONE = 0x00,
115 GSM_KEY_1 = 0x01,
116 GSM_KEY_2,
117 GSM_KEY_3,
118 GSM_KEY_4,
119 GSM_KEY_5,
120 GSM_KEY_6,
121 GSM_KEY_7,
122 GSM_KEY_8,
123 GSM_KEY_9,
124 GSM_KEY_0,
125 /**
126 * #
127 */
128 GSM_KEY_HASH,
129 /**
130 * *
131 */
132 GSM_KEY_ASTERISK,
133 GSM_KEY_POWER,
134 /**
135 * in some phone ie. N5110 sometimes works identical to POWER
136 */
137 GSM_KEY_GREEN,
138 /**
139 * (c) key in some phone: ie. N5110
140 */
141 GSM_KEY_RED,
142 /**
143 * doesn't available in some phones as separate button: ie. N5110
144 */
145 GSM_KEY_INCREASEVOLUME,
146 /**
147 * doesn't available in some phones as separate button: ie. N5110
148 */
149 GSM_KEY_DECREASEVOLUME,
150 GSM_KEY_UP = 0x17,
151 GSM_KEY_DOWN,
152 GSM_KEY_MENU,
153 /**
154 * doesn't available in some phone: ie. N5110
155 */
156 GSM_KEY_NAMES
157} GSM_KeyCode;
158
159GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length);
160
161/* ------------------------------- display features ------------------------ */
162
163typedef enum {
164 GSM_CallActive = 1,
165 /**
166 * blinking envelope
167 */
168 GSM_SMSMemoryFull,
169 GSM_FaxCall,
170 GSM_UnreadSMS,
171 GSM_DataCall,
172 GSM_VoiceCall,
173 GSM_KeypadLocked
174} GSM_DisplayFeature;
175
176typedef struct {
177 int Number;
178 GSM_DisplayFeature Feature[7];
179} GSM_DisplayFeatures;
180
181/* ----------------------------- power source ------------------------------ */
182
183typedef enum {
184 GSM_BatteryPowered = 1,
185 GSM_BatteryConnected,
186 GSM_BatteryNotConnected,
187 GSM_PowerFault
188} GSM_ChargeState;
189
190typedef struct {
191 /**
192 * Signal strength in percent, -1 = unknown
193 */
194 int BatteryPercent;
195 /**
196 * Charge state
197 */
198 GSM_ChargeState ChargeState;
199} GSM_BatteryCharge;
200
201/* ------------------------------ categories ------------------------------- */
202
203#define GSM_MAX_CATEGORY_NAME_LENGTH 50
204
205typedef enum {
206 Category_ToDo = 1,
207 Category_Phonebook
208} GSM_CategoryType;
209
210typedef struct {
211 GSM_CategoryType Type;
212 int Location;
213 unsigned char Name[(GSM_MAX_CATEGORY_NAME_LENGTH + 1)*2];
214} GSM_Category;
215
216typedef struct {
217 GSM_CategoryType Type;
218 int Used;
219} GSM_CategoryStatus;
220
221/* ------------------- radio FM stations ---------------------------------- */
222
223 #defineGSM_MAX_FMSTATION_LENGTH 12
224 #define GSM_MAX_FM_STATION 20
225
226typedef struct {
227 int Location;
228 char StationName [(GSM_MAX_FMSTATION_LENGTH+1)*2];
229 double Frequency;
230} GSM_FMStation;
231
232/* ----------------------- filesystem ------------------------------------- */
233
234typedef enum {
235 GSM_File_Java_JAR = 1,
236 GSM_File_Image_JPG,
237 GSM_File_Image_BMP,
238 GSM_File_Image_GIF,
239 GSM_File_Image_PNG,
240 GSM_File_Image_WBMP,
241 GSM_File_Video_3GP,
242 GSM_File_Sound_AMR,
243 GSM_File_Sound_NRT, /* DCT4 binary format */
244 GSM_File_Sound_MIDI,
245#ifdef DEVELOP
246 GSM_File_MMS,
247#endif
248 GSM_File_Other
249} GSM_FileType;
250
251typedef struct {
252 int Used; /* how many bytes used */
253 unsigned char Name[300]; /* Name */
254 bool Folder; /* true, when folder */
255 int Level;
256 GSM_FileTypeType;
257 unsigned charID_FullName[400];
258 unsigned char*Buffer;
259
260 GSM_DateTimeModified;
261 bool ModifiedEmpty;
262
263 /* File attributes */
264 bool Protected;
265 bool ReadOnly;
266 bool Hidden;
267 bool System;
268} GSM_File;
269
270GSM_Error GSM_ReadFile(char *FileName, GSM_File *File);
271
272GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size);
273
274void GSM_IdentifyFileFormat(GSM_File *File);
275
276typedef struct {
277 int Free;
278 int Used;
279} GSM_FileSystemStatus;
280
281/* ----------------------------- GPRS access points ----------------------- */
282
283typedef struct {
284 int Location;
285 unsigned char Name[300];
286 unsigned char URL[500];
287 bool Active;
288} GSM_GPRSAccessPoint;
289
290/* ------------------------------------------------------------------------ */
291
292typedef enum {
293 GSM_Date_DDMMYYYY = 1,
294 GSM_Date_MMDDYYYY,
295 GSM_Date_YYYYMMDD
296} GSM_DateFormat;
297
298typedef struct {
299 unsigned char DateSeparator;
300 GSM_DateFormatDateFormat;
301 bool AMPMTime;
302} GSM_Locale;
303
304/* ------------------------------------------------------------------------ */
305
306void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt);
307void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start);
308
309void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start);
310bool ReadVCALText(char *Buffer, char *Start, char *Value);
311
312#endif
313
314/* How should editor hadle tabs in this file? Add editor commands here.
315 * vim: noexpandtab sw=8 ts=8 sts=8:
316 */
diff --git a/gammu/emb/common/service/gsmnet.c b/gammu/emb/common/service/gsmnet.c
new file mode 100644
index 0000000..a0ddaa7
--- a/dev/null
+++ b/gammu/emb/common/service/gsmnet.c
@@ -0,0 +1,444 @@
1/* (c) 2001-2003 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmnet.h"
6#include "../misc/coding/coding.h"
7
8unsigned char *GSM_Countries[] = {
9 "202", "Greece",
10 "204", "Netherlands",
11 "206", "Belgium",
12 "208", "France",
13 "213", "Andorra" ,
14 "214", "Spain",
15 "216", "Hungary",
16 "218", "Bosnia Herzegovina",
17 "219", "Croatia",
18 "220", "Yugoslavia",
19 "222", "Italy",
20 "226", "Romania",
21 "228", "Switzerland",
22 "230", "Czech Republic",
23 "231", "Slovak Republic",
24 "232", "Austria",
25 "234", "United Kingdom",
26 "238", "Denmark",
27 "240", "Sweden",
28 "242", "Norway",
29 "244", "Finland",
30 "246", "Lithuania",
31 "247", "Latvia",
32 "248", "Estonia",
33 "250", "Russia",
34 "255", "Ukraine",
35 "259", "Moldova",
36 "260", "Poland",
37 "262", "Germany",
38 "266", "Gibraltar",
39 "268", "Portugal",
40 "270", "Luxembourg",
41 "272", "Ireland",
42 "274", "Iceland",
43 "276", "Albania",
44 "278", "Malta",
45 "280", "Cyprus",
46 "282", "Georgia",
47 "283", "Armenia",
48 "284", "Bulgaria",
49 "286", "Turkey",
50 "290", "Greenland",
51 "293", "Slovenia",
52 "294", "Macedonia",
53 "302", "Canada",
54 "310", "U.S.A.",
55 "340", "French West Indies",
56 "400", "Azerbaijan",
57 "404", "India",
58 "410", "Pakistan",
59 "413", "Sri Lanka",
60 "415", "Lebanon",
61 "416", "Jordan",
62 "417", "Syria",
63 "418", "Iraq",
64 "419", "Kuwait",
65 "420", "Saudi Arabia",
66 "422", "Oman",
67 "424", "United Arab Emirates",
68 "425", "Israel",
69 "426", "Bahrain",
70 "427", "Qatar",
71 "432", "Iran",
72 "434", "Uzbekistan",
73 "437", "Kyrgyz Republic",
74 "452", "Vietnam",
75 "454", "Hong Kong",
76 "455", "Macau",
77 "456", "Cambodia",
78 "457", "Lao",
79 "460", "China",
80 "466", "Taiwan",
81 "470", "Bangladesh",
82 "502", "Malaysia",
83 "505", "Australia",
84 "510", "Indonesia",
85 "515", "Philippines",
86 "520", "Thailand",
87 "525", "Singapore",
88 "528", "Brunei Darussalam",
89 "530", "New Zealand",
90 "542", "Fiji",
91 "546", "New Caledonia",
92 "547", "French Polynesia",
93 "602", "Egypt",
94 "603", "Algeria",
95 "604", "Morocco",
96 "605", "Tunisia",
97 "608", "Senegal",
98 "611", "Guinea",
99 "612", "Cote d'Ivoire",
100 "615", "Togo",
101 "617", "Mauritius",
102 "618", "Liberia",
103 "620", "Ghana",
104 "624", "Cameroon",
105 "625", "Cape Verde",
106 "633", "Seychelles",
107 "634", "Mozambique",
108 "634", "Sudan",
109 "635", "Rwanda",
110 "636", "Ethiopia",
111 "640", "Tanzania",
112 "641", "Uganda",
113 "645", "Zambia",
114 "646", "Madagascar",
115 "647", "Reunion",
116 "648", "Zimbabwe",
117 "649", "Namibia",
118 "650", "Malawi",
119 "651", "Lesotho",
120 "652", "Botswana",
121 "655", "South Africa",
122 "730", "Chile",
123 "734", "Venezuela",
124
125 NULL
126};
127
128unsigned char *GSM_Networks[] = {
129 "202 01", "Cosmote",
130 "202 05", "PANAFON",
131 "202 10", "TELESTET",
132 "204 04", "LIBERTEL",
133 "204 08", "KPN Telecom",
134 "204 12", "O2",
135 "204 16", "BEN",
136 "204 20", "Dutchtone NV",
137 "206 01", "PROXIMUS",
138 "206 10", "Mobistar",
139 "206 20", "Base",
140 "208 01", "ITINERIS",
141 "208 10", "SFR",
142 "208 20", "Bouygues Telecom",
143 "213 03", "MOBILAND",
144 "214 01", "Airtel GSM 900-Spain",
145 "214 03", "Retevision Movil",
146 "214 07", "MOVISTAR",
147 "216 01", "Pannon GSM",
148 "216 70", "Vodafone",
149 "216 30", "Westel 900",
150 "218 90", "GSMBIH",
151 "219 01", "CRONET",
152 "219 10", "VIP",
153 "220 01", "MOBTEL",
154 "220 02", "ProMonte GSM",
155 "220 03", "Telekom Srbije",
156 "222 01", "Telecom Italia Mobile",
157 "222 10", "OMNITEL",
158 "222 88", "Wind Telecomunicazioni SpA",
159 "226 01", "CONNEX GSM",
160 "226 10", "DIALOG",
161 "228 01", "NATEL International",
162 "228 02", "diAx Mobile AG",
163 "230 01", "T-Mobile CZ",
164 "230 02", "EuroTel",
165 "230 03", "Oskar",
166 "231 01", "Orange",
167 "231 02", "EuroTel GSM",
168 "232 01", "A1",
169 "232 03", "T-Mobile AT",
170 "232 05", "ONE",
171 "232 07", "tele.ring",
172 "234 10", "Cellnet",
173 "234 15", "Vodafone",
174 "234 30", "T-Mobile UK",
175 "234 33", "ORANGE",
176 "234 50", "Jersey Telecoms GSM",
177 "234 55", "Guernsey Telecoms GSM",
178 "234 58", "PRONTO GSM",
179 "238 01", "TDK-MOBIL",
180 "238 02", "SONOFON",
181 "238 20", "TELIA DK",
182 "238 30", "Mobilix",
183 "240 01", "Telia AB",
184 "240 07", "COMVIQ",
185 "240 08", "EUROPOLITAN",
186 "242 01", "Telenor Mobil",
187 "242 02", "NetCom GSM",
188 "244 03", "Telia City (Finland)",
189 "244 05", "Radiolinja",
190 "244 09", "Finnet",
191 "244 12", "DNA (FI2G)",
192 "244 14", "Alands Mobiltelefon",
193 "244 91", "Sonera",
194 "246 01", "OMNITEL",
195 "246 02", "Bite GSM",
196 "247 01", "LMT LV",
197 "247 02", "BALTCOM GSM",
198 "248 01", "EMT GSM",
199 "248 02", "Radiolinja Eesti AS",
200 "248 03", "Q GSM",
201 "250 01", "Mobile Telesystems",
202 "250 02", "North-West GSM",
203 "250 05", "Siberian Cellular Systems 900",
204 "250 07", "BM Telecom",
205 "250 10", "Don Telecom",
206 "250 12", "FECS-900",
207 "250 13", "Kuban GSM",
208 "250 39", "Uraltel",
209 "250 44", "North Caucasian GSM",
210 "250 99", "BeeLine",
211 "255 01", "UMC",
212 "255 02", "WellCOM",
213 "255 03", "Kyivstar",
214 "255 05", "Golden Telecom",
215 "259 01", "VOXTEL",
216 "260 01", "PLUS GSM",
217 "260 02", "ERA GSM",
218 "260 03", "IDEA Centertel",
219 "262 01", "T-Mobile D",
220 "262 02", "D2 PRIVAT",
221 "262 03", "E-Plus",
222 "262 07", "Interkom",
223 "266 01", "Gibtel GSM",
224 "268 01", "TELECEL",
225 "268 03", "OPTIMUS",
226 "268 06", "TMN",
227 "270 01", "LUXGSM",
228 "270 77", "TANGO",
229 "272 01", "EIRCELL-GSM",
230 "272 02", "Digifone",
231 "274 01", "Landssiminn GSM 900",
232 "274 02", "TAL hf",
233 "276 01", "AMC",
234 "278 01", "Vodafone Malta Limited",
235 "280 01", "CYTAGSM",
236 "282 01", "Geocell Limited",
237 "282 02", "Magti GSM",
238 "283 01", "ArmGSM",
239 "284 01", "M-TEL GSM BG",
240 "286 01", "Turkcell",
241 "286 02", "TELSIM GSM",
242 "288 01", "Faroese Telecom",
243 "290 01", "Tele Greenland",
244 "293 40", "SI.MOBIL d. d.",
245 "293 41", "MOBITEL",
246 "293 70", "SI VEGA 070",
247 "294 01", "MobiMak",
248 "302 37", "Microcell Connexions Inc",
249 "302 72", "Rogers AT&T",
250 "310 01", "Cellnet",
251 "310 02", "Sprint Spectrum",
252 "310 11", "Wireless 2000 Telephone Co.",
253 "310 15", "BellSouth Mobility DCS",
254 "310 16", "T-Mobile",
255 "310 17", "Pac Bell",
256 "310 20", "T-Mobile",
257 "310 21", "T-Mobile",
258 "310 22", "T-Mobile",
259 "310 23", "T-Mobile",
260 "310 24", "T-Mobile",
261 "310 25", "T-Mobile",
262 "310 26", "T-Mobile",
263 "310 27", "T-Mobile",
264 "310 31", "T-Mobile",
265 "310 38", "AT&T Wireless",
266 "310 58", "T-Mobile",
267 "310 66", "T-Mobile",
268 "310 77", "Iowa Wireless Services LP",
269 "310 80", "T-Mobile",
270 "340 01", "AMERIS",
271 "400 01", "AZERCELL GSM",
272 "400 02", "Bakcell GSM 2000",
273 "404 07", "TATA Cellular",
274 "404 10", "AirTel",
275 "404 11", "Essar Cellphone",
276 "404 12", "Escotel",
277 "404 14", "Modicom",
278 "404 15", "Essar Cellphone",
279 "404 20", "Max Touch",
280 "404 21", "BPL - Mobile",
281 "404 27", "BPL USWEST Cellular",
282 "404 30", "Command",
283 "404 40", "SkyCell",
284 "404 41", "RPG Cellular",
285 "404 42", "AIRCEL",
286 "410 01", "Mobilink",
287 "413 02", "DIALOG GSM",
288 "415 01", "CELLIS",
289 "415 03", "LIBANCELL",
290 "416 01", "Fastlink",
291 "417 09", "MOBILE SYRIA",
292 "419 02", "MTCNet",
293 "420 01", "Al Jawwal",
294 "420 07", "E.A.E",
295 "422 02", "GTO",
296 "424 02", "UAE-ETISALAT",
297 "425 01", "Partner Communications Company Ltd",
298 "425 02", "Cellcom Israel Ltd",
299 "426 01", "BHR MOBILE PLUS",
300 "427 01", "QATARNET",
301 "432 11", "TCI",
302 "434 04", "Daewoo Unitel",
303 "434 05", "Coscom",
304 "437 01", "Bitel",
305 "454 00", "TCSL GSM",
306 "454 04", "HKGHT",
307 "454 06", "SMARTONE GSM",
308 "454 10", "New World PCS",
309 "454 12", "PEOPLES",
310 "454 16", "SUNDAY",
311 "455 01", "TELEMOVEL+ GSM900-Macau",
312 "456 01", "MobiTel",
313 "456 02", "SAMART-GSM",
314 "457 01", "Lao Shinawatra Telecom",
315 "460 00", "China Telecom GSM",
316 "460 01", "CU-GSM",
317 "466 01", "Far EasTone Telecoms 900",
318 "466 06", "TUNTEX GSM 1800",
319 "466 88", "KG Telecom",
320 "466 92", "Chunghwa GSM",
321 "466 93", "MobiTai",
322 "466 97", "TWNGSM",
323 "466 99", "TransAsia",
324 "470 01", "GrameenPhone Ltd",
325 "470 19", "Mobile 2000",
326 "502 12", "Maxis Mobile",
327 "502 13", "TM Touch",
328 "502 16", "DiGi 1800",
329 "502 17", "ADAM",
330 "502 19", "CELCOM",
331 "505 01", "MobileNet",
332 "505 02", "OPTUS",
333 "505 03", "VODAFONE",
334 "505 08", "One.Tel",
335 "510 01", "SATELINDO",
336 "510 08", "LIPPO TELECOM",
337 "510 10", "TELKOMSEL",
338 "510 11", "Excelcom",
339 "510 21", "INDOSAT",
340 "515 01", "ISLACOM",
341 "515 02", "Globe Telecom",
342 "520 01", "AIS GSM",
343 "520 10", "WCS",
344 "520 18", "Worldphone 1800",
345 "520 23", "HELLO",
346 "525 01", "SingTel Mobile",
347 "525 02", "ST-PCN",
348 "525 03", "MOBILEONE",
349 "528 11", "DSTCom",
350 "530 01", "Vodafone New Zealand Limited",
351 "542 01", "Vodafone",
352 "546 01", "Mobilis",
353 "547 20", "VINI",
354 "602 01", "MobiNil",
355 "602 02", "Tunicell",
356 "603 01", "ALGERIAN MOBILE NETWORK",
357 "604 01", "I A M",
358 "608 01", "ALIZE",
359 "611 02", "Lagui",
360 "612 03", "IVOIRIS",
361 "612 05", "Telecel",
362 "615 01", "TOGO CELL",
363 "617 01", "Cellplus Mobile Comms",
364 "618 01", "Omega",
365 "620 01", "SPACEFON",
366 "625 01", "CVMOVEL",
367 "633 01", "Seychelles Cellular Services",
368 "633 10", "AIRTEL",
369 "634 01", "MobiTel",
370 "635 10", "Rwandacell",
371 "636 01", "ETMTN",
372 "640 01", "TRITEL",
373 "641 10", "MTN-Uganda",
374 "642 02", "ANTARIS",
375 "643 01", "T.D.M GSM 900",
376 "645 01", "ZAMCELL",
377 "646 01", "Madacom",
378 "646 03", "Sacel Madagascar S.A.",
379 "647 10", "SRR",
380 "648 01", "NET*ONE",
381 "648 03", "Telecel",
382 "649 01", "MTC",
383 "650 01", "Callpoint 900",
384 "651 01", "Vodacom Lesotho (Pty) Ltd",
385 "655 01", "Vodacom",
386 "655 10", "MTN",
387 "680 38", "NPI Wireless",
388 "730 01", "Entel Telefonia Movi",
389 "730 10", "Entel PCS",
390 "734 01", "Infonet",
391
392 NULL
393};
394
395char *GSM_GetNetworkName(char *NetworkCode)
396{
397 int i = 0;
398 static charretval[200];
399
400 EncodeUnicode(retval,"unknown",7);
401 while (GSM_Networks[i*2] != NULL) {
402 if (!strncmp(GSM_Networks[i*2],NetworkCode,6)) {
403 EncodeUnicode(retval, GSM_Networks[i*2+1], strlen(GSM_Networks[i*2+1]));
404 break;
405 }
406 i++;
407 }
408 return retval;
409}
410
411char *GSM_GetCountryName(char *CountryCode)
412{
413 int i = 0;
414 static charretval[200];
415
416 EncodeUnicode(retval,"unknown",7);
417 while (GSM_Countries[i*2] != NULL) {
418 if (!strncmp(GSM_Countries[i*2],CountryCode,3)) {
419 EncodeUnicode(retval, GSM_Countries[i*2+1], strlen(GSM_Countries[i*2+1]));
420 break;
421 }
422 i++;
423 }
424 return retval;
425}
426
427void NOKIA_EncodeNetworkCode(unsigned char* buffer, unsigned char* output)
428{
429 EncodeBCD(buffer, output, 6, false);
430 buffer[1] = buffer[1] | 0xf0;
431}
432
433void NOKIA_DecodeNetworkCode(unsigned char* buffer, unsigned char* output)
434{
435 DecodeBCD(output, buffer, 3);
436 output[6] = output[5];
437 output[5] = output[4];
438 output[4] = output[3];
439 output[3] = ' ';
440}
441
442/* How should editor hadle tabs in this file? Add editor commands here.
443 * vim: noexpandtab sw=8 ts=8 sts=8:
444 */
diff --git a/gammu/emb/common/service/gsmnet.h b/gammu/emb/common/service/gsmnet.h
new file mode 100644
index 0000000..aaea22f
--- a/dev/null
+++ b/gammu/emb/common/service/gsmnet.h
@@ -0,0 +1,98 @@
1/* (c) 2002-2003 by Marcin Wiacek & Michal Cihar */
2
3#ifndef __gsm_net_h
4#define __gsm_net_h
5
6/**
7 * Find network name from given network code.
8 */
9char *GSM_GetNetworkName(char *NetworkCode);
10
11/**
12 * Find country name from given country code.
13 */
14char *GSM_GetCountryName(char *CountryCode);
15
16/**
17 * Status of network logging
18 */
19typedef enum {
20 /**
21 * Home network for used SIM card.
22 */
23 GSM_HomeNetwork = 1,
24 /**
25 * No network available for used SIM card.
26 */
27 GSM_NoNetwork,
28 /**
29 * SIM card uses roaming.
30 */
31 GSM_RoamingNetwork,
32 /**
33 * Network registration denied - card blocked or expired or disabled.
34 */
35 GSM_RegistrationDenied,
36 /**
37 * Unknown network status.
38 */
39 GSM_NetworkStatusUnknown,
40 /**
41 * Network explicitely requested by user.
42 */
43 GSM_RequestingNetwork
44} GSM_NetworkInfo_State;
45
46/**
47 * Structure for getting the current network info.
48 */
49typedef struct {
50 /**
51 * Cell ID (CID)
52 */
53 unsigned char CID[10];
54 /**
55 * GSM network code.
56 */
57 char NetworkCode[10];
58 /**
59 * Status of network logging. If phone is not logged into any network,
60 * some values are not filled
61 */
62 GSM_NetworkInfo_State State;
63 /**
64 * LAC (Local Area Code).
65 */
66 unsigned char LAC[10];
67 /**
68 * Name of current network like returned from phone (or empty).
69 */
70 unsigned char NetworkName[15*2];
71} GSM_NetworkInfo;
72
73void NOKIA_EncodeNetworkCode (unsigned char* buffer, unsigned char* output);
74void NOKIA_DecodeNetworkCode (unsigned char* buffer, unsigned char* output);
75
76/**
77 * Information about signal quality, all these should be -1 when unknown.
78 */
79typedef struct {
80 /*
81 * Signal strength in dBm
82 */
83 int SignalStrength;
84 /**
85 * Signal strength in percent.
86 */
87 int SignalPercent;
88 /**
89 * Bit error rate in percent.
90 */
91 int BitErrorRate;
92} GSM_SignalQuality;
93
94#endif
95
96/* How should editor hadle tabs in this file? Add editor commands here.
97 * vim: noexpandtab sw=8 ts=8 sts=8:
98 */
diff --git a/gammu/emb/common/service/gsmpbk.c b/gammu/emb/common/service/gsmpbk.c
new file mode 100644
index 0000000..05e5cb9
--- a/dev/null
+++ b/gammu/emb/common/service/gsmpbk.c
@@ -0,0 +1,370 @@
1/* (c) 2001-2003 by Marcin Wiacek,... */
2
3#include <string.h>
4
5#include "../misc/coding/coding.h"
6#include "gsmpbk.h"
7#include "gsmmisc.h"
8
9unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry)
10{
11 /* We possibly store here "LastName, FirstName" so allocate enough memory */
12 static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2];
13 static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'};
14 int i;
15 int first = -1, last = -1, name = -1;
16 int len = 0;
17
18 for (i = 0; i < entry->EntriesNum; i++) {
19 switch (entry->Entries[i].EntryType) {
20 case PBK_Text_LastName:
21 last = i;
22 break;
23 case PBK_Text_FirstName:
24 first = i;
25 break;
26 case PBK_Text_Name:
27 name = i;
28 break;
29 default:
30 break;
31 }
32 }
33
34 if (name != -1) {
35 CopyUnicodeString(dest, entry->Entries[name].Text);
36 } else {
37 if (last != -1 && first != -1) {
38 len = UnicodeLength(entry->Entries[last].Text);
39 CopyUnicodeString(dest, entry->Entries[last].Text);
40 CopyUnicodeString(dest + 2*len, split);
41 CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text);
42 } else if (last != -1) {
43 CopyUnicodeString(dest, entry->Entries[last].Text);
44 } else if (first != -1) {
45 CopyUnicodeString(dest, entry->Entries[first].Text);
46 } else {
47 return NULL;
48 }
49 }
50
51 return dest;
52}
53
54void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
55{
56 int i;
57
58 *Name = -1;
59 *Number = -1;
60 *Group = -1;
61 for (i = 0; i < entry->EntriesNum; i++) {
62 switch (entry->Entries[i].EntryType) {
63 case PBK_Number_General : if (*Number == -1) *Number = i; break;
64 case PBK_Text_Name : if (*Name == -1) *Name = i; break;
65 case PBK_Caller_Group : if (*Group == -1) *Group = i; break;
66 default : break;
67 }
68 }
69 if ((*Number) == -1) {
70 for (i = 0; i < entry->EntriesNum; i++) {
71 switch (entry->Entries[i].EntryType) {
72 case PBK_Number_Mobile:
73 case PBK_Number_Work:
74 case PBK_Number_Fax:
75 case PBK_Number_Home:
76 case PBK_Number_Pager:
77 case PBK_Number_Other:
78 *Number = i;
79 break;
80 default:
81 break;
82 }
83 if (*Number != -1) break;
84 }
85 }
86 if ((*Name) == -1) {
87 for (i = 0; i < entry->EntriesNum; i++) {
88 if (entry->Entries[i].EntryType != PBK_Text_LastName) continue;
89 *Name = i;
90 break;
91 }
92 }
93 if ((*Name) == -1) {
94 for (i = 0; i < entry->EntriesNum; i++) {
95 if (entry->Entries[i].EntryType != PBK_Text_FirstName) continue;
96 *Name = i;
97 break;
98 }
99 }
100}
101
102void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version)
103{
104 int Name, Number, Group, i;
105 bool ignore;
106
107 GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group);
108
109 if (Version == Nokia_VCard10) {
110 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%c",13,10);
111 if (Name != -1) {
112 *Length+=sprintf(Buffer+(*Length),"N:%s%c%c",DecodeUnicodeString(pbk->Entries[Name].Text),13,10);
113 }
114 if (Number != -1) {
115 *Length +=sprintf(Buffer+(*Length),"TEL:%s%c%c",DecodeUnicodeString(pbk->Entries[Number].Text),13,10);
116 }
117 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
118 } else if (Version == Nokia_VCard21) {
119 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%cVERSION:2.1%c%c",13,10,13,10);
120 if (Name != -1) {
121 SaveVCALText(Buffer, Length, pbk->Entries[Name].Text, "N");
122 }
123 for (i=0; i < pbk->EntriesNum; i++) {
124 if (i != Name) {
125 ignore = false;
126 switch(pbk->Entries[i].EntryType) {
127 case PBK_Text_Name :
128 case PBK_Date :
129 case PBK_Caller_Group :
130 ignore = true;
131 break;
132 case PBK_Number_General :
133 *Length+=sprintf(Buffer+(*Length),"TEL");
134 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
135 break;
136 case PBK_Number_Mobile :
137 *Length+=sprintf(Buffer+(*Length),"TEL");
138 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
139 *Length+=sprintf(Buffer+(*Length),";CELL");
140 break;
141 case PBK_Number_Work :
142 *Length+=sprintf(Buffer+(*Length),"TEL");
143 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
144 *Length+=sprintf(Buffer+(*Length),";WORK;VOICE");
145 break;
146 case PBK_Number_Fax :
147 *Length+=sprintf(Buffer+(*Length),"TEL");
148 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
149 *Length+=sprintf(Buffer+(*Length),";FAX");
150 break;
151 case PBK_Number_Home :
152 *Length+=sprintf(Buffer+(*Length),"TEL");
153 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
154 *Length+=sprintf(Buffer+(*Length),";HOME;VOICE");
155 break;
156 case PBK_Text_Note :
157 *Length+=sprintf(Buffer+(*Length),"NOTE");
158 break;
159 case PBK_Text_Postal :
160 /* Don't ask why. Nokia phones save postal address
161 * double - once like LABEL, second like ADR
162 */
163 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "LABEL");
164 *Length+=sprintf(Buffer+(*Length),"ADR");
165 break;
166 case PBK_Text_Email :
167 case PBK_Text_Email2 :
168 *Length+=sprintf(Buffer+(*Length),"EMAIL");
169 break;
170 case PBK_Text_URL :
171 *Length+=sprintf(Buffer+(*Length),"URL");
172 break;
173 default :
174 ignore = true;
175 break;
176 }
177 if (!ignore) {
178 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "");
179 }
180 }
181 }
182 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
183 }
184}
185
186GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
187{
188 unsigned char Line[2000],Buff[2000];
189 int Level = 0;
190
191 Buff[0] = 0;
192 Pbk->EntriesNum = 0;
193
194 while (1) {
195 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
196 if (strlen(Line) == 0) break;
197 switch (Level) {
198 case 0:
199 if (strstr(Line,"BEGIN:VCARD")) Level = 1;
200 break;
201 case 1:
202 if (strstr(Line,"END:VCARD")) {
203 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
204 return ERR_NONE;
205 }
206 if (ReadVCALText(Line, "N", Buff)) {
207 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
208 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
209 Pbk->EntriesNum++;
210 }
211 if (ReadVCALText(Line, "TEL", Buff) ||
212 ReadVCALText(Line, "TEL;VOICE", Buff) ||
213 ReadVCALText(Line, "TEL;PREF", Buff) ||
214 ReadVCALText(Line, "TEL;PREF;VOICE", Buff)) {
215 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
216 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
217 Pbk->EntriesNum++;
218 }
219 if (ReadVCALText(Line, "TEL;CELL", Buff) ||
220 ReadVCALText(Line, "TEL;CELL;VOICE", Buff) ||
221 ReadVCALText(Line, "TEL;PREF;CELL", Buff) ||
222 ReadVCALText(Line, "TEL;PREF;CELL;VOICE", Buff)) {
223 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
224 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
225 Pbk->EntriesNum++;
226 }
227 if (ReadVCALText(Line, "TEL;WORK", Buff) ||
228 ReadVCALText(Line, "TEL;PREF;WORK", Buff) ||
229 ReadVCALText(Line, "TEL;WORK;VOICE", Buff) ||
230 ReadVCALText(Line, "TEL;PREF;WORK;VOICE", Buff)) {
231 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
233 Pbk->EntriesNum++;
234 }
235 if (ReadVCALText(Line, "TEL;FAX", Buff) ||
236 ReadVCALText(Line, "TEL;PREF;FAX", Buff) ||
237 ReadVCALText(Line, "TEL;FAX;VOICE", Buff) ||
238 ReadVCALText(Line, "TEL;PREF;FAX;VOICE", Buff)) {
239 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
240 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
241 Pbk->EntriesNum++;
242 }
243 if (ReadVCALText(Line, "TEL;HOME", Buff) ||
244 ReadVCALText(Line, "TEL;PREF;HOME", Buff) ||
245 ReadVCALText(Line, "TEL;HOME;VOICE", Buff) ||
246 ReadVCALText(Line, "TEL;PREF;HOME;VOICE", Buff)) {
247 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
248 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
249 Pbk->EntriesNum++;
250 }
251 if (ReadVCALText(Line, "NOTE", Buff)) {
252 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
253 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
254 Pbk->EntriesNum++;
255 }
256 if (ReadVCALText(Line, "ADR", Buff)) {
257 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
258 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
259 Pbk->EntriesNum++;
260 }
261 if (ReadVCALText(Line, "EMAIL", Buff)) {
262 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
263 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
264 Pbk->EntriesNum++;
265 }
266 if (ReadVCALText(Line, "URL", Buff)) {
267 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
268 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
269 Pbk->EntriesNum++;
270 }
271 break;
272 }
273 }
274
275 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
276 return ERR_NONE;
277}
278
279/* -------------- OLD functions (c) by Timo Teras -------------------------- */
280
281#ifndef ENABLE_LGPL
282
283static void ParseVCardLine(char **pos, char *Name, char *Parameters, char *Value)
284{
285 int i;
286
287 Name[0] = Parameters[0] = Value[0] = 0;
288
289 if (**pos == 0) return;
290
291 for (i=0; **pos && **pos != ':' && **pos != ';'; i++, (*pos)++) Name[i] = **pos;
292 Name[i] = 0;
293
294 //dbgprintf("ParseVCardLine: name tag = '%s'\n", Name);
295 if (**pos == ';') {
296 (*pos)++;
297 for (i=0; **pos && **pos != ':'; i++, (*pos)++) Parameters[i] = **pos;
298 Parameters[i] = ';';
299 Parameters[i+1] = 0;
300 //dbgprintf("ParseVCardLine: parameter tag = '%s'\n", Parameters);
301 }
302
303 if (**pos != 0) (*pos)++;
304
305 i=0;
306 while (**pos) {
307 if ((*pos)[0] == '\x0d' && (*pos)[1] == '\x0a') {
308 (*pos) += 2;
309 if (**pos != '\t' && **pos != ' ') break;
310 while (**pos == '\t' || **pos == ' ') (*pos)++;
311 continue;
312 }
313 Value[i++] = **pos;
314 (*pos)++;
315 }
316 Value[i] = 0;
317
318 //dbgprintf("ParseVCardLine: value tag = '%s'\n", Value);
319}
320
321void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk)
322{
323 char *pos = VCard;
324 char Name[32], Parameters[256], Value[1024];
325
326 dbgprintf("Parsing VCard:\n%s\n", VCard);
327
328 ParseVCardLine(&pos, Name, Parameters, Value);
329 if (!mystrncasecmp(Name, "BEGIN", 0) || !mystrncasecmp(Value, "VCARD", 0)) {
330 dbgprintf("No valid VCARD signature\n");
331 return;
332 }
333
334 while (1) {
335 GSM_SubMemoryEntry *pbe = &pbk->Entries[pbk->EntriesNum];
336
337 ParseVCardLine(&pos, Name, Parameters, Value);
338 if (Name[0] == 0x00 ||
339 (mystrncasecmp(Name, "END", 0) && mystrncasecmp(Value, "VCARD", 0)))
340 return;
341
342 if (mystrncasecmp(Name, "N", 0)) {
343 //FIXME: Name is tagged field which should be parsed
344 pbe->EntryType = PBK_Text_Name;
345 EncodeUnicode(pbe->Text, Value, strlen(Value));
346 pbk->EntriesNum++;
347 } else if (mystrncasecmp(Name, "EMAIL", 0)) {
348 pbe->EntryType = PBK_Text_Email;
349 EncodeUnicode(pbe->Text, Value, strlen(Value));
350 pbk->EntriesNum++;
351 } else if (mystrncasecmp(Name, "TEL", 0)) {
352 if (strstr(Parameters, "WORK;"))
353 pbe->EntryType = PBK_Number_Work;
354 else if (strstr(Name, "HOME;"))
355 pbe->EntryType = PBK_Number_Home;
356 else if (strstr(Name, "FAX;"))
357 pbe->EntryType = PBK_Number_Fax;
358 else pbe->EntryType = PBK_Number_General;
359
360 EncodeUnicode(pbe->Text, Value, strlen(Value));
361 pbk->EntriesNum++;
362 }
363 }
364}
365
366#endif
367
368/* How should editor hadle tabs in this file? Add editor commands here.
369 * vim: noexpandtab sw=8 ts=8 sts=8:
370 */
diff --git a/gammu/emb/common/service/gsmpbk.h b/gammu/emb/common/service/gsmpbk.h
new file mode 100644
index 0000000..e556793
--- a/dev/null
+++ b/gammu/emb/common/service/gsmpbk.h
@@ -0,0 +1,270 @@
1/* (c) 2001-2004 by Marcin Wiacek and Michal Cihar */
2
3#ifndef __gsm_pbk_h
4#define __gsm_pbk_h
5
6#include <stdlib.h>
7
8#include "../gsmcomon.h"
9#include "gsmmisc.h"
10
11/**
12 * Structure contains info about number of used/free entries in phonebook
13 * memory
14 */
15typedef struct {
16 /**
17 * Number of used entries
18 */
19 int MemoryUsed;
20 /**
21 * Memory type
22 */
23 GSM_MemoryType MemoryType;
24 /**
25 * Number of free entries
26 */
27 int MemoryFree;
28} GSM_MemoryStatus;
29
30/**
31 * Type of specific phonebook entry. In parenthesis is specified in which
32 * member of @ref GSM_SubMemoryEntry value is stored.
33 */
34typedef enum {
35 /**
36 * General number. (Text)
37 */
38 PBK_Number_General = 1,
39 /**
40 * Mobile number. (Text)
41 */
42 PBK_Number_Mobile,
43 /**
44 * Work number. (Text)
45 */
46 PBK_Number_Work,
47 /**
48 * Fax number. (Text)
49 */
50 PBK_Number_Fax,
51 /**
52 * Home number. (Text)
53 */
54 PBK_Number_Home,
55 /**
56 * Pager number. (Text)
57 */
58 PBK_Number_Pager,
59 /**
60 * Other number. (Text)
61 */
62 PBK_Number_Other,
63 /**
64 * Note. (Text)
65 */
66 PBK_Text_Note,
67 /**
68 * Complete postal address. (Text)
69 */
70 PBK_Text_Postal,
71 /**
72 * Email. (Text)
73 */
74 PBK_Text_Email,
75 /**
76 * Second email. (Text)
77 */
78 PBK_Text_Email2,
79 /**
80 * URL (Text)
81 */
82 PBK_Text_URL,
83 /**
84 * Date and time. FIXME: describe better (Date)
85 */
86 PBK_Date,
87 /**
88 * Caller group. (Text)
89 */
90 PBK_Caller_Group,
91 /**
92 * Name (Text)
93 */
94 PBK_Text_Name,
95 /**
96 * Last name. (Text)
97 */
98 PBK_Text_LastName,
99 /**
100 * First name. (Text)
101 */
102 PBK_Text_FirstName,
103 /**
104 * Company. (Text)
105 */
106 PBK_Text_Company,
107 /**
108 * Job title. (Text)
109 */
110 PBK_Text_JobTitle,
111 /**
112 * Category. (Number)
113 */
114 PBK_Category,
115 /**
116 * Whether entry is private. (Number)
117 */
118 PBK_Private,
119 /**
120 * Street address. (Text)
121 */
122 PBK_Text_StreetAddress,
123 /**
124 * City. (Text)
125 */
126 PBK_Text_City,
127 /**
128 * State. (Text)
129 */
130 PBK_Text_State,
131 /**
132 * Zip code. (Text)
133 */
134 PBK_Text_Zip,
135 /**
136 * Country. (Text)
137 */
138 PBK_Text_Country,
139 /**
140 * Custom information 1. (Text)
141 */
142 PBK_Text_Custom1,
143 /**
144 * Custom information 2. (Text)
145 */
146 PBK_Text_Custom2,
147 /**
148 * Custom information 3. (Text)
149 */
150 PBK_Text_Custom3,
151 /**
152 * Custom information 4. (Text)
153 */
154 PBK_Text_Custom4,
155 /**
156 * Ringtone ID. (Number)
157 */
158 PBK_RingtoneID,
159 /**
160 * Ringtone ID in phone filesystem. (Number)
161 */
162 PBK_RingtoneFileSystemID,
163 /**
164 * Picture ID. (Number)
165 */
166 PBK_PictureID,
167 PBK_SMSListID,
168 /**
169 * User ID. (Text)
170 */
171 PBK_Text_UserID
172} GSM_EntryType;
173
174#define GSM_PHONEBOOK_TEXT_LENGTH 200
175 #define GSM_PHONEBOOK_ENTRIES 26
176
177/**
178 * One value of phonebook memory entry.
179 */
180typedef struct {
181 /**
182 * Type of entry.
183 */
184 GSM_EntryType EntryType;
185 /**
186 * Text of entry (if applicable, see @ref GSM_EntryType).
187 */
188 unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH+1)*2];
189 /**
190 * Text of entry (if applicable, see @ref GSM_EntryType).
191 */
192 GSM_DateTime Date;
193 /**
194 * Number of entry (if applicable, see @ref GSM_EntryType).
195 */
196 int Number;
197 /**
198 * Voice dialling tag.
199 */
200 int VoiceTag;
201 int SMSList[20];
202} GSM_SubMemoryEntry;
203
204/**
205 * Structure for saving phonebook entries
206 */
207typedef struct {
208 /**
209 * Used memory for phonebook entry
210 */
211 GSM_MemoryType MemoryType;
212 /**
213 * Used location for phonebook entry
214 */
215 int Location;
216 /**
217 * Number of SubEntries in Entries table.
218 */
219 int EntriesNum;
220 /**
221 * Values of SubEntries.
222 */
223 GSM_SubMemoryEntry Entries[GSM_PHONEBOOK_ENTRIES];
224} GSM_MemoryEntry;
225
226typedef enum {
227 Nokia_VCard10 = 1,
228 Nokia_VCard21,
229 SonyEricsson_VCard10,
230 SonyEricsson_VCard21
231} GSM_VCardVersion;
232
233void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group);
234unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry);
235
236void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version);
237GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version);
238
239#ifndef ENABLE_LGPL
240/* (c) by Timo Teras */
241void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk);
242#endif
243
244/**
245 * Structure for saving speed dials
246 */
247typedef struct {
248 /**
249 * Number of speed dial: 2,3..,8,9
250 */
251 int Location;
252 /**
253 * ID of phone number used in phonebook entry
254 */
255 int MemoryNumberID;
256 /**
257 * Memory, where is saved used phonebook entry
258 */
259 GSM_MemoryType MemoryType;
260 /**
261 * Location in memory, where is saved used phonebook entry
262 */
263 int MemoryLocation;
264} GSM_SpeedDial;
265
266#endif
267
268/* How should editor hadle tabs in this file? Add editor commands here.
269 * vim: noexpandtab sw=8 ts=8 sts=8:
270 */
diff --git a/gammu/emb/common/service/gsmprof.h b/gammu/emb/common/service/gsmprof.h
new file mode 100644
index 0000000..2e3d087
--- a/dev/null
+++ b/gammu/emb/common/service/gsmprof.h
@@ -0,0 +1,104 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef __gsm_prof_h
4#define __gsm_prof_h
5
6typedef enum {
7 PROFILE_KEYPAD_LEVEL1 = 1,
8 PROFILE_KEYPAD_LEVEL2,
9 PROFILE_KEYPAD_LEVEL3,
10 PROFILE_KEYPAD_OFF,
11 PROFILE_CALLALERT_RINGING,
12 PROFILE_CALLALERT_BEEPONCE,
13 PROFILE_CALLALERT_OFF,
14 PROFILE_CALLALERT_RINGONCE,
15 PROFILE_CALLALERT_ASCENDING,
16 PROFILE_CALLALERT_CALLERGROUPS,
17 PROFILE_VOLUME_LEVEL1,
18 PROFILE_VOLUME_LEVEL2,
19 PROFILE_VOLUME_LEVEL3,
20 PROFILE_VOLUME_LEVEL4,
21 PROFILE_VOLUME_LEVEL5,
22 PROFILE_MESSAGE_NOTONE,
23 PROFILE_MESSAGE_STANDARD,
24 PROFILE_MESSAGE_SPECIAL,
25 PROFILE_MESSAGE_BEEPONCE,
26 PROFILE_MESSAGE_ASCENDING,
27 PROFILE_MESSAGE_PERSONAL,
28 PROFILE_VIBRATION_OFF,
29 PROFILE_VIBRATION_ON,
30 PROFILE_VIBRATION_FIRST,
31 PROFILE_WARNING_ON,
32 PROFILE_WARNING_OFF,
33 PROFILE_AUTOANSWER_ON,
34 PROFILE_AUTOANSWER_OFF,
35 PROFILE_LIGHTS_OFF,
36 PROFILE_LIGHTS_AUTO,
37 PROFILE_SAVER_ON,
38 PROFILE_SAVER_OFF,
39 PROFILE_SAVER_TIMEOUT_5SEC,
40 PROFILE_SAVER_TIMEOUT_20SEC,
41 PROFILE_SAVER_TIMEOUT_1MIN,
42 PROFILE_SAVER_TIMEOUT_2MIN,
43 PROFILE_SAVER_TIMEOUT_5MIN,
44 PROFILE_SAVER_TIMEOUT_10MIN
45} GSM_Profile_Feat_Value;
46
47typedef enum {
48 Profile_KeypadTone = 1,
49 Profile_CallAlert,
50 Profile_RingtoneVolume,
51 Profile_MessageTone,
52 Profile_Vibration,
53 Profile_WarningTone,
54 Profile_AutoAnswer,
55 Profile_Lights,
56 Profile_ScreenSaverTime,
57 Profile_ScreenSaver,
58
59 Profile_ScreenSaverNumber,
60 Profile_RingtoneID,
61 Profile_MessageToneID,
62 Profile_CallerGroups
63} GSM_Profile_Feat_ID;
64
65/**
66 * It contains phone profiles
67 */
68typedef struct {
69 bool Active;
70
71 /**
72 * Profile number
73 */
74 int Location;
75 /**
76 * Profile name
77 */
78 char Name[40*2];
79 /**
80 * Is it default name for profile ?
81 */
82 bool DefaultName;
83 bool HeadSetProfile;
84 bool CarKitProfile;
85
86 int FeaturesNumber;
87 GSM_Profile_Feat_ValueFeatureValue[15];
88 GSM_Profile_Feat_IDFeatureID[15];
89
90 bool CallerGroups[5];
91} GSM_Profile;
92
93typedef struct {
94 GSM_Profile_Feat_IDID;
95 GSM_Profile_Feat_ValueValue;
96 unsigned char PhoneID;
97 unsigned char PhoneValue;
98} GSM_Profile_PhoneTableValue;
99
100#endif
101
102/* How should editor hadle tabs in this file? Add editor commands here.
103 * vim: noexpandtab sw=8 ts=8 sts=8:
104 */
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
new file mode 100644
index 0000000..5a1ff87
--- a/dev/null
+++ b/gammu/emb/common/service/gsmring.c
@@ -0,0 +1,1600 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* Based on some work from Ralf Thelen (7110 ringtones),
3 * Gnokii (RTTL and SM) and others
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <ctype.h>
9#include <math.h>
10#ifdef WIN32
11# include <windows.h>
12#endif
13
14#include "../gsmcomon.h"
15#include "../misc/coding/coding.h"
16#include "../gsmstate.h"
17#include "gsmring.h"
18#include "sms/gsmsms.h"
19
20int GSM_RingNoteGetFrequency(GSM_RingNote Note)
21{
22 double freq=0;
23
24 /* Values according to the software from http://iki.fi/too/sw/xring/
25 * generated with:
26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
27 */
28 switch (Note.Note) {
29 case Note_C : freq = 523.3; break;
30 case Note_Cis: freq = 554.4; break;
31 case Note_D : freq = 587.3; break;
32 case Note_Dis: freq = 622.3; break;
33 case Note_E : freq = 659.3; break;
34 case Note_F : freq = 698.5; break;
35 case Note_Fis: freq = 740; break;
36 case Note_G : freq = 784; break;
37 case Note_Gis: freq = 830.6; break;
38 case Note_A : freq = 880; break;
39 case Note_Ais: freq = 932.3; break;
40 case Note_H : freq = 987.8; break;
41 case Note_Pause: break;
42 }
43 switch (Note.Scale) {
44 case Scale_440 : freq = freq / 2; break;
45 case Scale_880 : break;
46 case Scale_1760: freq = freq * 2; break;
47 case Scale_3520: freq = freq * 4; break;
48 default : break;
49 }
50 return (int)freq;
51}
52
53int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
54{
55 int duration = 1;
56
57 switch (Note.Duration) {
58 case Duration_Full : duration = 128; break;
59 case Duration_1_2 : duration = 64; break;
60 case Duration_1_4 : duration = 32; break;
61 case Duration_1_8 : duration = 16; break;
62 case Duration_1_16 : duration = 8; break;
63 case Duration_1_32 : duration = 4; break;
64 }
65 switch (Note.DurationSpec) {
66 case NoSpecialDuration : break;
67 case DottedNote : duration = duration * 3/2;break;
68 case DoubleDottedNote : duration = duration * 9/4;break;
69 case Length_2_3 : duration = duration * 2/3;break;
70 }
71 return duration;
72}
73
74#ifndef PI
75# define PI 3.141592654
76#endif
77
78#define WAV_SAMPLE_RATE 44100
79
80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
81{
82 unsigned char WAV_Header[] = {
83 'R','I','F','F',
84 0x00,0x00,0x00,0x00,/* Length */
85 'W','A','V','E'};
86 unsigned char FMT_Header[] = {'f','m','t',' ',
87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
89 unsigned char DATA_Header[] = {
90 'd','a','t','a',
91 0x00,0x00,0x00,0x00};/* Length */
92 short DATA_Buffer[60000];
93 long wavfilesize;
94 GSM_RingNote *Note;
95 long i,j,length=0;
96 double phase=0,phase_step;
97
98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
101
102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
104 Note = &ringtone->NoteTone.Commands[i].Note;
105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5;
106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) {
107 DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));
108 phase = phase + phase_step;
109 length++;
110 }
111 fwrite(&DATA_Buffer,sizeof(short),j,file);
112 }
113 }
114
115 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
116 WAV_Header[4] = ((unsigned char)wavfilesize % 256);
117 WAV_Header[5] = ((unsigned char)wavfilesize / 256);
118 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
119 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
120 wavfilesize = wavfilesize - 54;
121 DATA_Header[4] = ((unsigned char)wavfilesize % 256);
122 DATA_Header[5] = ((unsigned char)wavfilesize / 256);
123 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
124 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
125
126 fseek( file, 0, SEEK_SET);
127 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
128 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
129 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
130
131 return ERR_NONE;
132}
133
134static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
135{
136 char nullchar=0x00;
137
138 fwrite(&nullchar,1,1,file);
139 fwrite(&nullchar,1,1,file);
140 fprintf(file,"\x0C\x01\x2C");
141 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
142 fwrite(&nullchar,1,1,file);
143 fwrite(&nullchar,1,1,file);
144 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
145 return ERR_NONE;
146}
147
148static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
149{
150 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
151 return ERR_NONE;
152}
153
154GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
155{
156 GSM_RingNoteScaleDefNoteScale;
157 GSM_RingNoteDurationDefNoteDuration;
158
159 GSM_RingNoteStyleDefNoteStyle=0;
160 int DefNoteTempo=0;
161
162 bool started = false, firstcomma = true;
163 GSM_RingNote *Note;
164
165 unsigned char buffer[15];
166 int i,j,k=0;
167
168 /* Saves ringtone name */
169 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
170
171 /* Find the most frequently used duration */
172 for (i=0;i<6;i++) buffer[i]=0;
173 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
174 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
175 Note = &ringtone->NoteTone.Commands[i].Note;
176 /* some durations need 2 bytes in file, some 1 */
177 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
178 buffer[Note->Duration/32]++;
179 }
180 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
181 buffer[Note->Duration/32]+=2;
182 }
183 }
184 }
185 /* Now find the most frequently used */
186 j=0;
187 for (i=0;i<6;i++) {
188 if (buffer[i]>j) {
189 k=i;
190 j=buffer[i];
191 }
192 }
193 /* Finally convert the default duration */
194 DefNoteDuration = k * 32;
195 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
196 switch (DefNoteDuration) {
197 case Duration_Full:fprintf(file,"d=1"); break;
198 case Duration_1_2 :fprintf(file,"d=2"); break;
199 case Duration_1_4 :fprintf(file,"d=4"); break;
200 case Duration_1_8 :fprintf(file,"d=8"); break;
201 case Duration_1_16:fprintf(file,"d=16");break;
202 case Duration_1_32:fprintf(file,"d=32");break;
203 }
204
205 /* Find the most frequently used scale */
206 for (i=0;i<9;i++) buffer[i]=0;
207 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
208 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
209 Note = &ringtone->NoteTone.Commands[i].Note;
210 if (Note->Note!=Note_Pause &&
211 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
212 buffer[Note->Scale - 1]++;
213 }
214 }
215 }
216 j=0;
217 for (i=0;i<9;i++) {
218 if (buffer[i]>j) {
219 k = i;
220 j=buffer[i];
221 }
222 }
223 DefNoteScale = k + 1;
224 /* Save the default scale */
225 fprintf(file,",o=%i,",DefNoteScale);
226 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
227
228 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
229 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
230
231 Note = &ringtone->NoteTone.Commands[i].Note;
232
233 /* Trick from PPM Edit */
234 if (Note->DurationSpec == DoubleDottedNote) {
235 switch (Note->Duration) {
236 case Duration_Full:Note->Duration = Duration_Full;break;
237 case Duration_1_2 :Note->Duration = Duration_Full;break;
238 case Duration_1_4 :Note->Duration = Duration_1_2; break;
239 case Duration_1_8 :Note->Duration = Duration_1_4; break;
240 case Duration_1_16:Note->Duration = Duration_1_8; break;
241 case Duration_1_32:Note->Duration = Duration_1_16;break;
242 }
243 Note->DurationSpec = NoSpecialDuration;
244 }
245
246 if (!started) {
247 DefNoteTempo=Note->Tempo;
248 DefNoteStyle=Note->Style;
249 switch (Note->Style) {
250 case StaccatoStyle: fprintf(file,"s=S,"); break;
251 case NaturalStyle : fprintf(file,"s=N,"); break;
252 case ContinuousStyle : break;
253 }
254 /* Save the default tempo */
255 fprintf(file,"b=%i:",DefNoteTempo);
256 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo);
257 started = true;
258 firstcomma = true;
259 }
260
261 if (!started) continue;
262
263 if (Note->Style!=DefNoteStyle) {
264 /* And a separator */
265 if (!firstcomma) fprintf(file,",");
266 firstcomma = false;
267 DefNoteStyle=Note->Style;
268 switch (Note->Style) {
269 case StaccatoStyle : fprintf(file,"s=S"); break;
270 case NaturalStyle : fprintf(file,"s=N"); break;
271 case ContinuousStyle: fprintf(file,"s=C"); break;
272 }
273 }
274 if (Note->Tempo!=DefNoteTempo) {
275 /* And a separator */
276 if (!firstcomma) fprintf(file,",");
277 firstcomma = false;
278 DefNoteTempo=Note->Tempo;
279 fprintf(file,"b=%i",DefNoteTempo);
280 }
281 /* This note has a duration different than the default. We must save it */
282 if (Note->Duration!=DefNoteDuration) {
283 /* And a separator */
284 if (!firstcomma) fprintf(file,",");
285 firstcomma = false;
286 switch (Note->Duration) {
287 case Duration_Full:fprintf(file,"1"); break;
288 case Duration_1_2 :fprintf(file,"2"); break;
289 case Duration_1_4 :fprintf(file,"4"); break;
290 case Duration_1_8 :fprintf(file,"8"); break;
291 case Duration_1_16:fprintf(file,"16");break;
292 case Duration_1_32:fprintf(file,"32");break;
293 }
294 } else {
295 /* And a separator */
296 if (!firstcomma) fprintf(file,",");
297 firstcomma = false;
298 }
299 /* Now save the actual note */
300 switch (Note->Note) {
301 case Note_C :fprintf(file,"c");break;
302 case Note_Cis:fprintf(file,"c#");break;
303 case Note_D :fprintf(file,"d");break;
304 case Note_Dis:fprintf(file,"d#");break;
305 case Note_E :fprintf(file,"e");break;
306 case Note_F :fprintf(file,"f");break;
307 case Note_Fis:fprintf(file,"f#");break;
308 case Note_G :fprintf(file,"g");break;
309 case Note_Gis:fprintf(file,"g#");break;
310 case Note_A :fprintf(file,"a");break;
311 case Note_Ais:fprintf(file,"a#");break;
312 case Note_H :fprintf(file,"h");break;
313 default :fprintf(file,"p");break; /*Pause ?*/
314 }
315 switch (Note->DurationSpec) {
316 case DottedNote : fprintf(file,".");break;
317 default : break;
318 }
319 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
320 fprintf(file,"%i",Note->Scale);
321 }
322 }
323 return ERR_NONE;
324}
325
326void saveimelody(FILE *file, GSM_Ringtone *ringtone)
327{
328 char Buffer[2000];
329 int i=2000;
330
331 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true);
332
333 fwrite(Buffer, 1, i, file);
334}
335
336#ifndef ENABLE_LGPL
337
338static void WriteVarLen(unsigned char* midifile, int* current, long value)
339{
340 long buffer;
341
342 buffer = value & 0x7f;
343
344 while (value >>= 7) {
345 buffer <<= 8;
346 buffer |= 0x80;
347 buffer += (value & 0x7f);
348 }
349
350 while (1) {
351 midifile[(*current)++] = (unsigned char)buffer;
352 if (buffer & 0x80) {
353 buffer >>= 8;
354 } else {
355 break;
356 }
357 }
358}
359
360#define singlepauses
361
362/* FIXME: need adding tempo before each note and scale too ? */
363void savemid(FILE* file, GSM_Ringtone *ringtone)
364{
365 int pause = 0, current = 26, duration, i, note=0, length = 20;
366 bool started = false;
367 GSM_RingNote *Note;
368 unsigned char midifile[3000] = {
369 0x4D, 0x54, 0x68, 0x64, // MThd
370 0x00, 0x00, 0x00, 0x06, // chunk length
371 0x00, 0x00, // format 0
372 0x00, 0x01, // one track
373 0x00, 0x20, // 32 per quarter note
374 0x4D, 0x54, 0x72, 0x6B, // MTrk
375 0x00, 0x00, 0x00, 0x00, // chunk length
376 0x00, 0xFF, 0x51, 0x03, // tempo meta event
377 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note
378
379 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
380 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
381 Note = &ringtone->NoteTone.Commands[i].Note;
382 if (!started) {
383 /* readmid does not read pauses at the beginning */
384 if (Note->Note != Note_Pause) {
385 /* FIXME: we need add tempo before each note or so... */
386 long duration=60000000/Note->Tempo;
387
388 midifile[current++] = (unsigned char)(duration >> 16);
389 midifile[current++] = (unsigned char)(duration >> 8);
390 midifile[current++] = (unsigned char)duration;
391
392 started = true;
393 }
394 }
395 if (!started) continue;
396 duration = GSM_RingNoteGetFullDuration(*Note);
397 if (Note->Note == Note_Pause) {
398 pause += duration;
399#ifdef singlepauses
400 WriteVarLen(midifile,&current,pause);
401 pause=0;
402 midifile[current++]=0x00; // pause
403 midifile[current++]=0x00;
404#endif
405 } else {
406 if (Note->Note >= Note_C && Note->Note <= Note_H) {
407 note = Note->Note/16 + 12 * Note->Scale - 1;
408 }
409
410 WriteVarLen(midifile,&current,pause);
411 pause=0;
412 midifile[current++]=0x90; // note on
413 midifile[current++]=note;
414 midifile[current++]=0x64; // forte
415
416 WriteVarLen(midifile,&current,duration);
417 midifile[current++]=0x80; // note off
418 midifile[current++]=note;
419 midifile[current++]=0x64;
420 }
421 }
422 }
423 if (pause) {
424 WriteVarLen(midifile,&current,pause);
425 midifile[current++]=0x00; // pause
426 midifile[current++]=0x00; //
427 }
428 midifile[current++] = 0x00;
429 midifile[current++] = 0xFF; // track end
430 midifile[current++] = 0x2F;
431 midifile[current++] = 0x00;
432 midifile[length++] = (current-22) >> 8;
433 midifile[length++] = current-22;
434
435 fwrite(midifile,1,current,file);
436}
437
438#endif
439
440void saveott(FILE *file, GSM_Ringtone *ringtone)
441{
442 char Buffer[2000];
443 int i=2000;
444
445 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i);
446
447 fwrite(Buffer, 1, i, file);
448}
449
450GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
451{
452 FILE *file;
453
454 file = fopen(FileName, "wb");
455 if (file == NULL) return ERR_CANTOPENFILE;
456
457 switch (ringtone->Format) {
458 case RING_NOTETONE:
459 if (strstr(FileName,".ott")) {
460 saveott(file,ringtone);
461#ifndef ENABLE_LGPL
462 } else if (strstr(FileName,".mid")) {
463 savemid(file,ringtone);
464#endif
465 } else if (strstr(FileName,".rng")) {
466 saveott(file,ringtone);
467 } else if (strstr(FileName,".imy")) {
468 saveimelody(file,ringtone);
469 } else if (strstr(FileName,".ime")) {
470 saveimelody(file,ringtone);
471 } else if (strstr(FileName,".wav")) {
472 savewav(file,ringtone);
473 } else {
474 saverttl(file, ringtone);
475 }
476 break;
477 case RING_NOKIABINARY:
478 savebin(file, ringtone);
479 break;
480 case RING_MIDI:
481 savepuremidi(file, ringtone);
482 break;
483 }
484
485 fclose(file);
486
487 return ERR_NONE;
488}
489
490static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
491{
492 GSM_RingNoteScale DefNoteScale= Scale_880;
493 GSM_RingNoteDuration DefNoteDuration= Duration_1_4;
494 GSM_RingNoteStyle DefNoteStyle= NaturalStyle;
495 int DefNoteTempo= 63, i=0;
496
497 unsigned char buffer[2000],Name[100];
498 GSM_RingNote *Note;
499
500 fread(buffer, 2000, 1, file);
501
502 ringtone->NoteTone.NrCommands = 0;
503
504 /* -------------- name ---------------- */
505 while (buffer[i] != ':') {
506 if (buffer[i] == 0x00) return ERR_NONE;
507 i++;
508 }
509 if (i == 0) {
510 /* This is for RTTL ringtones without name. */
511 EncodeUnicode(ringtone->Name,"Gammu",5);
512 } else {
513 memcpy(Name,buffer,i);
514 Name[i] = 0x00;
515 EncodeUnicode(ringtone->Name,Name,strlen(Name));
516 }
517 i++;
518
519 /* --------- section with default ringtone settings ----------- */
520 while(1) {
521 switch (buffer[i]) {
522 case ':':
523 break;
524 case 0x00:
525 return ERR_NONE;
526 case 'd': case 'D':
527 switch (atoi(buffer+i+2)) {
528 case 1: DefNoteDuration = Duration_Full; break;
529 case 2: DefNoteDuration = Duration_1_2 ; break;
530 case 4: DefNoteDuration = Duration_1_4 ; break;
531 case 8: DefNoteDuration = Duration_1_8 ; break;
532 case 16: DefNoteDuration = Duration_1_16; break;
533 case 32: DefNoteDuration = Duration_1_32; break;
534 }
535 break;
536 case 'o': case 'O':
537 switch (atoi(buffer+i+2)) {
538 case 4: DefNoteScale = Scale_440 ; break;
539 case 5: DefNoteScale = Scale_880 ; break;
540 case 6: DefNoteScale = Scale_1760; break;
541 case 7: DefNoteScale = Scale_3520; break;
542 }
543 break;
544 case 'b': case 'B':
545 DefNoteTempo=atoi(buffer+i+2);
546 dbgprintf("Tempo = %i\n",DefNoteTempo);
547 break;
548 case 's': case 'S':
549 switch (buffer[i+1]) {
550 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
551 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
552 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
553 }
554 switch (buffer[i+2]) {
555 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
556 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
557 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
558 }
559 break;
560 }
561 while (buffer[i] != ':' && buffer[i] != ',') {
562 if (buffer[i] == 0x00) return ERR_NONE;
563 i++;
564 }
565 if (buffer[i] == ',') i++;
566 if (buffer[i] == ':') break;
567 }
568 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
569 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
570 i++;
571
572 /* ------------------------- notes ------------------------------ */
573 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) {
574 switch(buffer[i]) {
575 case 'z': case 'Z':
576 switch (buffer[i+1]) {
577 case 'd':
578 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
579 ringtone->NoteTone.NrCommands++;
580 break;
581 case 'D':
582 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
583 ringtone->NoteTone.NrCommands++;
584 break;
585 case 'v':
586 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra;
587 ringtone->NoteTone.NrCommands++;
588 break;
589 case 'V':
590 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
591 ringtone->NoteTone.NrCommands++;
592 break;
593 case 'l':
594 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight;
595 ringtone->NoteTone.NrCommands++;
596 break;
597 case 'L':
598 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
599 ringtone->NoteTone.NrCommands++;
600 }
601 break;
602 case 'o': case 'O':
603 switch (buffer[i+2]) {
604 case 4: DefNoteScale = Scale_440 ; break;
605 case 5: DefNoteScale = Scale_880 ; break;
606 case 6: DefNoteScale = Scale_1760; break;
607 case 7: DefNoteScale = Scale_3520; break;
608 }
609 break;
610 case 's': case 'S':
611 switch (buffer[i+1]) {
612 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
613 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
614 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
615 }
616 switch (buffer[i+2]) {
617 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
618 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
619 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
620 }
621 break;
622 default:
623 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
624 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
625 Note->Style = DefNoteStyle;
626 Note->Tempo = DefNoteTempo;
627 Note->Scale = DefNoteScale;
628 Note->Duration = DefNoteDuration;
629 Note->DurationSpec = NoSpecialDuration;
630 Note->Note = Note_Pause;
631
632 /* Duration */
633 switch (atoi(buffer+i)) {
634 case 1: Note->Duration = Duration_Full ; break;
635 case 2: Note->Duration = Duration_1_2 ; break;
636 case 4: Note->Duration = Duration_1_4 ; break;
637 case 8: Note->Duration = Duration_1_8 ; break;
638 case 16: Note->Duration = Duration_1_16 ; break;
639 case 32: Note->Duration = Duration_1_32 ; break;
640 }
641 /* We skip all numbers from duration specification */
642 while(isdigit(buffer[i])) i++;
643
644 /* Some files can have special duration here */
645 if (buffer[i]=='.') {
646 Note->DurationSpec = DottedNote;
647 i++;
648 }
649
650 /* Note */
651 /* B or b is not in specs, but I decided to put it, because
652 * it's in some RTTL files. It's the same to H note */
653 switch (buffer[i]) {
654 case 'A': case 'a': Note->Note = Note_A; break;
655 case 'B': case 'b': Note->Note = Note_H; break;
656 case 'C': case 'c': Note->Note = Note_C; break;
657 case 'D': case 'd': Note->Note = Note_D; break;
658 case 'E': case 'e': Note->Note = Note_E; break;
659 case 'F': case 'f': Note->Note = Note_F; break;
660 case 'G': case 'g': Note->Note = Note_G; break;
661 case 'H': case 'h': Note->Note = Note_H; break;
662 }
663 i++;
664
665 if (buffer[i]=='#') {
666 switch (Note->Note) {
667 case Note_A : Note->Note = Note_Ais; break;
668 case Note_C : Note->Note = Note_Cis; break;
669 case Note_D : Note->Note = Note_Dis; break;
670 case Note_F : Note->Note = Note_Fis; break;
671 case Note_G : Note->Note = Note_Gis; break;
672 default : break;
673 }
674 i++;
675 }
676
677 /* Some files can have special duration here */
678 if (buffer[i]=='.') {
679 Note->DurationSpec = DottedNote;
680 i++;
681 }
682
683 /* Scale */
684 if (Note->Note!=Note_Pause && isdigit(buffer[i])) {
685 switch (atoi(buffer+i)) {
686 case 4: Note->Scale = Scale_440 ; break;
687 case 5: Note->Scale = Scale_880 ; break;
688 case 6: Note->Scale = Scale_1760; break;
689 case 7: Note->Scale = Scale_3520; break;
690 }
691 i++;
692 }
693
694 ringtone->NoteTone.NrCommands++;
695 break;
696 }
697 while (buffer[i] != ',') {
698 if (buffer[i] == 0x00) return ERR_NONE;
699 i++;
700 }
701 if (buffer[i] == ',') i++;
702 }
703
704 return ERR_NONE;
705}
706
707static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
708{
709 char Buffer[2000];
710 int i;
711
712 i=fread(Buffer, 1, 2000, file);
713
714 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
715}
716
717static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
718{
719 char Buffer[4000];
720 int i,j;
721
722 i=fread(Buffer, 1, 4000, file);
723
724 i=0;j=0;
725 while (true) {
726 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
727 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
728 if (j==i-4) return ERR_UNKNOWN;
729 j++;
730 }
731 j++;
732
733 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j);
734}
735
736static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
737{
738 int i;
739 unsigned charbuffer[2000];
740
741 dbgprintf("loading binary\n");
742 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
743 i=5;
744 while (buffer[i]!=0x00) i++;
745 EncodeUnicode(ringtone->Name,buffer+5,i-5);
746 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
747 i++;
748 }
749 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
750 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
751 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
752 return ERR_NONE;
753}
754
755static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
756{
757 unsigned char buffer[30000];
758
759 dbgprintf("loading midi\n");
760 EncodeUnicode(ringtone->Name,"MIDI",4);
761 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
762 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
763 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
764 return ERR_NONE;
765}
766
767static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
768{
769 unsigned char buffer[2000];
770
771 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
772
773 if (buffer[18]==0x00 && buffer[21]!=0x02) {
774 /* DCT3, Unicode subformat, 62xx & 7110 */
775 CopyUnicodeString(ringtone->Name,buffer+18);
776 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
777 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
778 } else {
779 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
780 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
781 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
782 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
783 }
784 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
785 return ERR_NONE;
786}
787
788GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
789{
790 FILE *file;
791 unsigned charbuffer[300];
792 GSM_Errorerror = ERR_UNKNOWN;
793
794 dbgprintf("Loading ringtone %s\n",FileName);
795 file = fopen(FileName, "rb");
796 if (file == NULL) return ERR_CANTOPENFILE;
797
798 /* Read the header of the file. */
799 fread(buffer, 1, 4, file);
800 if (ringtone->Format == 0x00) {
801 ringtone->Format = RING_NOTETONE;
802 if (buffer[0]==0x00 && buffer[1]==0x00 &&
803 buffer[2]==0x0C && buffer[3]==0x01) {
804 ringtone->Format = RING_NOKIABINARY;
805 }
806 if (buffer[0]==0x00 && buffer[1]==0x00 &&
807 buffer[2]==0x00) {
808 ringtone->Format = RING_NOKIABINARY;
809 }
810 if (buffer[0]==0x4D && buffer[1]==0x54 &&
811 buffer[2]==0x68 && buffer[3]==0x64) {
812 ringtone->Format = RING_MIDI;
813 }
814 }
815 rewind(file);
816 switch (ringtone->Format) {
817 case RING_NOTETONE:
818 if (buffer[0]==0x02 && buffer[1]==0x4A) {
819 error=loadott(file,ringtone);
820 } else if (buffer[0]==0xC7 && buffer[1]==0x45) {
821 error=loadcommunicator(file,ringtone);
822 } else {
823 error=loadrttl(file,ringtone);
824 }
825 ringtone->NoteTone.AllNotesScale=false;
826 break;
827 case RING_NOKIABINARY:
828 if (buffer[0]==0x00 && buffer[1]==0x00 &&
829 buffer[2]==0x0C && buffer[3]==0x01) {
830 error=loadbin(file,ringtone);
831 }
832 if (buffer[0]==0x00 && buffer[1]==0x00 &&
833 buffer[2]==0x00) {
834 error=loadre(file,ringtone);
835 }
836 break;
837 case RING_MIDI:
838 EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
839 error = loadpuremidi(file,ringtone);
840 }
841 fclose(file);
842 return(error);
843}
844
845/* -------------------------- required with Nokia & RTTL ------------------- */
846
847/* Beats per Minute like written in Smart Messaging */
848static int SM_BeatsPerMinute[] = {
849 25, 28, 31, 35, 40, 45, 50, 56, 63,70,
850 80, 90, 100, 112, 125, 140, 160, 180, 200,225,
851 250, 285, 320, 355, 400, 450, 500, 565, 635,715,
852 800,900
853};
854
855int GSM_RTTLGetTempo(int Beats)
856{
857 int i=0;
858
859 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
860
861 return i<<3;
862}
863
864/* This function packs the ringtone from the structure "ringtone" to
865 "package", where maxlength means length of package.
866 Function returns number of packed notes and change maxlength to
867 number of used chars in "package" */
868unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength)
869{
870 unsigned char CommandLength = 0x02;
871 unsigned char Loop = 0x15;/* Infinite */
872
873 unsigned char Buffer[200];
874 int StartBit=0, OldStartBit;
875 int StartBitHowManyCommands;
876 int HowManyCommands = 0;/* How many instructions packed */
877 int HowManyNotes= 0;
878 int i,j;
879 bool started;
880 GSM_RingNote *Note;
881
882 GSM_RingNoteScale DefScale = 255;
883 GSM_RingNoteStyle DefStyle = 255;
884 int DefTempo = 255;
885
886 AddBufferByte(package, &StartBit, CommandLength, 8);
887 AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7);
888
889 /* According to specification we need have next part octet-aligned */
890 BufferAlign(package, &StartBit);
891
892 AddBufferByte(package, &StartBit, SM_Command_Sound, 7);
893 AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3);
894
895 /* Packing the name of the tune. */
896 EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name));
897 AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4);
898 AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer));
899
900 /* Packing info about song pattern */
901 AddBufferByte(package, &StartBit, 0x01, 8); //one pattern
902 AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3);
903 AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2);
904 AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4);
905
906 /* Later here will be HowManyCommands */
907 StartBitHowManyCommands=StartBit;
908 StartBit = StartBit + 8;
909
910 started = false;
911 for (i=0; i<ringtone.NoteTone.NrCommands; i++) {
912 if (ringtone.NoteTone.Commands[i].Type != RING_Note) {
913 HowManyNotes++;
914 continue;
915 }
916 Note = &ringtone.NoteTone.Commands[i].Note;
917 if (!started) {
918 /* First note can't be Pause - it makes problems
919 * for example with PC Composer
920 */
921 if (Note->Note != Note_Pause) started = true;
922 }
923 if (!started) {
924 HowManyNotes++;
925 continue;
926 }
927 OldStartBit = StartBit;
928 /* we don't write Scale & Style info before "Pause" note - it saves place */
929 if (Note->Note!=Note_Pause) {
930 if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) {
931 j = StartBit+5+8;
932 BufferAlignNumber(&j);
933 if ((j/8)>(*maxlength)) {
934 StartBit = OldStartBit;
935 break;
936 }
937 DefScale = Note->Scale;
938 AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3);
939 AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2);
940 HowManyCommands++;
941 }
942 if (DefStyle != Note->Style) {
943 j = StartBit+5+8;
944 BufferAlignNumber(&j);
945 if ((j/8)>(*maxlength)) {
946 StartBit = OldStartBit;
947 break;
948 }
949 DefStyle = Note->Style;
950 AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3);
951 AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2);
952 HowManyCommands++;
953 }
954 }
955 /* Beats per minute/tempo of the tune */
956 if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) {
957 j = StartBit+8+8;
958 BufferAlignNumber(&j);
959 if ((j/8)>(*maxlength)) {
960 StartBit = OldStartBit;
961 break;
962 }
963 DefTempo=GSM_RTTLGetTempo(Note->Tempo);
964 /* Adding beats per minute (tempo) of the tune */
965 AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3);
966 AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5);
967 HowManyCommands++;
968 }
969 j = StartBit+12+8;
970 BufferAlignNumber(&j);
971 if ((j/8)>(*maxlength)) {
972 StartBit = OldStartBit;
973 break;
974 }
975 /* Note */
976 AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3);
977 AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4);
978 AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3);
979 AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2);
980 HowManyCommands++;
981 /* We are sure, we pack it for SMS or setting to phone, not for OTT file */
982 if (*maxlength<1000) {
983 /* Like Pc Composer say - before of phone limitations...*/
984 if (HowManyNotes==130-1) break;
985 }
986 HowManyNotes++;
987 }
988
989 BufferAlign(package, &StartBit);
990 AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8);
991
992 OldStartBit = StartBit;
993 StartBit = StartBitHowManyCommands;
994 /* HowManyCommands */
995 AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8);
996 StartBit = OldStartBit;
997
998 *maxlength=StartBit/8;
999
1000 return(i);
1001}
1002
1003GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength)
1004{
1005 int StartBit=0, HowMany, l, q, i, spec;
1006 char Buffer[100];
1007 GSM_RingNote *Note;
1008
1009 /* Default ringtone parameters */
1010 GSM_RingNoteScale DefScale= Scale_880;
1011 GSM_RingNoteStyle DefStyle = NaturalStyle;
1012 int DefTempo= 63;
1013
1014 ringtone->Format = RING_NOTETONE;
1015 ringtone->NoteTone.NrCommands = 0;
1016
1017 GetBufferInt(package,&StartBit,&l,8);
1018 if (l!=0x02) {
1019 dbgprintf("Not header\n");
1020 return ERR_NOTSUPPORTED;
1021 }
1022
1023 GetBufferInt(package,&StartBit,&l,7);
1024 if (l!=SM_Command_RingingToneProgramming) {
1025 dbgprintf("Not RingingToneProgramming\n");
1026 return ERR_NOTSUPPORTED;
1027 }
1028
1029 /* According to specification we need have next part octet-aligned */
1030 BufferAlignNumber(&StartBit);
1031
1032 GetBufferInt(package,&StartBit,&l,7);
1033 if (l!=SM_Command_Sound) {
1034 dbgprintf("Not Sound\n");
1035 return ERR_NOTSUPPORTED;
1036 }
1037
1038 GetBufferInt(package,&StartBit,&l,3);
1039 if (l!=SM_Song_BasicSongType) {
1040 dbgprintf("Not BasicSongType\n");
1041 return ERR_NOTSUPPORTED;
1042 }
1043
1044 /* Getting length of the tune name */
1045 GetBufferInt(package,&StartBit,&l,4);
1046 l=l>>4;
1047
1048 /* Unpacking the name of the tune. */
1049 GetBuffer(package, &StartBit, Buffer, 8*l);
1050 Buffer[l]=0;
1051 EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer));
1052 DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name));
1053 CopyUnicodeString(ringtone->Name,Buffer);
1054
1055 GetBufferInt(package,&StartBit,&l,8);
1056 dbgprintf("Number of song patterns: %i\n",l);
1057 /* we support only one song pattern */
1058 if (l!=1) return ERR_NOTSUPPORTED;
1059
1060 GetBufferInt(package,&StartBit,&l,3);
1061 if (l!=SM_InstructionID_PatternHeaderId) {
1062 dbgprintf("Not PatternHeaderId\n");
1063 return ERR_NOTSUPPORTED;
1064 }
1065
1066 /* Pattern ID - we ignore it */
1067 StartBit+=2;
1068
1069 GetBufferInt(package,&StartBit,&l,4);
1070 l=l>>4;
1071 dbgprintf("Loop value: %i\n",l);
1072
1073 HowMany=0;
1074 GetBufferInt(package, &StartBit, &HowMany, 8);
1075
1076 for (i=0;i<HowMany;i++) {
1077 GetBufferInt(package,&StartBit,&q,3);
1078 switch (q) {
1079 case SM_InstructionID_VolumeInstructionId:
1080 StartBit+=4;
1081 break;
1082 case SM_InstructionID_StyleInstructionId:
1083 GetBufferInt(package,&StartBit,&l,2);
1084 if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l;
1085 break;
1086 case SM_InstructionID_TempoInstructionId:
1087 GetBufferInt(package,&StartBit,&l,5);
1088 DefTempo=SM_BeatsPerMinute[l>>3];
1089 break;
1090 case SM_InstructionID_ScaleInstructionId:
1091 GetBufferInt(package,&StartBit,&l,2);
1092 DefScale=(l>>6)+4;
1093 break;
1094 case SM_InstructionID_NoteInstructionId:
1095 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
1096 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
1097
1098 GetBufferInt(package,&StartBit,&l,4);
1099 Note->Note=Note_Pause;
1100 if (l >= Note_C && l <= Note_H) Note->Note = l;
1101
1102 GetBufferInt(package,&StartBit,&l,3);
1103 if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l;
1104
1105 GetBufferInt(package,&StartBit,&spec,2);
1106 if (spec >= NoSpecialDuration && spec <= Length_2_3) {
1107 Note->DurationSpec = spec;
1108 }
1109
1110 Note->Scale = DefScale;
1111 Note->Style = DefStyle;
1112 Note->Tempo = DefTempo;
1113 if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break;
1114 ringtone->NoteTone.NrCommands++;
1115 break;
1116 default:
1117 dbgprintf("Unsupported block %i %i\n",q,i);
1118 return ERR_NOTSUPPORTED;
1119 }
1120 }
1121 return ERR_NONE;
1122}
1123
1124static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src)
1125{
1126 int current = 0, i, note, lastnote = 0, duration;
1127 GSM_RingNote *Note;
1128 unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
1129 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
1130 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B};
1131
1132 strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3;
1133 dest->NokiaBinary.Frame[current++]=0x00;
1134
1135 /*This command can be used to loop, where 0xLL = 0x01 - 0x10
1136 *0x01=loop once [...] 0x10=loop infinite
1137 *Commented now
1138
1139 dest->NokiaBinary.Frame[current++]=0x05;
1140 dest->NokiaBinary.Frame[current++]=0xLL;
1141 */
1142 strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2;
1143
1144 for (i=0; i<src->NoteTone.NrCommands; i++) {
1145 if (src->NoteTone.Commands[i].Type != RING_Note) continue;
1146
1147 Note = &src->NoteTone.Commands[i].Note;
1148 note = 64; /* Pause */
1149 if (Note->Note!=Note_Pause) {
1150 if (Note->Note >= Note_C && Note->Note <= Note_H) {
1151 note = 113 + Note->Note/16;
1152 }
1153 switch (Note->Scale) {
1154 case Scale_440 : break;
1155 case Scale_880 : note = note + 12; break;
1156 case Scale_1760: note = note + 24;break;
1157 case Scale_3520: note = note + 36; break;
1158 default : break;
1159 }
1160 }
1161
1162 /* In 7110 we have 8 ms long sounds */
1163 duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256;
1164
1165 switch (Note->Style) {
1166 case StaccatoStyle:
1167 if (duration) {
1168 /* Note needs only one sound */
1169 dest->NokiaBinary.Frame[current++] = note;
1170 dest->NokiaBinary.Frame[current++] = 1;
1171 duration--;
1172 }
1173 note = 0x40; /* The rest is pause */
1174 case NaturalStyle:
1175 if (note != 0x40 && duration) {
1176 dest->NokiaBinary.Frame[current++] = 0x40;
1177 /* There is small pause between notes */
1178 dest->NokiaBinary.Frame[current++] = 1;
1179 duration--;
1180 }
1181 default:
1182 if (note != 0x40 && note == lastnote && duration) {
1183 dest->NokiaBinary.Frame[current++] = 0x40;
1184 /* There is small pause between same notes */
1185 dest->NokiaBinary.Frame[current++] = 1;
1186 duration--;
1187 }
1188 while (duration > 125) {
1189 dest->NokiaBinary.Frame[current++] = note;
1190 dest->NokiaBinary.Frame[current++] = 125;
1191 duration -= 125;
1192 }
1193 dest->NokiaBinary.Frame[current++] = note;
1194 dest->NokiaBinary.Frame[current++] = duration;
1195 }
1196 lastnote = note;
1197 }
1198 for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i];
1199 dest->NokiaBinary.Length=current;
1200}
1201
1202static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src)
1203{
1204 int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy;
1205 int StartRepeat = 0, EndRepeat, Speed;
1206 unsigned char command,length=0;
1207 int NotesLen[500];
1208 GSM_RingNoteScale NotesScale[500];
1209 GSM_RingNoteNote Notes[500];
1210 int Lengths[6*4];
1211 GSM_RingNoteDurationSpec DurationSpec[6*4];
1212 GSM_RingNoteDuration Duration[6*4];
1213 bool foundlen;
1214 GSM_RingNote *Note;
1215
1216 while (i<src->NokiaBinary.Length) {
1217 command = src->NokiaBinary.Frame[i];
1218 i++;
1219 if (command != 0x06 && command != 0x00 && command != 0x09) {
1220 length = src->NokiaBinary.Frame[i];
1221 i++;
1222 dbgprintf("Block %02x %02x - ",length,command);
1223 } else dbgprintf("Block %02x - ",command);
1224 if (command >= 114 && command <= 161) {
1225 dbgprintf("note\n");
1226 if (command >= 114 && command <= 124) {
1227 NotesScale[NrNotes] = Scale_440; command -= 114;
1228 } else if (command >= 125 && command <= 137) {
1229 NotesScale[NrNotes] = Scale_880; command -= 126;
1230 } else if (command >= 138 && command <= 149) {
1231 NotesScale[NrNotes] = Scale_1760; command -= 138;
1232 } else if (command >= 150 && command <= 161) {
1233 NotesScale[NrNotes] = Scale_3520; command -= 150;
1234 }
1235 switch (command) {
1236 case 0 : Notes[NrNotes] = Note_C;break;
1237 case 1 : Notes[NrNotes] = Note_Cis;break;
1238 case 2 : Notes[NrNotes] = Note_D;break;
1239 case 3 : Notes[NrNotes] = Note_Dis;break;
1240 case 4 : Notes[NrNotes] = Note_E;break;
1241 case 5 : Notes[NrNotes] = Note_F;break;
1242 case 6 : Notes[NrNotes] = Note_Fis;break;
1243 case 7 : Notes[NrNotes] = Note_G;break;
1244 case 8 : Notes[NrNotes] = Note_Gis;break;
1245 case 9 : Notes[NrNotes] = Note_A;break;
1246 case 10 : Notes[NrNotes] = Note_Ais;break;
1247 case 11 : Notes[NrNotes] = Note_H;break;
1248 }
1249 if (NrNotes > 0) {
1250 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1251 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1252 NotesLen[NrNotes-1]+=length;
1253 } else {
1254 NotesLen[NrNotes]=length;
1255 NrNotes++;
1256 }
1257 } else {
1258 NotesLen[NrNotes]=length;
1259 NrNotes++;
1260 }
1261 } else switch (command) {
1262 case 0x00:
1263 dbgprintf("Unknown\n");
1264 break;
1265 case 0x05:
1266 dbgprintf("repeat %i times\n",length);
1267 repeat = length;
1268 StartRepeat = NrNotes;
1269 break;
1270 case 0x06:
1271 dbgprintf("end repeat\n");
1272 EndRepeat = NrNotes;
1273 for (z=0;z<repeat-1;z++) {
1274 for (j=StartRepeat;j<EndRepeat;j++) {
1275 Notes[NrNotes] = Notes[j];
1276 NotesScale[NrNotes] = NotesScale[j];
1277 NotesLen[NrNotes] = NotesLen[j];
1278 NrNotes++;
1279 dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]);
1280 }
1281 }
1282 break;
1283 case 0x07:
1284 if (length == 0x0B) {
1285 dbgprintf("Ringtone end\n");
1286 i = src->NokiaBinary.Length + 1;
1287 }
1288 break;
1289 case 0x09:
1290 dbgprintf("Unknown\n");
1291 break;
1292 case 0x0A:
1293 if (length == 0x01) {
1294 dbgprintf("Let's start our song\n");
1295 break;
1296 }
1297 if (length == 0x0A) {
1298 dbgprintf("Ending joining note\n");
1299 break;
1300 }
1301 if (length == 0xFE) {
1302 dbgprintf("Starting joining note\n");
1303 break;
1304 }
1305 break;
1306 case 0x40:
1307 dbgprintf("Pause\n");
1308 Notes[NrNotes] = Note_Pause;
1309 if (NrNotes > 0) {
1310 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1311 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1312 NotesLen[NrNotes-1]+=length;
1313 } else {
1314 NotesLen[NrNotes]=length;
1315 NrNotes++;
1316 }
1317 } else {
1318 NotesLen[NrNotes]=length;
1319 NrNotes++;
1320 }
1321 break;
1322 default:
1323 dbgprintf("Unknown\n");
1324 }
1325 }
1326
1327 while (NrNotes>0) {
1328 if (Notes[NrNotes-1] == Note_Pause) {
1329 NrNotes--;
1330 } else break;
1331 }
1332
1333 for (accuracy=1; accuracy<5; accuracy++) {
1334 i = 1;
1335 while (i < 1000) {
1336 Lengths[0] = 30000/i;
1337 for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2;
1338 for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2;
1339 for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4;
1340 for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3;
1341
1342#ifdef DEBUG
1343 dbgprintf("Length matrix (%i) : ",i);
1344 for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]);
1345 dbgprintf("\n");
1346#endif
1347 foundlen = false;
1348
1349 for (j=0;j<NrNotes;j++) {
1350 dbgprintf("Comparing to %i\n",NotesLen[j]);
1351 foundlen = false;
1352 for (z=0;z<6*4;z++) {
1353 if (NotesLen[j] - Lengths[z] > -accuracy &&
1354 NotesLen[j] - Lengths[z] < accuracy) {
1355 foundlen = true;
1356 break;
1357 }
1358 }
1359 if (!foundlen) break;
1360 }
1361 if (foundlen) break;
1362 i++;
1363 }
1364
1365 if (foundlen) {
1366 Speed = i;
1367 Duration[5] = Duration_1_32; Duration[4] = Duration_1_16;
1368 Duration[3] = Duration_1_8; Duration[2] = Duration_1_4;
1369 Duration[1] = Duration_1_2; Duration[0] = Duration_Full;
1370 for (i=0;i<6;i++) Duration[i] = Duration[i];
1371 for (i=0;i<6;i++) Duration[i+6] = Duration[i];
1372 for (i=0;i<6;i++) Duration[i+12] = Duration[i];
1373 for (i=0;i<6;i++) Duration[i+18] = Duration[i];
1374 for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration;
1375 for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote;
1376 for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote;
1377 for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3;
1378
1379 for (i=0;i<NrNotes;i++) {
1380 dest->NoteTone.Commands[i].Type= RING_Note;
1381 Note = &dest->NoteTone.Commands[i].Note;
1382 Note->Note = Notes[i];
1383 Note->Tempo = Speed;
1384 Note->Style = ContinuousStyle;
1385 if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i];
1386 for (z=0;z<6*4;z++) {
1387 if (NotesLen[i] - Lengths[z] > -accuracy &&
1388 NotesLen[i] - Lengths[z] < accuracy) {
1389 Note->Duration = Duration[z];
1390 Note->DurationSpec = DurationSpec[z];
1391 /* Trick from PPM Edit */
1392 if (Note->DurationSpec == DoubleDottedNote) {
1393 switch (Note->Duration) {
1394 case Duration_Full:Note->Duration = Duration_Full;break;
1395 case Duration_1_2 :Note->Duration = Duration_Full;break;
1396 case Duration_1_4 :Note->Duration = Duration_1_2; break;
1397 case Duration_1_8 :Note->Duration = Duration_1_4; break;
1398 case Duration_1_16:Note->Duration = Duration_1_8; break;
1399 case Duration_1_32:Note->Duration = Duration_1_16;break;
1400 }
1401 Note->DurationSpec = NoSpecialDuration;
1402 }
1403 /* Here happy creation */
1404 if (Note->DurationSpec == Length_2_3) {
1405 Note->DurationSpec = NoSpecialDuration;
1406 }
1407
1408 break;
1409 }
1410 }
1411 }
1412 dest->NoteTone.NrCommands = NrNotes;
1413 dbgprintf("speed = %i\n",Speed);
1414 break;
1415 }
1416 }
1417
1418 if (!foundlen) dest->NoteTone.NrCommands = 0;
1419}
1420
1421 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat)
1422{
1423 dest->Format = Format;
1424 CopyUnicodeString(dest->Name,src->Name);
1425 if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) {
1426 RTTL2Binary(dest, src);
1427 return ERR_NONE;
1428 }
1429 if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) {
1430 Binary2RTTL(dest, src);
1431 return ERR_NONE;
1432 }
1433 /* The same source and target format */
1434 if (src->Format==Format) {
1435 memcpy(dest,src,sizeof(GSM_Ringtone));
1436 return ERR_NONE;
1437 }
1438 return ERR_NOTIMPLEMENTED;
1439}
1440
1441/* 0 = No header and footer, 0.5 = partial header and footer,
1442 * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */
1443unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start)
1444{
1445 int i, NrNotes = 0, Len, Max = *maxlength;
1446
1447 GSM_RingNote *Note;
1448
1449 GSM_RingNoteScaleDefNoteScale;
1450 GSM_RingNoteStyleDefNoteStyle=0;
1451 int DefNoteTempo=0;
1452
1453 bool started = false, end;
1454
1455 *maxlength = 0;
1456
1457 if (start) {
1458 if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10);
1459 if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10);
1460 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10);
1461 if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10);
1462 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10);
1463 }
1464
1465 DefNoteScale = Scale_880; /* by iMelody definition */
1466
1467 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1468 Len = *maxlength;
1469 if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue;
1470
1471 Note = &ringtone.NoteTone.Commands[i].Note;
1472 if (Note->Note == Note_Pause) continue;
1473
1474 if (version == 1.2 && start) {
1475 /* Save the default tempo */
1476 DefNoteTempo = Note->Tempo;
1477 Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10);
1478 dbgprintf("DefNoteTempo=%d\n",DefNoteTempo);
1479
1480 /* Save default style */
1481 DefNoteStyle = Note->Style;
1482 switch (DefNoteStyle) {
1483 case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break;
1484 case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break;
1485 case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break;
1486 }
1487 }
1488 Len+=sprintf(package+Len,"MELODY:");
1489 if (version != 0) {
1490 /* 15 = Len of END:IMELODY... */
1491 if ((Len+15) > Max) { end = true; break; }
1492 } else {
1493 if (Len > Max) { end = true; break; }
1494 }
1495 *maxlength = Len;
1496 break;
1497 }
1498
1499 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1500 end = false;
1501 Len = *maxlength;
1502 switch (ringtone.NoteTone.Commands[i].Type) {
1503 case RING_Note:
1504 Note = &ringtone.NoteTone.Commands[i].Note;
1505 if (!started && Note->Note != Note_Pause) started = true;
1506 if (!started) break;
1507 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
1508 Len+=sprintf(package+Len,"*%i",Note->Scale-1);
1509 }
1510 switch (Note->Note) {
1511 case Note_C :Len+=sprintf(package+Len,"c");break;
1512 case Note_Cis:Len+=sprintf(package+Len,"#c");break;
1513 case Note_D :Len+=sprintf(package+Len,"d");break;
1514 case Note_Dis:Len+=sprintf(package+Len,"#d");break;
1515 case Note_E :Len+=sprintf(package+Len,"e");break;
1516 case Note_F :Len+=sprintf(package+Len,"f");break;
1517 case Note_Fis:Len+=sprintf(package+Len,"#f");break;
1518 case Note_G :Len+=sprintf(package+Len,"g");break;
1519 case Note_Gis:Len+=sprintf(package+Len,"#g");break;
1520 case Note_A :Len+=sprintf(package+Len,"a");break;
1521 case Note_Ais:Len+=sprintf(package+Len,"#a");break;
1522 case Note_H :Len+=sprintf(package+Len,"b");break;
1523 case Note_Pause :Len+=sprintf(package+Len,"r");break;
1524 }
1525 switch (Note->Duration) {
1526 case Duration_Full : package[Len++]='0';break;
1527 case Duration_1_2 : package[Len++]='1';break;
1528 case Duration_1_4 : package[Len++]='2';break;
1529 case Duration_1_8 : package[Len++]='3';break;
1530 case Duration_1_16 : package[Len++]='4';break;
1531 case Duration_1_32 : package[Len++]='5';break;
1532 default : break;
1533 }
1534 switch (Note->DurationSpec) {
1535 case DottedNote : package[Len++] = '.'; break;
1536 case DoubleDottedNote: package[Len++] = ':'; break;
1537 case Length_2_3 : package[Len++] = ';'; break;
1538 default : break;
1539 }
1540 if (version != 0) {
1541 /* 15 = Len of END:IMELODY... */
1542 if ((Len+15) > Max) { end = true; break; }
1543 } else {
1544 if (Len > Max) { end = true; break; }
1545 }
1546 *maxlength = Len;
1547 break;
1548 case RING_DisableLED:
1549 if ((Len + 6) > Max) { end = true; break; }
1550 (*maxlength)+=sprintf(package+Len,"ledoff");
1551 break;
1552 case RING_EnableLED:
1553 if ((Len + 5) > Max) { end = true; break; }
1554 (*maxlength)+=sprintf(package+Len,"ledon");
1555 break;
1556 case RING_DisableVibra:
1557 if ((Len + 7) > Max) { end = true; break; }
1558 (*maxlength)+=sprintf(package+Len,"vibeoff");
1559 break;
1560 case RING_EnableVibra:
1561 if ((Len + 6) > Max) { end = true; break; }
1562 (*maxlength)+=sprintf(package+Len,"vibeon");
1563 break;
1564 case RING_DisableLight:
1565 if ((Len + 7) > Max) { end = true; break; }
1566 (*maxlength)+=sprintf(package+Len,"backoff");
1567 break;
1568 case RING_EnableLight:
1569 if ((Len + 6) > Max) { end = true; break; }
1570 (*maxlength)+=sprintf(package+Len,"backon");
1571 break;
1572 default:
1573 break;
1574 }
1575 if (end) break;
1576 NrNotes ++;
1577 }
1578
1579 if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10);
1580
1581 return NrNotes;
1582}
1583
1584char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID)
1585{
1586 int i;
1587 static char ala[2];
1588
1589 for (i=0;i<Info->Number;i++) {
1590 if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name;
1591 }
1592
1593 ala[0] = 0;
1594 ala[1] = 0;
1595 return ala;
1596}
1597
1598/* How should editor hadle tabs in this file? Add editor commands here.
1599 * vim: noexpandtab sw=8 ts=8 sts=8:
1600 */
diff --git a/gammu/emb/common/service/gsmring.h b/gammu/emb/common/service/gsmring.h
new file mode 100644
index 0000000..207cf31
--- a/dev/null
+++ b/gammu/emb/common/service/gsmring.h
@@ -0,0 +1,202 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_ring_h
4#define __gsm_ring_h
5
6/* --------------- Smart Messaging Specification 2.0 & 3.0 ----------------- */
7
8 #define SM_CommandEnd_CommandEnd 0x00
9
10/* specification gives also other */
11 #define SM_Command_RingingToneProgramming 0x25<<1
12 #define SM_Command_Sound 0x1d<<1
13/* specification gives also other */
14
15 #define SM_Song_BasicSongType 0x01<<5
16/* specification gives also other */
17
18 #define SM_PatternID_A_part 0x00<<6
19/* specification gives also other */
20
21 #define SM_InstructionID_PatternHeaderId 0x00<<5
22 #define SM_InstructionID_NoteInstructionId 0x01<<5
23 #define SM_InstructionID_ScaleInstructionId 0x02<<5
24 #define SM_InstructionID_StyleInstructionId 0x03<<5
25 #define SM_InstructionID_TempoInstructionId 0x04<<5
26 #define SM_InstructionID_VolumeInstructionId 0x05<<5
27
28/* ------ end of Smart Messaging Specification 2.0 & 3.0 definitions ------- */
29
30#define MAX_RINGTONE_NOTES 255
31
32typedef enum {
33 /**
34 * Natural style (rest between notes)
35 */
36 NaturalStyle = 0x00<<6,
37 /**
38 * Continuous style (no rest between notes)
39 */
40 ContinuousStyle = 0x01<<6,
41 /**
42 * Staccato style (shorter notes and longer rest period)
43 */
44 StaccatoStyle = 0x02<<6
45} GSM_RingNoteStyle;
46
47typedef enum {
48 Note_Pause = 0x00<<4,
49 Note_C = 0x01<<4,
50 Note_Cis = 0x02<<4,
51 Note_D = 0x03<<4,
52 Note_Dis = 0x04<<4,
53 Note_E = 0x05<<4,
54 Note_F = 0x06<<4,
55 Note_Fis = 0x07<<4,
56 Note_G = 0x08<<4,
57 Note_Gis = 0x09<<4,
58 Note_A = 0x0a<<4,
59 Note_Ais = 0x0b<<4,
60 Note_H = 0x0c<<4
61} GSM_RingNoteNote;
62
63typedef enum {
64 Duration_Full = 0x00<<5,
65 Duration_1_2 = 0x01<<5,
66 Duration_1_4 = 0x02<<5,
67 Duration_1_8 = 0x03<<5,
68 Duration_1_16 = 0x04<<5,
69 Duration_1_32 = 0x05<<5
70} GSM_RingNoteDuration;
71
72typedef enum {
73 NoSpecialDuration = 0x00<<6,
74 DottedNote = 0x01<<6,
75 DoubleDottedNote = 0x02<<6,
76 Length_2_3 = 0x03<<6
77} GSM_RingNoteDurationSpec;
78
79typedef enum {
80 Scale_55 = 1, /* 55 Hz for note A */
81 Scale_110, /* 110 Hz for note A */
82 Scale_220,
83 Scale_440, /* first scale for Nokia */
84 Scale_880,
85 Scale_1760,
86 Scale_3520, /* last scale for Nokia */
87 Scale_7040,
88 Scale_14080
89} GSM_RingNoteScale;
90
91typedef struct {
92 GSM_RingNoteDuration Duration;
93 GSM_RingNoteDurationSpec DurationSpec;
94 GSM_RingNoteNote Note;
95 GSM_RingNoteStyle Style;
96 GSM_RingNoteScale Scale;
97 int Tempo;
98} GSM_RingNote;
99
100typedef enum {
101 RING_Note = 1,
102 RING_EnableVibra,
103 RING_DisableVibra,
104 RING_EnableLight,
105 RING_DisableLight,
106 RING_EnableLED,
107 RING_DisableLED,
108 RING_Repeat
109} GSM_RingCommandType;
110
111typedef struct {
112 GSM_RingCommandType Type;
113 GSM_RingNote Note;
114 unsigned char Value;
115} GSM_RingCommand;
116
117typedef struct {
118 int NrCommands;
119 GSM_RingCommand Commands[MAX_RINGTONE_NOTES];
120 bool AllNotesScale;
121} GSM_NoteRingtone;
122
123/* Structure to hold Nokia binary ringtones. */
124typedef struct {
125 unsigned char Frame[30000];
126 int Length;
127} GSM_NokiaBinaryRingtone;
128
129typedef struct {
130 unsigned char *Frame;
131 int Length;
132} GSM_BinaryTone;
133
134typedef enum {
135 RING_NOTETONE = 1,
136 RING_NOKIABINARY,
137 RING_MIDI
138} GSM_RingtoneFormat;
139
140/**
141 * Structure for saving various ringtones formats
142 */
143typedef struct {
144 /**
145 * Ringtone saved in one of three formats
146 */
147 GSM_NokiaBinaryRingtone NokiaBinary;
148 GSM_BinaryTone BinaryTone;
149 GSM_NoteRingtone NoteTone;
150 /**
151 * Ringtone format
152 */
153 GSM_RingtoneFormat Format;
154 /**
155 * Ringtone name
156 */
157 char Name[20*2];
158 /**
159 * Ringtone location
160 */
161 int Location;
162} GSM_Ringtone;
163
164typedef struct {
165 int Group;//Nokia specific
166 int ID;
167 char Name[30*2];
168} GSM_RingtoneInfo;
169
170typedef struct {
171 int Number;
172 GSM_RingtoneInfo Ringtone[100];
173} GSM_AllRingtonesInfo;
174
175GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
176GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
177
178void saveott(FILE *file, GSM_Ringtone *ringtone);
179void savemid(FILE *file, GSM_Ringtone *ringtone);
180void saverng(FILE *file, GSM_Ringtone *ringtone);
181void saveimelody(FILE *file, GSM_Ringtone *ringtone);
182GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone);
183GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone);
184
185 unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength);
186 unsigned char GSM_EncodeEMSSound (GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start);
187
188 GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength);
189
190 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat);
191
192 int GSM_RTTLGetTempo (int Beats);
193 int GSM_RingNoteGetFrequency(GSM_RingNote Note);
194 int GSM_RingNoteGetFullDuration(GSM_RingNote Note);
195
196char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID);
197
198#endif
199
200/* How should editor hadle tabs in this file? Add editor commands here.
201 * vim: noexpandtab sw=8 ts=8 sts=8:
202 */
diff --git a/gammu/emb/common/service/sms/gsmems.c b/gammu/emb/common/service/sms/gsmems.c
new file mode 100644
index 0000000..a7e20f4
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmems.c
@@ -0,0 +1,765 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmlogo.h"
12#include "../gsmring.h"
13#include "../gsmdata.h"
14#include "../gsmnet.h"
15#include "gsmsms.h"
16#include "gsmmulti.h"
17
18/* EMS Developers' Guidelines from www.sonyericsson.com
19 * docs from Alcatel
20 */
21 GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
22 GSM_MultiSMSMessage *SMS,
23 GSM_UDH UDHType)
24{
25 unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
26 int i,UsedText,j,Length,Width,Height,z,x,y;
27 unsigned int Len;
28 int Used,FreeText,FreeBytes,Width2,CopiedText,CopiedSMSText;
29 unsigned char UDHID;
30 GSM_Bitmap Bitmap,Bitmap2;
31 GSM_Ringtone Ring;
32 GSM_Coding_Type Coding = SMS_Coding_Default;
33 GSM_Phone_Bitmap_TypesBitmapType;
34 MultiPartSMSEntry *Entry;
35 bool start;
36 GSM_DateTime Date;
37
38#ifdef DEBUG
39 if (UDHType != UDH_NoUDH) dbgprintf("linked EMS\n");
40#endif
41
42 if (Info->UnicodeCoding) Coding = SMS_Coding_Unicode;
43
44 /* Cleaning on the start */
45 for (i=0;i<MAX_MULTI_SMS;i++) {
46 GSM_SetDefaultSMSData(&SMS->SMS[i]);
47 SMS->SMS[i].UDH.Type = UDHType;
48 GSM_EncodeUDHHeader(&SMS->SMS[i].UDH);
49 SMS->SMS[i].Coding = Coding;
50 }
51
52 /* Packing */
53 for (i=0;i<Info->EntriesNum;i++) {
54 Entry = &Info->Entries[i];
55
56 switch (Entry->ID) {
57 case SMS_ConcatenatedTextLong:
58 case SMS_ConcatenatedTextLong16bit:
59 Len = 0;
60 while(1) {
61 if (Entry->Left || Entry->Right ||
62 Entry->Center || Entry->Large ||
63 Entry->Small || Entry->Bold ||
64 Entry->Italic || Entry->Underlined ||
65 Entry->Strikethrough) {
66 Buffer[0] = 0x0A;/* ID for text format */
67 Buffer[1] = 0x03; /* length of rest*/
68 Buffer[2] = 0x00; /* Position in EMS msg*/
69 Buffer[3] = 0x00; /* how many chars */
70 Buffer[4] = 0x00; /* formatting bits*/
71 if (Entry->Left) {
72 } else if (Entry->Right) {Buffer[4] |= 1;
73 } else if (Entry->Center) {Buffer[4] |= 2;
74 } else Buffer[4] |= 3;
75 if (Entry->Large) { Buffer[4] |= 4;
76 } else if (Entry->Small) {Buffer[4] |= 8;}
77 if (Entry->Bold) Buffer[4] |= 16;
78 if (Entry->Italic) Buffer[4] |= 32;
79 if (Entry->Underlined) Buffer[4] |= 64;
80 if (Entry->Strikethrough) Buffer[4] |= 128;
81 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5,true,&UsedText,&CopiedText,&CopiedSMSText);
82 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
83 if (FreeText == 0) continue;
84 }
85 GSM_AddSMS_Text_UDH(SMS,Coding,Entry->Buffer+Len*2,UnicodeLength(Entry->Buffer) - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
86 if (Entry->Left || Entry->Right ||
87 Entry->Center || Entry->Large ||
88 Entry->Small || Entry->Bold ||
89 Entry->Italic || Entry->Underlined ||
90 Entry->Strikethrough) {
91 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3] = UsedText;
92 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = CopiedSMSText;
93 }
94 Len += CopiedText;
95 if (Len == UnicodeLength(Entry->Buffer)) break;
96 dbgprintf("%i %i\n",Len,UnicodeLength(Entry->Buffer));
97 }
98 break;
99 case SMS_EMSPredefinedSound:
100 case SMS_EMSPredefinedAnimation:
101 if (Entry->ID == SMS_EMSPredefinedSound) {
102 Buffer[0] = 0x0B; /* ID for def.sound*/
103 } else {
104 Buffer[0] = 0x0D; /* ID for def.animation*/
105 }
106 Buffer[1] = 0x02; /* Length of rest */
107 Buffer[2] = 0x00; /* Position in EMS msg*/
108 Buffer[3] = Entry->Number; /* Number of anim.*/
109 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
110 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = UsedText;
111 break;
112 case SMS_EMSSonyEricssonSound:
113 case SMS_EMSSound10:
114 case SMS_EMSSound12:
115 if (Entry->Protected) {
116 Buffer[0] = 0x17; /* ID for ODI */
117 Buffer[1] = 2; /* Length of rest */
118 Buffer[2] = 1; /* Number of protected objects */
119 Buffer[3] = 1; /* 1=Protected,0=Not protected */
120 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
121 }
122
123 Length = 128; /* 128 bytes is maximal length from specs */
124 switch (Entry->ID) {
125 case SMS_EMSSound10:
126 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.0, true);
127 break;
128 case SMS_EMSSound12:
129 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.2, true);
130 break;
131 case SMS_EMSSonyEricssonSound:
132 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 0, true);
133 break;
134 default:
135 break;
136 }
137
138 Buffer[0] = 0x0C; /* ID for EMS sound */
139 Buffer[1] = Length+1; /* Length of rest */
140 Buffer[2] = 0x00; /* Position in EMS msg */
141 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
142 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
143 break;
144 case SMS_EMSSonyEricssonSoundLong:
145 case SMS_EMSSound10Long:
146 case SMS_EMSSound12Long:
147 Ring = *Entry->Ringtone;
148
149 /* First check if we can use classic format */
150 Length = 128; /* 128 bytes is maximal length from specs */
151 switch (Entry->ID) {
152 case SMS_EMSSound10Long:
153 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, true);
154 break;
155 case SMS_EMSSound12Long:
156 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, true);
157 break;
158 case SMS_EMSSonyEricssonSoundLong:
159 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, true);
160 break;
161 default:
162 break;
163 }
164 if (Entry->RingtoneNotes == Ring.NoteTone.NrCommands) {
165 if (Entry->Protected) {
166 Buffer[0] = 0x17; /* ID for ODI */
167 Buffer[1] = 2; /* Length of rest */
168 Buffer[2] = 1; /* Number of protected objects */
169 Buffer[3] = 1; /* 1=Protected,0=Not protected */
170 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
171 }
172
173 Buffer[0] = 0x0C; /* ID for EMS sound */
174 Buffer[1] = Length+1; /* Length of rest */
175 Buffer[2] = 0x00; /* Position in EMS msg */
176 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
177 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
178 break;
179 }
180
181 /* Find free place in first SMS */
182 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
183 Length = FreeBytes - 3;
184 if (Entry->Protected) Length = Length - 4;
185 if (Length < 0) Length = 128;
186 if (Length > 128) Length = 128;
187
188 Ring = *Entry->Ringtone;
189
190 /* Checking number of SMS */
191 Used = 0;
192 FreeBytes = 0;
193 start = true;
194 while (1) {
195 if (FreeBytes != 0) {
196 z = 0;
197 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
198 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
199 z++;
200 }
201 Ring.NoteTone.NrCommands -= FreeBytes;
202 if (Ring.NoteTone.NrCommands == 0) break;
203 Length = 128; /* 128 bytes is maximal length from specs */
204 }
205 switch (Entry->ID) {
206 case SMS_EMSSound10Long:
207 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
208 break;
209 case SMS_EMSSound12Long:
210 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
211 break;
212 case SMS_EMSSonyEricssonSoundLong:
213 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
214 break;
215 default:
216 break;
217 }
218 start = false;
219 Used++;
220 }
221 dbgprintf("Used SMS: %i\n",Used);
222
223 if (Entry->Protected) {
224 Buffer[0] = 0x17; /* ID for ODI */
225 Buffer[1] = 2; /* Length of rest */
226 Buffer[2] = Used+1; /* Number of protected objects */
227 Buffer[3] = 1; /* 1=Protected,0=Not protected */
228 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
229 }
230
231 /* Save UPI UDH */
232 Buffer[0] = 0x13; /* ID for UPI */
233 Buffer[1] = 1; /* Length of rest */
234 Buffer[2] = Used; /* Number of used parts*/
235 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
236
237 /* Find free place in first SMS */
238 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
239 Length = FreeBytes - 3;
240 if (Length < 0) Length = 128;
241 if (Length > 128) Length = 128;
242
243 Ring = *Entry->Ringtone;
244
245 /* Saving */
246 FreeBytes = 0;
247 start = true;
248 while (1) {
249 if (FreeBytes != 0) {
250 z = 0;
251 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
252 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
253 z++;
254 }
255 Ring.NoteTone.NrCommands -= FreeBytes;
256 if (Ring.NoteTone.NrCommands == 0) break;
257 Length = 128; /* 128 bytes is maximal length from specs */
258 }
259 switch (Entry->ID) {
260 case SMS_EMSSound10Long:
261 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
262 break;
263 case SMS_EMSSound12Long:
264 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
265 break;
266 case SMS_EMSSonyEricssonSoundLong:
267 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
268 break;
269 default:
270 break;
271 }
272 Buffer[0] = 0x0C; /* ID for EMS sound */
273 Buffer[1] = Length+1; /* Length of rest */
274 Buffer[2] = 0x00; /* Position in EMS msg */
275 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
276 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
277 start = false;
278 }
279
280 Entry->RingtoneNotes = Entry->Ringtone->NoteTone.NrCommands;
281
282 break;
283 case SMS_EMSAnimation:
284 if (Entry->Protected) {
285 Buffer[0] = 0x17; /* ID for ODI */
286 Buffer[1] = 2; /* Length of rest */
287 Buffer[2] = 1; /* Number of protected objects */
288 Buffer[3] = 1; /* 1=Protected,0=Not protected */
289 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
290 }
291
292 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 8 || Entry->Bitmap->Bitmap[0].BitmapHeight > 8) {
293 BitmapType = GSM_EMSMediumPicture;/* Bitmap 16x16 */
294 Buffer[0] = 0x0E; /* ID for 16x16 animation */
295 } else {
296 BitmapType = GSM_EMSSmallPicture;/* Bitmap 8x8 */
297 Buffer[0] = 0x0F; /* ID for 8x8 animation */
298 }
299 Length = PHONE_GetBitmapSize(BitmapType,0,0);
300
301 Buffer[1] = Length*Entry->Bitmap->Number + 1; /* Length of rest */
302 Buffer[2] = 0x00; /* Position in EMS msg */
303 for (j=0;j<Entry->Bitmap->Number;j++) {
304 PHONE_EncodeBitmap(BitmapType, Buffer+3+j*Length, &Entry->Bitmap->Bitmap[j]);
305 }
306 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length*Entry->Bitmap->Number,true,&UsedText,&CopiedText,&CopiedSMSText);
307 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length*Entry->Bitmap->Number] = UsedText;
308 break;
309 case SMS_EMSFixedBitmap:
310 if (Entry->Protected) {
311 Buffer[0] = 0x17; /* ID for ODI */
312 Buffer[1] = 2; /* Length of rest */
313 Buffer[2] = 1; /* Number of protected objects */
314 Buffer[3] = 1; /* 1=Protected,0=Not protected */
315 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
316 }
317
318 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 16 || Entry->Bitmap->Bitmap[0].BitmapHeight > 16) {
319 BitmapType = GSM_EMSBigPicture; /* Bitmap 32x32 */
320 Buffer[0] = 0x10; /* ID for EMS bitmap*/
321 } else {
322 BitmapType = GSM_EMSMediumPicture; /* Bitmap 16x16 */
323 Buffer[0] = 0x11; /* ID for EMS bitmap*/
324 }
325 Length = PHONE_GetBitmapSize(BitmapType,0,0);
326 PHONE_GetBitmapWidthHeight(BitmapType, &Width, &Height);
327
328 Buffer[1] = Length + 1; /* Length of rest */
329 Buffer[2] = 0x00; /* Position in EMS msg*/
330 PHONE_EncodeBitmap(BitmapType,Buffer+3, &Entry->Bitmap->Bitmap[0]);
331 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
332 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length] = UsedText;
333 break;
334 case SMS_EMSVariableBitmapLong:
335 BitmapType = GSM_EMSVariablePicture;
336 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
337 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
338 Bitmap = Entry->Bitmap->Bitmap[0];
339
340 /* First check if we can use classical format */
341 while (1) {
342 /* Width should be multiply of 8 */
343 while (Width % 8 != 0) Width--;
344
345 /* specs */
346 if (Width <= 96 && Height <= 128) break;
347
348 Height--;
349 }
350 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
351 if (Length <= 128) {
352 if (Entry->Protected) {
353 Buffer[0] = 0x17; /* ID for ODI */
354 Buffer[1] = 2; /* Length of rest */
355 Buffer[2] = 1; /* Number of protected objects */
356 Buffer[3] = 1; /* 1=Protected,0=Not protected */
357 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
358 }
359
360 Buffer[0] = 0x12; /* ID for EMS bitmap*/
361 Buffer[1] = Length + 3; /* Length of rest */
362 Buffer[2] = 0x00; /* Position in EMS msg*/
363 Buffer[3] = Width/8; /* Bitmap width/8 */
364 Buffer[4] = Height; /* Bitmap height */
365
366 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
367#ifdef DEBUG
368 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
369#endif
370 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
371 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
372 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
373 break;
374 }
375
376 /* Find free place in first SMS */
377 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
378 Used = 0;
379 Length = FreeBytes - 3;
380 if (Entry->Protected)Length = Length - 4;
381 if (Length < 0) Length = 128;
382 if (Length > 128) Length = 128;
383
384 /* Checking number of SMS */
385 FreeBytes = 0;
386 while (FreeBytes != Width) {
387 Width2 = 8;
388 while (FreeBytes + Width2 != Width) {
389 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
390
391 Width2 = Width2 + 8;
392 }
393 FreeBytes = FreeBytes + Width2;
394 Length = 128;
395 Used ++;
396 }
397 dbgprintf("Used SMS: %i\n",Used);
398
399 if (Entry->Protected) {
400 Buffer[0] = 0x17; /* ID for ODI */
401 Buffer[1] = 2; /* Length of rest */
402 Buffer[2] = Used+1; /* Number of protected objects */
403 Buffer[3] = 1; /* 1=Protected,0=Not protected */
404 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
405 }
406
407 /* Save UPI UDH */
408 Buffer[0] = 0x13; /* ID for UPI */
409 Buffer[1] = 1; /* Length of rest */
410 Buffer[2] = Used; /* Number of used parts*/
411
412 /* Find free place in first SMS */
413 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
414 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
415 Length = FreeBytes - 3;
416 if (Length < 0) Length = 128;
417 if (Length > 128) Length = 128;
418
419#ifdef DEBUG
420 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
421#endif
422
423 /* Saving SMS */
424 FreeBytes = 0;
425 while (FreeBytes != Width) {
426 Width2 = 8;
427 while (FreeBytes + Width2 != Width) {
428 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
429
430 Width2 = Width2 + 8;
431 }
432
433 /* Copying part of bitmap to new structure */
434 Bitmap2.BitmapWidth = Width2;
435 Bitmap2.BitmapHeight = Height;
436 GSM_ClearBitmap(&Bitmap2);
437 for (x=0;x<Width2;x++) {
438 for (y=0;y<Height;y++) {
439 if (GSM_IsPointBitmap(&Bitmap,x+FreeBytes,y)) {
440 GSM_SetPointBitmap(&Bitmap2, x, y);
441 }
442 }
443 }
444#ifdef DEBUG
445 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap2);
446#endif
447
448 /* Adding new bitmap to SMS */
449 Length = PHONE_GetBitmapSize(BitmapType,Width2,Height);
450 Buffer[0] = 0x12; /* ID for EMS bitmap*/
451 Buffer[1] = Length + 3; /* Length of rest */
452 Buffer[2] = 0x00; /* Position in EMS msg*/
453 Buffer[3] = Width2/8; /* Bitmap width/8 */
454 Buffer[4] = Height; /* Bitmap height */
455 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap2);
456 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
457 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
458
459 FreeBytes = FreeBytes + Width2;
460 Length = 128;
461 }
462 break;
463 case SMS_EMSVariableBitmap:
464 if (Entry->Protected) {
465 Buffer[0] = 0x17; /* ID for ODI */
466 Buffer[1] = 2; /* Length of rest */
467 Buffer[2] = 1; /* Number of protected objects */
468 Buffer[3] = 1; /* 1=Protected,0=Not protected */
469 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
470 }
471
472 BitmapType = GSM_EMSVariablePicture;
473 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
474 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
475
476 while (1) {
477 /* Width should be multiply of 8 */
478 while (Width % 8 != 0) Width--;
479
480 /* specs */
481 if (PHONE_GetBitmapSize(BitmapType,Width,Height) <= 128) break;
482
483 Height--;
484 }
485
486 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
487
488 Buffer[0] = 0x12; /* ID for EMS bitmap*/
489 Buffer[1] = Length + 3; /* Length of rest */
490 Buffer[2] = 0x00; /* Position in EMS msg*/
491 Buffer[3] = Width/8; /* Bitmap width/8 */
492 Buffer[4] = Height; /* Bitmap height */
493
494 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
495#ifdef DEBUG
496 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
497#endif
498 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
499 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
500 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
501 break;
502 default:
503 break;
504 }
505 }
506
507 SMS->Number++;
508
509 if (UDHType == UDH_ConcatenatedMessages) {
510 UDHID = GSM_MakeSMSIDFromTime();
511 for (i=0;i<SMS->Number;i++) {
512 SMS->SMS[i].UDH.Text[2+1] = UDHID;
513 SMS->SMS[i].UDH.Text[3+1] = SMS->Number;
514 SMS->SMS[i].UDH.Text[4+1] = i+1;
515 }
516 }
517 if (UDHType == UDH_ConcatenatedMessages16bit) {
518 UDHID = GSM_MakeSMSIDFromTime();
519 GSM_GetCurrentDateTime (&Date);
520 for (i=0;i<SMS->Number;i++) {
521 SMS->SMS[i].UDH.Text[2+1] = Date.Hour;
522 SMS->SMS[i].UDH.Text[3+1] = UDHID;
523 SMS->SMS[i].UDH.Text[4+1] = SMS->Number;
524 SMS->SMS[i].UDH.Text[5+1] = i+1;
525 }
526 }
527
528#ifdef DEBUG
529 dbgprintf("SMS number is %i\n",SMS->Number);
530 for (i=0;i<SMS->Number;i++) {
531 dbgprintf("UDH length %i\n",SMS->SMS[i].UDH.Length);
532 DumpMessage(di.df, di.dl, SMS->SMS[i].UDH.Text, SMS->SMS[i].UDH.Length);
533 dbgprintf("SMS length %i\n",UnicodeLength(SMS->SMS[i].Text)*2);
534 DumpMessage(di.df, di.dl, SMS->SMS[i].Text, UnicodeLength(SMS->SMS[i].Text)*2);
535 }
536#endif
537 return ERR_NONE;
538}
539
540static bool AddEMSText(GSM_SMSMessage *SMS, GSM_MultiPartSMSInfo *Info, int *Pos, int Len)
541{
542 int BufferLen;
543
544 if (Len==0) return true;
545
546 if (Info->Entries[Info->EntriesNum].ID!=SMS_ConcatenatedTextLong &&
547 Info->Entries[Info->EntriesNum].ID!=0) {
548 (Info->EntriesNum)++;
549 }
550 BufferLen = UnicodeLength(Info->Entries[Info->EntriesNum].Buffer)*2;
551 switch (SMS->Coding) {
552 case SMS_Coding_8bit:
553 // memcpy(Info->Entries[Info->EntriesNum].Buffer+BufferLen,SMS->Text+(*Pos),Len);
554 // BufferLen+=Len;
555 // (*Pos)+=Len;
556 break;
557 case SMS_Coding_Unicode:
558 case SMS_Coding_Default:
559 Info->Entries[Info->EntriesNum].Buffer = realloc(Info->Entries[Info->EntriesNum].Buffer, BufferLen + (Len * 2) + 2);
560 if (Info->Entries[Info->EntriesNum].Buffer == NULL) return false;
561 memcpy(Info->Entries[Info->EntriesNum].Buffer + BufferLen, SMS->Text + (*Pos) *2, Len * 2);
562 BufferLen += Len * 2;
563 break;
564 }
565 (*Pos)+=Len;
566 Info->Entries[Info->EntriesNum].Buffer[BufferLen]= 0;
567 Info->Entries[Info->EntriesNum].Buffer[BufferLen+1]= 0;
568 Info->Entries[Info->EntriesNum].ID = SMS_ConcatenatedTextLong;
569 return true;
570}
571
572 bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
573 GSM_MultiSMSMessage *SMS)
574{
575 int i, w, Pos, z, UPI = 1, width, height;
576 bool RetVal = false, NewPicture = true;
577 GSM_Phone_Bitmap_Types BitmapType;
578 GSM_Bitmap Bitmap,Bitmap2;
579
580 for (i=0;i<MAX_MULTI_SMS;i++) {
581 Info->Entries[i].ID = 0;
582 }
583
584 for (i=0;i<SMS->Number;i++) {
585 Pos = 0;
586 w= 1;
587 while (w < SMS->SMS[i].UDH.Length) {
588 if (Info->EntriesNum + 1 == MAX_MULTI_SMS) {
589 dbgprintf("Couldn't parse SMS, contains too many EMS parts!\n");
590 return false;
591 }
592 switch(SMS->SMS[i].UDH.Text[w]) {
593 case 0x00:
594 dbgprintf("UDH part - linked SMS with 8 bit ID\n");
595 break;
596 case 0x08:
597 dbgprintf("UDH part - linked SMS with 16 bit ID\n");
598 break;
599 // case 0x0A:
600 // dbgprintf("UDH part - EMS text formatting\n");
601 // break;
602 case 0x0B:
603 dbgprintf("UDH part - default EMS sound\n");
604 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
605 z = Pos;
606 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
607 }
608 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
609 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
610 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedSound;
611 RetVal = true;
612 break;
613 // case 0x0C:
614 // dbgprintf("UDH part - EMS sound\n");
615 // break;
616 case 0x0D:
617 dbgprintf("UDH part - default EMS animation\n");
618 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
619 z = Pos;
620 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
621 }
622 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
623 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
624 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedAnimation;
625 RetVal = true;
626 break;
627 case 0x0E:
628 case 0x0F:
629 if (SMS->SMS[i].UDH.Text[w] == 0x0E) {
630 dbgprintf("UDH part - EMS 16x16 animation\n");
631 BitmapType = GSM_EMSMediumPicture;
632 } else {
633 dbgprintf("UDH part - EMS 8x8 animation\n");
634 BitmapType = GSM_EMSSmallPicture;
635 }
636 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
637 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
638 z = Pos;
639 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
640 }
641 (Info->EntriesNum)++;
642 Info->Entries[Info->EntriesNum].ID = SMS_EMSAnimation;
643 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
644 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
645 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
646 for (z=0;z<((SMS->SMS[i].UDH.Text[w+1]-1)/PHONE_GetBitmapSize(BitmapType,0,0));z++) {
647 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z].Type = GSM_PictureImage;
648 PHONE_DecodeBitmap(BitmapType,
649 SMS->SMS[i].UDH.Text + w + 3 + PHONE_GetBitmapSize(BitmapType,0,0) * z,
650 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z]);
651 Info->Entries[Info->EntriesNum].Bitmap->Number++;
652 }
653 RetVal = true;
654 break;
655 case 0x10:
656 case 0x11:
657 if (SMS->SMS[i].UDH.Text[w] == 0x10) {
658 dbgprintf("UDH part - EMS 32x32 picture\n");
659 BitmapType = GSM_EMSBigPicture;
660 } else {
661 dbgprintf("UDH part - EMS 16x16 picture\n");
662 BitmapType = GSM_EMSMediumPicture;
663 }
664 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
665 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
666 z = Pos;
667 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
668 }
669 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
670 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
671 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
672 PHONE_DecodeBitmap(BitmapType,
673 SMS->SMS[i].UDH.Text + w + 3,
674 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
675 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
676 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
677 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
678 Info->Entries[Info->EntriesNum].ID = SMS_EMSFixedBitmap;
679 RetVal = true;
680 break;
681 case 0x12:
682 dbgprintf("UDH part - EMS variable width bitmap\n");
683 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
684 z = Pos;
685 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
686 }
687 if (NewPicture) {
688 (Info->EntriesNum)++;
689 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
690 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = 0;
691 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = 0;
692 }
693 Bitmap.BitmapWidth = SMS->SMS[i].UDH.Text[w+3]*8;
694 Bitmap.BitmapHeight = SMS->SMS[i].UDH.Text[w+4];
695 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
696 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
697 if (NewPicture) {
698 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth;
699 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap.BitmapHeight;
700 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
701 SMS->SMS[i].UDH.Text + w + 5,
702 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
703 } else {
704 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
705 SMS->SMS[i].UDH.Text + w + 5,
706 &Bitmap);
707 Bitmap2 = Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0];
708 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth+Bitmap2.BitmapWidth;
709 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap2.BitmapHeight;
710 for (width=0;width<Bitmap2.BitmapWidth;width++) {
711 for (height=0;height<Bitmap2.BitmapHeight;height++) {
712 if (GSM_IsPointBitmap(&Bitmap2, width, height)) {
713 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
714 } else {
715 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
716 }
717 }
718 }
719 for (width=0;width<Bitmap.BitmapWidth;width++) {
720 for (height=0;height<Bitmap2.BitmapHeight;height++) {
721 if (GSM_IsPointBitmap(&Bitmap, width, height)) {
722 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
723 } else {
724 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
725 }
726 }
727 }
728 }
729 if (UPI == 1) {
730 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
731 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
732 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
733 Info->Entries[Info->EntriesNum].ID = SMS_EMSVariableBitmap;
734 RetVal = true;
735 NewPicture = true;
736 dbgprintf("New variable picture\n");
737 } else {
738 NewPicture = false;
739 UPI--;
740 }
741 break;
742 case 0x13:
743 dbgprintf("UDH part - UPI\n");
744 dbgprintf("Value %i\n",SMS->SMS[i].UDH.Text[w+2]);
745 UPI = SMS->SMS[i].UDH.Text[w+2];
746 break;
747 case 0x17:
748 dbgprintf("UDH part - Object Distribution Indicator (Media Rights Protecting) ignored now\n");
749 break;
750 default:
751 dbgprintf("UDH part - block %02x\n",SMS->SMS[i].UDH.Text[w]);
752 Info->Unknown = true;
753 } /* switch */
754 w=w+SMS->SMS[i].UDH.Text[w+1]+2;
755 } /* while */
756 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].Length-Pos)) return false;
757 RetVal = true;
758 }
759 if (RetVal) (Info->EntriesNum)++;
760 return RetVal;
761}
762
763/* How should editor hadle tabs in this file? Add editor commands here.
764 * vim: noexpandtab sw=8 ts=8 sts=8:
765 */
diff --git a/gammu/emb/common/service/sms/gsmems.h b/gammu/emb/common/service/sms/gsmems.h
new file mode 100644
index 0000000..6701d28
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmems.h
@@ -0,0 +1,20 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef __gsm_ems_h
4#define __gsm_ems_h
5
6#include "../../gsmcomon.h"
7#include "gsmmulti.h"
8
9 GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
10 GSM_MultiSMSMessage *SMS,
11 GSM_UDH UDHType);
12
13 bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
14 GSM_MultiSMSMessage *SMS);
15
16#endif
17
18/* How should editor hadle tabs in this file? Add editor commands here.
19 * vim: noexpandtab sw=8 ts=8 sts=8:
20 */
diff --git a/gammu/emb/common/service/sms/gsmmulti.c b/gammu/emb/common/service/sms/gsmmulti.c
new file mode 100644
index 0000000..6c1cdcd
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmmulti.c
@@ -0,0 +1,1148 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmlogo.h"
12#include "../gsmring.h"
13#include "../gsmdata.h"
14#include "../gsmnet.h"
15#include "gsmsms.h"
16#include "gsmmulti.h"
17#include "gsmems.h"
18
19/* ----------------- Splitting SMS into parts ------------------------------ */
20
21unsigned char GSM_MakeSMSIDFromTime(void)
22{
23 GSM_DateTime Date;
24 unsigned charretval;
25
26 GSM_GetCurrentDateTime (&Date);
27 retval = Date.Second;
28 switch (Date.Minute/10) {
29 case 2: case 7: retval = retval + 60; break;
30 case 4: case 8: retval = retval + 120; break;
31 case 9: case 5: case 0: retval = retval + 180; break;
32 }
33 retval += Date.Minute/10;
34 return retval;
35}
36
37void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes)
38{
39 int UsedBytes;
40
41 switch (Coding) {
42 case SMS_Coding_Default:
43 FindDefaultAlphabetLen(SMS.Text,&UsedBytes,UsedText,500);
44 UsedBytes = *UsedText * 7 / 8;
45 if (UsedBytes * 8 / 7 != *UsedText) UsedBytes++;
46 *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes;
47 *FreeText = (GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length) * 8 / 7 - *UsedText;
48 break;
49 case SMS_Coding_Unicode:
50 *UsedText = UnicodeLength(SMS.Text);
51 UsedBytes = *UsedText * 2;
52 *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes;
53 *FreeText = *FreeBytes / 2;
54 break;
55 case SMS_Coding_8bit:
56 *UsedText = UsedBytes = SMS.Length;
57 *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes;
58 *FreeText = *FreeBytes;
59 break;
60 }
61 dbgprintf("UDH len %i, UsedBytes %i, FreeText %i, UsedText %i, FreeBytes %i\n",SMS.UDH.Length,UsedBytes,*FreeText,*UsedText,*FreeBytes);
62}
63
64 GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS,
65 GSM_Coding_Type Coding,
66 char *Buffer,
67 int BufferLen,
68 bool UDH,
69 int *UsedText,
70 int *CopiedText,
71 int *CopiedSMSText)
72{
73 int FreeText,FreeBytes,Copy,i,j;
74
75 dbgprintf("Checking used\n");
76 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
77
78 if (UDH) {
79 dbgprintf("Adding UDH\n");
80 if (FreeBytes - BufferLen <= 0) {
81 dbgprintf("Going to the new SMS\n");
82 SMS->Number++;
83 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
84 }
85 if (SMS->SMS[SMS->Number].UDH.Length == 0) {
86 SMS->SMS[SMS->Number].UDH.Length = 1;
87 SMS->SMS[SMS->Number].UDH.Text[0] = 0x00;
88 }
89 memcpy(SMS->SMS[SMS->Number].UDH.Text+SMS->SMS[SMS->Number].UDH.Length,Buffer,BufferLen);
90 SMS->SMS[SMS->Number].UDH.Length += BufferLen;
91 SMS->SMS[SMS->Number].UDH.Text[0] += BufferLen;
92 SMS->SMS[SMS->Number].UDH.Type = UDH_UserUDH;
93 dbgprintf("UDH added %i\n",BufferLen);
94 } else {
95 dbgprintf("Adding text\n");
96 if (FreeText == 0) {
97 dbgprintf("Going to the new SMS\n");
98 SMS->Number++;
99 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
100 }
101
102 Copy = FreeText;
103 dbgprintf("copy %i\n",Copy);
104 if (BufferLen < Copy) Copy = BufferLen;
105 dbgprintf("copy %i\n",Copy);
106
107 switch (Coding) {
108 case SMS_Coding_Default:
109 FindDefaultAlphabetLen(Buffer,&i,&j,FreeText);
110 dbgprintf("def length %i %i\n",i,j);
111 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2] = 0;
112 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2+1] = 0;
113 memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,i*2);
114 *CopiedText = i;
115 *CopiedSMSText = j;
116 SMS->SMS[SMS->Number].Length += i;
117 break;
118 case SMS_Coding_Unicode:
119 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2] = 0;
120 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2+1] = 0;
121 memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,Copy*2);
122 *CopiedText = *CopiedSMSText = Copy;
123 SMS->SMS[SMS->Number].Length += Copy;
124 break;
125 case SMS_Coding_8bit:
126 memcpy(SMS->SMS[SMS->Number].Text+SMS->SMS[SMS->Number].Length,Buffer,Copy);
127 SMS->SMS[SMS->Number].Length += Copy;
128 *CopiedText = *CopiedSMSText = Copy;
129 break;
130 }
131 dbgprintf("Text added\n");
132 }
133
134 dbgprintf("Checking on the end\n");
135 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
136
137 return ERR_NONE;
138}
139
140 void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage*SMS,
141 unsigned char *MessageBuffer,
142 int MessageLength,
143 GSM_UDH UDHType,
144 GSM_Coding_TypeCoding,
145 int Class,
146 unsigned char ReplaceMessage)
147{
148 int j,Len,UsedText,CopiedText,CopiedSMSText;
149 unsigned char UDHID;
150 GSM_DateTime Date;
151
152 Len = 0;
153 while(1) {
154 GSM_SetDefaultSMSData(&SMS->SMS[SMS->Number]);
155 SMS->SMS[SMS->Number].Class = Class;
156 SMS->SMS[SMS->Number].Coding = Coding;
157
158 SMS->SMS[SMS->Number].UDH.Type = UDHType;
159 GSM_EncodeUDHHeader(&SMS->SMS[SMS->Number].UDH);
160
161 if (Coding == SMS_Coding_8bit) {
162 GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
163 } else {
164 GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len*2,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
165 }
166 Len += CopiedText;
167 dbgprintf("%i %i\n",Len,MessageLength);
168 if (Len == MessageLength) break;
169 if (SMS->Number == MAX_MULTI_SMS) break;
170 SMS->Number++;
171 }
172
173 SMS->Number++;
174
175 UDHID = GSM_MakeSMSIDFromTime();
176 GSM_GetCurrentDateTime (&Date);
177 for (j=0;j<SMS->Number;j++) {
178 SMS->SMS[j].UDH.Type = UDHType;
179 SMS->SMS[j].UDH.ID8bit = UDHID;
180 SMS->SMS[j].UDH.ID16bit = UDHID + 256 * Date.Hour;
181 SMS->SMS[j].UDH.PartNumber = j+1;
182 SMS->SMS[j].UDH.AllParts = SMS->Number;
183 GSM_EncodeUDHHeader(&SMS->SMS[j].UDH);
184 }
185 if (SMS->Number == 1) SMS->SMS[0].ReplaceMessage = ReplaceMessage;
186}
187
188/* Calculates number of SMS and number of left chars in SMS */
189 void GSM_SMSCounter(int MessageLength,
190 unsigned char *MessageBuffer,
191 GSM_UDH UDHType,
192 GSM_Coding_Type Coding,
193 int *SMSNum,
194 int *CharsLeft)
195{
196 int UsedText,FreeBytes;
197 GSM_MultiSMSMessage MultiSMS;
198
199 MultiSMS.Number = 0;
200 GSM_MakeMultiPartSMS(&MultiSMS,MessageBuffer,MessageLength,UDHType,Coding,-1,false);
201 GSM_Find_Free_Used_SMS2(Coding,MultiSMS.SMS[MultiSMS.Number-1], &UsedText, CharsLeft, &FreeBytes);
202 *SMSNum = MultiSMS.Number;
203}
204
205/* Nokia Smart Messaging 3.0 */
206static void GSM_EncodeSMS30MultiPartSMS(GSM_MultiPartSMSInfo *Info,
207 char *Buffer, int *Length)
208{
209 int len;
210
211 /*SM version. Here 3.0*/
212 Buffer[(*Length)++] = 0x30;
213
214 if (Info->Entries[0].ID == SMS_NokiaProfileLong) {
215 if (Info->Entries[0].Buffer != NULL) {
216 if (Info->Entries[0].Buffer[0]!=0x00 || Info->Entries[0].Buffer[1]!=0x00) {
217 Buffer[(*Length)++] = SM30_PROFILENAME;
218 Buffer[(*Length)++] = 0x00;
219 Buffer[(*Length)++] = 2*UnicodeLength(Info->Entries[0].Buffer);
220 CopyUnicodeString(Buffer+(*Length),Info->Entries[0].Buffer);
221 *Length = *Length + 2*UnicodeLength(Info->Entries[0].Buffer);
222 }
223 }
224 if (Info->Entries[0].Ringtone != NULL) {
225 Buffer[(*Length)++] = SM30_RINGTONE;
226 /* Length for this part later will be changed */
227 Buffer[(*Length)++] = 0x01;
228 Buffer[(*Length)++] = 0x00;
229 /* Smart Messaging 3.0 says: 16*9=144 bytes,
230 * but on 3310 4.02 it was possible to save about 196 chars
231 * (without cutting) */
232 len = 196;
233 Info->Entries[0].RingtoneNotes=GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer+(*Length),&len);
234 Buffer[(*Length)-2] = len / 256;
235 Buffer[(*Length)-1] = len % 256;
236 *Length = *Length + len;
237 }
238 }
239 if (Info->Entries[0].Bitmap != NULL) {
240 if (Info->Entries[0].ID == SMS_NokiaPictureImageLong) {
241 Buffer[(*Length)++] = SM30_OTA;
242 } else {
243 Buffer[(*Length)++] = SM30_SCREENSAVER;
244 }
245 Buffer[(*Length)++] = 0x01;
246 Buffer[(*Length)++] = 0x00;
247 NOKIA_CopyBitmap(GSM_NokiaPictureImage, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, Length);
248 if (Info->Entries[0].Bitmap->Bitmap[0].Text[0]!=0 || Info->Entries[0].Bitmap->Bitmap[0].Text[1]!=0) {
249 if (Info->UnicodeCoding) {
250 Buffer[(*Length)++] = SM30_UNICODETEXT;
251 /* Length for text part */
252 Buffer[(*Length)++] = 0x00;
253 Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2;
254 memcpy(Buffer+(*Length),Info->Entries[0].Bitmap->Bitmap[0].Text,UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2);
255 *Length = *Length + UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2;
256 } else {
257 /*ID for ISO-8859-1 text*/
258 Buffer[(*Length)++] = SM30_ISOTEXT;
259 Buffer[(*Length)++] = 0x00;
260 Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text);
261 memcpy(Buffer+(*Length),DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text),UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text));
262 *Length = *Length +UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text);
263 }
264 }
265 }
266}
267
268/* Alcatel docs from www.alcatel.com/wap/ahead */
269 GSM_Error GSM_EncodeAlcatelMultiPartSMS(GSM_MultiSMSMessage *SMS,
270 unsigned char *Data,
271 int Len,
272 unsigned char *Name,
273 int Type)
274{
275 unsigned char buff[100],UDHID;
276 int p,i;
277 GSM_UDHHeaderMyUDH;
278
279 for (i=0;i<MAX_MULTI_SMS;i++) {
280 GSM_SetDefaultSMSData(&SMS->SMS[i]);
281 SMS->SMS[i].UDH.Type = UDH_UserUDH;
282 SMS->SMS[i].UDH.Text[1] = 0x80;/* Alcatel */
283 p = UnicodeLength(Name);
284 EncodeDefault(buff, Name, &p, true, NULL);
285 SMS->SMS[i].UDH.Text[2]= GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p) + 4;
286 SMS->SMS[i].UDH.Text[3]= GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p);
287 SMS->SMS[i].UDH.Text[4] = Type;
288 SMS->SMS[i].UDH.Text[5] = Len / 256;
289 SMS->SMS[i].UDH.Text[6] = Len % 256;
290 SMS->SMS[i].UDH.Text[0] = 6 + SMS->SMS[i].UDH.Text[3];
291 SMS->SMS[i].UDH.Length = SMS->SMS[i].UDH.Text[0] + 1;
292
293 if (Len > 140 - SMS->SMS[i].UDH.Length) {
294 MyUDH.Type = UDH_ConcatenatedMessages;
295 GSM_EncodeUDHHeader(&MyUDH);
296
297 memcpy(SMS->SMS[i].UDH.Text+SMS->SMS[i].UDH.Length,MyUDH.Text+1,MyUDH.Length-1);
298 SMS->SMS[i].UDH.Text[0] += MyUDH.Length-1;
299 SMS->SMS[i].UDH.Length += MyUDH.Length-1;
300 }
301
302 SMS->SMS[i].Coding = SMS_Coding_8bit;
303 SMS->SMS[i].Class = 1;
304 }
305
306 p = 0;
307 while (p != Len) {
308 i = 140-SMS->SMS[SMS->Number].UDH.Length;
309 if (Len - p < i) i = Len - p;
310 memcpy(SMS->SMS[SMS->Number].Text,Data+p,i);
311 p += i;
312 SMS->SMS[SMS->Number].Length = i;
313 SMS->Number++;
314
315 }
316
317 /* Linked sms UDH */
318 if (SMS->Number != 1) {
319 UDHID = GSM_MakeSMSIDFromTime();
320 for (i=0;i<SMS->Number;i++) {
321 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-3] = UDHID;
322 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-2] = SMS->Number;
323 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-1] = i+1;
324 }
325 }
326
327 return ERR_NONE;
328}
329
330/* Alcatel docs from www.alcatel.com/wap/ahead and other */
331 GSM_Error GSM_EncodeMultiPartSMS(GSM_MultiPartSMSInfo *Info,
332 GSM_MultiSMSMessage *SMS)
333{
334 unsigned charBuffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
335 unsigned charBuffer2[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
336 int Length = 0,smslen,i, Class = -1, j,p;
337 GSM_Errorerror;
338 GSM_Coding_Type Coding = SMS_Coding_8bit;
339 GSM_UDH UDH= UDH_NoUDH;
340 GSM_UDHHeader UDHHeader;
341 bool EMS= false;
342 int textnum = 0;
343
344 SMS->Number = 0;
345
346 if (Info->Entries[0].ID == SMS_AlcatelSMSTemplateName) {
347 Buffer[Length++] = 0x00; //number of elements
348 for (i=1;i<Info->EntriesNum;i++) {
349 switch (Info->Entries[i].ID) {
350 case SMS_EMSSound10:
351 case SMS_EMSSound12:
352 case SMS_EMSSonyEricssonSound:
353 case SMS_EMSSound10Long:
354 case SMS_EMSSound12Long:
355 case SMS_EMSSonyEricssonSoundLong:
356 case SMS_EMSVariableBitmap:
357 case SMS_EMSAnimation:
358 case SMS_EMSVariableBitmapLong:
359 break;
360 case SMS_EMSPredefinedSound:
361 Buffer[0]++;
362 Buffer[Length++] = 0x01; //type of data
363 Buffer[Length++] = 1 % 256;//len
364 Buffer[Length++] = 1 / 256; //len
365 Buffer[Length++] = Info->Entries[i].Number;
366 break;
367 case SMS_EMSPredefinedAnimation:
368 Buffer[0]++;
369 Buffer[Length++] = 0x02; //type of data
370 Buffer[Length++] = 1 % 256;//len
371 Buffer[Length++] = 1 / 256; //len
372 Buffer[Length++] = Info->Entries[i].Number;
373 break;
374 case SMS_ConcatenatedTextLong:
375 Buffer[0]++;
376 p = UnicodeLength(Info->Entries[i].Buffer);
377 EncodeDefault(Buffer2, Info->Entries[i].Buffer, &p, true, NULL);
378 Buffer[Length++] = 0x00; //type of data
379 Length = Length + 2;
380 smslen = GSM_PackSevenBitsToEight(0, Buffer2, Buffer+Length, p);
381 Buffer[Length-2] = smslen % 256; //len
382 Buffer[Length-1] = smslen / 256; //len
383 Length = Length + smslen;
384 break;
385 default:
386 return ERR_UNKNOWN;
387 }
388 }
389 Buffer[0] = Buffer[0] * 2;
390 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Buffer,ALCATELTDD_SMSTEMPLATE);
391 }
392
393 for (i=0;i<Info->EntriesNum;i++) {
394 switch (Info->Entries[i].ID) {
395 case SMS_EMSPredefinedAnimation:
396 case SMS_EMSPredefinedSound:
397 case SMS_EMSSound10:
398 case SMS_EMSSound12:
399 case SMS_EMSSonyEricssonSound:
400 case SMS_EMSSound10Long:
401 case SMS_EMSSound12Long:
402 case SMS_EMSSonyEricssonSoundLong:
403 case SMS_EMSFixedBitmap:
404 case SMS_EMSVariableBitmap:
405 case SMS_EMSAnimation:
406 case SMS_EMSVariableBitmapLong:
407 EMS = true;
408 break;
409 case SMS_ConcatenatedTextLong:
410 case SMS_ConcatenatedTextLong16bit:
411
412 /* This covers situation, when somebody will call function
413 * with two or more SMS_Concatenated.... entries only.
414 * It will be still only linked sms, but functions below
415 * will pack only first entry according to own limits.
416 * We redirect to EMS functions, because they are more generic
417 * here and will handle it correctly and produce linked sms
418 * from all entries
419 */
420 textnum ++;
421 if (textnum > 1) EMS = true;
422
423 if (Info->Entries[i].Left || Info->Entries[i].Right ||
424 Info->Entries[i].Center || Info->Entries[i].Large ||
425 Info->Entries[i].Small || Info->Entries[i].Bold ||
426 Info->Entries[i].Italic || Info->Entries[i].Underlined ||
427 Info->Entries[i].Strikethrough) {
428 EMS = true;
429 }
430 default:
431 break;
432 }
433 if (EMS) break;
434 }
435 if (EMS) {
436 error=GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_NoUDH);
437 if (error != ERR_NONE) return error;
438 if (SMS->Number != 1) {
439 SMS->Number = 0;
440 for (i=0;i<Info->EntriesNum;i++) {
441 if (Info->Entries[i].ID == SMS_ConcatenatedTextLong16bit) {
442 return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages);
443 }
444 }
445 return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages16bit);
446 }
447 return error;
448 }
449
450 if (Info->EntriesNum != 1) return ERR_UNKNOWN;
451
452 switch (Info->Entries[0].ID) {
453 case SMS_AlcatelMonoBitmapLong:
454 Buffer[0] = Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth;
455 Buffer[1] = Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight;
456 PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+2, &Info->Entries[0].Bitmap->Bitmap[0]);
457 Length = PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight)+2;
458 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_PICTURE);
459 case SMS_AlcatelMonoAnimationLong:
460 /* Number of sequence words */
461 Buffer[0] = (Info->Entries[0].Bitmap->Number+1) % 256;
462 Buffer[1] = (Info->Entries[0].Bitmap->Number+1) / 256;
463 /* Picture display time 1 second (1 = 100ms) */
464 Buffer[2] = 10 % 256;
465 Buffer[3] = 10 / 256 + 0xF0;
466
467 Length = 4;
468 j = 0;
469
470 /* Offsets to bitmaps */
471 for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
472 Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) % 256;
473 Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) / 256;
474 j += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight)+2;
475 }
476
477 /* Bitmaps */
478 for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
479 Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth;
480 Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight;
481 PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+Length, &Info->Entries[0].Bitmap->Bitmap[i]);
482 Length += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight);
483 }
484 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_ANIMATION);
485 case SMS_MMSIndicatorLong:
486 Class= 1;
487 UDH= UDH_MMSIndicatorLong;
488 GSM_EncodeMMSIndicatorSMSText(Buffer,&Length,*Info->Entries[0].MMSIndicator);
489 break;
490 case SMS_NokiaRingtoneLong:
491 case SMS_NokiaRingtone:
492 UDH= UDH_NokiaRingtone;
493 Class= 1;
494 /* 7 = length of UDH_NokiaRingtone UDH header */
495 Length = GSM_MAX_8BIT_SMS_LENGTH-7;
496 Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
497 if (Info->Entries[0].ID == SMS_NokiaRingtone) break;
498 if (Info->Entries[0].RingtoneNotes != Info->Entries[0].Ringtone->NoteTone.NrCommands) {
499 UDH = UDH_NokiaRingtoneLong;
500 Length = (GSM_MAX_8BIT_SMS_LENGTH-12)*3;
501 Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
502 }
503 break;
504 case SMS_NokiaOperatorLogoLong:
505 if (Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth > 72 || Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight > 14) {
506 UDH= UDH_NokiaOperatorLogoLong;
507 Class = 1;
508 NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
509 Length = Length + 3;
510 NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
511 break;
512 }
513 case SMS_NokiaOperatorLogo:
514 UDH= UDH_NokiaOperatorLogo;
515 Class = 1;
516 NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
517 Length = Length + 3;
518 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
519 break;
520 case SMS_NokiaCallerLogo:
521 UDH= UDH_NokiaCallerLogo;
522 Class = 1;
523 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
524 break;
525 case SMS_NokiaProfileLong:
526 case SMS_NokiaPictureImageLong:
527 case SMS_NokiaScreenSaverLong:
528 Class = 1;
529 UDH= UDH_NokiaProfileLong;
530 GSM_EncodeSMS30MultiPartSMS(Info,Buffer,&Length);
531 break;
532 case SMS_NokiaWAPBookmarkLong:
533 Class= 1;
534 NOKIA_EncodeWAPBookmarkSMSText(Buffer,&Length,Info->Entries[0].Bookmark);
535 /* 7 = length of UDH_NokiaWAP UDH header */
536 if (Length>(GSM_MAX_8BIT_SMS_LENGTH-7)) {
537 UDH=UDH_NokiaWAPLong;
538 } else {
539 UDH=UDH_NokiaWAP;
540 }
541 break;
542 case SMS_NokiaWAPSettingsLong:
543 Class= 1;
544 UDH= UDH_NokiaWAPLong;
545 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,false);
546 break;
547 case SMS_NokiaMMSSettingsLong:
548 Class= 1;
549 UDH= UDH_NokiaWAPLong;
550 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,true);
551 break;
552 case SMS_NokiaVCARD10Long:
553 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
554 /* is 1 SMS ? 8 = length of ..SCKE2 */
555 if (Length<=GSM_MAX_SMS_LENGTH-8) {
556 sprintf(Buffer,"//SCKE2 ");
557 Length = 8;
558 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
559 } else {
560 /* FIXME: It wasn't checked */
561 UDH = UDH_NokiaPhonebookLong;
562 }
563 Coding = SMS_Coding_Default;
564 memcpy(Buffer2,Buffer,Length);
565 EncodeUnicode(Buffer,Buffer2,Length);
566 break;
567 case SMS_NokiaVCARD21Long:
568 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
569 /* Is 1 SMS ? 12 = length of ..SCKL23F4 */
570 if (Length<=GSM_MAX_SMS_LENGTH-12) {
571 sprintf(Buffer,"//SCKL23F4%c%c",13,10);
572 Length = 12;
573 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
574 } else {
575 UDH = UDH_NokiaPhonebookLong;
576 /* Here can be also 8 bit coding */
577 }
578 Coding = SMS_Coding_Default;
579 memcpy(Buffer2,Buffer,Length);
580 EncodeUnicode(Buffer,Buffer2,Length);
581 break;
582 case SMS_VCARD10Long:
583 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
584 if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
585 Coding = SMS_Coding_Default;
586 memcpy(Buffer2,Buffer,Length);
587 EncodeUnicode(Buffer,Buffer2,Length);
588 break;
589 case SMS_VCARD21Long:
590 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
591 if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
592 Coding = SMS_Coding_Default;
593 memcpy(Buffer2,Buffer,Length);
594 EncodeUnicode(Buffer,Buffer2,Length);
595 break;
596 case SMS_NokiaVCALENDAR10Long:
597 error=GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
598 if (error != ERR_NONE) return error;
599 /* Is 1 SMS ? 8 = length of ..SCKE4 */
600 if (Length<=GSM_MAX_SMS_LENGTH-8) {
601 sprintf(Buffer,"//SCKE4 ");
602 Length = 8;
603 GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
604 } else {
605 UDH = UDH_NokiaCalendarLong;
606 /* can be here 8 bit coding ? */
607 }
608 Coding = SMS_Coding_Default;
609 memcpy(Buffer2,Buffer,Length);
610 EncodeUnicode(Buffer,Buffer2,Length);
611 break;
612 case SMS_NokiaVTODOLong:
613 error=GSM_EncodeVTODO(Buffer,&Length,Info->Entries[0].ToDo,true,Nokia_VToDo);
614 if (error != ERR_NONE) return error;
615 UDH = UDH_NokiaCalendarLong;
616 Coding = SMS_Coding_Default;
617 memcpy(Buffer2,Buffer,Length);
618 EncodeUnicode(Buffer,Buffer2,Length);
619 break;
620 case SMS_DisableVoice:
621 case SMS_DisableFax:
622 case SMS_DisableEmail:
623 case SMS_EnableVoice:
624 case SMS_EnableFax:
625 case SMS_EnableEmail:
626 case SMS_VoidSMS:
627 case SMS_Text:
628 Class = Info->Class;
629 switch (Info->Entries[0].ID) {
630 case SMS_DisableVoice: UDH = UDH_DisableVoice; break;
631 case SMS_DisableFax : UDH = UDH_DisableFax; break;
632 case SMS_DisableEmail: UDH = UDH_DisableEmail; break;
633 case SMS_EnableVoice: UDH = UDH_EnableVoice; break;
634 case SMS_EnableFax : UDH = UDH_EnableFax; break;
635 case SMS_EnableEmail: UDH = UDH_EnableEmail; break;
636 case SMS_VoidSMS : UDH = UDH_VoidSMS; break;
637 case SMS_Text : UDH = UDH_NoUDH; break;
638 default : break;
639 }
640 UDHHeader.Type = UDH;
641 GSM_EncodeUDHHeader(&UDHHeader);
642 memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
643 if (Info->UnicodeCoding) {
644 Coding = SMS_Coding_Unicode;
645 Length = UnicodeLength(Info->Entries[0].Buffer);
646 if (Length>(140-UDHHeader.Length)/2) Length = (140-UDHHeader.Length)/2;
647 } else {
648 Coding = SMS_Coding_Default;
649 FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,(GSM_MAX_8BIT_SMS_LENGTH-UDHHeader.Length)*8/7);
650 }
651 break;
652 case SMS_ConcatenatedAutoTextLong:
653 case SMS_ConcatenatedAutoTextLong16bit:
654 smslen = UnicodeLength(Info->Entries[0].Buffer);
655 memcpy(Buffer,Info->Entries[0].Buffer,smslen*2);
656 EncodeDefault(Buffer2, Buffer, &smslen, true, NULL);
657 DecodeDefault(Buffer, Buffer2, smslen, true, NULL);
658#ifdef DEBUG
659 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) {
660 dbgprintf("Info->Entries[0].Buffer:\n");
661 DumpMessage(di.df, di.dl, Info->Entries[0].Buffer, UnicodeLength(Info->Entries[0].Buffer)*2);
662 dbgprintf("Buffer:\n");
663 DumpMessage(di.df, di.dl, Buffer, UnicodeLength(Buffer)*2);
664 }
665#endif
666 Info->UnicodeCoding = false;
667 for (smslen=0;smslen<(int)(UnicodeLength(Info->Entries[0].Buffer)*2);smslen++) {
668 if (Info->Entries[0].Buffer[smslen] != Buffer[smslen]) {
669 Info->UnicodeCoding = true;
670 dbgprintf("Setting to Unicode %i\n",smslen);
671 break;
672 }
673 }
674 /* No break here - we go to the SMS_ConcatenatedTextLong */
675 case SMS_ConcatenatedTextLong:
676 case SMS_ConcatenatedTextLong16bit:
677 Class = Info->Class;
678 memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
679 UDH = UDH_NoUDH;
680 if (Info->UnicodeCoding) {
681 Coding = SMS_Coding_Unicode;
682 Length = UnicodeLength(Info->Entries[0].Buffer);
683 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit ||
684 Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) {
685 if (Length>70) UDH=UDH_ConcatenatedMessages16bit;
686 } else {
687 if (Length>70) UDH=UDH_ConcatenatedMessages;
688 }
689 } else {
690 Coding = SMS_Coding_Default;
691 FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,5000);
692 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit ||
693 Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) {
694 if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages16bit;
695 } else {
696 if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages;
697 }
698 }
699 default:
700 break;
701 }
702 GSM_MakeMultiPartSMS(SMS,Buffer,Length,UDH,Coding,Class,Info->ReplaceMessage);
703 return ERR_NONE;
704}
705
706void GSM_ClearMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info)
707{
708 int i;
709
710 for (i=0;i<MAX_MULTI_SMS;i++) {
711 Info->Entries[i].Number = 0;
712 Info->Entries[i].Ringtone= NULL;
713 Info->Entries[i].Bitmap = NULL;
714 Info->Entries[i].Bookmark= NULL;
715 Info->Entries[i].Settings= NULL;
716 Info->Entries[i].MMSIndicator= NULL;
717 Info->Entries[i].Phonebook= NULL;
718 Info->Entries[i].Calendar= NULL;
719 Info->Entries[i].ToDo = NULL;
720 Info->Entries[i].Protected= false;
721
722 Info->Entries[i].Buffer = NULL;
723 Info->Entries[i].Left = false;
724 Info->Entries[i].Right = false;
725 Info->Entries[i].Center = false;
726 Info->Entries[i].Large = false;
727 Info->Entries[i].Small = false;
728 Info->Entries[i].Bold = false;
729 Info->Entries[i].Italic = false;
730 Info->Entries[i].Underlined= false;
731 Info->Entries[i].Strikethrough= false;
732
733 Info->Entries[i].RingtoneNotes= 0;
734 }
735 Info->Unknown = false;
736 Info->EntriesNum= 0;
737 Info->Class = -1;
738 Info->ReplaceMessage= 0;
739 Info->UnicodeCoding= false;
740}
741
742void GSM_FreeMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info)
743{
744 int i;
745
746 for (i=0;i<MAX_MULTI_SMS;i++) {
747 free(Info->Entries[i].Ringtone);
748 Info->Entries[i].Ringtone = NULL;
749 free(Info->Entries[i].Bitmap);
750 Info->Entries[i].Bitmap = NULL;
751 free(Info->Entries[i].Bookmark);
752 Info->Entries[i].Bookmark = NULL;
753 free(Info->Entries[i].Settings);
754 Info->Entries[i].Settings = NULL;
755 free(Info->Entries[i].MMSIndicator);
756 Info->Entries[i].MMSIndicator = NULL;
757 free(Info->Entries[i].Phonebook);
758 Info->Entries[i].Phonebook = NULL;
759 free(Info->Entries[i].Calendar);
760 Info->Entries[i].Calendar = NULL;
761 free(Info->Entries[i].ToDo);
762 Info->Entries[i].ToDo = NULL;
763 free(Info->Entries[i].Buffer);
764 Info->Entries[i].Buffer = NULL;
765 }
766}
767
768/* ----------------- Joining SMS from parts -------------------------------- */
769
770 bool GSM_DecodeMultiPartSMS(GSM_MultiPartSMSInfo*Info,
771 GSM_MultiSMSMessage *SMS,
772 bool ems)
773{
774 int i, Length = 0;
775 charBuffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
776 bool emsexist = false;
777
778 GSM_ClearMultiPartSMSInfo(Info);
779 if (ems) {
780 emsexist = true;
781 for (i=0;i<SMS->Number;i++) {
782 if (SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages &&
783 SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages16bit &&
784 SMS->SMS[i].UDH.Type != UDH_UserUDH) {
785 emsexist = false;
786 break;
787 }
788 }
789 }
790
791 /* EMS decoding */
792 if (emsexist) return GSM_DecodeEMSMultiPartSMS(Info,SMS);
793
794 /* Smart Messaging decoding */
795 if (SMS->SMS[0].UDH.Type == UDH_NokiaRingtone && SMS->Number == 1) {
796 Info->Entries[0].Ringtone = (GSM_Ringtone *)malloc(sizeof(GSM_Ringtone));
797 if (Info->Entries[0].Ringtone == NULL) return false;
798 if (GSM_DecodeNokiaRTTLRingtone(Info->Entries[0].Ringtone, SMS->SMS[0].Text, SMS->SMS[0].Length)==ERR_NONE) {
799 Info->Entries[0].ID = SMS_NokiaRingtone;
800 Info->EntriesNum= 1;
801 return true;
802 }
803 }
804 if (SMS->SMS[0].UDH.Type == UDH_NokiaCallerLogo && SMS->Number == 1) {
805 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
806 if (Info->Entries[0].Bitmap == NULL) return false;
807 Info->Entries[0].Bitmap->Number = 1;
808 PHONE_DecodeBitmap(GSM_NokiaCallerLogo, SMS->SMS[0].Text+4, &Info->Entries[0].Bitmap->Bitmap[0]);
809#ifdef DEBUG
810 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
811#endif
812 Info->Entries[0].ID = SMS_NokiaCallerLogo;
813 Info->EntriesNum= 1;
814 return true;
815 }
816 if (SMS->SMS[0].UDH.Type == UDH_NokiaOperatorLogo && SMS->Number == 1) {
817 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
818 if (Info->Entries[0].Bitmap == NULL) return false;
819 Info->Entries[0].Bitmap->Number = 1;
820 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo, SMS->SMS[0].Text+7, &Info->Entries[0].Bitmap->Bitmap[0]);
821 NOKIA_DecodeNetworkCode(SMS->SMS[0].Text, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
822#ifdef DEBUG
823 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
824#endif
825 Info->Entries[0].ID = SMS_NokiaOperatorLogo;
826 Info->EntriesNum= 1;
827 return true;
828 }
829 if (SMS->SMS[0].UDH.Type == UDH_NokiaProfileLong) {
830 for (i=0;i<SMS->Number;i++) {
831 if (SMS->SMS[i].UDH.Type != UDH_NokiaProfileLong ||
832 SMS->SMS[i].UDH.Text[11] != i+1 ||
833 SMS->SMS[i].UDH.Text[10] != SMS->Number) {
834 return false;
835 }
836 memcpy(Buffer+Length,SMS->SMS[i].Text,SMS->SMS[i].Length);
837 Length = Length + SMS->SMS[i].Length;
838 }
839 Info->EntriesNum = 1;
840 Info->Entries[0].ID = SMS_NokiaPictureImageLong;
841 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
842 if (Info->Entries[0].Bitmap == NULL) return false;
843 Info->Entries[0].Bitmap->Number = 1;
844 Info->Entries[0].Bitmap->Bitmap[0].Text[0] = 0;
845 Info->Entries[0].Bitmap->Bitmap[0].Text[1] = 0;
846 i=1;
847 while (i!=Length) {
848 switch (Buffer[i]) {
849 case SM30_ISOTEXT:
850 dbgprintf("ISO 8859-2 text\n");
851 Info->Unknown = true;
852 break;
853 case SM30_UNICODETEXT:
854 dbgprintf("Unicode text\n");
855 memcpy(Info->Entries[0].Bitmap->Bitmap[0].Text,Buffer+i+3,Buffer[i+1]*256+Buffer[i+2]);
856 Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]] = 0;
857 Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]+ 1] = 0;
858 dbgprintf("Unicode Text \"%s\"\n",DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text));
859 break;
860 case SM30_OTA:
861 dbgprintf("OTA bitmap as Picture Image\n");
862 PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]);
863#ifdef DEBUG
864 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
865#endif
866 break;
867 case SM30_RINGTONE:
868 dbgprintf("RTTL ringtone\n");
869 Info->Unknown = true;
870 break;
871 case SM30_PROFILENAME:
872 dbgprintf("Profile Name\n");
873 Info->Entries[0].ID = SMS_NokiaProfileLong;
874 Info->Unknown = true;
875 break;
876 case SM30_SCREENSAVER:
877 dbgprintf("OTA bitmap as Screen Saver\n");
878 PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]);
879#ifdef DEBUG
880 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
881#endif
882 Info->Entries[0].ID = SMS_NokiaScreenSaverLong;
883 break;
884 }
885 i = i + Buffer[i+1]*256 + Buffer[i+2] + 3;
886 dbgprintf("%i %i\n",i,Length);
887 }
888 return true;
889 }
890
891 /* Linked sms */
892 if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages ||
893 SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) {
894 Info->EntriesNum = 1;
895 Info->Entries[0].ID = SMS_ConcatenatedTextLong;
896 if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) {
897 Info->Entries[0].ID = SMS_ConcatenatedTextLong16bit;
898 }
899
900 for (i=0;i<SMS->Number;i++) {
901 switch (SMS->SMS[i].Coding) {
902 case SMS_Coding_8bit:
903 Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + SMS->SMS[i].Length + 2);
904 if (Info->Entries[0].Buffer == NULL) return false;
905
906 memcpy(Info->Entries[0].Buffer + Length, SMS->SMS[i].Text, SMS->SMS[i].Length);
907 Length=Length+SMS->SMS[i].Length;
908 break;
909 case SMS_Coding_Unicode:
910 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong) {
911 Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong;
912 }
913 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit) {
914 Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong16bit;
915 }
916 case SMS_Coding_Default:
917 Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + UnicodeLength(SMS->SMS[i].Text)*2 + 2);
918 if (Info->Entries[0].Buffer == NULL) return false;
919
920 memcpy(Info->Entries[0].Buffer+Length,SMS->SMS[i].Text,UnicodeLength(SMS->SMS[i].Text)*2);
921 Length=Length+UnicodeLength(SMS->SMS[i].Text)*2;
922 break;
923 }
924 }
925 Info->Entries[0].Buffer[Length] = 0;
926 Info->Entries[0].Buffer[Length+1] = 0;
927 return true;
928 }
929
930 return false;
931}
932
933GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems)
934{
935 bool *INPUTSorted, copyit;
936 int i,OUTPUTNum,j,z,w;
937
938 i = 0;
939 while (INPUT[i] != NULL) i++;
940
941 INPUTSorted = calloc(i, sizeof(bool));
942 if (INPUTSorted == NULL) return ERR_MOREMEMORY;
943
944 OUTPUTNum = 0;
945 OUTPUT[0] = NULL;
946
947 if (ems) {
948 i=0;
949 while (INPUT[i] != NULL) {
950 if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) {
951 w=1;
952 while (w < INPUT[i]->SMS[0].UDH.Length) {
953 switch(INPUT[i]->SMS[0].UDH.Text[w]) {
954 case 0x00:
955 dbgprintf("Adding ID to user UDH - linked SMS with 8 bit ID\n");
956 INPUT[i]->SMS[0].UDH.ID8bit= INPUT[i]->SMS[0].UDH.Text[w+2];
957 INPUT[i]->SMS[0].UDH.AllParts= INPUT[i]->SMS[0].UDH.Text[w+3];
958 INPUT[i]->SMS[0].UDH.PartNumber= INPUT[i]->SMS[0].UDH.Text[w+4];
959 break;
960 case 0x08:
961 dbgprintf("Adding ID to user UDH - linked SMS with 16 bit ID\n");
962 INPUT[i]->SMS[0].UDH.ID16bit= INPUT[i]->SMS[0].UDH.Text[w+2]*256+INPUT[i]->SMS[0].UDH.Text[w+3];
963 INPUT[i]->SMS[0].UDH.AllParts= INPUT[i]->SMS[0].UDH.Text[w+4];
964 INPUT[i]->SMS[0].UDH.PartNumber= INPUT[i]->SMS[0].UDH.Text[w+5];
965 break;
966 default:
967 dbgprintf("Block %02x\n",INPUT[i]->SMS[0].UDH.Text[w]);
968 }
969 dbgprintf("%i %i %i %i\n",
970 INPUT[i]->SMS[0].UDH.ID8bit,
971 INPUT[i]->SMS[0].UDH.ID16bit,
972 INPUT[i]->SMS[0].UDH.PartNumber,
973 INPUT[i]->SMS[0].UDH.AllParts);
974 w=w+INPUT[i]->SMS[0].UDH.Text[w+1]+2;
975 }
976 }
977 i++;
978 }
979 }
980
981 i=0;
982 while (INPUT[i]!=NULL) {
983 /* If this one SMS was sorted earlier, do not touch */
984 if (INPUTSorted[i]) {
985 i++;
986 continue;
987 }
988 copyit = false;
989 /* If we have:
990 * - linked sms returned by phone driver
991 * - sms without linking
992 * we copy it to OUTPUT
993 */
994 if (INPUT[i]->Number != 1 ||
995 INPUT[i]->SMS[0].UDH.Type == UDH_NoUDH ||
996 INPUT[i]->SMS[0].UDH.PartNumber == -1) {
997 copyit = true;
998 }
999 /* If we have unknown UDH, we copy it to OUTPUT */
1000 if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) {
1001 if (!ems) copyit = true;
1002 if (ems && INPUT[i]->SMS[0].UDH.PartNumber == -1) copyit = true;
1003 }
1004 if (copyit) {
1005 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1006 if (OUTPUT[OUTPUTNum] == NULL) {
1007 free(INPUTSorted);
1008 return ERR_MOREMEMORY;
1009 }
1010 OUTPUT[OUTPUTNum+1] = NULL;
1011
1012 memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage));
1013 INPUTSorted[i]=true;
1014 OUTPUTNum++;
1015 i = 0;
1016 continue;
1017 }
1018 /* We have 1'st part of linked sms. It's single.
1019 * We will try to find other parts
1020 */
1021 if (INPUT[i]->SMS[0].UDH.PartNumber == 1) {
1022 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1023 if (OUTPUT[OUTPUTNum] == NULL) {
1024 free(INPUTSorted);
1025 return ERR_MOREMEMORY;
1026 }
1027 OUTPUT[OUTPUTNum+1] = NULL;
1028
1029 memcpy(&OUTPUT[OUTPUTNum]->SMS[0],&INPUT[i]->SMS[0],sizeof(GSM_SMSMessage));
1030 OUTPUT[OUTPUTNum]->Number = 1;
1031 INPUTSorted[i]= true;
1032 j = 1;
1033 /* We're searching for other parts in sequence */
1034 while (j!=INPUT[i]->SMS[0].UDH.AllParts) {
1035 z=0;
1036 while(INPUT[z]!=NULL) {
1037 /* This was sorted earlier or is not single */
1038 if (INPUTSorted[z] || INPUT[z]->Number != 1) {
1039 z++;
1040 continue;
1041 }
1042 if (ems && INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages &&
1043 INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit &&
1044 INPUT[i]->SMS[0].UDH.Type != UDH_UserUDH &&
1045 INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages &&
1046 INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit &&
1047 INPUT[z]->SMS[0].UDH.Type != UDH_UserUDH) {
1048 if (INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) {
1049 z++;
1050 continue;
1051 }
1052 }
1053 if (!ems && INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) {
1054 z++;
1055 continue;
1056 }
1057 dbgprintf("compare %i %i %i %i %i",
1058 j+1,
1059 INPUT[i]->SMS[0].UDH.ID8bit,
1060 INPUT[i]->SMS[0].UDH.ID16bit,
1061 INPUT[i]->SMS[0].UDH.PartNumber,
1062 INPUT[i]->SMS[0].UDH.AllParts);
1063 dbgprintf(" %i %i %i %i\n",
1064 INPUT[z]->SMS[0].UDH.ID8bit,
1065 INPUT[z]->SMS[0].UDH.ID16bit,
1066 INPUT[z]->SMS[0].UDH.PartNumber,
1067 INPUT[z]->SMS[0].UDH.AllParts);
1068 if (INPUT[z]->SMS[0].UDH.ID8bit != INPUT[i]->SMS[0].UDH.ID8bit||
1069 INPUT[z]->SMS[0].UDH.ID16bit != INPUT[i]->SMS[0].UDH.ID16bit||
1070 INPUT[z]->SMS[0].UDH.AllParts != INPUT[i]->SMS[0].UDH.AllParts ||
1071 INPUT[z]->SMS[0].UDH.PartNumber != j+1) {
1072 z++;
1073 continue;
1074 }
1075 /* For SMS_Deliver compare also SMSC and Sender number */
1076 if (INPUT[z]->SMS[0].PDU == SMS_Deliver &&
1077 (strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].SMSC.Number),DecodeUnicodeString(INPUT[i]->SMS[0].SMSC.Number)) ||
1078 strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].Number),DecodeUnicodeString(INPUT[i]->SMS[0].Number)))) {
1079 z++;
1080 continue;
1081 }
1082 /* DCT4 Outbox: SMS Deliver. Empty number and SMSC. We compare dates */
1083 if (INPUT[z]->SMS[0].PDU == SMS_Deliver &&
1084 UnicodeLength(INPUT[z]->SMS[0].SMSC.Number)==0 &&
1085 UnicodeLength(INPUT[z]->SMS[0].Number)==0 &&
1086 (INPUT[z]->SMS[0].DateTime.Day != INPUT[i]->SMS[0].DateTime.Day ||
1087 INPUT[z]->SMS[0].DateTime.Month != INPUT[i]->SMS[0].DateTime.Month ||
1088 INPUT[z]->SMS[0].DateTime.Year != INPUT[i]->SMS[0].DateTime.Year ||
1089 INPUT[z]->SMS[0].DateTime.Hour != INPUT[i]->SMS[0].DateTime.Hour ||
1090 INPUT[z]->SMS[0].DateTime.Minute != INPUT[i]->SMS[0].DateTime.Minute ||
1091 INPUT[z]->SMS[0].DateTime.Second != INPUT[i]->SMS[0].DateTime.Second)) {
1092 z++;
1093 continue;
1094 }
1095 /* We found correct sms. Copy it */
1096 memcpy(&OUTPUT[OUTPUTNum]->SMS[j],&INPUT[z]->SMS[0],sizeof(GSM_SMSMessage));
1097 OUTPUT[OUTPUTNum]->Number++;
1098 INPUTSorted[z]=true;
1099 break;
1100 }
1101 /* Incomplete sequence */
1102 if (OUTPUT[OUTPUTNum]->Number==j) {
1103 dbgprintf("Incomplete sequence\n");
1104 break;
1105 }
1106 j++;
1107 }
1108 OUTPUTNum++;
1109 i = 0;
1110 continue;
1111 }
1112 /* We have some next linked sms from sequence */
1113 if (INPUT[i]->SMS[0].UDH.PartNumber > 1) {
1114 j = 0;
1115 while (INPUT[j]!=NULL) {
1116 if (INPUTSorted[j]) {
1117 j++;
1118 continue;
1119 }
1120 /* We have some not unassigned first sms from sequence.
1121 * We can't touch other sms from sequences
1122 */
1123 if (INPUT[j]->SMS[0].UDH.PartNumber == 1) break;
1124 j++;
1125 }
1126 if (INPUT[j]==NULL) {
1127 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1128 if (OUTPUT[OUTPUTNum] == NULL) {
1129 free(INPUTSorted);
1130 return ERR_MOREMEMORY;
1131 }
1132 OUTPUT[OUTPUTNum+1] = NULL;
1133
1134 memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage));
1135 INPUTSorted[i]=true;
1136 OUTPUTNum++;
1137 i = 0;
1138 continue;
1139 } else i++;
1140 }
1141 }
1142 free(INPUTSorted);
1143 return ERR_NONE;
1144}
1145
1146/* How should editor hadle tabs in this file? Add editor commands here.
1147 * vim: noexpandtab sw=8 ts=8 sts=8:
1148 */
diff --git a/gammu/emb/common/service/sms/gsmmulti.h b/gammu/emb/common/service/sms/gsmmulti.h
new file mode 100644
index 0000000..c672261
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmmulti.h
@@ -0,0 +1,271 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_multi_h
4#define __gsm_multi_h
5
6#include "../../gsmcomon.h"
7#include "../gsmlogo.h"
8#include "../gsmcal.h"
9#include "../gsmpbk.h"
10#include "../gsmdata.h"
11#include "../gsmring.h"
12#include "gsmsms.h"
13
14/* ---------------------- multi SMS --------------------------------------- */
15
16/* Identifiers for Smart Messaging 3.0 multipart SMS */
17
18#define SM30_ISOTEXT 0 /* ISO 8859-1 text */
19#define SM30_UNICODETEXT 1
20 #define SM30_OTA 2
21#define SM30_RINGTONE 3
22#define SM30_PROFILENAME 4
23/* ... */
24#define SM30_SCREENSAVER 6
25
26/* Identifiers for Alcatel Terminal Data Download */
27#define ALCATELTDD_PICTURE 4
28#define ALCATELTDD_ANIMATION 5
29#define ALCATELTDD_SMSTEMPLATE 6
30
31 void GSM_SMSCounter(int MessageLength,
32 unsigned char *MessageBuffer,
33 GSM_UDH UDHType,
34 GSM_Coding_Type Coding,
35 int *SMSNum,
36 int *CharsLeft);
37
38#define MAX_MULTI_SMS 10
39
40/**
41 * Multiple SMS messages, used for Smart Messaging 3.0/EMS.
42 */
43typedef struct {
44 /**
45 * Sender or recipient number.
46 */
47 unsigned char Number;
48 /**
49 * Array of SMSes.
50 */
51 GSM_SMSMessage SMS[MAX_MULTI_SMS];
52} GSM_MultiSMSMessage;
53
54GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS,
55 GSM_Coding_Type Coding,
56 char *Buffer,
57 int BufferLen,
58 bool UDH,
59 int *UsedText,
60 int *CopiedText,
61 int *CopiedSMSText);
62
63void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage *SMS,
64 unsigned char *MessageBuffer,
65 int MessageLength,
66 GSM_UDH UDHType,
67 GSM_Coding_Type Coding,
68 int Class,
69 unsigned char RejectDuplicates);
70
71void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes);
72
73unsigned char GSM_MakeSMSIDFromTime(void);
74
75/**
76 * ID during packing SMS for Smart Messaging 3.0, EMS and other
77 */
78typedef enum {
79 /**
80 * 1 text SMS.
81 */
82 SMS_Text = 1,
83 /**
84 * Contacenated SMS, when longer than 1 SMS.
85 */
86 SMS_ConcatenatedTextLong,
87 /**
88 * Contacenated SMS, auto Default/Unicode coding.
89 */
90 SMS_ConcatenatedAutoTextLong,
91 SMS_ConcatenatedTextLong16bit,
92 SMS_ConcatenatedAutoTextLong16bit,
93 /**
94 * Nokia profile = Name, Ringtone, ScreenSaver
95 */
96 SMS_NokiaProfileLong,
97 /**
98 * Nokia Picture Image + (text)
99 */
100 SMS_NokiaPictureImageLong,
101 /**
102 * Nokia screen saver + (text)
103 */
104 SMS_NokiaScreenSaverLong,
105 /**
106 * Nokia ringtone - old SM2.0 format, 1 SMS
107 */
108 SMS_NokiaRingtone,
109 /**
110 * Nokia ringtone contacenated, when very long
111 */
112 SMS_NokiaRingtoneLong,
113 /**
114 * Nokia 72x14 operator logo, 1 SMS
115 */
116 SMS_NokiaOperatorLogo,
117 /**
118 * Nokia 72x14 op logo or 78x21 in 2 SMS
119 */
120 SMS_NokiaOperatorLogoLong,
121 /**
122 * Nokia 72x14 caller logo, 1 SMS
123 */
124 SMS_NokiaCallerLogo,
125 /**
126 * Nokia WAP bookmark in 1 or 2 SMS
127 */
128 SMS_NokiaWAPBookmarkLong,
129 /**
130 * Nokia WAP settings in 2 SMS
131 */
132 SMS_NokiaWAPSettingsLong,
133 /**
134 * Nokia MMS settings in 2 SMS
135 */
136 SMS_NokiaMMSSettingsLong,
137 /**
138 * Nokia VCARD 1.0 - only name and default number
139 */
140 SMS_NokiaVCARD10Long,
141 /**
142 * Nokia VCARD 2.1 - all numbers + text
143 */
144 SMS_NokiaVCARD21Long,
145 /**
146 * Nokia VCALENDAR 1.0 - can be in few sms
147 */
148 SMS_NokiaVCALENDAR10Long,
149 SMS_NokiaVTODOLong,
150 SMS_VCARD10Long,
151 SMS_VCARD21Long,
152 SMS_DisableVoice,
153 SMS_DisableFax,
154 SMS_DisableEmail,
155 SMS_EnableVoice,
156 SMS_EnableFax,
157 SMS_EnableEmail,
158 SMS_VoidSMS,
159 /**
160 * IMelody 1.0
161 */
162 SMS_EMSSound10,
163 /**
164 * IMelody 1.2
165 */
166 SMS_EMSSound12,
167 /**
168 * IMelody without header - SonyEricsson extension
169 */
170 SMS_EMSSonyEricssonSound,
171 /**
172 * IMelody 1.0 with UPI.
173 */
174 SMS_EMSSound10Long,
175 /***
176 * IMelody 1.2 with UPI.
177 */
178 SMS_EMSSound12Long,
179 /**
180 * IMelody without header with UPI.
181 */
182 SMS_EMSSonyEricssonSoundLong,
183 SMS_EMSPredefinedSound,
184 SMS_EMSPredefinedAnimation,
185 SMS_EMSAnimation,
186 /**
187 * Fixed bitmap of size 16x16 or 32x32.
188 */
189 SMS_EMSFixedBitmap,
190 SMS_EMSVariableBitmap,
191 SMS_EMSVariableBitmapLong,
192 SMS_MMSIndicatorLong,
193 /**
194 * Variable bitmap with black and white colors
195 */
196 SMS_AlcatelMonoBitmapLong,
197 /**
198 * Variable animation with black and white colors
199 */
200 SMS_AlcatelMonoAnimationLong,
201 SMS_AlcatelSMSTemplateName
202} EncodeMultiPartSMSID;
203
204typedef struct {
205 EncodeMultiPartSMSID ID;
206
207 int Number;
208 GSM_Ringtone *Ringtone;
209 GSM_MultiBitmap *Bitmap;
210 GSM_WAPBookmark *Bookmark;
211 GSM_WAPSettings *Settings;
212 GSM_MMSIndicator*MMSIndicator;
213 GSM_MemoryEntry *Phonebook;
214 GSM_CalendarEntry *Calendar;
215 GSM_ToDoEntry *ToDo;
216 bool Protected;
217
218 unsigned char *Buffer;
219 bool Left;
220 bool Right;
221 bool Center;
222 bool Large;
223 bool Small;
224 bool Bold;
225 bool Italic;
226 bool Underlined;
227 bool Strikethrough;
228
229 /* Return values */
230 int RingtoneNotes;
231} MultiPartSMSEntry;
232
233typedef struct {
234 MultiPartSMSEntryEntries[MAX_MULTI_SMS];
235 int EntriesNum;
236 bool UnicodeCoding;
237 int Class;
238 unsigned char ReplaceMessage;
239 bool Unknown;
240} GSM_MultiPartSMSInfo;
241
242/**
243 * Encodes multi part SMS from "readable" format.
244 */
245GSM_Error GSM_EncodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS);
246
247/**
248 * Decodes multi part SMS to "readable" format.
249 */
250bool GSM_DecodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, bool ems);
251
252/**
253 * Clears @ref GSM_MultiPartSMSInfo to default values.
254 */
255void GSM_ClearMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
256
257/**
258 * Frees any allocated structures inside @ref GSM_MultiPartSMSInfo.
259 */
260void GSM_FreeMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
261
262/**
263 * Links SMS messages according to IDs.
264 */
265GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems);
266
267#endif
268
269/* How should editor hadle tabs in this file? Add editor commands here.
270 * vim: noexpandtab sw=8 ts=8 sts=8:
271 */
diff --git a/gammu/emb/common/service/sms/gsmsms.c b/gammu/emb/common/service/sms/gsmsms.c
new file mode 100644
index 0000000..9920835
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmsms.c
@@ -0,0 +1,663 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Pawel Kot, others and Gnokii */
3
4#include <ctype.h>
5#include <string.h>
6#include <time.h>
7
8#include "../../gsmcomon.h"
9#include "../../misc/coding/coding.h"
10#include "../gsmcal.h"
11#include "../gsmpbk.h"
12#include "../gsmlogo.h"
13#include "../gsmring.h"
14#include "../gsmdata.h"
15#include "../gsmnet.h"
16#include "gsmsms.h"
17
18/* User data headers */
19static GSM_UDHHeader UDHHeaders[] = {
20 /* See GSM 03.40 section 9.2.3.24.1
21 * 1 byte 0x00
22 * 1 byte 0x03
23 * 1 byte 0x01: unique ID for message series
24 * 1 byte 0x00: how many SMS in sequence
25 * 1 byte 0x00: number of current SMS in sequence */
26 { UDH_ConcatenatedMessages, 0x05, "\x00\x03\x01\x00\x00",2,-1,4,3},
27
28 /* See GSM 03.40 section 9.2.3.24.2 for voice, fax and email messages */
29 { UDH_DisableVoice, 0x04, "\x01\x02\x00\x00",-1,-1,-1,-1},
30 { UDH_DisableFax, 0x04, "\x01\x02\x01\x00",-1,-1,-1,-1},
31 { UDH_DisableEmail, 0x04, "\x01\x02\x02\x00",-1,-1,-1,-1},
32 { UDH_EnableVoice, 0x04, "\x01\x02\x00\x01",-1,-1,-1,-1},
33 { UDH_EnableFax, 0x04, "\x01\x02\x01\x01",-1,-1,-1,-1},
34 { UDH_EnableEmail, 0x04, "\x01\x02\x02\x01",-1,-1,-1,-1},
35
36 /* When send such SMS to some phones, they don't display anything,
37 * only beep and enable vibra/light
38 */
39 { UDH_VoidSMS, 0x08, "\x01\x02\x02\x01\x01\x02\x02\x00",-1,-1,-1,-1},
40
41 /* Nokia Smart Messaging (short version) UDH
42 * General format :
43 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
44 * 1 byte 0x04 : IEI length
45 * 2 bytes : destination address : high & low byte
46 * 2 bytes 0x00 0x00 : originator address : high & low byte */
47 { UDH_NokiaRingtone, 0x06, "\x05\x04\x15\x81\x00\x00",-1,-1,-1,-1},
48 { UDH_NokiaOperatorLogo, 0x06, "\x05\x04\x15\x82\x00\x00",-1,-1,-1,-1},
49 { UDH_NokiaCallerLogo, 0x06, "\x05\x04\x15\x83\x00\x00",-1,-1,-1,-1},
50 { UDH_NokiaWAP, 0x06, "\x05\x04\xc3\x4f\x00\x00",-1,-1,-1,-1},
51
52 /* Nokia Smart Messaging (long version) UDH and other
53 * General format:
54 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
55 * 1 byte 0x04 : IEI length
56 * 2 bytes 0x00 0x00 : destination address : high & low byte
57 * 2 bytes 0x00 0x00 : originator address : high & low byte
58 * 1 byte 0x00 : SAR
59 * 1 byte 0x03 : SAR length
60 * 1 byte : diagram reference number (unique ID for message series)
61 * 1 byte : number of all SMS
62 * 1 byte : number of current SMS */
63 { UDH_NokiaCalendarLong, 0x0b, "\x05\x04\x00\xe4\x00\x00\x00\x03\xc7\x00\x00",8,-1,10,9},
64 { UDH_MMSIndicatorLong, 0x0b, "\x05\x04\x0b\x84\x23\xf0\x00\x03\xe5\x00\x00",8,-1,10,9},
65 { UDH_NokiaRingtoneLong, 0x0b, "\x05\x04\x15\x81\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
66 { UDH_NokiaOperatorLogoLong, 0x0b, "\x05\x04\x15\x82\x00\x00\x00\x03\x02\x00\x00",8,-1,10,9},
67 { UDH_NokiaProfileLong, 0x0b, "\x05\x04\x15\x8a\x00\x00\x00\x03\xce\x00\x00",8,-1,10,9},
68 { UDH_NokiaPhonebookLong, 0x0b, "\x05\x04\x23\xf4\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
69 { UDH_NokiaWAPLong, 0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x7f\x00\x00",8,-1,10,9},
70
71 { UDH_ConcatenatedMessages16bit,0x06, "\x08\x04\x00\x00\x00\x00",-1,2,5,4},
72
73 { UDH_NoUDH, 0x00, "",-1,-1,-1,-1}
74};
75
76/* --------------------------- Unpacking SMS ------------------------------- */
77
78/* See GSM 03.40 section 9.2.3.11 */
79static GSM_Error GSM_DecodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
80{
81 DT->Year = DecodeWithBCDAlphabet(req[0]);
82 if (DT->Year<90) DT->Year=DT->Year+2000; else DT->Year=DT->Year+1990;
83 DT->Month = DecodeWithBCDAlphabet(req[1]);
84 DT->Day = DecodeWithBCDAlphabet(req[2]);
85 DT->Hour = DecodeWithBCDAlphabet(req[3]);
86 DT->Minute = DecodeWithBCDAlphabet(req[4]);
87 DT->Second = DecodeWithBCDAlphabet(req[5]);
88
89 /* Base for timezone is GMT. It's in quarters */
90 DT->Timezone=(10*(req[6]&0x07)+(req[6]>>4))/4;
91
92 if (req[6]&0x08) DT->Timezone = -DT->Timezone;
93
94 dbgprintf("Decoding date & time: ");
95 dbgprintf("%s %4d/%02d/%02d ", DayOfWeek(DT->Year, DT->Month, DT->Day),
96 DT->Year, DT->Month, DT->Day);
97 dbgprintf("%02d:%02d:%02d %02d00\n", DT->Hour, DT->Minute, DT->Second, DT->Timezone);
98
99 return ERR_NONE;
100}
101
102void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH)
103{
104 inti, tmp, w;
105 boolUDHOK;
106
107 UDH->Type = UDH_UserUDH;
108 UDH->ID8bit= -1;
109 UDH->ID16bit= -1;
110 UDH->PartNumber= -1;
111 UDH->AllParts= -1;
112
113 i=-1;
114 while (true) {
115 i++;
116 if (UDHHeaders[i].Type==UDH_NoUDH) break;
117
118 tmp=UDHHeaders[i].Length;
119 /* if length is the same */
120 if (tmp==UDH->Text[0]) {
121
122 if (tmp==0x05) tmp=tmp-3;/*three last bytes can be different for such UDH*/
123 if (tmp==0x0b) tmp=tmp-3;/*three last bytes can be different for such UDH*/
124 if (tmp==0x06 && UDH->Text[1] == 0x08) tmp=tmp-4;
125
126 UDHOK=true;
127 for (w=0;w<tmp;w++) {
128 if (UDHHeaders[i].Text[w]!=UDH->Text[w+1]) {
129 UDHOK=false;
130 break;
131 }
132 }
133 if (UDHOK) {
134 UDH->Type=UDHHeaders[i].Type;
135
136 if (UDHHeaders[i].ID8bit !=-1) UDH->ID8bit = UDH->Text[UDHHeaders[i].ID8bit+1];
137 if (UDHHeaders[i].ID16bit !=-1) UDH->ID16bit = UDH->Text[UDHHeaders[i].ID16bit+1]*256+UDH->Text[UDHHeaders[i].ID16bit+2];
138 if (UDHHeaders[i].PartNumber !=-1) UDH->PartNumber = UDH->Text[UDHHeaders[i].PartNumber+1];
139 if (UDHHeaders[i].AllParts !=-1) UDH->AllParts = UDH->Text[UDHHeaders[i].AllParts+1];
140 break;
141 }
142 }
143 }
144
145#ifdef DEBUG
146 dbgprintf("Type of UDH: ");
147 switch (UDH->Type) {
148 case UDH_ConcatenatedMessages : dbgprintf("Concatenated (linked) message"); break;
149 case UDH_ConcatenatedMessages16bit : dbgprintf("Concatenated (linked) message"); break;
150 case UDH_DisableVoice : dbgprintf("Disables voice indicator"); break;
151 case UDH_EnableVoice : dbgprintf("Enables voice indicator"); break;
152 case UDH_DisableFax : dbgprintf("Disables fax indicator"); break;
153 case UDH_EnableFax : dbgprintf("Enables fax indicator"); break;
154 case UDH_DisableEmail : dbgprintf("Disables email indicator"); break;
155 case UDH_EnableEmail : dbgprintf("Enables email indicator"); break;
156 case UDH_VoidSMS : dbgprintf("Void SMS"); break;
157 case UDH_NokiaWAP : dbgprintf("Nokia WAP Bookmark"); break;
158 case UDH_NokiaOperatorLogoLong : dbgprintf("Nokia operator logo"); break;
159 case UDH_NokiaWAPLong : dbgprintf("Nokia WAP Bookmark or WAP/MMS Settings");break;
160 case UDH_NokiaRingtone : dbgprintf("Nokia ringtone"); break;
161 case UDH_NokiaRingtoneLong : dbgprintf("Nokia ringtone"); break;
162 case UDH_NokiaOperatorLogo : dbgprintf("Nokia GSM operator logo"); break;
163 case UDH_NokiaCallerLogo : dbgprintf("Nokia caller logo"); break;
164 case UDH_NokiaProfileLong : dbgprintf("Nokia profile"); break;
165 case UDH_NokiaCalendarLong : dbgprintf("Nokia calendar note"); break;
166 case UDH_NokiaPhonebookLong : dbgprintf("Nokia phonebook entry"); break;
167 case UDH_UserUDH : dbgprintf("User UDH"); break;
168 case UDH_MMSIndicatorLong : dbgprintf("MMS indicator"); break;
169 case UDH_NoUDH: break;
170 }
171 if (UDH->ID8bit != -1) dbgprintf(", ID 8 bit %i",UDH->ID8bit);
172 if (UDH->ID16bit != -1) dbgprintf(", ID 16 bit %i",UDH->ID16bit);
173 if (UDH->PartNumber != -1 && UDH->AllParts != -1) {
174 dbgprintf(", part %i of %i",UDH->PartNumber,UDH->AllParts);
175 }
176 dbgprintf("\n");
177 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, UDH->Text, UDH->Length);
178#endif
179}
180
181GSM_Error GSM_DecodeSMSFrameText(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
182{
183 int off=0; // length of the User Data Header
184 int w,i,tmp=0;
185 unsigned charoutput[161];
186
187 SMS->UDH.Length = 0;
188 /* UDH header available */
189 if (buffer[Layout.firstbyte] & 64) {
190 /* Length of UDH header */
191 off = (buffer[Layout.Text] + 1);
192 SMS->UDH.Length = off;
193 dbgprintf("UDH header available (length %i)\n",off);
194
195 /* Copy UDH header into SMS->UDH */
196 for (i = 0; i < off; i++) SMS->UDH.Text[i] = buffer[Layout.Text + i];
197
198 GSM_DecodeUDHHeader(&SMS->UDH);
199 }
200
201 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
202 if ((buffer[Layout.TPDCS] & 0xf4) == 0xf4) SMS->Coding=SMS_Coding_8bit;
203 if ((buffer[Layout.TPDCS] & 0x08) == 0x08) SMS->Coding=SMS_Coding_Unicode;
204
205 switch (SMS->Coding) {
206 case SMS_Coding_Default:
207 i = 0;
208 do {
209 i+=7;
210 w=(i-off)%i;
211 } while (w<0);
212 SMS->Length=buffer[Layout.TPUDL] - (off*8 + w) / 7;
213 tmp=GSM_UnpackEightBitsToSeven(w, buffer[Layout.TPUDL]-off, SMS->Length, buffer+(Layout.Text+off), output);
214 dbgprintf("7 bit SMS, length %i\n",SMS->Length);
215 DecodeDefault (SMS->Text, output, SMS->Length, true, NULL);
216 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
217 break;
218 case SMS_Coding_8bit:
219 SMS->Length=buffer[Layout.TPUDL] - off;
220 memcpy(SMS->Text,buffer+(Layout.Text+off),SMS->Length);
221#ifdef DEBUG
222 dbgprintf("8 bit SMS, length %i\n",SMS->Length);
223 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->Text, SMS->Length);
224#endif
225 break;
226 case SMS_Coding_Unicode:
227 SMS->Length=(buffer[Layout.TPUDL] - off) / 2;
228 DecodeUnicodeSpecialNOKIAChars(SMS->Text,buffer+(Layout.Text+off), SMS->Length);
229#ifdef DEBUG
230 dbgprintf("Unicode SMS, length %i\n",SMS->Length);
231 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, buffer+(Layout.Text+off), SMS->Length*2);
232 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
233#endif
234 break;
235 }
236
237 return ERR_NONE;
238}
239
240GSM_Error GSM_DecodeSMSFrameStatusReportData(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
241{
242 SMS->DeliveryStatus = buffer[Layout.TPStatus];
243
244 if (buffer[Layout.TPStatus] < 0x03) {
245 EncodeUnicode(SMS->Text,"Delivered",9);
246 SMS->Length = 9;
247 } else if (buffer[Layout.TPStatus] & 0x40) {
248 EncodeUnicode(SMS->Text,"Failed",6);
249 SMS->Length = 6;
250 } else if (buffer[Layout.TPStatus] & 0x20) {
251 EncodeUnicode(SMS->Text,"Pending",7);
252 SMS->Length = 7;
253 } else {
254 EncodeUnicode(SMS->Text,"Unknown",7);
255 SMS->Length = 7;
256 }
257
258#ifdef DEBUG
259 /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
260 if (buffer[Layout.TPStatus] & 0x40) {
261 if (buffer[Layout.TPStatus] & 0x20) {
262 /* 0x60, 0x61, ... */
263 dbgprintf("Temporary error, SC is not making any more transfer attempts\n");
264 } else {
265 /* 0x40, 0x41, ... */
266 dbgprintf("Permanent error, SC is not making any more transfer attempts\n");
267 }
268 } else if (buffer[Layout.TPStatus] & 0x20) {
269 /* 0x20, 0x21, ... */
270 dbgprintf("Temporary error, SC still trying to transfer SM\n");
271 }
272 switch (buffer[Layout.TPStatus]) {
273 case 0x00: dbgprintf("SM received by the SME"); break;
274 case 0x01: dbgprintf("SM forwarded by the SC to the SME but the SC is unable to confirm delivery");break;
275 case 0x02: dbgprintf("SM replaced by the SC"); break;
276 case 0x20: dbgprintf("Congestion"); break;
277 case 0x21: dbgprintf("SME busy"); break;
278 case 0x22: dbgprintf("No response from SME"); break;
279 case 0x23: dbgprintf("Service rejected"); break;
280 case 0x24: dbgprintf("Quality of service not available"); break;
281 case 0x25: dbgprintf("Error in SME"); break;
282 case 0x40: dbgprintf("Remote procedure error"); break;
283 case 0x41: dbgprintf("Incompatibile destination"); break;
284 case 0x42: dbgprintf("Connection rejected by SME"); break;
285 case 0x43: dbgprintf("Not obtainable"); break;
286 case 0x44: dbgprintf("Quality of service not available"); break;
287 case 0x45: dbgprintf("No internetworking available"); break;
288 case 0x46: dbgprintf("SM Validity Period Expired"); break;
289 case 0x47: dbgprintf("SM deleted by originating SME"); break;
290 case 0x48: dbgprintf("SM Deleted by SC Administration"); break;
291 case 0x49: dbgprintf("SM does not exist"); break;
292 case 0x60: dbgprintf("Congestion"); break;
293 case 0x61: dbgprintf("SME busy"); break;
294 case 0x62: dbgprintf("No response from SME"); break;
295 case 0x63: dbgprintf("Service rejected"); break;
296 case 0x64: dbgprintf("Quality of service not available"); break;
297 case 0x65: dbgprintf("Error in SME"); break;
298 default : dbgprintf("Reserved/Specific to SC: %x",buffer[Layout.TPStatus]);break;
299 }
300 dbgprintf("\n");
301#endif
302
303 return ERR_NONE;
304}
305
306GSM_Error GSM_DecodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
307{
308 GSM_DateTimezerodt = {0,0,0,0,0,0,0};
309#ifdef DEBUG
310 if (Layout.firstbyte == 255) {
311 dbgprintf("ERROR: firstbyte in SMS layout not set\n");
312 return ERR_UNKNOWN;
313 }
314 if (Layout.TPDCS != 255) dbgprintf("TPDCS : %02x %i\n",buffer[Layout.TPDCS] ,buffer[Layout.TPDCS]);
315 if (Layout.TPMR != 255) dbgprintf("TPMR : %02x %i\n",buffer[Layout.TPMR] ,buffer[Layout.TPMR]);
316 if (Layout.TPPID != 255) dbgprintf("TPPID : %02x %i\n",buffer[Layout.TPPID] ,buffer[Layout.TPPID]);
317 if (Layout.TPUDL != 255) dbgprintf("TPUDL : %02x %i\n",buffer[Layout.TPUDL] ,buffer[Layout.TPUDL]);
318 if (Layout.firstbyte != 255) dbgprintf("FirstByte : %02x %i\n",buffer[Layout.firstbyte],buffer[Layout.firstbyte]);
319 if (Layout.Text != 255) dbgprintf("Text : %02x %i\n",buffer[Layout.Text] ,buffer[Layout.Text]);
320#endif
321
322 SMS->UDH.Type = UDH_NoUDH;
323 SMS->Coding = SMS_Coding_Default;
324 SMS->Length = 0;
325 SMS->SMSC.Location = 0;
326 SMS->SMSC.DefaultNumber[0]= 0;
327 SMS->SMSC.DefaultNumber[1]= 0;
328 SMS->SMSC.Number[0] = 0;
329 SMS->SMSC.Number[1] = 0;
330 SMS->SMSC.Name[0] = 0;
331 SMS->SMSC.Name[1] = 0;
332 SMS->SMSC.Validity.Format= SMS_Validity_NotAvailable;
333 SMS->SMSC.Format = SMS_FORMAT_Text;
334 SMS->Number[0] = 0;
335 SMS->Number[1] = 0;
336 SMS->Name[0] = 0;
337 SMS->Name[1] = 0;
338 SMS->ReplyViaSameSMSC = false;
339 if (Layout.SMSCNumber!=255) {
340 GSM_UnpackSemiOctetNumber(SMS->SMSC.Number,buffer+Layout.SMSCNumber,false);
341 dbgprintf("SMS center number : \"%s\"\n",DecodeUnicodeString(SMS->SMSC.Number));
342 }
343 if ((buffer[Layout.firstbyte] & 0x80)!=0) SMS->ReplyViaSameSMSC=true;
344#ifdef DEBUG
345 if (SMS->ReplyViaSameSMSC) dbgprintf("SMS centre set for reply\n");
346#endif
347 if (Layout.Number!=255) {
348 GSM_UnpackSemiOctetNumber(SMS->Number,buffer+Layout.Number,true);
349 dbgprintf("Remote number : \"%s\"\n",DecodeUnicodeString(SMS->Number));
350 }
351 if (Layout.Text != 255 && Layout.TPDCS!=255 && Layout.TPUDL!=255) {
352 GSM_DecodeSMSFrameText(SMS, buffer, Layout);
353 }
354 if (Layout.DateTime != 255) {
355 GSM_DecodeSMSDateTime(&SMS->DateTime,buffer+(Layout.DateTime));
356 } else {
357 SMS->DateTime = zerodt;
358 }
359 if (Layout.SMSCTime != 255 && Layout.TPStatus != 255) {
360 /* GSM 03.40 section 9.2.3.11 (TP-Service-Centre-Time-Stamp) */
361 dbgprintf("SMSC response date: ");
362 GSM_DecodeSMSDateTime(&SMS->SMSCTime, buffer+(Layout.SMSCTime));
363 GSM_DecodeSMSFrameStatusReportData(SMS,buffer,Layout);
364 } else {
365 SMS->SMSCTime = zerodt;
366 }
367 SMS->Class = -1;
368 if (Layout.TPDCS != 255) {
369 if ((buffer[Layout.TPDCS] & 0xF3)==0xF0) SMS->Class = 0;
370 if ((buffer[Layout.TPDCS] & 0xF3)==0xF1) SMS->Class = 1;
371 if ((buffer[Layout.TPDCS] & 0xF3)==0xF2) SMS->Class = 2;
372 if ((buffer[Layout.TPDCS] & 0xF3)==0xF3) SMS->Class = 3;
373 }
374 dbgprintf("SMS class: %i\n",SMS->Class);
375
376 SMS->MessageReference = 0;
377 if (Layout.TPMR != 255) SMS->MessageReference = buffer[Layout.TPMR];
378
379 SMS->ReplaceMessage = 0;
380 if (Layout.TPPID != 255) {
381 if (buffer[Layout.TPPID] > 0x40 && buffer[Layout.TPPID] < 0x48) {
382 SMS->ReplaceMessage = buffer[Layout.TPPID] - 0x40;
383 }
384 }
385 SMS->RejectDuplicates = false;
386 if ((buffer[Layout.firstbyte] & 0x04)==0x04) SMS->RejectDuplicates = true;
387
388 return ERR_NONE;
389}
390
391/* ----------------------------- Packing SMS ------------------------------- */
392
393/* See GSM 03.40 section 9.2.3.11 */
394static GSM_Error GSM_EncodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
395{
396 int Year;
397
398 dbgprintf("Encoding SMS datetime: %02i/%02i/%04i %02i:%02i:%02i\n",
399 DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second);
400
401 /* We need to have only two last digits of year */
402 if (DT->Year>1900) {
403 if (DT->Year<2000) Year = DT->Year-1900;
404 else Year = DT->Year-2000;
405 } else Year = DT->Year;
406
407 req[0]=EncodeWithBCDAlphabet(Year);
408 req[1]=EncodeWithBCDAlphabet(DT->Month);
409 req[2]=EncodeWithBCDAlphabet(DT->Day);
410 req[3]=EncodeWithBCDAlphabet(DT->Hour);
411 req[4]=EncodeWithBCDAlphabet(DT->Minute);
412 req[5]=EncodeWithBCDAlphabet(DT->Second);
413
414 /* FIXME: do it */
415 req[6]=0; /* TimeZone = +-0 */
416
417 return ERR_NONE;
418}
419
420static int GSM_EncodeSMSFrameText(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
421{
422 int off = 0;// length of the User Data Header
423 intsize = 0, size2 = 0, w,p;
424 charbuff[200];
425
426 if (SMS->UDH.Type!=UDH_NoUDH) {
427 buffer[Layout.firstbyte] |= 0x40; /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
428 off = 1 + SMS->UDH.Text[0]; /* off - length of the User Data Header */
429 memcpy(buffer+Layout.Text, SMS->UDH.Text, off); /* we copy the udh */
430#ifdef DEBUG
431 dbgprintf("UDH, length %i\n",off);
432 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->UDH.Text, off);
433#endif
434 }
435 switch (SMS->Coding) {
436 case SMS_Coding_8bit:
437 /* the mask for the 8-bit data */
438 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
439 * and GSM 03.38 section 4 */
440 buffer[Layout.TPDCS] |= 0xf4;
441 memcpy(buffer+(Layout.Text+off), SMS->Text, SMS->Length);
442 size2 = size = SMS->Length+off;
443#ifdef DEBUG
444 dbgprintf("8 bit SMS, length %i\n",SMS->Length);
445 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->Text, SMS->Length);
446#endif
447 break;
448 case SMS_Coding_Default:
449 p = 0;
450 do {
451 p+=7;
452 w=(p-off)%p;
453 } while (w<0);
454 p = UnicodeLength(SMS->Text);
455 EncodeDefault(buff, SMS->Text, &p, true, NULL);
456 size = GSM_PackSevenBitsToEight(w, buff, buffer+(Layout.Text+off), p);
457 size += off;
458 size2 = (off*8 + w) / 7 + p;
459 dbgprintf("7 bit SMS, length %i, %i\n",size,size2);
460 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
461 if (size > GSM_MAX_8BIT_SMS_LENGTH) {
462 size = 0; size2 = 0;
463 }
464 break;
465 case SMS_Coding_Unicode:
466 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
467 * and GSM 03.38 section 4 */
468 buffer[Layout.TPDCS] |= 0x08;
469 EncodeUnicodeSpecialNOKIAChars(buffer+(Layout.Text+off), SMS->Text, UnicodeLength(SMS->Text));
470 size=size2=UnicodeLength(buffer+(Layout.Text+off))*2+off;
471#ifdef DEBUG
472 dbgprintf("Unicode SMS, length %i\n",(size2-off)/2);
473 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, buffer+(Layout.Text+off), size2-off);
474 dbgprintf("%s\n",DecodeUnicodeString(buffer+(Layout.Text+off)));
475#endif
476 break;
477 }
478
479 /* GSM 03.40 section 9.2.3.16 (TP-User-Data-Length)
480 * SMS->Length is:
481 - integer representation of the number od octets within the
482 user data when TP-User-Data is coded using 8 bit data
483 - the sum of the number of septets in UDH including any padding
484 and the number of septets in TP-User-Data in other case
485 */
486 buffer[Layout.TPUDL] = size2;
487 return size;
488}
489
490GSM_Error GSM_EncodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear)
491{
492 int i;
493
494 if (clear) {
495 /* Cleaning up to the SMS text */
496 for (i=0;i<Layout.Text;i++) buffer[i] = 0;
497 }
498
499 /* GSM 03.40 section 9.2.3.1 (TP-Message-Type-Indicator) */
500 switch (SMS->PDU) {
501 case SMS_Submit:
502 buffer[Layout.firstbyte] |= 0x01;
503 break;
504 /* SMS_Status_Report when Submit sms should have delivery report */
505 /* We DON'T CREATE FRAME FOR REAL SMS_STATUS_REPORT */
506 case SMS_Status_Report:
507 buffer[Layout.firstbyte] |= 0x01;
508 /* GSM 03.40 section 9.2.3.5 (TP-Status-Raport-Request) */
509 /* Set when want delivery report from SMSC */
510 buffer[Layout.firstbyte] |= 0x20;
511 break;
512 case SMS_Deliver:
513 buffer[Layout.firstbyte] |= 0x00;
514 }
515
516 /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
517 if (SMS->ReplyViaSameSMSC) buffer[Layout.firstbyte] |= 0x80;
518
519 if (Layout.Number!=255) {
520 buffer[Layout.Number] = GSM_PackSemiOctetNumber(SMS->Number,buffer+(Layout.Number+1),true);
521 dbgprintf("Recipient number \"%s\"\n",DecodeUnicodeString(SMS->Number));
522 }
523 if (Layout.SMSCNumber!=255) {
524 buffer[Layout.SMSCNumber]=GSM_PackSemiOctetNumber(SMS->SMSC.Number,buffer+(Layout.SMSCNumber+1), false);
525 dbgprintf("SMSC number \"%s\"\n",DecodeUnicodeString(SMS->SMSC.Number));
526 }
527
528 /* Message Class*/
529 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
530 if (Layout.TPDCS != 255) {
531 if (SMS->Class>=0 && SMS->Class<5) buffer[Layout.TPDCS] |= (240+SMS->Class);
532 dbgprintf("SMS class %i\n",SMS->Class);
533 }
534
535 if (Layout.TPVP != 255) {
536 /* GSM 03.40 section 9.2.3.3 (TP-Validity-Period-Format) */
537 /* Bits 4 and 3: 10. TP-VP field present and integer represent (relative) */
538 buffer[Layout.firstbyte] |= 0x10;
539 buffer[Layout.TPVP]=((unsigned char)SMS->SMSC.Validity.Relative);
540 dbgprintf("SMS validity %02x\n",SMS->SMSC.Validity.Relative);
541 }
542
543 if (Layout.DateTime != 255) {
544 GSM_EncodeSMSDateTime(&SMS->DateTime, buffer+Layout.DateTime);
545 }
546
547 if (Layout.TPMR != 255) {
548 dbgprintf("TPMR: %02x %i\n",SMS->MessageReference,SMS->MessageReference);
549 buffer[Layout.TPMR] = SMS->MessageReference;
550 }
551
552 if (SMS->RejectDuplicates) {
553 /* GSM 03.40 section 9.2.3.25 (TP Reject Duplicates) */
554 buffer[Layout.firstbyte] |= 0x04;
555 }
556
557 if (Layout.TPPID != 255) {
558 buffer[Layout.TPPID] = 0;
559 if (SMS->ReplaceMessage > 0 && SMS->ReplaceMessage < 8) {
560 buffer[Layout.TPPID] = 0x40 + SMS->ReplaceMessage;
561 }
562 }
563
564 /* size is the length of the data in octets including UDH */
565 *length=GSM_EncodeSMSFrameText(SMS,buffer,Layout);
566 //if (*length == 0) return GE_UNKNOWN;
567 *length += Layout.Text;
568
569 return ERR_NONE;
570}
571
572/* ----------------- Some help functions ----------------------------------- */
573
574void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS)
575{
576 SMS->Class = -1;
577 SMS->SMSC.Location = 1;
578 SMS->SMSC.Format = SMS_FORMAT_Text;
579 SMS->SMSC.Validity.Format= SMS_Validity_RelativeFormat;
580 SMS->SMSC.Validity.Relative= SMS_VALID_Max_Time;
581 SMS->ReplyViaSameSMSC = false;
582 SMS->UDH.Type = UDH_NoUDH;
583 SMS->UDH.Length = 0;
584 SMS->UDH.Text[0] = 0;
585 SMS->UDH.ID8bit = 0;
586 SMS->UDH.ID16bit = 0;
587 SMS->UDH.PartNumber = 0;
588 SMS->UDH.AllParts = 0;
589 SMS->Coding = SMS_Coding_Default;
590 SMS->Text[0] = 0;
591 SMS->Text[1] = 0;
592 SMS->PDU = SMS_Submit;
593 SMS->RejectDuplicates = false;
594 SMS->MessageReference = 0;
595 SMS->ReplaceMessage = 0;
596 SMS->Length = 0;
597
598 /* This part is required to save SMS */
599 SMS->State = SMS_UnSent;
600 SMS->Location = 0;
601 SMS->Folder = 0x02;/*Outbox*/
602 GSM_GetCurrentDateTime (&SMS->DateTime);
603 SMS->Name[0] = 0;
604 SMS->Name[1] = 0;
605}
606
607/**
608 * GSM 03.40 section 9.2.3.24
609 */
610void GSM_EncodeUDHHeader(GSM_UDHHeader *UDH)
611{
612 int i=0;
613
614 if (UDH->Type == UDH_NoUDH) {
615 UDH->Length = 0;
616 return;
617 }
618 if (UDH->Type == UDH_UserUDH) {
619 UDH->Length = UDH->Text[0] + 1;
620 return;
621 }
622 while (true) {
623 if (UDHHeaders[i].Type==UDH_NoUDH) {
624 dbgprintf("Not supported UDH type\n");
625 break;
626 }
627 if (UDHHeaders[i].Type!=UDH->Type) {
628 i++;
629 continue;
630 }
631 /* UDH Length */
632 UDH->Text[0] = UDHHeaders[i].Length;
633 memcpy(UDH->Text+1, UDHHeaders[i].Text, UDHHeaders[i].Length);
634 UDH->Length = UDH->Text[0] + 1;
635
636 if (UDHHeaders[i].ID8bit != -1) {
637 UDH->Text[UDHHeaders[i].ID8bit+1] = UDH->ID8bit % 256;
638 } else {
639 UDH->ID8bit = -1;
640 }
641 if (UDHHeaders[i].ID16bit != -1) {
642 UDH->Text[UDHHeaders[i].ID16bit+1] = UDH->ID16bit / 256;
643 UDH->Text[UDHHeaders[i].ID16bit+2] = UDH->ID16bit % 256;
644 } else {
645 UDH->ID16bit = -1;
646 }
647 if (UDHHeaders[i].PartNumber != -1) {
648 UDH->Text[UDHHeaders[i].PartNumber+1] = UDH->PartNumber;
649 } else {
650 UDH->PartNumber = -1;
651 }
652 if (UDHHeaders[i].AllParts != -1) {
653 UDH->Text[UDHHeaders[i].AllParts+1] = UDH->AllParts;
654 } else {
655 UDH->AllParts = -1;
656 }
657 break;
658 }
659}
660
661/* How should editor hadle tabs in this file? Add editor commands here.
662 * vim: noexpandtab sw=8 ts=8 sts=8:
663 */
diff --git a/gammu/emb/common/service/sms/gsmsms.h b/gammu/emb/common/service/sms/gsmsms.h
new file mode 100644
index 0000000..d87ff60
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmsms.h
@@ -0,0 +1,492 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Pawel Kot, others and Gnokii */
3
4#ifndef __gsm_sms_h
5#define __gsm_sms_h
6
7#include "../../gsmcomon.h"
8#include "../gsmlogo.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmdata.h"
12#include "../gsmring.h"
13
14/* --------------------- Some general definitions ------------------------- */
15
16 #define GSM_MAX_UDH_LENGTH 140
17 #define GSM_MAX_SMS_LENGTH 160
18 #define GSM_MAX_8BIT_SMS_LENGTH 140
19
20/* -------------------- Cell Broadcast ------------------------------------ */
21
22/**
23 * Structure for Cell Broadcast messages.
24 */
25typedef struct {
26 /**
27 * Message text.
28 */
29 char Text[300];
30 /**
31 * Channel number.
32 */
33 int Channel;
34} GSM_CBMessage;
35
36/* ------------------------ SMS status ------------------------------------ */
37
38/**
39 * Status of SMS memory.
40 */
41typedef struct {
42 /**
43 * Number of unread messages on SIM.
44 */
45 int SIMUnRead;
46 /**
47 * Number of all saved messages (including unread) on SIM.
48 */
49 int SIMUsed;
50 /**
51 * Number of all possible messages on SIM.
52 */
53 int SIMSize;
54 /**
55 * Number of used templates (62xx/63xx/7110/etc.).
56 */
57 int TemplatesUsed;
58 /**
59 * Number of unread messages in phone.
60 */
61 int PhoneUnRead;
62 /**
63 * Number of all saved messages in phone.
64 */
65 int PhoneUsed;
66 /**
67 * Number of all possible messages on phone.
68 */
69 int PhoneSize;
70} GSM_SMSMemoryStatus;
71
72/* --------------------- SMS Center --------------------------------------- */
73
74/**
75 * Enum defines format of SMS messages. See GSM 03.40 section 9.2.3.9
76 */
77typedef enum {
78 SMS_FORMAT_Pager = 1,
79 SMS_FORMAT_Fax,
80 SMS_FORMAT_Email,
81 SMS_FORMAT_Text
82 /* Some values not handled here */
83} GSM_SMSFormat;
84
85/**
86 * Enum defines some the most often used validity lengths for SMS messages
87 * for relative validity format. See GSM 03.40 section 9.2.3.12.1 - it gives
88 * more values
89 */
90typedef enum {
91 SMS_VALID_1_Hour = 0x0b,
92 SMS_VALID_6_Hours = 0x47,
93 SMS_VALID_1_Day = 0xa7,
94 SMS_VALID_3_Days = 0xa9,
95 SMS_VALID_1_Week = 0xad,
96 SMS_VALID_Max_Time = 0xff
97} GSM_ValidityPeriod;
98
99/**
100 * Enum defines format of validity period for SMS messages.
101 * See GSM 03.40 section 9.2.3.12
102 */
103typedef enum {
104 SMS_Validity_NotAvailable = 1,
105 SMS_Validity_RelativeFormat
106 /* Specification gives also other possibilities */
107} GSM_ValidityPeriodFormat;
108
109/**
110 * Structure for validity of SMS messages
111 */
112typedef struct {
113 GSM_ValidityPeriodFormatFormat;
114 /**
115 * Value defines period for relative format
116 */
117 GSM_ValidityPeriod Relative;
118} GSM_SMSValidity;
119
120 #define GSM_MAX_SMSC_NAME_LENGTH30
121
122/**
123 * Structure for SMSC (SMS Center) information.
124 */
125typedef struct {
126 /**
127 * Number of the SMSC on SIM
128 */
129 int Location;
130 /**
131 * Name of the SMSC
132 */
133 unsigned char Name[(GSM_MAX_SMSC_NAME_LENGTH+1)*2];
134 /**
135 * SMSC phone number.
136 */
137 unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
138 /**
139 * Validity of SMS messages.
140 */
141 GSM_SMSValidity Validity;
142 /**
143 * Format of sent SMS messages.
144 */
145 GSM_SMSFormat Format;
146 /**
147 * Default recipient number. In old DCT3 ignored
148 */
149 unsigned char DefaultNumber[(GSM_MAX_NUMBER_LENGTH+1)*2];
150} GSM_SMSC;
151
152/* --------------------- single SMS --------------------------------------- */
153
154/**
155 * Status of SMS message.
156 */
157typedef enum {
158 SMS_Sent = 1,
159 SMS_UnSent,
160 SMS_Read,
161 SMS_UnRead
162} GSM_SMS_State;
163
164/**
165 * Coding type of SMS.
166 */
167typedef enum {
168 /**
169 * Unicode
170 */
171 SMS_Coding_Unicode = 1,
172 /**
173 * Default GSM aplhabet.
174 */
175 SMS_Coding_Default,
176 /**
177 * 8-bit.
178 */
179 SMS_Coding_8bit
180} GSM_Coding_Type;
181
182/**
183 * Types of UDH (User Data Header).
184 */
185typedef enum {
186 UDH_NoUDH = 1,
187 /**
188 * Linked SMS.
189 */
190 UDH_ConcatenatedMessages,
191 /**
192 * Linked SMS with 16 bit reference.
193 */
194 UDH_ConcatenatedMessages16bit,
195 UDH_DisableVoice,
196 UDH_DisableFax,
197 UDH_DisableEmail,
198 UDH_EnableVoice,
199 UDH_EnableFax,
200 UDH_EnableEmail,
201 UDH_VoidSMS,
202 UDH_NokiaRingtone,
203 UDH_NokiaRingtoneLong,
204 UDH_NokiaOperatorLogo,
205 UDH_NokiaOperatorLogoLong,
206 UDH_NokiaCallerLogo,
207 UDH_NokiaWAP,
208 UDH_NokiaWAPLong,
209 UDH_NokiaCalendarLong,
210 UDH_NokiaProfileLong,
211 UDH_NokiaPhonebookLong,
212 UDH_UserUDH,
213 UDH_MMSIndicatorLong
214} GSM_UDH;
215
216/**
217 * Structure for User Data Header.
218 */
219typedef struct {
220 /**
221 * UDH type.
222 */
223 GSM_UDH Type;
224 /**
225 * UDH length.
226 */
227 int Length;
228 /**
229 * UDH text.
230 */
231 unsigned char Text[GSM_MAX_UDH_LENGTH];
232 /**
233 * 8-bit ID, when required (-1 otherwise).
234 */
235 int ID8bit;
236 /**
237 * 16-bit ID, when required (-1 otherwise).
238 */
239 int ID16bit;
240 /**
241 * Number of current part.
242 */
243 int PartNumber;
244 /**
245 * Total number of parts.
246 */
247 int AllParts;
248} GSM_UDHHeader;
249
250/**
251 * TP-Message-Type-Indicator. See GSM 03.40 section 9.2.3.1.
252 */
253 typedef enum {
254 /**
255 * SMS in Inbox.
256 */
257 SMS_Deliver = 1,
258 /**
259 * Delivery Report
260 */
261 SMS_Status_Report,
262 /**
263 * SMS for sending or in Outbox
264 */
265 SMS_Submit
266 /* specification gives more */
267} GSM_SMSMessageType;
268
269/**
270 * Maximal length of SMS name.
271 */
272 #define GSM_MAX_SMS_NAME_LENGTH 40
273
274/**
275 * SMS message data.
276 */
277typedef struct {
278 /**
279 * Message to be replaced.
280 */
281 unsigned char ReplaceMessage;
282 /**
283 * Whether to reject duplicates.
284 */
285 bool RejectDuplicates;
286 /**
287 * UDH (User Data Header)
288 */
289 GSM_UDHHeader UDH;
290 /**
291 * Sender or recipient number.
292 */
293 unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
294 /**
295 * SMSC (SMS Center)
296 */
297 GSM_SMSC SMSC;
298 /**
299 * For saved SMS: where exactly it's saved (SIM/phone)
300 */
301 GSM_MemoryType Memory;
302 /**
303 * For saved SMS: location of SMS in memory.
304 */
305 int Location;
306 /**
307 * For saved SMS: number of folder, where SMS is saved
308 */
309 int Folder;
310 /**
311 * For saved SMS: whether SMS is really in Inbox.
312 */
313 bool InboxFolder;
314 /**
315 * Length of the SMS message.
316 */
317 int Length;
318 /**
319 * Status (read/unread/...) of SMS message.
320 */
321 GSM_SMS_State State;
322 /**
323 * Name in Nokia with SMS memory (6210/7110, etc.) Ignored in other.
324 */
325 unsigned char Name[(GSM_MAX_SMS_NAME_LENGTH+1)*2];
326 /**
327 * Text for SMS.
328 */
329 unsigned char Text[(GSM_MAX_SMS_LENGTH+1)*2];
330 /**
331 * Type of message.
332 */
333 GSM_SMSMessageType PDU;
334 /**
335 * Type of coding.
336 */
337 GSM_Coding_Type Coding;
338 /**
339 * Date and time, when SMS was saved or sent
340 */
341 GSM_DateTime DateTime;
342 /**
343 * Date of SMSC response in DeliveryReport messages.
344 */
345 GSM_DateTime SMSCTime;
346 /**
347 * In delivery reports: status.
348 */
349 unsigned char DeliveryStatus;
350 /**
351 * Indicates whether "Reply via same center" is set.
352 */
353 bool ReplyViaSameSMSC;
354 /**
355 * SMS class.
356 */
357 char Class;
358 /**
359 * Message reference.
360 */
361 unsigned char MessageReference;
362} GSM_SMSMessage;
363
364/* In layouts are saved locations for some SMS part. Below are listed
365 * specs, which describe them
366 */
367typedef struct {
368 /**
369 * TP-User-Data. GSM 03.40 section 9.2.3.24.
370 */
371 unsigned char Text;
372 /**
373 * - In SMS-Deliver: TP-Originating-Address. GSM 03.40 section 9.2.3.7.
374 * - In SMS-Submit: TP-Destination-Address. GSM 03.40 section 9.2.3.8.
375 * - In SMS-Status-Report: TP-Recipient-Address. GSM 03.40 section 9.2.3.14.
376 */
377 unsigned char Number;
378 /**
379 * SMSC number
380 */
381 unsigned char SMSCNumber;
382 /**
383 * TP-Data-Coding-Scheme. GSM 03.40 section 9.2.3.10
384 */
385 unsigned char TPDCS;
386 /**
387 * - For SMS-Submit: TP-Validity-Period. GSM 03.40 section 9.2.3.12.
388 * - For SMS-Status-Report: TP-Discharge Time. GSM 03.40 section 9.2.3.13.
389 */
390 unsigned char DateTime;
391 /**
392 * TP-Service-Centre-Time-Stamp in SMS-Status-Report. GSM 03.40 section 9.2.3.11.
393 */
394 unsigned char SMSCTime;
395 /**
396 * TP-Status in SMS-Status-Report. GSM 03.40 section 9.2.3.15.
397 */
398 unsigned char TPStatus;
399 /**
400 * TP-User-Data-Length. GSM 03.40 section 9.2.3.16.
401 */
402 unsigned char TPUDL;
403 /**
404 * TP-Validity Period in SMS-Submit. GSM 03.40 section 9.2.3.12.
405 */
406 unsigned char TPVP;
407 /**
408 * Byte contains in SMS-Deliver:
409 * - TP-Message-Type-Indicator (2 bits) GSM 03.40 section 9.2.3.1
410 * - TP-More-Messages-To-Send (1 bit). GSM 03.40 section 9.2.3.2
411 * - TP-Reply-Path (1 bit). GSM 03.40 section 9.2.3.17
412 * - TP-User-Data-Header-Indicator (1 bit). GSM 03.40 section 9.2.3.23
413 * - TP-Status-Report-Indicator (1 bit). GSM 03.40 section 9.2.3.4
414 *
415 * Byte contains in SMS-Submit:
416 * - TP-Message-Type-Indicator (2 bits) GSM 03.40 section 9.2.3.1
417 * - TP-Reject-Duplicates (1 bit). GSM 03.40 section
418 * - TP-Validity-Period-Format (2 bits).GSM 03.40 section 9.2.3.3
419 * - TP-Reply-Path (1 bit). GSM 03.40 section 9.2.3.17
420 * - TP-User-Data-Header-Indicator (1 bit). GSM 03.40 section 9.2.3.23
421 * - TP-Status-Report-Request (1 bit). GSM 03.40 section 9.2.3.5
422 */
423 unsigned char firstbyte;
424 /**
425 * TP-Message Reference in SMS-Submit. GSM 03.40 section 9.2.3.6
426 */
427 unsigned char TPMR;
428 /**
429 * TP-Protocol-Identifier. GSM 03.40 section 9.2.3.9
430 */
431 unsigned char TPPID;
432} GSM_SMSMessageLayout;
433
434GSM_Error GSM_DecodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
435GSM_Error GSM_EncodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear);
436
437GSM_Error GSM_DecodeSMSFrameStatusReportData (GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
438 GSM_Error GSM_DecodeSMSFrameText (GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
439
440void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH);
441void GSM_EncodeUDHHeader(GSM_UDHHeader *UDH);
442
443void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS);
444
445/* ---------------------- SMS folders ------------------------------------- */
446
447/**
448 * Number of possible SMS folders.
449 */
450 #define GSM_MAX_SMS_FOLDERS 24
451/**
452 * Maximal length of SMS folder name.
453 */
454#define GSM_MAX_SMS_FOLDER_NAME_LEN 20
455
456/**
457 * Information about SMS folder.
458 */
459typedef struct {
460 /**
461 * Whether it is really inbox.
462 */
463 bool InboxFolder;
464 /**
465 * Where exactly it's saved
466 */
467 GSM_MemoryType Memory;
468 /**
469 * Name for SMS folder.
470 */
471 char Name[(GSM_MAX_SMS_FOLDER_NAME_LEN+1)*2];
472} GSM_OneSMSFolder;
473
474/**
475 * List of SMS folders.
476 */
477typedef struct {
478 /**
479 * Array of structures holding information about each folder.
480 */
481 GSM_OneSMSFolderFolder[GSM_MAX_SMS_FOLDERS];
482 /**
483 * Number of SMS folders.
484 */
485 unsigned char Number;
486} GSM_SMSFolders;
487
488#endif
489
490/* How should editor hadle tabs in this file? Add editor commands here.
491 * vim: noexpandtab sw=8 ts=8 sts=8:
492 */