summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/phone
Unidiff
Diffstat (limited to 'gammu/emb/common/phone') (more/less context) (ignore whitespace changes)
-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
35 files changed, 26270 insertions, 0 deletions
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 */