1 /* (c) 2002-2005 by Marcin Wiacek */
2
3 #include <gammu-config.h>
4
5 #ifdef GSM_ENABLE_NOKIA6510
6
7 #include <string.h>
8 #include <time.h>
9
10 #include "../../../../misc/coding/coding.h"
11 #include "../../../../gsmcomon.h"
12 #include "../../../../service/gsmlogo.h"
13 #include "../../../../service/gsmcal.h"
14 #include "../../nfunc.h"
15 #include "../../nfuncold.h"
16 #include "../../../pfunc.h"
17 #include "../dct4func.h"
18 #include "n6510.h"
19
20 /* method 3 */
N6510_ReplyGetCalendarInfo3(GSM_Protocol_Message * msg,GSM_StateMachine * s,GSM_NOKIACalToDoLocations * Last)21 GSM_Error N6510_ReplyGetCalendarInfo3(GSM_Protocol_Message *msg, GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last)
22 {
23 size_t i=0,j=0;
24
25 while (Last->Location[j] != 0x00) j++;
26 if (j >= GSM_MAXCALENDARTODONOTES) {
27 smprintf(s, "Increase GSM_MAXCALENDARTODONOTES\n");
28 return ERR_MOREMEMORY;
29 }
30 if (j == 0) {
31 Last->Number = msg->Buffer[8]*256 + msg->Buffer[9];
32 smprintf(s, "Number of Entries: %i\n", Last->Number);
33 }
34 smprintf(s, "Locations: ");
35 while (14+(i*4) <= msg->Length) {
36 Last->Location[j] = msg->Buffer[12+i*4]*256 + msg->Buffer[13+i*4];
37 smprintf(s, "%i ", Last->Location[j]);
38 i++;
39 j++;
40 }
41 smprintf(s, "\nNumber of Entries in frame: %ld\n", (long)i);
42 Last->Location[j] = 0;
43 smprintf(s, "\n");
44 if (i == 1 && msg->Buffer[12+0*4]*256+msg->Buffer[13+0*4] == 0) return ERR_EMPTY;
45 if (i == 0) return ERR_EMPTY;
46 return ERR_NONE;
47 }
48
49 /* method 3 */
N6510_GetCalendarInfo3(GSM_StateMachine * s,GSM_NOKIACalToDoLocations * Last,char Type)50 GSM_Error N6510_GetCalendarInfo3(GSM_StateMachine *s, GSM_NOKIACalToDoLocations *Last, char Type)
51 {
52 GSM_Error error = ERR_UNKNOWN;
53 int i;
54 unsigned char req[] = {N6110_FRAME_HEADER, 0x9E, 0xFF, 0xFF, 0x00, 0x00,
55 0x00, 0x00, /* First location */
56 0x00}; /* 0 = calendar, 1 = ToDo in 6610 style, 2 = Notes */
57
58 Last->Location[0] = 0x00;
59 Last->Number = 0;
60
61 req[10] = Type;
62 if (Type == 0) {
63 smprintf(s, "Getting locations for calendar method 3\n");
64 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
65 } else if (Type == 1) {
66 smprintf(s, "Getting locations for ToDo method 2\n");
67 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
68 } else if (Type == 2) {
69 smprintf(s, "Getting locations for Notes\n");
70 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetNote);
71 }
72 if (error != ERR_NONE && error != ERR_EMPTY) return error;
73
74 while (1) {
75 i=0;
76 while (Last->Location[i] != 0x00) i++;
77 smprintf(s, "i = %i last_number = %i\n",i,Last->Number);
78 if (i == Last->Number) break;
79 if (i != Last->Number && error == ERR_EMPTY) {
80 smprintf(s, "Phone doesn't support some notes with this method. Workaround\n");
81 Last->Number = i;
82 break;
83 }
84 req[8] = Last->Location[i-1] / 256;
85 req[9] = Last->Location[i-1] % 256;
86 if (Type == 0) {
87 smprintf(s, "Getting locations for calendar method 3\n");
88 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetCalendarNotesInfo);
89 } else if (Type == 1) {
90 smprintf(s, "Getting locations for todo method 2\n");
91 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetToDo);
92 } else if (Type == 2) {
93 smprintf(s, "Getting locations for Notes\n");
94 error = GSM_WaitFor (s, req, 11, 0x13, 4, ID_GetNote);
95 }
96 if (error != ERR_NONE && error != ERR_EMPTY) return error;
97 }
98 return ERR_NONE;
99 }
100
101 /* method 3 */
N6510_ReplyGetCalendar3(GSM_Protocol_Message * msg,GSM_StateMachine * s)102 GSM_Error N6510_ReplyGetCalendar3(GSM_Protocol_Message *msg, GSM_StateMachine *s)
103 {
104 GSM_CalendarEntry *entry = s->Phone.Data.Cal;
105 unsigned long diff;
106 int i;
107 gboolean found = FALSE;
108 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
109 int len;
110
111 smprintf(s, "Calendar note received method 3\n");
112
113 smprintf(s,"Note type %02i: ",msg->Buffer[27]);
114 switch(msg->Buffer[27]) {
115 case 0x00: smprintf(s,"Reminder\n"); entry->Type = GSM_CAL_REMINDER; break;
116 case 0x01: smprintf(s,"Meeting\n"); entry->Type = GSM_CAL_MEETING; break;
117 case 0x02: smprintf(s,"Call\n"); entry->Type = GSM_CAL_CALL; break;
118 case 0x04: smprintf(s,"Birthday\n"); entry->Type = GSM_CAL_BIRTHDAY; break;
119 case 0x08: smprintf(s,"Memo\n"); entry->Type = GSM_CAL_MEMO; break;
120 case 0x20: smprintf(s,"Birthday\n"); entry->Type = GSM_CAL_BIRTHDAY; break;
121 default : smprintf(s,"unknown\n"); entry->Type = GSM_CAL_MEMO;
122 }
123
124 smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
125 msg->Buffer[28]*256+msg->Buffer[29],
126 msg->Buffer[30],msg->Buffer[31],msg->Buffer[32],
127 msg->Buffer[33]);
128 GSM_GetCurrentDateTime(&entry->Entries[0].Date);
129 entry->Entries[0].Date.Year = msg->Buffer[28]*256+msg->Buffer[29];
130 if (entry->Type == GSM_CAL_BIRTHDAY) {
131 entry->Entries[0].Date.Year = entry->Entries[0].Date.Year;
132 smprintf(s,"%i\n",entry->Entries[0].Date.Year);
133 }
134 entry->Entries[0].Date.Month = msg->Buffer[30];
135 entry->Entries[0].Date.Day = msg->Buffer[31];
136 entry->Entries[0].Date.Hour = msg->Buffer[32];
137 entry->Entries[0].Date.Minute = msg->Buffer[33];
138 /* Garbage seen with 3510i 3.51 */
139 if (entry->Entries[0].Date.Month == 0 &&
140 entry->Entries[0].Date.Day == 0 &&
141 entry->Entries[0].Date.Hour == 0 &&
142 entry->Entries[0].Date.Minute == 0)
143 return ERR_EMPTY;
144 entry->Entries[0].Date.Second = 0;
145 entry->Entries[0].EntryType = CAL_START_DATETIME;
146 entry->EntriesNum++;
147
148 GSM_GetCalendarRecurranceRepeat(&(s->di), msg->Buffer+40, msg->Buffer+46, entry);
149
150 if (entry->Type != GSM_CAL_BIRTHDAY) {
151 smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
152 msg->Buffer[34]*256+msg->Buffer[35],
153 msg->Buffer[36],msg->Buffer[37],msg->Buffer[38],
154 msg->Buffer[39]);
155 entry->Entries[entry->EntriesNum].Date.Year = msg->Buffer[34]*256+msg->Buffer[35];
156 entry->Entries[entry->EntriesNum].Date.Month = msg->Buffer[36];
157 entry->Entries[entry->EntriesNum].Date.Day = msg->Buffer[37];
158 entry->Entries[entry->EntriesNum].Date.Hour = msg->Buffer[38];
159 entry->Entries[entry->EntriesNum].Date.Minute = msg->Buffer[39];
160 entry->Entries[entry->EntriesNum].Date.Second = 0;
161 entry->Entries[entry->EntriesNum].EntryType = CAL_END_DATETIME;
162 entry->EntriesNum++;
163 }
164
165 smprintf(s, "Note icon: %02x\n",msg->Buffer[21]);
166 for(i=0;i<Priv->CalendarIconsNum;i++) {
167 if (Priv->CalendarIconsTypes[i] == entry->Type) {
168 found = TRUE;
169 }
170 }
171 if (!found) {
172 Priv->CalendarIconsTypes[Priv->CalendarIconsNum] = entry->Type;
173 Priv->CalendarIcons [Priv->CalendarIconsNum] = msg->Buffer[21];
174 Priv->CalendarIconsNum++;
175 }
176
177 if (msg->Buffer[14] == 0xFF && msg->Buffer[15] == 0xFF && msg->Buffer[16] == 0xff && msg->Buffer[17] == 0xff) {
178 smprintf(s, "No alarm\n");
179 } else {
180 diff = ((unsigned int)msg->Buffer[14]) << 24;
181 diff += ((unsigned int)msg->Buffer[15]) << 16;
182 diff += ((unsigned int)msg->Buffer[16]) << 8;
183 diff += msg->Buffer[17];
184
185 memcpy(&entry->Entries[entry->EntriesNum].Date,&entry->Entries[0].Date,sizeof(GSM_DateTime));
186 GetTimeDifference(diff, &entry->Entries[entry->EntriesNum].Date, FALSE, 60);
187 smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
188 entry->Entries[entry->EntriesNum].Date.Day, entry->Entries[entry->EntriesNum].Date.Month,
189 entry->Entries[entry->EntriesNum].Date.Year, entry->Entries[entry->EntriesNum].Date.Hour,
190 entry->Entries[entry->EntriesNum].Date.Minute,entry->Entries[entry->EntriesNum].Date.Second);
191
192 entry->Entries[entry->EntriesNum].EntryType = CAL_TONE_ALARM_DATETIME;
193 if (msg->Buffer[22]==0x00 && msg->Buffer[23]==0x00 &&
194 msg->Buffer[24]==0x00 && msg->Buffer[25]==0x00) {
195 entry->Entries[entry->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
196 smprintf(s, "Alarm type : Silent\n");
197 }
198 entry->EntriesNum++;
199 }
200
201 if (entry->Type == GSM_CAL_BIRTHDAY) {
202 if (msg->Buffer[42] == 0xff && msg->Buffer[43] == 0xff) {
203 entry->Entries[0].Date.Year = 0;
204 } else {
205 entry->Entries[0].Date.Year = msg->Buffer[42]*256+msg->Buffer[43];
206 }
207 }
208
209 len = msg->Buffer[50] * 256 + msg->Buffer[51];
210 if (len > GSM_MAX_CALENDAR_TEXT_LENGTH) {
211 smprintf(s, "Calendar text too long (%d), truncating to %d\n", len, GSM_MAX_CALENDAR_TEXT_LENGTH);
212 len = GSM_MAX_CALENDAR_TEXT_LENGTH;
213 }
214 memcpy(entry->Entries[entry->EntriesNum].Text,
215 msg->Buffer + 54,
216 len * 2);
217 entry->Entries[entry->EntriesNum].Text[len * 2] = 0;
218 entry->Entries[entry->EntriesNum].Text[len * 2 + 1] = 0;
219 entry->Entries[entry->EntriesNum].EntryType = CAL_TEXT;
220 entry->EntriesNum++;
221 smprintf(s, "Note text: \"%s\"\n",DecodeUnicodeString(entry->Entries[entry->EntriesNum-1].Text));
222
223 if (entry->Type == GSM_CAL_CALL) {
224 memcpy(entry->Entries[entry->EntriesNum].Text, msg->Buffer+(54+msg->Buffer[51]*2), msg->Buffer[52]*2);
225 entry->Entries[entry->EntriesNum].Text[msg->Buffer[52]*2] = 0;
226 entry->Entries[entry->EntriesNum].Text[msg->Buffer[52]*2+1] = 0;
227 entry->Entries[entry->EntriesNum].EntryType = CAL_PHONE;
228 entry->EntriesNum++;
229 }
230 if (entry->Type == GSM_CAL_MEETING) {
231 memcpy(entry->Entries[entry->EntriesNum].Text, msg->Buffer+(54+msg->Buffer[51]*2), msg->Buffer[52]*2);
232 entry->Entries[entry->EntriesNum].Text[msg->Buffer[52]*2] = 0;
233 entry->Entries[entry->EntriesNum].Text[msg->Buffer[52]*2+1] = 0;
234 entry->Entries[entry->EntriesNum].EntryType = CAL_LOCATION;
235 entry->EntriesNum++;
236 }
237
238 return ERR_NONE;
239 }
240
N6510_PrivGetGenericCalendar3(GSM_StateMachine * s,int Location,GSM_Phone_RequestID ID)241 static GSM_Error N6510_PrivGetGenericCalendar3(GSM_StateMachine *s, int Location, GSM_Phone_RequestID ID)
242 {
243 unsigned char req[] = {N6110_FRAME_HEADER,0x7D,0x00,0x00,0x00,0x00,
244 0x00,0x99, /* Location */
245 0xff,0xff,0xff,0xff};
246
247 req[8] = Location / 256;
248 req[9] = Location % 256;
249
250 return GSM_WaitFor (s, req, 14, 0x13, 4, ID);
251 }
252
N6510_PrivGetCalendar3(GSM_StateMachine * s,GSM_CalendarEntry * Note,gboolean start,int * LastCalendarYear)253 static GSM_Error N6510_PrivGetCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, gboolean start, int *LastCalendarYear)
254 {
255 GSM_Error error;
256 GSM_DateTime date_time;
257
258 if (start) {
259 /* We have to get current year. It's NOT written in frame for
260 * Birthday
261 */
262 error=s->Phone.Functions->GetDateTime(s,&date_time);
263 switch (error) {
264 case ERR_EMPTY:
265 case ERR_NOTIMPLEMENTED:
266 GSM_GetCurrentDateTime(&date_time);
267 break;
268 case ERR_NONE:
269 break;
270 default:
271 return error;
272 }
273 *LastCalendarYear = date_time.Year;
274 }
275
276 Note->EntriesNum = 0;
277 Note->Entries[0].Date.Year = *LastCalendarYear;
278
279 s->Phone.Data.Cal=Note;
280 smprintf(s, "Getting calendar note method 3\n");
281 return N6510_PrivGetGenericCalendar3(s, Note->Location, ID_GetCalendarNote);
282 }
283
284 /* method 3 */
N6510_GetNextCalendar3(GSM_StateMachine * s,GSM_CalendarEntry * Note,gboolean start,GSM_NOKIACalToDoLocations * LastCalendar,int * LastCalendarYear,int * LastCalendarPos)285 static GSM_Error N6510_GetNextCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, gboolean start, GSM_NOKIACalToDoLocations *LastCalendar, int *LastCalendarYear, int *LastCalendarPos)
286 {
287 GSM_Error error;
288 gboolean start2;
289
290 if (start) {
291 error=N6510_GetCalendarInfo3(s,LastCalendar,0);
292 if (error!=ERR_NONE) return error;
293 if (LastCalendar->Number == 0) return ERR_EMPTY;
294
295 *LastCalendarPos = 0;
296 } else {
297 (*LastCalendarPos)++;
298 }
299
300 error = ERR_EMPTY;
301 start2 = start;
302 while (error == ERR_EMPTY) {
303 if (*LastCalendarPos >= LastCalendar->Number) return ERR_EMPTY;
304
305 Note->Location = LastCalendar->Location[*LastCalendarPos];
306 error=N6510_PrivGetCalendar3(s, Note, start2, LastCalendarYear);
307 if (error == ERR_EMPTY) (*LastCalendarPos)++;
308
309 start2 = FALSE;
310 }
311 return error;
312 }
313
N6510_ReplyGetCalendarInfo(GSM_Protocol_Message * msg,GSM_StateMachine * s)314 GSM_Error N6510_ReplyGetCalendarInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
315 {
316 switch (msg->Buffer[3]) {
317 case 0x3B:
318 /* Old method 1 for accessing calendar */
319 return N71_65_ReplyGetCalendarInfo1(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
320 case 0x9F:
321 smprintf(s, "Info with calendar notes locations received method 3\n");
322 return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastCalendar);
323 }
324 return ERR_UNKNOWNRESPONSE;
325 }
326
327 /* method 3 */
N6510_ReplyGetCalendarNotePos3(GSM_Protocol_Message * msg,GSM_StateMachine * s,int * FirstCalendarPos)328 GSM_Error N6510_ReplyGetCalendarNotePos3(GSM_Protocol_Message *msg, GSM_StateMachine *s,int *FirstCalendarPos)
329 {
330 smprintf(s, "First calendar location: %i\n",msg->Buffer[8]*256+msg->Buffer[9]);
331 *FirstCalendarPos = msg->Buffer[8]*256+msg->Buffer[9];
332 return ERR_NONE;
333 }
334
335 /* method 3 */
N6510_GetCalendarNotePos3(GSM_StateMachine * s)336 static GSM_Error N6510_GetCalendarNotePos3(GSM_StateMachine *s)
337 {
338 unsigned char req[] = {N6110_FRAME_HEADER, 0x95, 0x00};
339
340 smprintf(s, "Getting first free calendar note location\n");
341 return GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNotePos);
342 }
343
N6510_ReplyGetCalendarNotePos(GSM_Protocol_Message * msg,GSM_StateMachine * s)344 GSM_Error N6510_ReplyGetCalendarNotePos(GSM_Protocol_Message *msg, GSM_StateMachine *s)
345 {
346 switch (msg->Buffer[3]) {
347 case 0xf0:
348 return ERR_NOTSUPPORTED;
349 case 0x32:
350 /* Old method 1 for accessing calendar */
351 return N71_65_ReplyGetCalendarNotePos1(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
352 case 0x96:
353 return N6510_ReplyGetCalendarNotePos3(msg, s,&s->Phone.Data.Priv.N6510.FirstCalendarPos);
354 }
355 return ERR_UNKNOWNRESPONSE;
356 }
357
N6510_FindCalendarIconID3(GSM_StateMachine * s,GSM_CalendarEntry * Entry,unsigned char * ID)358 static GSM_Error N6510_FindCalendarIconID3(GSM_StateMachine *s, GSM_CalendarEntry *Entry, unsigned char *ID)
359 {
360 int i,j,LastCalendarYear;
361 GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
362 GSM_CalendarEntry Note;
363 GSM_NOKIACalToDoLocations LastCalendar1,LastCalendar2;
364 GSM_Error error;
365 gboolean found;
366
367 for(i=0;i<Priv->CalendarIconsNum;i++) {
368 if (Priv->CalendarIconsTypes[i] == Entry->Type) {
369 *ID = Priv->CalendarIcons[i];
370 return ERR_NONE;
371 }
372 }
373
374 smprintf(s, "Starting finding note ID\n");
375
376 error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,0);
377 memcpy(&LastCalendar1,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
378 if (error != ERR_NONE) return error;
379
380 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35) ||
381 GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
382 GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
383 error=N71_65_AddCalendar2(s,Entry);
384 } else {
385 /* First method 1 was used for meeting only
386 * but it made problems with 6230 RH-12 4.44
387 * (probably for other Series 40 2.0 phones too)
388 * For now meeting, call and memo uses method 1
389 * Please note, that method 1 is the oldest one and in some
390 * moment Nokia can remove it from firmware
391 */
392 /* if (Entry->Type == GSM_CAL_MEETING) { */
393 if (Entry->Type == GSM_CAL_MEETING || Entry->Type == GSM_CAL_CALL || Entry->Type == GSM_CAL_MEMO) {
394 error=N71_65_AddCalendar1(s, Entry, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
395 } else {
396 error=N71_65_AddCalendar2(s,Entry);
397 }
398 }
399 if (error != ERR_NONE) return error;
400
401 error=N6510_GetCalendarInfo3(s, &Priv->LastCalendar,0);
402 memcpy(&LastCalendar2,&Priv->LastCalendar,sizeof(GSM_NOKIACalToDoLocations));
403 if (error != ERR_NONE) return error;
404
405 smprintf(s,"Number of entries: %i %i\n",LastCalendar1.Number,LastCalendar2.Number);
406
407 for(i=0;i<LastCalendar2.Number;i++) {
408 found = TRUE;
409 for(j=0;j<LastCalendar1.Number;j++) {
410 if (LastCalendar1.Location[j] == LastCalendar2.Location[i]) {
411 found = FALSE;
412 break;
413 }
414 }
415 if (found) {
416 Note.Location = LastCalendar2.Location[i];
417 error=N6510_PrivGetCalendar3(s, &Note, TRUE, &LastCalendarYear);
418 if (error != ERR_NONE) return error;
419
420 error=N71_65_DelCalendar(s, &Note);
421 if (error != ERR_NONE) return error;
422
423 smprintf(s, "Ending finding note ID\n");
424
425 for(j=0;j<Priv->CalendarIconsNum;j++) {
426 if (Priv->CalendarIconsTypes[j] == Entry->Type) {
427 *ID = Priv->CalendarIcons[j];
428 return ERR_NONE;
429 }
430 }
431 return ERR_UNKNOWN;
432 }
433 }
434
435 return ERR_UNKNOWN;
436 }
437
438 /* method 3 */
N6510_ReplyAddCalendar3(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)439 GSM_Error N6510_ReplyAddCalendar3(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
440 {
441 smprintf(s, "Calendar note added\n");
442 return ERR_NONE;
443 }
444
445 /* method 3 */
N6510_AddCalendar3(GSM_StateMachine * s,GSM_CalendarEntry * Note,int * FirstCalendarPos)446 static GSM_Error N6510_AddCalendar3(GSM_StateMachine *s, GSM_CalendarEntry *Note, int *FirstCalendarPos)
447 {
448 GSM_CalendarNoteType NoteType, OldNoteType;
449 time_t t_time1,t_time2;
450 long diff;
451 GSM_Error error;
452 GSM_DateTime DT,date_time;
453 int Text, Time, Alarm, Phone, EndTime, Location, count=54;
454 unsigned char req[5000] = {
455 N6110_FRAME_HEADER, 0x65,
456 0x00, /* 0 = calendar, 1 = todo */
457 0x00, 0x00, 0x00,
458 0x00, 0x00, /* location */
459 0x00, 0x00, 0x00, 0x00,
460 0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
461 0x80, 0x00, 0x00,
462 0x01, /* note icon */
463 0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
464 0x00, /* 0x02 or 0x00 */
465 0x01, /* note type */
466 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
467 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
468 0x00, 0x00, /* recurrance */
469 0x00, 0x00, /* birth year */
470 0x20, /* ToDo priority */
471 0x00, /* ToDo completed ? */
472 0x00, 0x00, /* How many times repeat cal note or 0 */
473 0x00,
474 0x00, /* note text length */
475 0x00, /* phone length/meeting place */
476 0x00, 0x00, 0x00};
477
478 error=N6510_GetCalendarNotePos3(s);
479 if (error!=ERR_NONE) return error;
480 Note->Location = *FirstCalendarPos;
481 req[8] = *FirstCalendarPos/256;
482 req[9] = *FirstCalendarPos%256;
483
484 NoteType = N71_65_FindCalendarType(Note->Type, s->Phone.Data.ModelInfo);
485
486 switch(NoteType) {
487 case GSM_CAL_REMINDER : req[27]=0x00; req[26]=0x02; break;
488 case GSM_CAL_MEETING : req[27]=0x01; break;
489 case GSM_CAL_CALL : req[27]=0x02; break;
490 case GSM_CAL_BIRTHDAY : req[27]=0x04; break;
491 case GSM_CAL_MEMO : req[27]=0x08; break;
492 default : return ERR_UNKNOWN;
493 }
494
495 OldNoteType = Note->Type;
496 Note->Type = NoteType;
497 error=N6510_FindCalendarIconID3(s, Note, &req[21]);
498 Note->Type = OldNoteType;
499 if (error!=ERR_NONE) return error;
500
501 GSM_CalendarFindDefaultTextTimeAlarmPhone(Note, &Text, &Time, &Alarm, &Phone, &EndTime, &Location);
502
503 if (Time == -1) {
504 smprintf(s,"No time!\n");
505 return ERR_UNKNOWN;
506 }
507 smprintf(s, "Time OK\n");
508 memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
509 req[28] = DT.Year / 256;
510 req[29] = DT.Year % 256;
511 req[30] = DT.Month;
512 req[31] = DT.Day;
513 req[32] = DT.Hour;
514 req[33] = DT.Minute;
515
516 if (NoteType == GSM_CAL_BIRTHDAY) {
517 error=s->Phone.Functions->GetDateTime(s,&date_time);
518 switch (error) {
519 case ERR_EMPTY:
520 case ERR_NOTIMPLEMENTED:
521 GSM_GetCurrentDateTime(&date_time);
522 break;
523 case ERR_NONE:
524 break;
525 default:
526 return error;
527 }
528 req[28] = date_time.Year / 256;
529 req[29] = date_time.Year % 256;
530 if (DT.Year == 0) {
531 req[42] = 0xff;
532 req[43] = 0xff;
533 } else {
534 req[42] = DT.Year / 256;
535 req[43] = DT.Year % 256;
536 }
537 }
538
539 if (EndTime != -1) memcpy(&DT,&Note->Entries[EndTime].Date,sizeof(GSM_DateTime));
540
541 req[34] = DT.Year / 256;
542 req[35] = DT.Year % 256;
543 req[36] = DT.Month;
544 req[37] = DT.Day;
545 req[38] = DT.Hour;
546 req[39] = DT.Minute;
547 if (NoteType == GSM_CAL_BIRTHDAY) {
548 req[34] = date_time.Year / 256;
549 req[35] = date_time.Year % 256;
550 }
551
552 GSM_SetCalendarRecurranceRepeat(&(s->di), req+40, req+52, Note);
553
554 if (Alarm != -1) {
555 memcpy(&DT,&Note->Entries[Time].Date,sizeof(GSM_DateTime));
556 if (Note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
557 req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
558 }
559 if (NoteType == GSM_CAL_BIRTHDAY) DT.Year = date_time.Year;
560 t_time2 = Fill_Time_T(DT);
561 t_time1 = Fill_Time_T(Note->Entries[Alarm].Date);
562 diff = (t_time1-t_time2)/60;
563
564 smprintf(s, " Difference : %li seconds or minutes\n", -diff);
565 req[14] = (unsigned char)(-diff >> 24);
566 req[15] = (unsigned char)(-diff >> 16);
567 req[16] = (unsigned char)(-diff >> 8);
568 req[17] = (unsigned char)(-diff);
569 }
570
571 if (Text != -1) {
572 req[48] = UnicodeLength(Note->Entries[Text].Text) / 256;
573 req[49] = UnicodeLength(Note->Entries[Text].Text) % 256;
574 CopyUnicodeString(req + 54, Note->Entries[Text].Text);
575 count += req[49] * 2 + (req[48] * 256) * 2;
576 }
577
578 if (Phone != -1 && NoteType == GSM_CAL_CALL) {
579 req[50] = UnicodeLength(Note->Entries[Phone].Text);
580 CopyUnicodeString(req+54+req[49]*2,Note->Entries[Phone].Text);
581 count+= req[50]*2;
582 }
583
584 if (Location != -1 && NoteType == GSM_CAL_MEETING) {
585 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62) ||
586 GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL65) ||
587 GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL35)) {
588 } else {
589 req[50] = UnicodeLength(Note->Entries[Location].Text);
590 CopyUnicodeString(req+54+req[49]*2,Note->Entries[Location].Text);
591 count+= req[50]*2;
592 }
593 }
594
595 req[count++] = 0x00;
596
597 smprintf(s, "Writing calendar note method 3\n");
598 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetCalendarNote);
599 }
600
N6510_GetNextCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note,gboolean start)601 GSM_Error N6510_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, gboolean start)
602 {
603 #ifdef GSM_FORCE_DCT4_CALENDAR_6210
604 /* Method 1. Some features missed. Not working with some notes in 3510 */
605 return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
606 #endif
607
608 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
609 /* Method 1. Some features missed. Not working with some notes in 3510 */
610 return N71_65_GetNextCalendar1(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
611
612 /* Method 2. In known phones texts of notes cut to 50 chars. Some features missed */
613 /* return N71_65_GetNextCalendar2(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos); */
614 } else {
615 /* Method 3. All DCT4 features supported. Not supported by 8910 */
616 return N6510_GetNextCalendar3(s,Note,start,&s->Phone.Data.Priv.N6510.LastCalendar,&s->Phone.Data.Priv.N6510.LastCalendarYear,&s->Phone.Data.Priv.N6510.LastCalendarPos);
617 }
618 }
619
N6510_GetCalendarStatus(GSM_StateMachine * s,GSM_CalendarStatus * Status)620 GSM_Error N6510_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
621 {
622 GSM_Error error;
623
624 #ifdef GSM_FORCE_DCT4_CALENDAR_6210
625 /* Method 1 */
626 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
627 if (error!=ERR_NONE) return error;
628 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
629 return ERR_NONE;
630 #endif
631
632 /**
633 * @todo This should be acquired from phone
634 */
635 Status->Free = 100;
636
637 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
638 /* Method 1 */
639 error=N71_65_GetCalendarInfo1(s, &s->Phone.Data.Priv.N6510.LastCalendar);
640 if (error!=ERR_NONE) return error;
641 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
642 return ERR_NONE;
643
644 /* Method 2 */
645 /* return ERR_NOTSUPPORTED; */
646 } else {
647 /* Method 3 */
648 error=N6510_GetCalendarInfo3(s,&s->Phone.Data.Priv.N6510.LastCalendar,0);
649 if (error!=ERR_NONE) return error;
650 Status->Used = s->Phone.Data.Priv.N6510.LastCalendar.Number;
651 return ERR_NONE;
652 }
653 }
654
N6510_AddCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)655 GSM_Error N6510_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
656 {
657 #ifdef GSM_FORCE_DCT4_CALENDAR_6210
658 return N71_65_AddCalendar2(s,Note);
659 #endif
660
661 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_CAL62)) {
662 return N71_65_AddCalendar2(s,Note);
663 /* return N71_65_AddCalendar1(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos); */
664 } else {
665 /* Method 3. All DCT4 features supported. Not supported by 8910 */
666 return N6510_AddCalendar3(s, Note, &s->Phone.Data.Priv.N6510.FirstCalendarPos);
667 }
668 }
669
N6510_ReplyGetNoteInfo(GSM_Protocol_Message * msg,GSM_StateMachine * s)670 GSM_Error N6510_ReplyGetNoteInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
671 {
672 return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastNote);
673 }
674
N6510_ReplyGetNote(GSM_Protocol_Message * msg,GSM_StateMachine * s)675 GSM_Error N6510_ReplyGetNote(GSM_Protocol_Message *msg, GSM_StateMachine *s)
676 {
677 int len;
678
679 smprintf(s, "Note received\n");
680 len = msg->Buffer[50] * 256 + msg->Buffer[51];
681 if (len > GSM_MAX_NOTE_TEXT_LENGTH) {
682 smprintf(s, "Note too long (%d), truncating to %d\n", len, GSM_MAX_NOTE_TEXT_LENGTH);
683 len = GSM_MAX_NOTE_TEXT_LENGTH;
684 }
685 memcpy(s->Phone.Data.Note->Text,
686 msg->Buffer + 54,
687 len * 2);
688 s->Phone.Data.Note->Text[len * 2] = 0;
689 s->Phone.Data.Note->Text[(len * 2) + 1] = 0;
690 return ERR_NONE;
691 }
692
N6510_GetNextNote(GSM_StateMachine * s,GSM_NoteEntry * Note,gboolean start)693 GSM_Error N6510_GetNextNote(GSM_StateMachine *s, GSM_NoteEntry *Note, gboolean start)
694 {
695 GSM_Error error;
696 GSM_NOKIACalToDoLocations *LastNote = &s->Phone.Data.Priv.N6510.LastNote;
697
698 if (!GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOTES)) return ERR_NOTSUPPORTED;
699
700 if (start) {
701 error=N6510_GetCalendarInfo3(s,LastNote,2);
702 if (error!=ERR_NONE) return error;
703 Note->Location = 1;
704 } else {
705 Note->Location++;
706 }
707
708 if (Note->Location > LastNote->Number) return ERR_EMPTY;
709
710 s->Phone.Data.Note = Note;
711 smprintf(s, "Getting note\n");
712 return N6510_PrivGetGenericCalendar3(s, LastNote->Location[Note->Location-1], ID_GetNote);
713 }
714
N6510_DeleteNote(GSM_StateMachine * s,GSM_NoteEntry * Not)715 GSM_Error N6510_DeleteNote(GSM_StateMachine *s, GSM_NoteEntry *Not)
716 {
717 GSM_Error error;
718 GSM_NOKIACalToDoLocations *LastNote = &s->Phone.Data.Priv.N6510.LastNote;
719 GSM_CalendarEntry Note;
720
721 if (!GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOTES)) return ERR_NOTSUPPORTED;
722
723 error=N6510_GetCalendarInfo3(s,LastNote,2);
724 if (error!=ERR_NONE) return error;
725
726 smprintf(s, "Deleting Note\n");
727
728 if (Not->Location > LastNote->Number || Not->Location == 0) return ERR_INVALIDLOCATION;
729
730 Note.Location = LastNote->Location[Not->Location-1];
731 return N71_65_DelCalendar(s,&Note);
732 }
733
N6510_ReplyGetNoteFirstLoc(GSM_Protocol_Message * msg,GSM_StateMachine * s)734 GSM_Error N6510_ReplyGetNoteFirstLoc(GSM_Protocol_Message *msg, GSM_StateMachine *s)
735 {
736 smprintf(s, "First Note location: %i\n",msg->Buffer[8]*256+msg->Buffer[9]);
737 s->Phone.Data.Note->Location = msg->Buffer[8]*256+msg->Buffer[9];
738 return ERR_NONE;
739 }
740
N6510_ReplyAddNote(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)741 GSM_Error N6510_ReplyAddNote(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
742 {
743 smprintf(s, "Note added\n");
744 return ERR_NONE;
745 }
746
N6510_AddNote(GSM_StateMachine * s,GSM_NoteEntry * Not)747 GSM_Error N6510_AddNote(GSM_StateMachine *s, GSM_NoteEntry *Not)
748 {
749 GSM_Error error;
750 int count=54;
751 unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x95,
752 0x02}; /* 1 = todo, 2 = note */
753 unsigned char req[GSM_MAX_NOTE_TEXT_LENGTH + 500] = {
754 N6110_FRAME_HEADER, 0x65,
755 0x02, /* 0 = calendar, 1 = todo, 2 = note */
756 0x00, 0x00, 0x00,
757 0x00, 0x00, /* location */
758 0x00, 0x00, 0x00, 0x00,
759 0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
760 0x80, 0x00, 0x00,
761 0xA9, /* note icon */
762 0x00, 0x00, 0x00, 0x00, /* alarm type */
763 0x00, /* 0x02 or 0x00 */
764 0x80, /* note type */
765 0x07, 0xD2, 0x01, 0x01, 0x00, 0x00, /* start date/time */
766 0x07, 0xD2, 0x01, 0x11, 0x00, 0x00, /* end date/time */
767 0x00, 0x00, /* recurrance */
768 0xFF, 0xFF, /* birth year */
769 0x00, /* ToDo priority */
770 0x00, /* ToDo completed ? */
771 0x00, 0x00, 0x00,
772 0x00, /* note text length */
773 0x00, /* phone length/meeting place */
774 0x00, 0x00, 0x00};
775 size_t length;
776
777 s->Phone.Data.Note = Not;
778
779 smprintf(s, "Getting first free Note location\n");
780 error = GSM_WaitFor (s, reqLoc, 5, 0x13, 4, ID_SetNote);
781 if (error!=ERR_NONE) return error;
782 req[8] = Not->Location / 256;
783 req[9] = Not->Location % 256;
784
785 length = UnicodeLength(Not->Text);
786 req[48] = length / 256;
787 req[49] = length % 256;
788 CopyUnicodeString(req + 54, Not->Text);
789 count += length * 2;
790
791 req[count++] = 0x00;
792
793 smprintf(s, "Adding Note\n");
794 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetNote);
795 }
796
N6510_GetNoteStatus(GSM_StateMachine * s,GSM_ToDoStatus * status)797 GSM_Error N6510_GetNoteStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
798 {
799 GSM_NOKIACalToDoLocations *LastNote = &s->Phone.Data.Priv.N6510.LastNote;
800 GSM_Error error;
801
802 error = N6510_GetCalendarInfo3(s,LastNote,2);
803 if (error!=ERR_NONE) return error;
804
805 status->Used = LastNote->Number;
806 return ERR_NONE;
807 }
808
809 /* ToDo support - 6310 style */
N6510_ReplyGetToDoStatus1(GSM_Protocol_Message * msg,GSM_StateMachine * s)810 GSM_Error N6510_ReplyGetToDoStatus1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
811 {
812 int i;
813 GSM_NOKIACalToDoLocations *Last = &s->Phone.Data.Priv.N6510.LastToDo;
814
815 smprintf(s, "TODO locations received\n");
816 Last->Number=msg->Buffer[6]*256+msg->Buffer[7];
817 smprintf(s, "Number of Entries: %i\n",Last->Number);
818 smprintf(s, "Locations: ");
819 for (i=0;i<Last->Number;i++) {
820 Last->Location[i]=msg->Buffer[12+(i*4)]*256+msg->Buffer[(i*4)+13];
821 smprintf(s, "%i ",Last->Location[i]);
822 }
823 smprintf(s, "\n");
824 return ERR_NONE;
825 }
826
827 /* ToDo support - 6310 style */
N6510_GetToDoStatus1(GSM_StateMachine * s,GSM_ToDoStatus * status)828 static GSM_Error N6510_GetToDoStatus1(GSM_StateMachine *s, GSM_ToDoStatus *status)
829 {
830 GSM_Error error;
831 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
832 unsigned char reqLoc[] = {
833 N6110_FRAME_HEADER,
834 0x15, 0x01, 0x00, 0x00,
835 0x00, 0x00, 0x00};
836
837 smprintf(s, "Getting ToDo locations\n");
838 error = GSM_WaitFor (s, reqLoc, 10, 0x55, 4, ID_GetToDo);
839 if (error != ERR_NONE) return error;
840
841 status->Used = LastToDo->Number;
842 /**
843 * @todo This should be acquired from phone
844 */
845 status->Free = 100;
846 return ERR_NONE;
847 }
848
N6510_GetToDoStatus2(GSM_StateMachine * s,GSM_ToDoStatus * status)849 static GSM_Error N6510_GetToDoStatus2(GSM_StateMachine *s, GSM_ToDoStatus *status)
850 {
851 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
852 GSM_Error error;
853
854 error = N6510_GetCalendarInfo3(s,LastToDo,1);
855 if (error!=ERR_NONE) return error;
856
857 status->Used = LastToDo->Number;
858 /**
859 * @todo This should be acquired from phone
860 */
861 status->Free = 100;
862 return ERR_NONE;
863 }
864
N6510_GetToDoStatus(GSM_StateMachine * s,GSM_ToDoStatus * status)865 GSM_Error N6510_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *status)
866 {
867 status->Used = 0;
868
869 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
870 return N6510_GetToDoStatus1(s, status);
871 } else if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
872 return N6510_GetToDoStatus2(s, status);
873 } else {
874 return ERR_NOTSUPPORTED;
875 }
876 }
877
878 /* ToDo support - 6310 style */
N6510_ReplyGetToDo1(GSM_Protocol_Message * msg,GSM_StateMachine * s)879 GSM_Error N6510_ReplyGetToDo1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
880 {
881 GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
882
883 smprintf(s, "TODO received method 1\n");
884
885 /**
886 * @todo There might be better type.
887 */
888 Last->Type = GSM_CAL_MEMO;
889
890 switch (msg->Buffer[4]) {
891 case 1 : Last->Priority = GSM_Priority_High; break;
892 case 2 : Last->Priority = GSM_Priority_Medium; break;
893 case 3 : Last->Priority = GSM_Priority_Low; break;
894 default : return ERR_UNKNOWN;
895 }
896 smprintf(s, "Priority: %i\n",msg->Buffer[4]);
897
898 CopyUnicodeString(Last->Entries[0].Text,msg->Buffer+14);
899 Last->Entries[0].EntryType = TODO_TEXT;
900 Last->EntriesNum = 1;
901 smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
902
903 return ERR_NONE;
904 }
905
906 /* ToDo support - 6310 style */
N6510_GetNextToDo1(GSM_StateMachine * s,GSM_ToDoEntry * ToDo,gboolean refresh)907 static GSM_Error N6510_GetNextToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, gboolean refresh)
908 {
909 GSM_Error error;
910 GSM_ToDoStatus status;
911 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
912 unsigned char reqGet[] = {
913 N6110_FRAME_HEADER,
914 0x03, 0x00, 0x00, 0x80, 0x00,
915 0x00, 0x17}; /* Location */
916
917 if (refresh) {
918 error = N6510_GetToDoStatus(s, &status);
919 if (error != ERR_NONE) return error;
920 ToDo->Location = 1;
921 } else {
922 ToDo->Location++;
923 }
924 if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
925
926 reqGet[8] = LastToDo->Location[ToDo->Location-1] / 256;
927 reqGet[9] = LastToDo->Location[ToDo->Location-1] % 256;
928 s->Phone.Data.ToDo = ToDo;
929 smprintf(s, "Getting ToDo\n");
930 return GSM_WaitFor (s, reqGet, 10, 0x55, 4, ID_GetToDo);
931 }
932
N6510_ReplyGetToDoStatus2(GSM_Protocol_Message * msg,GSM_StateMachine * s)933 GSM_Error N6510_ReplyGetToDoStatus2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
934 {
935 return N6510_ReplyGetCalendarInfo3(msg, s, &s->Phone.Data.Priv.N6510.LastToDo);
936 }
937
938 /* Similiar to getting calendar method 3 */
N6510_ReplyGetToDo2(GSM_Protocol_Message * msg,GSM_StateMachine * s)939 GSM_Error N6510_ReplyGetToDo2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
940 {
941 GSM_ToDoEntry *Last = s->Phone.Data.ToDo;
942 GSM_DateTime Date;
943 unsigned long diff;
944 int len;
945
946 smprintf(s, "ToDo received method 2\n");
947
948 /**
949 * @todo There might be better type.
950 */
951 Last->Type = GSM_CAL_MEMO;
952
953 switch (msg->Buffer[44]) {
954 case 0x10: Last->Priority = GSM_Priority_Low; break;
955 case 0x20: Last->Priority = GSM_Priority_Medium; break;
956 case 0x30: Last->Priority = GSM_Priority_High; break;
957 default : return ERR_UNKNOWN;
958 }
959
960 len = msg->Buffer[50] * 256 + msg->Buffer[51];
961 if (len > GSM_MAX_TODO_TEXT_LENGTH) {
962 smprintf(s, "Todo text too long (%d), truncating to %d\n", len, GSM_MAX_TODO_TEXT_LENGTH);
963 len = GSM_MAX_TODO_TEXT_LENGTH;
964 }
965 memcpy(Last->Entries[0].Text,
966 msg->Buffer + 54,
967 len * 2);
968 Last->Entries[0].Text[len * 2] = 0;
969 Last->Entries[0].Text[(len * 2) + 1] = 0;
970 Last->Entries[0].EntryType = TODO_TEXT;
971 smprintf(s, "Text: \"%s\"\n",DecodeUnicodeString(Last->Entries[0].Text));
972
973 smprintf(s,"EndTime: %04i-%02i-%02i %02i:%02i\n",
974 msg->Buffer[34]*256+msg->Buffer[35],
975 msg->Buffer[36],msg->Buffer[37],msg->Buffer[38],
976 msg->Buffer[39]);
977 Date.Year = msg->Buffer[34]*256+msg->Buffer[35];
978 Date.Month = msg->Buffer[36];
979 Date.Day = msg->Buffer[37];
980 Date.Hour = msg->Buffer[38];
981 Date.Minute = msg->Buffer[39];
982 Date.Second = 0;
983 Date.Timezone = 0;
984 Last->Entries[1].EntryType = TODO_END_DATETIME;
985 memcpy(&Last->Entries[1].Date, &Date, sizeof(GSM_DateTime));
986
987 smprintf(s,"StartTime: %04i-%02i-%02i %02i:%02i\n",
988 msg->Buffer[28]*256+msg->Buffer[29],
989 msg->Buffer[30],msg->Buffer[31],msg->Buffer[32],
990 msg->Buffer[33]);
991 Date.Year = msg->Buffer[28]*256+msg->Buffer[29];
992 Date.Month = msg->Buffer[30];
993 Date.Day = msg->Buffer[31];
994 Date.Hour = msg->Buffer[32];
995 Date.Minute = msg->Buffer[33];
996 Date.Second = 0;
997 Date.Timezone = 0;
998
999 Last->EntriesNum = 2;
1000
1001 if (msg->Buffer[45] == 0x01) {
1002 Last->Entries[2].Number = msg->Buffer[45];
1003 Last->Entries[2].EntryType = TODO_COMPLETED;
1004 Last->EntriesNum++;
1005 smprintf(s,"Completed\n");
1006 }
1007
1008 if (msg->Buffer[14] == 0xFF && msg->Buffer[15] == 0xFF && msg->Buffer[16] == 0xff && msg->Buffer[17] == 0xff) {
1009 smprintf(s, "No alarm\n");
1010 } else {
1011 diff = ((unsigned int)msg->Buffer[14]) << 24;
1012 diff += ((unsigned int)msg->Buffer[15]) << 16;
1013 diff += ((unsigned int)msg->Buffer[16]) << 8;
1014 diff += msg->Buffer[17];
1015
1016 memcpy(&Last->Entries[Last->EntriesNum].Date,&Date,sizeof(GSM_DateTime));
1017 GetTimeDifference(diff, &Last->Entries[Last->EntriesNum].Date, FALSE, 60);
1018 smprintf(s, "Alarm date : %02i-%02i-%04i %02i:%02i:%02i\n",
1019 Last->Entries[Last->EntriesNum].Date.Day, Last->Entries[Last->EntriesNum].Date.Month,
1020 Last->Entries[Last->EntriesNum].Date.Year, Last->Entries[Last->EntriesNum].Date.Hour,
1021 Last->Entries[Last->EntriesNum].Date.Minute,Last->Entries[Last->EntriesNum].Date.Second);
1022
1023 Last->Entries[Last->EntriesNum].EntryType = TODO_ALARM_DATETIME;
1024 if (msg->Buffer[22]==0x00 && msg->Buffer[23]==0x00 &&
1025 msg->Buffer[24]==0x00 && msg->Buffer[25]==0x00)
1026 {
1027 Last->Entries[Last->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
1028 smprintf(s, "Alarm type : Silent\n");
1029 }
1030 Last->EntriesNum++;
1031 }
1032
1033 return ERR_NONE;
1034 }
1035
1036 /* ToDo support - 6610 style */
N6510_GetNextToDo2(GSM_StateMachine * s,GSM_ToDoEntry * ToDo,gboolean refresh)1037 static GSM_Error N6510_GetNextToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, gboolean refresh)
1038 {
1039 GSM_Error error;
1040 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
1041
1042 if (refresh) {
1043 error=N6510_GetCalendarInfo3(s,LastToDo,1);
1044 if (error!=ERR_NONE) return error;
1045 ToDo->Location = 1;
1046 } else {
1047 ToDo->Location++;
1048 }
1049
1050 if (ToDo->Location > LastToDo->Number) return ERR_EMPTY;
1051
1052 s->Phone.Data.ToDo = ToDo;
1053 smprintf(s, "Getting todo method 2\n");
1054 return N6510_PrivGetGenericCalendar3(s, LastToDo->Location[ToDo->Location-1], ID_GetToDo);
1055 }
1056
N6510_GetNextToDo(GSM_StateMachine * s,GSM_ToDoEntry * ToDo,gboolean refresh)1057 GSM_Error N6510_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo, gboolean refresh)
1058 {
1059 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
1060 return N6510_GetNextToDo1(s, ToDo, refresh);
1061 } else if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
1062 return N6510_GetNextToDo2(s, ToDo, refresh);
1063 } else {
1064 return ERR_NOTSUPPORTED;
1065 }
1066 }
1067
1068 /* ToDo support - 6310 style */
N6510_ReplyDeleteAllToDo1(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)1069 GSM_Error N6510_ReplyDeleteAllToDo1(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
1070 {
1071 smprintf(s, "All TODO deleted\n");
1072 return ERR_NONE;
1073 }
1074
1075 /* ToDo support - 6310 style */
N6510_DeleteAllToDo1(GSM_StateMachine * s)1076 GSM_Error N6510_DeleteAllToDo1(GSM_StateMachine *s)
1077 {
1078 unsigned char req[] = {N6110_FRAME_HEADER, 0x11};
1079
1080 if (!GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
1081 return ERR_NOTSUPPORTED;
1082 }
1083
1084 smprintf(s, "Deleting all ToDo method 1\n");
1085 return GSM_WaitFor (s, req, 4, 0x55, 4, ID_DeleteAllToDo);
1086 }
1087
N6510_DeleteToDo2(GSM_StateMachine * s,GSM_ToDoEntry * ToDo)1088 GSM_Error N6510_DeleteToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
1089 {
1090 GSM_Error error;
1091 GSM_NOKIACalToDoLocations *LastToDo = &s->Phone.Data.Priv.N6510.LastToDo;
1092 GSM_CalendarEntry Note;
1093
1094 if (!GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
1095 return ERR_NOTSUPPORTED;
1096 }
1097
1098 error=N6510_GetCalendarInfo3(s,LastToDo,1);
1099 if (error!=ERR_NONE) return error;
1100
1101 smprintf(s, "Deleting ToDo method 2\n");
1102
1103 if (ToDo->Location > LastToDo->Number || ToDo->Location == 0) return ERR_INVALIDLOCATION;
1104
1105 Note.Location = LastToDo->Location[ToDo->Location-1];
1106 return N71_65_DelCalendar(s,&Note);
1107 }
1108
1109 /* ToDo support - 6310 style */
N6510_ReplyGetToDoFirstLoc1(GSM_Protocol_Message * msg,GSM_StateMachine * s)1110 GSM_Error N6510_ReplyGetToDoFirstLoc1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1111 {
1112 smprintf(s, "TODO first location received method 1: %02x\n",msg->Buffer[9]);
1113 s->Phone.Data.ToDo->Location = msg->Buffer[9];
1114 return ERR_NONE;
1115 }
1116
1117 /* ToDo support - 6310 style */
N6510_ReplyAddToDo1(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)1118 GSM_Error N6510_ReplyAddToDo1(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
1119 {
1120 smprintf(s, "TODO set OK\n");
1121 return ERR_NONE;
1122 }
1123
1124 /* ToDo support - 6310 style */
N6510_AddToDo1(GSM_StateMachine * s,GSM_ToDoEntry * ToDo)1125 static GSM_Error N6510_AddToDo1(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
1126 {
1127 int Text, Alarm, EndTime, Completed, ulen, Phone;
1128 GSM_Error error;
1129 unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x0F};
1130 unsigned char reqSet[500] = {
1131 N6110_FRAME_HEADER, 0x01,
1132 0x03, /* Priority */
1133 0x00, /* Length of text */
1134 0x80,0x00,0x00,
1135 0x18}; /* Location */
1136
1137 s->Phone.Data.ToDo = ToDo;
1138
1139 smprintf(s, "Getting first ToDo location\n");
1140 error = GSM_WaitFor (s, reqLoc, 4, 0x55, 4, ID_SetToDo);
1141 if (error != ERR_NONE) return error;
1142 reqSet[9] = ToDo->Location;
1143
1144 switch (ToDo->Priority) {
1145 case GSM_Priority_Low : reqSet[4] = 3; break;
1146 case GSM_Priority_Medium: reqSet[4] = 2; break;
1147 case GSM_Priority_High : reqSet[4] = 1; break;
1148 default: break;
1149 }
1150
1151 GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
1152
1153 if (Text == -1) return ERR_NOTSUPPORTED; /* XXX: shouldn't this be handled different way? */
1154 ulen = UnicodeLength(ToDo->Entries[Text].Text);
1155 reqSet[5] = ulen+1;
1156 CopyUnicodeString(reqSet+10,ToDo->Entries[Text].Text);
1157 reqSet[10+ulen*2] = 0x00;
1158 reqSet[10+ulen*2+1] = 0x00;
1159 smprintf(s, "Adding ToDo method 1\n");
1160 return GSM_WaitFor (s, reqSet, 12+ulen*2, 0x55, 4, ID_SetToDo);
1161 }
1162
N6510_ReplyAddToDo2(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)1163 GSM_Error N6510_ReplyAddToDo2(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
1164 {
1165 smprintf(s, "ToDo added method 2\n");
1166 return ERR_NONE;
1167 }
1168
N6510_ReplyGetToDoFirstLoc2(GSM_Protocol_Message * msg,GSM_StateMachine * s)1169 GSM_Error N6510_ReplyGetToDoFirstLoc2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1170 {
1171 smprintf(s, "First ToDo location method 2: %i\n",msg->Buffer[8]*256+msg->Buffer[9]);
1172 s->Phone.Data.ToDo->Location = msg->Buffer[8]*256+msg->Buffer[9];
1173 return ERR_NONE;
1174 }
1175
N6510_AddToDo2(GSM_StateMachine * s,GSM_ToDoEntry * ToDo)1176 static GSM_Error N6510_AddToDo2(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
1177 {
1178 GSM_CalendarEntry Note;
1179 time_t t_time1,t_time2;
1180 long diff;
1181 GSM_Error error;
1182 GSM_DateTime DT;
1183 int Text, Alarm, EndTime, Completed, count=54, Phone;
1184 unsigned char reqLoc[] = {N6110_FRAME_HEADER, 0x95,
1185 0x01}; /* 1 = todo, 2 = note */
1186 unsigned char req[GSM_MAX_TODO_TEXT_LENGTH + 500] = {
1187 N6110_FRAME_HEADER, 0x65,
1188 0x01, /* 0 = calendar, 1 = todo */
1189 0x00, 0x00, 0x00,
1190 0x00, 0x00, /* location */
1191 0x00, 0x00, 0x00, 0x00,
1192 0xFF, 0xFF, 0xFF, 0xFF, /* alarm */
1193 0x80, 0x00, 0x00,
1194 0x01, /* note icon */
1195 0xFF, 0xFF, 0xFF, 0xFF, /* alarm type */
1196 0x00, /* 0x02 or 0x00 */
1197 0x01, /* note type */
1198 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* start date/time */
1199 0x07, 0xD0, 0x01, 0x12, 0x0C, 0x00, /* end date/time */
1200 0x00, 0x00, /* recurrance */
1201 0x00, 0x00, /* birth year */
1202 0x20, /* ToDo priority */
1203 0x00, /* ToDo completed ? */
1204 0x00, 0x00, /* How many times repeat cal note or 0 */
1205 0x00,
1206 0x00, /* note text length */
1207 0x00, /* phone length/meeting place */
1208 0x00, 0x00, 0x00};
1209
1210 s->Phone.Data.ToDo = ToDo;
1211
1212 smprintf(s, "Getting first free ToDo location method 2\n");
1213 error = GSM_WaitFor (s, reqLoc, 5, 0x13, 4, ID_SetToDo);
1214 if (error!=ERR_NONE) return error;
1215 req[8] = ToDo->Location/256;
1216 req[9] = ToDo->Location%256;
1217
1218 Note.Type = GSM_CAL_MEETING;
1219 DT.Year = 2004; DT.Month = 1; DT.Day = 1;
1220 DT.Hour = 12; DT.Minute = 12; DT.Second = 0;
1221 DT.Timezone = 0;
1222 memcpy(&Note.Entries[0].Date,&DT,sizeof(GSM_DateTime));
1223 Note.Entries[0].EntryType = CAL_START_DATETIME;
1224 memcpy(&Note.Entries[1].Date,&DT,sizeof(GSM_DateTime));
1225 Note.Entries[1].EntryType = CAL_END_DATETIME;
1226 EncodeUnicode(Note.Entries[2].Text,"ala",3);
1227 Note.Entries[2].EntryType = CAL_TEXT;
1228 Note.EntriesNum = 3;
1229 error=N6510_FindCalendarIconID3(s, &Note, &req[21]);
1230 if (error!=ERR_NONE) return error;
1231
1232 switch (ToDo->Priority) {
1233 case GSM_Priority_Low : req[44] = 0x10; break;
1234 case GSM_Priority_Medium: req[44] = 0x20; break;
1235 case GSM_Priority_High : req[44] = 0x30; break;
1236 default: break;
1237 }
1238
1239 GSM_ToDoFindDefaultTextTimeAlarmCompleted(ToDo, &Text, &Alarm, &Completed, &EndTime, &Phone);
1240
1241 if (Completed != -1) req[45] = 0x01;
1242
1243 if (EndTime == -1) {
1244 GSM_GetCurrentDateTime(&DT);
1245 } else {
1246 memcpy(&DT,&ToDo->Entries[EndTime].Date,sizeof(GSM_DateTime));
1247 }
1248 /*Start time*/
1249 req[28] = DT.Year / 256;
1250 req[29] = DT.Year % 256;
1251 req[30] = DT.Month;
1252 req[31] = DT.Day;
1253 req[32] = DT.Hour;
1254 req[33] = DT.Minute;
1255 /*End time*/
1256 req[34] = DT.Year / 256;
1257 req[35] = DT.Year % 256;
1258 req[36] = DT.Month;
1259 req[37] = DT.Day;
1260 req[38] = DT.Hour;
1261 req[39] = DT.Minute;
1262
1263 if (Alarm != -1) {
1264 if (ToDo->Entries[Alarm].EntryType == TODO_SILENT_ALARM_DATETIME)
1265 {
1266 req[22] = 0x00; req[23] = 0x00; req[24] = 0x00; req[25] = 0x00;
1267 }
1268 t_time2 = Fill_Time_T(DT);
1269 t_time1 = Fill_Time_T(ToDo->Entries[Alarm].Date);
1270 diff = (t_time1-t_time2)/60;
1271
1272 smprintf(s, " Difference : %li seconds or minutes\n", -diff);
1273 req[14] = (unsigned char)(-diff >> 24);
1274 req[15] = (unsigned char)(-diff >> 16);
1275 req[16] = (unsigned char)(-diff >> 8);
1276 req[17] = (unsigned char)(-diff);
1277 }
1278
1279 if (Text != -1) {
1280 req[48] = UnicodeLength(ToDo->Entries[Text].Text) / 256;
1281 req[49] = UnicodeLength(ToDo->Entries[Text].Text) % 256;
1282 CopyUnicodeString(req + 54, ToDo->Entries[Text].Text);
1283 count += req[49] * 2 + (req[48] * 256) * 2;
1284 }
1285
1286 req[count++] = 0x00;
1287
1288 smprintf(s, "Adding ToDo method 2\n");
1289 return GSM_WaitFor (s, req, count, 0x13, 4, ID_SetToDo);
1290 }
1291
N6510_AddToDo(GSM_StateMachine * s,GSM_ToDoEntry * ToDo)1292 GSM_Error N6510_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *ToDo)
1293 {
1294 if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO63)) {
1295 return N6510_AddToDo1(s, ToDo);
1296 } else if (GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_TODO66)) {
1297 return N6510_AddToDo2(s, ToDo);
1298 } else {
1299 return ERR_NOTSUPPORTED;
1300 }
1301 }
1302
N6510_ReplyGetCalendarSettings(GSM_Protocol_Message * msg,GSM_StateMachine * s)1303 GSM_Error N6510_ReplyGetCalendarSettings(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1304 {
1305 GSM_CalendarSettings *sett = s->Phone.Data.CalendarSettings;
1306
1307 switch (msg->Buffer[3]) {
1308 case 0x86:
1309 smprintf(s, "Auto deleting setting received\n");
1310 sett->AutoDelete = msg->Buffer[4];
1311 return ERR_NONE;
1312 case 0x8E:
1313 smprintf(s, "Start day for calendar received\n");
1314 switch(msg->Buffer[4]) {
1315 case 0x04:
1316 sett->StartDay = 1;
1317 return ERR_NONE;
1318 case 0x03:
1319 sett->StartDay = 6;
1320 return ERR_NONE;
1321 case 0x02:
1322 sett->StartDay = 7;
1323 return ERR_NONE;
1324 case 0x01:
1325 sett->StartDay = 1;
1326 return ERR_NONE;
1327 }
1328 break;
1329 }
1330 return ERR_UNKNOWNRESPONSE;
1331 }
1332
N6510_GetCalendarSettings(GSM_StateMachine * s,GSM_CalendarSettings * settings)1333 GSM_Error N6510_GetCalendarSettings(GSM_StateMachine *s, GSM_CalendarSettings *settings)
1334 {
1335 GSM_Error error;
1336 unsigned char req1[] = {N6110_FRAME_HEADER, 0x85};
1337 unsigned char req2[] = {N6110_FRAME_HEADER, 0x8D};
1338
1339 s->Phone.Data.CalendarSettings = settings;
1340
1341 smprintf(s, "Getting auto delete\n");
1342 error = GSM_WaitFor (s, req1, 4, 0x13, 4, ID_GetCalendarSettings);
1343 if (error != ERR_NONE) return error;
1344
1345 smprintf(s, "Getting start day for week\n");
1346 return GSM_WaitFor (s, req2, 4, 0x13, 4, ID_GetCalendarSettings);
1347 }
1348
1349 #endif
1350
1351 /* How should editor hadle tabs in this file? Add editor commands here.
1352 * vim: noexpandtab sw=8 ts=8 sts=8:
1353 */
1354