summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/phone/alcatel/alcatel.c
Unidiff
Diffstat (limited to 'gammu/emb/common/phone/alcatel/alcatel.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/phone/alcatel/alcatel.c3991
1 files changed, 3991 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 */