summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/phone/nokia/dct3/n6110.c
Unidiff
Diffstat (limited to 'gammu/emb/common/phone/nokia/dct3/n6110.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/phone/nokia/dct3/n6110.c2884
1 files changed, 2884 insertions, 0 deletions
diff --git a/gammu/emb/common/phone/nokia/dct3/n6110.c b/gammu/emb/common/phone/nokia/dct3/n6110.c
new file mode 100644
index 0000000..263d12b
--- a/dev/null
+++ b/gammu/emb/common/phone/nokia/dct3/n6110.c
@@ -0,0 +1,2884 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Markus Plail and Gnokii */
3/* Authentication function (c) 1999 or earlier by Pavel Janik */
4/* 5210 calendar IDs by Frederick Ros */
5
6#include "../../../gsmstate.h"
7
8#ifdef GSM_ENABLE_NOKIA6110
9
10#include <string.h>
11
12#include "../../../../cfg/config.h"
13#include "../../../misc/coding/coding.h"
14#include "../../../service/sms/gsmsms.h"
15#include "../../../gsmcomon.h"
16#include "../../pfunc.h"
17#include "../nfunc.h"
18#include "n6110.h"
19#include "dct3func.h"
20
21static unsigned char N6110_MEMORY_TYPES[] = {
22 MEM_ME, 0x02,
23 MEM_SM, 0x03,
24 MEM_ON, 0x05,
25 MEM_DC, 0x07,
26 MEM_RC, 0x08,
27 MEM_MC, 0x09,
28 MEM_VM, 0x0b,
29 0x00, 0x00
30};
31
32static GSM_Error N6110_ReplyGetPhoneLanguage(GSM_Protocol_Message msg, GSM_StateMachine *s)
33{
34 N6110_Language lang = N6110_Auto;
35
36 if (msg.Buffer[3] == 0x15) return ERR_NONE;
37
38 smprintf(s, "Phone language is %02x\n",msg.Buffer[6]);
39 switch (msg.Buffer[6]) {
40 case 0x21: lang = N6110_Europe; break; //Polish
41 }
42 s->Phone.Data.Priv.N6110.PhoneLanguage = lang;
43 return ERR_NONE;
44}
45
46static GSM_Error N6110_GetPhoneLanguage(GSM_StateMachine *s)
47{
48 unsigned char feat_req[] = {N6110_FRAME_HEADER, 0x13, 0x01,
49 0x00, /* Profile location */
50 0x00}; /* Feature number */
51
52 s->Phone.Data.Priv.N6110.PhoneLanguage = N6110_Auto;
53
54 feat_req[5] = 0;
55 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
56 feat_req[6] = 0x1E;
57 } else {
58 feat_req[6] = 0x21;
59 }
60 smprintf(s, "Getting profile feature\n");
61 return GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetLanguage);
62}
63
64struct N6110_Lang_Char {
65 N6110_Language Lang;
66 unsigned char Phone;
67 unsigned char Unicode1;
68 unsigned char Unicode2;
69};
70
71static struct N6110_Lang_Char N6110_Lang_Table[] = {
72{N6110_Europe,0x13,0x01,0x04},//Latin capital letter a with ogonek
73{N6110_Europe,0x14,0x01,0x05},//Latin small letter a with ogonek
74{N6110_Europe,0x15,0x01,0x06},//Latin capital letter c with acute
75{N6110_Europe,0x17,0x01,0x07},//Latin small letter c with acute
76{N6110_Europe,0x1D,0x01,0x18},//Latin capital letter e with ogonek
77{N6110_Europe,0x1E,0x01,0x19},//Latin small letter e with ogonek
78{N6110_Europe,0x83,0x00,0xD3},//Latin capital letter o with acute
79{N6110_Europe,0x8E,0x01,0x41},//Latin capital letter l with stroke
80{N6110_Europe,0x90,0x01,0x42},//Latin small letter l with stroke
81{N6110_Europe,0x92,0x01,0x43},//Latin capital letter n with acute
82{N6110_Europe,0x93,0x01,0x44},//Latin small letter n with acute
83{N6110_Europe,0x9A,0x00,0xF3},//Latin small letter o with acute
84{N6110_Europe,0xB2,0x20,0xAC},//euro
85{N6110_Europe,0xB5,0x01,0x5A},//Latin capital letter s with acute
86{N6110_Europe,0xB6,0x01,0x5B},//Latin small letter s with acute
87{N6110_Europe,0xE7,0x01,0x79},//Latin capital letter z with acute
88{N6110_Europe,0xEE,0x01,0x7A},//Latin small letter z with acute
89{N6110_Europe,0xF4,0x01,0x7C},//Latin small letter z with dot above
90{N6110_Europe,0xF0,0x01,0x7B},//Latin capital letter z with dot above
91{0,0,0,0}
92};
93
94static void N6110_EncodeUnicode(GSM_StateMachine *s, unsigned char *dest, const unsigned char *src, int len)
95{
96 int i_len = 0, o_len, i;
97 wchar_t wc;
98 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
99 bool found;
100
101 for (o_len = 0; i_len < len; o_len++) {
102 found = false;
103 if (Priv->PhoneLanguage != N6110_Auto) {
104 i = 0;
105 while(1) {
106 if (N6110_Lang_Table[i].Lang == 0) break;
107 if (N6110_Lang_Table[i].Lang == Priv->PhoneLanguage &&
108 N6110_Lang_Table[i].Phone == src[i_len]) {
109 dest[o_len*2] = N6110_Lang_Table[i].Unicode1;
110 dest[(o_len*2)+1] = N6110_Lang_Table[i].Unicode2;
111 i_len++;
112 found = true;
113 break;
114 }
115 i++;
116 }
117 }
118 if (!found) {
119 i_len += EncodeWithUnicodeAlphabet(&src[i_len], &wc);
120 dest[o_len*2] = (wc >> 8) & 0xff;
121 dest[(o_len*2)+1] = wc & 0xff;
122 }
123 }
124 dest[o_len*2] = 0;
125 dest[(o_len*2)+1] = 0;
126}
127
128#ifndef ENABLE_LGPL
129
130/* This function provides Nokia authentication protocol.
131 * Nokia authentication protocol is used in the communication between Nokia
132 * mobile phones (e.g. Nokia 6110) and Nokia Cellular Data Suite software,
133 * commercially sold by Nokia Corp.
134 * The authentication scheme is based on the token send by the phone to the
135 * software. The software does it's magic (see the function
136 * N6110_GetNokiaAuthentication) and returns the result back to the phone.
137 * If the result is correct the phone responds with the message "Accessory
138 * connected!" displayed on the LCD. Otherwise it will display "Accessory not
139 * supported" and some functions will not be available for use (?).
140 * The specification of the protocol is not publicly available, no comment.
141 */
142static void N6110_GetNokiaAuthentication(unsigned char *Imei, unsigned char *MagicBytes, unsigned char *MagicResponse)
143{
144 int i, j, CRC=0;
145 unsigned char Temp[16]; /* This is our temporary working area. */
146
147 /* Here we put FAC (Final Assembly Code) and serial number into our area. */
148 Temp[0] = Imei[6]; Temp[1] = Imei[7];
149 Temp[2] = Imei[8]; Temp[3] = Imei[9];
150 Temp[4] = Imei[10]; Temp[5] = Imei[11];
151 Temp[6] = Imei[12]; Temp[7] = Imei[13];
152
153 /* And now the TAC (Type Approval Code). */
154 Temp[8] = Imei[2]; Temp[9] = Imei[3];
155 Temp[10] = Imei[4]; Temp[11] = Imei[5];
156
157 /* And now we pack magic bytes from the phone. */
158 Temp[12] = MagicBytes[0]; Temp[13] = MagicBytes[1];
159 Temp[14] = MagicBytes[2]; Temp[15] = MagicBytes[3];
160
161 for (i=0; i<=11; i++) if (Temp[i + 1]& 1) Temp[i]<<=1;
162 switch (Temp[15] & 0x03) {
163 case 1:
164 case 2: j = Temp[13] & 0x07;
165 for (i=0; i<=3; i++) Temp[i+j] ^= Temp[i+12];
166 break;
167 default: j = Temp[14] & 0x07;
168 for (i=0; i<=3; i++) Temp[i + j] |= Temp[i + 12];
169 }
170 for (i=0; i<=15; i++) CRC ^= Temp[i];
171 for (i=0; i<=15; i++) {
172 switch (Temp[15 - i] & 0x06) {
173 case 0: j = Temp[i] | CRC; break;
174 case 2:
175 case 4: j = Temp[i] ^ CRC; break;
176 case 6: j = Temp[i] & CRC; break;
177 }
178 if (j == CRC) j = 0x2c;
179 if (Temp[i] == 0) j = 0;
180 MagicResponse[i] = j;
181 }
182}
183
184static GSM_Error N6110_ReplyGetMagicBytes(GSM_Protocol_Message msg, GSM_StateMachine *s)
185{
186 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
187 GSM_Phone_Data *Data = &s->Phone.Data;
188
189 sprintf(Data->IMEI, "%s", msg.Buffer+9);
190 sprintf(Data->HardwareCache, "%s", msg.Buffer+39);
191 sprintf(Data->ProductCodeCache, "%s", msg.Buffer+31);
192
193 smprintf(s, "Message: Mobile phone identification received:\n");
194 smprintf(s, "IMEI : %s\n", msg.Buffer+9);
195 smprintf(s, "Model : %s\n", msg.Buffer+25);
196 smprintf(s, "Production Code : %s\n", msg.Buffer+31);
197 smprintf(s, "HW : %s\n", msg.Buffer+39);
198 smprintf(s, "Firmware : %s\n", msg.Buffer+44);
199
200 /* These bytes are probably the source of the "Accessory not connected"
201 * messages on the phone when trying to emulate NCDS... I hope....
202 * UPDATE: of course, now we have the authentication algorithm.
203 */
204 smprintf(s, " Magic bytes : %02x %02x %02x %02x\n", msg.Buffer[50], msg.Buffer[51], msg.Buffer[52], msg.Buffer[53]);
205
206 Priv->MagicBytes[0]=msg.Buffer[50];
207 Priv->MagicBytes[1]=msg.Buffer[51];
208 Priv->MagicBytes[2]=msg.Buffer[52];
209 Priv->MagicBytes[3]=msg.Buffer[53];
210
211 return ERR_NONE;
212}
213
214static GSM_Error N6110_MakeAuthentication(GSM_StateMachine *s)
215{
216 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
217 GSM_Error error;
218 unsigned char connect4[] = {N6110_FRAME_HEADER, 0x10};
219 unsigned char magic_connect[] = {
220 N6110_FRAME_HEADER, 0x12,
221 /* The real magic goes here ... These bytes are filled in
222 * with the function N6110_GetNokiaAuthentication. */
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 /* NOKIA&GNOKII Accessory */
226 'N', 'O', 'K', 'I', 'A', '&', 'N', 'O', 'K', 'I', 'A',
227 'a', 'c', 'c', 'e', 's', 's', 'o', 'r', 'y',
228 0x00, 0x00, 0x00, 0x00};
229
230 smprintf(s, "Getting magic bytes for authentication\n");
231 error=GSM_WaitFor (s, connect4, 4, 0x64, 4, ID_MakeAuthentication);
232 if (error!=ERR_NONE) return error;
233
234 N6110_GetNokiaAuthentication(s->Phone.Data.IMEI, Priv->MagicBytes, magic_connect+4);
235 smprintf(s, "Sending authentication bytes\n");
236 return s->Protocol.Functions->WriteMessage(s, magic_connect, 45, 0x64);
237}
238
239#endif
240
241static GSM_Error N6110_ShowStartInfo(GSM_StateMachine *s, bool enable)
242{
243#ifdef ENABLE_LGPL
244 return ERR_NONE;
245#else
246 GSM_Error error=ERR_NONE;
247
248 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_MAGICBYTES)) {
249 if (s->ConnectionType == GCT_FBUS2 ||
250 s->ConnectionType == GCT_FBUS2IRDA) {
251 error=N6110_MakeAuthentication(s);
252 }
253 }
254 return error;
255#endif
256}
257
258static GSM_Error N6110_Initialise (GSM_StateMachine *s)
259{
260#ifdef DEBUG
261 DCT3_SetIncomingCB(s,true);
262#endif
263 N6110_GetPhoneLanguage(s);
264 return ERR_NONE;
265}
266
267static GSM_Error N6110_GetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
268{
269 return DCT3_GetDateTime(s, date_time, 0x11);
270}
271
272static GSM_Error N6110_GetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
273{
274 return DCT3_GetAlarm(s, alarm, 0x11);
275}
276
277static GSM_Error N6110_SetDateTime(GSM_StateMachine *s, GSM_DateTime *date_time)
278{
279 return DCT3_SetDateTime(s, date_time, 0x11);
280}
281
282static GSM_Error N6110_SetAlarm(GSM_StateMachine *s, GSM_Alarm *alarm)
283{
284 return DCT3_SetAlarm(s, alarm, 0x11);
285}
286
287static GSM_Error N6110_ReplyGetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
288{
289 int count;
290 GSM_Phone_Data *Data = &s->Phone.Data;
291
292 smprintf(s, "Phonebook entry received\n");
293 switch (msg.Buffer[3]) {
294 case 0x02:
295 Data->Memory->EntriesNum = 0;
296 count=5;
297 /* If name is not empty */
298 if (msg.Buffer[count]!=0x00) {
299 if (msg.Buffer[count]>GSM_PHONEBOOK_TEXT_LENGTH) {
300 smprintf(s, "Too long text\n");
301 return ERR_UNKNOWNRESPONSE;
302 }
303 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Text_Name;
304 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
305 if (Data->Memory->MemoryType==MEM_DC ||
306 Data->Memory->MemoryType==MEM_RC ||
307 Data->Memory->MemoryType==MEM_MC ||
308 Data->Memory->MemoryType==MEM_ME) {
309 N6110_EncodeUnicode(s,Data->Memory->Entries[Data->Memory->EntriesNum].Text,
310 msg.Buffer+count+1,msg.Buffer[count]);
311 } else {
312 EncodeUnicode(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
313 msg.Buffer+count+1,msg.Buffer[count]);
314 }
315 } else {
316 memcpy(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
317 msg.Buffer+count+1,msg.Buffer[count]);
318 Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]]=0x00;
319 Data->Memory->Entries[Data->Memory->EntriesNum].Text[msg.Buffer[count]+1]=0x00;
320 }
321 smprintf(s, "Name \"%s\"\n",
322 DecodeUnicodeString(Data->Memory->Entries[Data->Memory->EntriesNum].Text));
323 Data->Memory->EntriesNum++;
324 }
325 count=count+msg.Buffer[count]+1;
326
327 /* If number is empty */
328 if (msg.Buffer[count]==0x00) return ERR_EMPTY;
329
330 if (msg.Buffer[count]>GSM_PHONEBOOK_TEXT_LENGTH) {
331 smprintf(s, "Too long text\n");
332 return ERR_UNKNOWNRESPONSE;
333 }
334 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType = PBK_Number_General;
335 Data->Memory->Entries[Data->Memory->EntriesNum].VoiceTag = 0;
336 Data->Memory->Entries[Data->Memory->EntriesNum].SMSList[0] = 0;
337 EncodeUnicode(Data->Memory->Entries[Data->Memory->EntriesNum].Text,
338 msg.Buffer+count+1,msg.Buffer[count]);
339 smprintf(s, "Number \"%s\"\n",
340 DecodeUnicodeString(Data->Memory->Entries[Data->Memory->EntriesNum].Text));
341 Data->Memory->EntriesNum++;
342 count=count+msg.Buffer[count]+1;
343
344 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALLER)) {
345 if (msg.Buffer[count]<5) {
346 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Caller_Group;
347 smprintf(s, "Caller group \"%i\"\n",msg.Buffer[count]);
348 Data->Memory->Entries[Data->Memory->EntriesNum].Number=msg.Buffer[count]+1;
349 Data->Memory->EntriesNum++;
350 }
351 }
352 count++;
353
354 if (Data->Memory->MemoryType==MEM_DC ||
355 Data->Memory->MemoryType==MEM_RC ||
356 Data->Memory->MemoryType==MEM_MC) {
357 NOKIA_DecodeDateTime(s, msg.Buffer+count+1,&Data->Memory->Entries[Data->Memory->EntriesNum].Date);
358 Data->Memory->Entries[Data->Memory->EntriesNum].EntryType=PBK_Date;
359
360 /* These values are set, when date and time unavailable in phone.
361 * Values from 3310 - in other can be different */
362 if (Data->Memory->Entries[2].Date.Day !=20 ||
363 Data->Memory->Entries[2].Date.Month !=1 ||
364 Data->Memory->Entries[2].Date.Year !=2118||
365 Data->Memory->Entries[2].Date.Hour !=3 ||
366 Data->Memory->Entries[2].Date.Minute!=14 ||
367 Data->Memory->Entries[2].Date.Second!=7)
368 Data->Memory->EntriesNum++;
369 }
370
371 return ERR_NONE;
372 default:
373 switch (msg.Buffer[4]) {
374 case 0x6f:
375 smprintf(s, "Phone is OFF\n");
376 return ERR_PHONEOFF;
377 case 0x74:
378 /* TODO: check if not too high */
379 smprintf(s, "ERROR: Empty ????\n");
380 Data->Memory->EntriesNum = 0;
381 return ERR_EMPTY;
382 case 0x7d:
383 smprintf(s, "ERROR: Invalid memory type\n");
384 return ERR_NOTSUPPORTED;
385 case 0x8d:
386 smprintf(s, "ERROR: no PIN\n");
387 return ERR_SECURITYERROR;
388 default:
389 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
390 }
391 }
392 return ERR_UNKNOWNRESPONSE;
393}
394
395static GSM_Error N6110_GetMemory (GSM_StateMachine *s, GSM_MemoryEntry *entry)
396{
397 unsigned char req[] = {N6110_FRAME_HEADER, 0x01,
398 0x00, /* memory type */
399 0x00, /* location */
400 0x00};
401
402 req[4] = NOKIA_GetMemoryType(s, entry->MemoryType,N6110_MEMORY_TYPES);
403 if (req[4]==0xff) return ERR_NOTSUPPORTED;
404
405 req[5] = entry->Location;
406 if (entry->MemoryType==MEM_DC || entry->MemoryType==MEM_RC || entry->MemoryType==MEM_MC) req[5]--;
407
408 s->Phone.Data.Memory=entry;
409 smprintf(s, "Getting phonebook entry\n");
410 return GSM_WaitFor (s, req, 7, 0x03, 4, ID_GetMemory);
411}
412
413static GSM_Error N6110_ReplyGetMemoryStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
414{
415 GSM_Phone_Data *Data = &s->Phone.Data;
416
417 smprintf(s, "Memory status received\n");
418 switch (msg.Buffer[3]) {
419 case 0x08:
420 smprintf(s, "Memory type: %i\n",msg.Buffer[4]);
421
422 smprintf(s, "Free : %i\n",msg.Buffer[5]);
423 Data->MemoryStatus->MemoryFree=msg.Buffer[5];
424
425 smprintf(s, "Used : %i\n",msg.Buffer[6]);
426 Data->MemoryStatus->MemoryUsed=msg.Buffer[6];
427
428 return ERR_NONE;
429 break;
430 case 0x09:
431 switch (msg.Buffer[4]) {
432 case 0x6f:
433 smprintf(s, "Phone is probably powered off.\n");
434 return ERR_TIMEOUT;
435 case 0x7d:
436 smprintf(s, "Memory type not supported by phone model.\n");
437 return ERR_NOTSUPPORTED;
438 case 0x8d:
439 smprintf(s, "Waiting for security code.\n");
440 return ERR_SECURITYERROR;
441 default:
442 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
443 }
444 default:
445 return ERR_UNKNOWNRESPONSE;
446 }
447}
448
449static GSM_Error N6110_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
450{
451 unsigned char req[] = {N6110_FRAME_HEADER, 0x07,
452 0x00}; /* memory type */
453
454 req[4] = NOKIA_GetMemoryType(s, Status->MemoryType,N6110_MEMORY_TYPES);
455 if (req[4]==0xff) return ERR_NOTSUPPORTED;
456
457 s->Phone.Data.MemoryStatus=Status;
458 smprintf(s, "Getting memory status\n");
459 return GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetMemoryStatus);
460}
461
462static GSM_Error N6110_ReplyGetSMSStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
463{
464 GSM_Phone_Data *Data = &s->Phone.Data;
465
466 smprintf(s, "SMS status received\n");
467 switch (msg.Buffer[3]) {
468 case 0x37:
469 smprintf(s, "SIM size : %i\n",msg.Buffer[7]);
470 smprintf(s, "Used in SIM : %i\n",msg.Buffer[10]);
471 smprintf(s, "Unread in SIM : %i\n",msg.Buffer[11]);
472 Data->SMSStatus->SIMUsed = msg.Buffer[10];
473 Data->SMSStatus->SIMUnRead = msg.Buffer[11];
474 Data->SMSStatus->SIMSize = msg.Buffer[7];
475 Data->SMSStatus->PhoneUsed = 0;
476 Data->SMSStatus->PhoneUnRead = 0;
477 Data->SMSStatus->PhoneSize = 0;
478 Data->SMSStatus->TemplatesUsed = 0;
479 return ERR_NONE;
480 case 0x38:
481 smprintf(s, "Error. No PIN ?\n");
482 return ERR_SECURITYERROR;
483 }
484 return ERR_UNKNOWNRESPONSE;
485}
486
487static GSM_Error N6110_ReplyGetSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
488{
489 GSM_Phone_Data *Data = &s->Phone.Data;
490
491 smprintf(s, "SMS Message received\n");
492 switch(msg.Buffer[3]) {
493 case 0x08:
494 Data->GetSMSMessage->Number = 1;
495 Data->GetSMSMessage->SMS[0].Name[0] = 0;
496 Data->GetSMSMessage->SMS[0].Name[1] = 0;
497 Data->GetSMSMessage->SMS[0].Memory = MEM_SM;
498 NOKIA_DecodeSMSState(s, msg.Buffer[4], &Data->GetSMSMessage->SMS[0]);
499 switch (msg.Buffer[7]) {
500 case 0x00: case 0x01: /* Report or SMS_Deliver */
501 Data->GetSMSMessage->SMS[0].Folder = 0x01;
502 Data->GetSMSMessage->SMS[0].InboxFolder = true;
503 break;
504 case 0x02: /* SMS_Submit */
505 Data->GetSMSMessage->SMS[0].Folder = 0x02;
506 Data->GetSMSMessage->SMS[0].InboxFolder = false;
507 break;
508 default:
509 return ERR_UNKNOWNRESPONSE;
510 }
511 DCT3_DecodeSMSFrame(s, &Data->GetSMSMessage->SMS[0],msg.Buffer+8);
512 return ERR_NONE;
513 case 0x09:
514 switch (msg.Buffer[4]) {
515 case 0x00:
516 smprintf(s, "Unknown. Probably phone too busy\n");
517 return ERR_UNKNOWN;
518 case 0x02:
519 smprintf(s, "Too high location ?\n");
520 return ERR_INVALIDLOCATION;
521 case 0x06:
522 smprintf(s, "Phone is OFF\n");
523 return ERR_PHONEOFF;
524 case 0x07:
525 smprintf(s, "Empty\n");
526 return ERR_EMPTY;
527 case 0x0c:
528 smprintf(s, "Access error. No PIN ?\n");
529 return ERR_SECURITYERROR;
530 default:
531 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
532 }
533 }
534 return ERR_UNKNOWNRESPONSE;
535}
536
537static GSM_Error N6110_GetSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
538{
539 unsigned char req[] = {N6110_FRAME_HEADER, 0x07, 0x02,
540 0x00, /* Location */
541 0x01, 0x64};
542
543 if (sms->SMS[0].Folder!=0x00) return ERR_NOTSUPPORTED;
544
545 req[5] = sms->SMS[0].Location;
546
547 s->Phone.Data.GetSMSMessage=sms;
548 smprintf(s, "Getting sms\n");
549 return GSM_WaitFor (s, req, 8, 0x02, 4, ID_GetSMSMessage);
550}
551
552static GSM_Error N6110_GetNextSMSMessage(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, bool start)
553{
554 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
555 GSM_Error error;
556
557 if (start) {
558 error=s->Phone.Functions->GetSMSStatus(s,&Priv->LastSMSStatus);
559 if (error!=ERR_NONE) return error;
560 Priv->LastSMSRead=0;
561 sms->SMS[0].Location=0;
562 }
563 while (true) {
564 sms->SMS[0].Location++;
565 if (Priv->LastSMSRead>=(Priv->LastSMSStatus.SIMUsed+Priv->LastSMSStatus.PhoneUsed+Priv->LastSMSStatus.TemplatesUsed)) return ERR_EMPTY;
566 error=s->Phone.Functions->GetSMS(s, sms);
567 if (error==ERR_NONE) {
568 Priv->LastSMSRead++;
569 break;
570 }
571 if (error != ERR_EMPTY) return error;
572 }
573 return error;
574}
575
576static GSM_Error N6110_ReplyGetStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
577{
578 GSM_Phone_Data *Data = &s->Phone.Data;
579
580#ifdef DEBUG
581 smprintf(s, "Phone status received :\n");
582 smprintf(s, "Mode : ");
583 switch (msg.Buffer[4]) {
584 case 0x01: smprintf(s, "registered within the network\n"); break;
585 case 0x02: smprintf(s, "call in progress\n"); break; /* ringing or already answered call */
586 case 0x03: smprintf(s, "waiting for security code\n"); break;
587 case 0x04: smprintf(s, "powered off\n"); break;
588 default : smprintf(s, "unknown\n");
589 }
590 smprintf(s, "Power source : ");
591 switch (msg.Buffer[7]) {
592 case 0x01: smprintf(s, "AC/DC\n"); break;
593 case 0x02: smprintf(s, "battery\n"); break;
594 default : smprintf(s, "unknown\n");
595 }
596 smprintf(s, "Battery Level : %d\n", msg.Buffer[8]);
597 smprintf(s, "Signal strength : %d\n", msg.Buffer[5]);
598#endif
599
600 switch (Data->RequestID) {
601 case ID_GetBatteryCharge:
602 Data->BatteryCharge->BatteryPercent = ((int)msg.Buffer[8])*25;
603 switch (msg.Buffer[7]) {
604 case 0x01: Data->BatteryCharge->ChargeState = GSM_BatteryConnected; break;
605 case 0x02: Data->BatteryCharge->ChargeState = GSM_BatteryPowered; break;
606 default : Data->BatteryCharge->ChargeState = 0;
607 }
608 return ERR_NONE;
609 case ID_GetSignalQuality:
610 Data->SignalQuality->SignalPercent = ((int)msg.Buffer[5])*25;
611 return ERR_NONE;
612 default:
613 return ERR_UNKNOWNRESPONSE;
614 }
615}
616
617static GSM_Error N6110_GetStatus(GSM_StateMachine *s, int ID)
618{
619 unsigned char req[] = {N6110_FRAME_HEADER, 0x01};
620
621 return GSM_WaitFor (s, req, 4, 0x04, 4, ID);
622}
623
624static GSM_Error N6110_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
625{
626 char value[100];
627 GSM_Error error;
628
629 sig->BitErrorRate = -1;
630 sig->SignalStrength = -1; /* TODO for netmon */
631
632 smprintf(s, "Getting network level\n");
633 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_POWER_BATT)) {
634 error = DCT3_Netmonitor(s, 1, value);
635 if (error!=ERR_NONE) return error;
636 sig->SignalPercent = 100;
637 if (value[4]!='-') {
638 if (value[5]=='9' && value[6]>'4') sig->SignalPercent = 25;
639 if (value[5]=='9' && value[6]<'5') sig->SignalPercent = 50;
640 if (value[5]=='8' && value[6]>'4') sig->SignalPercent = 75;
641 } else sig->SignalPercent = 0;
642 return ERR_NONE;
643 } else {
644 s->Phone.Data.SignalQuality = sig;
645 return N6110_GetStatus(s, ID_GetSignalQuality);
646 }
647}
648
649static GSM_Error N6110_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
650{
651 char value[100];
652 GSM_Error error;
653
654 smprintf(s, "Getting battery level\n");
655 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_POWER_BATT)) {
656 error = DCT3_Netmonitor(s, 23, value);
657 if (error!=ERR_NONE) return error;
658 bat->BatteryPercent = 100;
659 bat->ChargeState = 0;
660 if (value[29]=='7') bat->BatteryPercent = 75;
661 if (value[29]=='5') bat->BatteryPercent = 50;
662 if (value[29]=='2') bat->BatteryPercent = 25;
663 return ERR_NONE;
664 } else {
665 s->Phone.Data.BatteryCharge = bat;
666 return N6110_GetStatus(s, ID_GetBatteryCharge);
667 }
668}
669
670static GSM_Error N6110_ReplySaveSMSMessage(GSM_Protocol_Message msg, GSM_StateMachine *s)
671{
672 GSM_Phone_Data *Data = &s->Phone.Data;
673
674 smprintf(s, "SMS message saving status\n");
675 switch (msg.Buffer[3]) {
676 case 0x05:
677 smprintf(s, "Saved at location %i\n",msg.Buffer[5]);
678 Data->SaveSMSMessage->Location=msg.Buffer[5];
679 return ERR_NONE;
680 case 0x06:
681 switch (msg.Buffer[4]) {
682 case 0x02:
683 smprintf(s, "All locations busy\n");
684 return ERR_FULL;
685 case 0x03:
686 smprintf(s, "Too high ?\n");
687 return ERR_INVALIDLOCATION;
688 default:
689 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
690 }
691 }
692 return ERR_UNKNOWNRESPONSE;
693}
694
695static GSM_Error N6110_PrivSetSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
696{
697 int length;
698 GSM_Error error;
699 unsigned char req[256] = {N6110_FRAME_HEADER, 0x04,
700 0x00, /* SMS status */
701 0x02,
702 0x00, /* SMS location */
703 0x02}; /* SMS type */
704
705 req[6] = sms->Location;
706 if (sms->Folder==1) { /* Inbox */
707 req[4] = 1; /* SMS status - GSM_Read */
708 req[7] = 0x00; /* SMS type */
709 sms->PDU = SMS_Deliver;
710 error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSDeliver,&length,true);
711 } else { /* Outbox */
712 req[4] = 5; /* SMS status - GSM_Sent */
713 req[7] = 0x02; /* SMS type */
714 sms->PDU = SMS_Submit;
715 error=PHONE_EncodeSMSFrame(s,sms,req+8,PHONE_SMSSubmit,&length,true);
716 }
717 if (error != ERR_NONE) return error;
718
719 /* SMS State - GSM_Read -> GSM_Unread and GSM_Sent -> GSM_UnSent */
720 if (sms->State == SMS_UnSent || sms->State == SMS_UnRead) req[4] |= 0x02;
721
722 s->Phone.Data.SaveSMSMessage=sms;
723 smprintf(s, "Saving sms\n");
724 return GSM_WaitFor (s, req, 8+length, 0x14, 4, ID_SaveSMSMessage);
725}
726
727static GSM_Error N6110_SetSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
728{
729 if (sms->Location == 0) return ERR_INVALIDLOCATION;
730 return N6110_PrivSetSMSMessage(s, sms);
731}
732
733static GSM_Error N6110_AddSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
734{
735 sms->Location = 0;
736 return N6110_PrivSetSMSMessage(s, sms);
737}
738
739static GSM_Error N6110_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
740{
741 switch (msg.Buffer[3]) {
742 case 0x37:
743 smprintf(s, "Ringtone set OK\n");
744 return ERR_NONE;
745 break;
746 case 0x38:
747 smprintf(s, "Error setting ringtone\n");
748 switch (msg.Buffer[4]) {
749 case 0x7d:
750 smprintf(s, "Too high location ?\n");
751 return ERR_INVALIDLOCATION;
752 default:
753 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
754 }
755 }
756 return ERR_UNKNOWNRESPONSE;
757}
758
759static GSM_Error N6110_ReplySetBinRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
760{
761 switch (msg.Buffer[4]) {
762 case 0x00:
763 smprintf(s, "Set at location %i\n",msg.Buffer[3]+1);
764 return ERR_NONE;
765 default:
766 smprintf(s, "Invalid location. Too high ?\n");
767 return ERR_INVALIDLOCATION;
768 }
769}
770
771static GSM_Error N6110_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength)
772{
773 GSM_NetworkInfo NetInfo;
774 GSM_Error error;
775 int size=200,current=8;
776 GSM_UDHHeader UDHHeader;
777 unsigned char req[1000] = {N6110_FRAME_HEADER, 0x36,
778 0x00, /* Location */
779 0x00,0x78};
780 unsigned char reqBin[1000] = {0x00,0x01,0xa0,0x00,0x00,0x0c,0x01,0x2c};
781
782 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NORING)) return ERR_NOTSUPPORTED;
783 if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
784
785 switch (Ringtone->Format) {
786 case RING_NOTETONE:
787 if (Ringtone->Location==255) {
788 /* Only 6110, 6130 and 6150 support it */
789 if (strcmp(s->Phone.Data.Model,"NSE-3") == 0 || strcmp(s->Phone.Data.Model,"NSK-3") == 0 ||
790 strcmp(s->Phone.Data.Model,"NSM-1") == 0) {
791 req[0] = 0x0c;
792 req[1] = 0x01;
793 UDHHeader.Type = UDH_NokiaRingtone;
794 GSM_EncodeUDHHeader(&UDHHeader);
795 /* We copy UDH now */
796 memcpy(req+2,UDHHeader.Text,UDHHeader.Length);
797 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+2+UDHHeader.Length, &size);
798 error = s->Protocol.Functions->WriteMessage(s, req, 2+UDHHeader.Length+size, 0x12);
799 if (error!=ERR_NONE) return error;
800 my_sleep(1000);
801 /* We have to make something (not important, what) now */
802 /* no answer from phone*/
803 return DCT3_GetNetworkInfo(s,&NetInfo);
804 } else {
805 return ERR_NOTSUPPORTED;
806 }
807 }
808 *maxlength=GSM_EncodeNokiaRTTLRingtone(*Ringtone, req+7, &size);
809 req[4] = Ringtone->Location - 1;
810 smprintf(s, "Setting ringtone\n");
811 return GSM_WaitFor (s, req, 7 + size, 0x05, 4, ID_SetRingtone);
812 case RING_NOKIABINARY:
813 error=DCT3_EnableSecurity (s, 0x01);
814 if (error!=ERR_NONE) return error;
815 memcpy(reqBin+current,DecodeUnicodeString(Ringtone->Name),UnicodeLength(Ringtone->Name));
816 current += UnicodeLength(Ringtone->Name);
817 reqBin[current++] = 0x00;
818 reqBin[current++] = 0x00;
819 reqBin[current++] = 0x00;/*xxx*/
820 memcpy(reqBin+current,Ringtone->NokiaBinary.Frame,Ringtone->NokiaBinary.Length);
821 current=current+Ringtone->NokiaBinary.Length;
822 reqBin[3]=Ringtone->Location-1;
823 if (!strcmp(s->Phone.Data.ModelInfo->model,"3210")) reqBin[5]=0x10;
824 smprintf(s, "Setting binary ringtone\n");
825 return GSM_WaitFor (s, reqBin, current, 0x40, 4, ID_SetRingtone);
826 case RING_MIDI:
827 return ERR_NOTSUPPORTED;
828 }
829 return ERR_NOTSUPPORTED;
830}
831
832static GSM_Error N6110_ReplyGetOpLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
833{
834 int count=5;
835 GSM_Phone_Data *Data = &s->Phone.Data;
836
837 smprintf(s, "Operator logo received\n");
838 NOKIA_DecodeNetworkCode(msg.Buffer+count,Data->Bitmap->NetworkCode);
839 count = count + 3;
840 smprintf(s, "Network code : %s\n", Data->Bitmap->NetworkCode);
841 smprintf(s, "Network name for Gammu : %s ",
842 DecodeUnicodeString(GSM_GetNetworkName(Data->Bitmap->NetworkCode)));
843 smprintf(s, "(%s)\n",DecodeUnicodeString(GSM_GetCountryName(Data->Bitmap->NetworkCode)));
844
845 count = count + 3; /* We ignore size */
846 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
847 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
848 count++;
849 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo,msg.Buffer+count,Data->Bitmap);
850 return ERR_NONE;
851}
852
853static GSM_Error N6110_ReplyGetStartup(GSM_Protocol_Message msg, GSM_StateMachine *s)
854{
855 int i, count = 5;
856 GSM_Phone_Data *Data = &s->Phone.Data;
857
858 smprintf(s, "Startup logo & notes received\n");
859 for (i=0;i<msg.Buffer[4];i++) {
860 switch (msg.Buffer[count++]) {
861 case 0x01:
862 smprintf(s, "Startup logo\n");
863 if (Data->Bitmap->Type == GSM_StartupLogo) {
864 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
865 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
866 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, msg.Buffer + count, Data->Bitmap);
867 } else {
868 count = count + 2;
869 }
870 count = count + PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0);
871 break;
872 case 0x02:
873 smprintf(s, "Welcome note\n");
874 if (Data->Bitmap->Type == GSM_WelcomeNote_Text) {
875 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
876 smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
877 }
878 count = count + msg.Buffer[count] + 1;
879 break;
880 case 0x03:
881 smprintf(s, "Dealer welcome note\n");
882 if (Data->Bitmap->Type == GSM_DealerNote_Text) {
883 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count, msg.Buffer[count]);
884 smprintf(s, "Text is \"%s\"\n",Data->Bitmap->Text);
885 }
886 count = count + msg.Buffer[count] + 1;
887 break;
888 default:
889 smprintf(s, "Unknown block\n");
890 return ERR_UNKNOWNRESPONSE;
891 break;
892 }
893 }
894 return ERR_NONE;
895}
896
897static GSM_Error N6110_ReplyGetCallerLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
898{
899 int count;
900 GSM_Phone_Data *Data = &s->Phone.Data;
901
902 switch (msg.Buffer[3]) {
903 case 0x11:
904 smprintf(s, "Caller group info received\n");
905 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+6,msg.Buffer[5]);
906 smprintf(s, "Name : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
907 Data->Bitmap->DefaultName = false;
908 if (msg.Buffer[5] == 0x00) Data->Bitmap->DefaultName = true;
909 count = msg.Buffer[5] + 6;
910 Data->Bitmap->RingtoneID = msg.Buffer[count++];
911 Data->Bitmap->DefaultRingtone = false;
912 Data->Bitmap->FileSystemRingtone = false;
913 if (Data->Bitmap->RingtoneID == 16) Data->Bitmap->DefaultRingtone = true;
914 smprintf(s, "Ringtone ID: %02x\n",Data->Bitmap->RingtoneID);
915 Data->Bitmap->BitmapEnabled=(msg.Buffer[count++]==1);
916#ifdef DEBUG
917 smprintf(s, "Caller group logo ");
918 if (Data->Bitmap->BitmapEnabled) {
919 smprintf(s, "enabled\n");
920 } else {
921 smprintf(s, "disabled\n");
922 }
923#endif
924 count = count + 3; /* We ignore size */
925 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
926 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
927 count++;
928 PHONE_DecodeBitmap(GSM_NokiaCallerLogo,msg.Buffer+count,Data->Bitmap);
929 Data->Bitmap->DefaultBitmap = false;
930 return ERR_NONE;
931 case 0x12:
932 smprintf(s, "Error getting caller group info\n");
933 return ERR_INVALIDLOCATION;
934 }
935 return ERR_UNKNOWNRESPONSE;
936}
937
938static GSM_Error N6110_ReplyGetSetPicture(GSM_Protocol_Message msg, GSM_StateMachine *s)
939{
940 int count = 5, i;
941 GSM_Phone_Data *Data = &s->Phone.Data;
942
943 switch (msg.Buffer[3]) {
944 case 0x02:
945 smprintf(s, "Picture Image received\n");
946 if (msg.Buffer[count]!=0) {
947 GSM_UnpackSemiOctetNumber(Data->Bitmap->Sender, msg.Buffer + 5, true);
948 /* Convert number of semioctets to number of chars */
949 i = msg.Buffer[5];
950 if (i % 2) i++;
951 i=i / 2 + 1;
952 count = count + i + 1;
953 } else {
954 Data->Bitmap->Sender[0] = 0x00;
955 Data->Bitmap->Sender[1] = 0x00;
956 count+=2;
957 }
958 smprintf(s, "Sender : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Sender));
959 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPICTUREUNI) ||
960 (!strcmp(Data->Model,"NHM-5") && Data->VerNum < 5.79)) {
961 count++;
962 EncodeUnicode(Data->Bitmap->Text,msg.Buffer+count+1,msg.Buffer[count]);
963 count += UnicodeLength(Data->Bitmap->Text) + 1;
964 } else {
965 if (!strcmp(Data->Model,"NHM-5")) {
966 i = msg.Buffer[count] * 256 + msg.Buffer[count+1];
967 } else {
968 /* 3410 4.26 */
969 i = msg.Buffer[count] * 256 + msg.Buffer[count+1] - 2;
970 count += 2;
971 }
972 memcpy(Data->Bitmap->Text,msg.Buffer+count+2,i);
973 Data->Bitmap->Text[i] = 0;
974 Data->Bitmap->Text[i+1] = 0;
975 count += i + 2;
976 }
977 smprintf(s, "Text : \"%s\"\n",DecodeUnicodeString(Data->Bitmap->Text));
978 Data->Bitmap->BitmapWidth = msg.Buffer[count++];
979 Data->Bitmap->BitmapHeight = msg.Buffer[count++];
980 PHONE_DecodeBitmap(GSM_NokiaPictureImage, msg.Buffer + count + 2, Data->Bitmap);
981#ifdef DEBUG
982 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,Data->Bitmap);
983#endif
984 return ERR_NONE;
985 break;
986 case 0x04:
987 smprintf(s, "Picture Image set OK\n");
988 return ERR_NONE;
989 case 0x05:
990 smprintf(s, "Can't set Picture Image - invalid location ?\n");
991 return ERR_INVALIDLOCATION;
992 break;
993 case 0x06:
994 smprintf(s, "Can't get Picture Image - invalid location ?\n");
995 return ERR_INVALIDLOCATION;
996 break;
997 }
998 return ERR_UNKNOWNRESPONSE;
999}
1000
1001static GSM_Error N6110_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
1002{
1003 GSM_Error error;
1004 unsigned char req[10] = {N6110_FRAME_HEADER};
1005
1006 s->Phone.Data.Bitmap=Bitmap;
1007 switch (Bitmap->Type) {
1008 case GSM_StartupLogo:
1009 case GSM_WelcomeNote_Text:
1010 case GSM_DealerNote_Text:
1011 if (Bitmap->Type == GSM_StartupLogo && IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTUP)) return ERR_NOTSUPPORTED;
1012 req[3] = 0x16;
1013 return GSM_WaitFor (s, req, 4, 0x05, 4, ID_GetBitmap);
1014 case GSM_CallerGroupLogo:
1015 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLER)) return ERR_NOTSUPPORTED;
1016 req[3] = 0x10;
1017 req[4] = Bitmap->Location - 1;
1018 error = GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetBitmap);
1019 if (error==ERR_NONE) NOKIA_GetDefaultCallerGroupName(s,Bitmap);
1020 return error;
1021 case GSM_OperatorLogo:
1022 req[3] = 0x33;
1023 req[4] = 0x01;
1024 return GSM_WaitFor (s, req, 5, 0x05, 4, ID_GetBitmap);
1025 case GSM_PictureImage:
1026 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOPICTURE)) return ERR_NOTSUPPORTED;
1027 req[3] = 0x01;
1028 req[4] = Bitmap->Location - 1;
1029 return GSM_WaitFor (s, req, 5, 0x47, 4, ID_GetBitmap);
1030 default:
1031 break;
1032 }
1033 return ERR_NOTSUPPORTED;
1034}
1035
1036static GSM_Error N6110_ReplySetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1037{
1038 switch (msg.Buffer[3]) {
1039 case 0x11:
1040 smprintf(s, "Feature of profile set\n");
1041 return ERR_NONE;
1042 case 0x12:
1043 smprintf(s, "Error setting profile feature\n");
1044 return ERR_NOTSUPPORTED;
1045 }
1046 return ERR_UNKNOWNRESPONSE;
1047}
1048
1049static GSM_Error N6110_SetProfileFeature(GSM_StateMachine *s, unsigned char profile, unsigned char feature, unsigned char value)
1050{
1051 unsigned char req[] = {N6110_FRAME_HEADER, 0x10, 0x01,
1052 0x00, /* Profile */
1053 0x00, /* Feature */
1054 0x00}; /* Value */
1055
1056 req[5]=profile;
1057 req[6]=feature;
1058 req[7]=value;
1059 smprintf(s, "Setting profile feature\n");
1060 return GSM_WaitFor (s, req, 8, 0x05, 4, ID_SetProfile);
1061}
1062
1063static GSM_Error N6110_ReplySetStartup(GSM_Protocol_Message msg, GSM_StateMachine *s)
1064{
1065 smprintf(s, "Startup logo set OK\n");
1066 return ERR_NONE;
1067}
1068
1069static GSM_Error N6110_ReplySetCallerLogo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1070{
1071 switch (msg.Buffer[3]) {
1072 case 0x14:
1073 smprintf(s, "Caller group set OK\n");
1074 return ERR_NONE;
1075 case 0x15:
1076 smprintf(s, "Error setting caller group\n");
1077 return ERR_INVALIDLOCATION;
1078 }
1079 return ERR_UNKNOWNRESPONSE;
1080}
1081
1082static GSM_Error N6110_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
1083{
1084 unsigned char reqPreview[1000] = {0x0c,0x01};
1085 unsigned char req[600] = {N6110_FRAME_HEADER};
1086 GSM_UDH UDHType = UDH_NokiaOperatorLogo;
1087 int count = 0, textlen, Width, Height;
1088 GSM_UDHHeader UDHHeader;
1089 GSM_NetworkInfo NetInfo;
1090 GSM_Error error;
1091
1092 switch (Bitmap->Type) {
1093 case GSM_CallerGroupLogo:
1094 case GSM_OperatorLogo:
1095 if (Bitmap->Location == 255) {
1096 /* Only 6110, 6130 and 6150 support it */
1097 if (strcmp(s->Phone.Data.Model,"NSE-3") == 0 || strcmp(s->Phone.Data.Model,"NSK-3") == 0 ||
1098 strcmp(s->Phone.Data.Model,"NSM-1") == 0) {
1099 if (Bitmap->Type==GSM_CallerGroupLogo) UDHType = UDH_NokiaCallerLogo;
1100 UDHHeader.Type = UDHType;
1101 GSM_EncodeUDHHeader(&UDHHeader);
1102 /* We copy UDH now */
1103 memcpy(reqPreview+2,UDHHeader.Text,UDHHeader.Length);
1104 count = count + UDHHeader.Length;
1105 if (Bitmap->Type == GSM_OperatorLogo) {
1106 NOKIA_EncodeNetworkCode(reqPreview+count,Bitmap->NetworkCode);
1107 count = count + 3;
1108 } else {
1109 if (Bitmap->DefaultBitmap) {
1110 Bitmap->BitmapWidth = 72;
1111 Bitmap->BitmapHeight = 14;
1112 GSM_ClearBitmap(Bitmap);
1113 }
1114 }
1115 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo,Bitmap,reqPreview, &count);
1116 reqPreview[count]=0x00;
1117 error = s->Protocol.Functions->WriteMessage(s, reqPreview, count + 1, 0x12);
1118 if (error!=ERR_NONE) return error;
1119 my_sleep(1000);
1120 /* We have to make something (not important, what) now */
1121 /* no answer from phone*/
1122 return DCT3_GetNetworkInfo(s,&NetInfo);
1123 } else {
1124 smprintf(s, "%s\n",s->Phone.Data.Model);
1125 return ERR_NOTSUPPORTED;
1126 }
1127 }
1128 break;
1129 default:
1130 break;
1131 }
1132
1133 count = 3;
1134
1135 switch (Bitmap->Type) {
1136 case GSM_StartupLogo:
1137 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTUP)) return ERR_NOTSUPPORTED;
1138 if (Bitmap->Location != 1) {
1139 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTANI)) return ERR_NOTSUPPORTED;
1140 }
1141 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOSTARTANI)) {
1142 if (!strcmp(s->Phone.Data.ModelInfo->model,"3210")) {
1143 error = N6110_SetProfileFeature(s,0,0x2e,((unsigned char)(Bitmap->Location-1)));
1144 } else {
1145 error = N6110_SetProfileFeature(s,0,0x29,((unsigned char)(Bitmap->Location-1)));
1146 }
1147 if (error == ERR_NOTSUPPORTED) error = ERR_SECURITYERROR;
1148 if (error != ERR_NONE) return error;
1149 if (Bitmap->Location != 1) return ERR_NONE;
1150 }
1151 req[count++] = 0x18;
1152 req[count++] = 0x01; /* One block */
1153 req[count++] = 0x01;
1154 PHONE_GetBitmapWidthHeight(GSM_NokiaStartupLogo, &Width, &Height);
1155 req[count++] = Height;
1156 req[count++] = Width;
1157 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, req + count, Bitmap);
1158 count = count + PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0);
1159 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1160 case GSM_WelcomeNote_Text:
1161 case GSM_DealerNote_Text:
1162 req[count++] = 0x18;
1163 req[count++] = 0x01; /* One block */
1164 if (Bitmap->Type == GSM_WelcomeNote_Text) {
1165 req[count++] = 0x02;
1166 } else {
1167 req[count++] = 0x03;
1168 }
1169 textlen = UnicodeLength(Bitmap->Text);
1170 req[count++] = textlen;
1171 memcpy(req + count,DecodeUnicodeString(Bitmap->Text),textlen);
1172 count += textlen;
1173 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1174 case GSM_CallerGroupLogo:
1175 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOCALLER)) return ERR_NOTSUPPORTED;
1176 req[count++] = 0x13;
1177 req[count++] = Bitmap->Location - 1;
1178 if (Bitmap->DefaultName) {
1179 req[count++] = 0;
1180 } else {
1181 textlen = UnicodeLength(Bitmap->Text);
1182 req[count++] = textlen;
1183 memcpy(req+count,DecodeUnicodeString(Bitmap->Text),textlen);
1184 count += textlen;
1185 }
1186 if (Bitmap->DefaultRingtone) {
1187 req[count++] = 16;
1188 } else {
1189 req[count++] = Bitmap->RingtoneID;
1190 }
1191 /* Value here is number of phone menu connected
1192 * with caller logo in Nokia 61x0: 0x00 = Off, 0x01 = On,
1193 * 0x02 = View Graphics, 0x03 = Send Graphics,
1194 * 0x04 = Send via IR. For higher menu option connected with
1195 * caller logo is not displayed
1196 */
1197 if (Bitmap->DefaultBitmap) {
1198 Bitmap->BitmapWidth = 72;
1199 Bitmap->BitmapHeight = 14;
1200 GSM_ClearBitmap(Bitmap);
1201 req[count++] = 0;
1202 } else {
1203 if (Bitmap->BitmapEnabled) req[count++] = 0x01; else req[count++] = 0x00;
1204 }
1205 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) / 256;
1206 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) % 256;
1207 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, Bitmap, req, &count);
1208 return GSM_WaitFor (s, req, count, 0x03, 4, ID_SetBitmap);
1209 case GSM_OperatorLogo:
1210 req[count++] = 0x30;
1211 req[count++] = 0x01;
1212 NOKIA_EncodeNetworkCode(req+count, Bitmap->NetworkCode);
1213 count = count + 3;
1214 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaOperatorLogo,0,0) + 4) / 256;
1215 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaOperatorLogo,0,0) + 4) % 256;
1216 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, Bitmap, req, &count);
1217 return GSM_WaitFor (s, req, count, 0x05, 4, ID_SetBitmap);
1218 case GSM_PictureImage:
1219 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NOPICTURE)) return ERR_NOTSUPPORTED;
1220 req[count++] = 0x03;
1221 req[count++] = Bitmap->Location - 1;
1222 if (Bitmap->Sender[0]!=0 || Bitmap->Sender[1]!=0) {
1223 req[count]=GSM_PackSemiOctetNumber(Bitmap->Sender, req+count+1,true);
1224 /* Convert number of semioctets to number of chars and add count */
1225 textlen = req[count];
1226 if (textlen % 2) textlen++;
1227 count += textlen / 2 + 1;
1228 count++;
1229 } else {
1230 req[count++] = 0x00;
1231 req[count++] = 0x00;
1232 }
1233 req[count++] = 0x00;
1234 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPICTUREUNI) ||
1235 (!strcmp(s->Phone.Data.Model,"NHM-5") && s->Phone.Data.VerNum < 5.79)) {
1236 textlen = UnicodeLength(Bitmap->Text);
1237 req[count++] = textlen;
1238 memcpy(req+count,DecodeUnicodeString(Bitmap->Text),textlen);
1239 count += textlen;
1240 } else {
1241 textlen = UnicodeLength(Bitmap->Text)*2;
1242 if (!strcmp(s->Phone.Data.Model,"NHM-5")) {
1243 req[count++] = textlen;
1244 } else {
1245 /* 3410 4.26 */
1246 req[count++] = textlen+2;
1247 req[count++] = 0x00;
1248 req[count++] = 0x1e;
1249 }
1250 memcpy(req+count,Bitmap->Text,textlen);
1251 count += textlen;
1252 }
1253 NOKIA_CopyBitmap(GSM_NokiaPictureImage, Bitmap, req, &count);
1254 return GSM_WaitFor (s, req, count, 0x47, 4, ID_SetBitmap);
1255 default:
1256 break;
1257 }
1258 return ERR_NOTSUPPORTED;
1259}
1260
1261static GSM_Error N6110_ReplyCallInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
1262{
1263 GSM_Phone_Data *Data = &s->Phone.Data;
1264 int tmp, count;
1265 GSM_Call call;
1266
1267 call.CallIDAvailable = true;
1268 call.Status = 0;
1269 smprintf(s, "Call info, ");
1270 switch (msg.Buffer[3]) {
1271 case 0x02:
1272 smprintf(s, "Call established, waiting for answer\n");
1273 call.Status = GSM_CALL_CallEstablished;
1274 break;
1275 case 0x03:
1276 smprintf(s, "Call started\n");
1277 /* no phone number in frame */
1278 call.Status = GSM_CALL_CallStart;
1279 break;
1280 case 0x04:
1281 smprintf(s, "Remote end hang up\n");
1282 smprintf(s, "CC : %i\n",msg.Buffer[6]);
1283 call.Status = GSM_CALL_CallRemoteEnd;
1284 call.StatusCode = msg.Buffer[6];
1285 break;
1286 case 0x05:
1287 smprintf(s, "Incoming call\n");
1288 smprintf(s, "Number : \"");
1289 count=msg.Buffer[6];
1290 for (tmp=0; tmp <count; tmp++) smprintf(s, "%c", msg.Buffer[7+tmp]);
1291 smprintf(s, "\"\nName : \"");
1292 for (tmp=0; tmp<msg.Buffer[7+count]; tmp++) smprintf(s, "%c", msg.Buffer[8+count+tmp]);
1293 smprintf(s, "\"\n");
1294
1295 call.Status = GSM_CALL_IncomingCall;
1296 EncodeUnicode(call.PhoneNumber, msg.Buffer+7, msg.Buffer[6]);
1297 break;
1298 case 0x07:
1299 smprintf(s, "Call answer initiated\n");
1300 break;
1301 case 0x09:
1302 smprintf(s, "Call released\n");
1303 call.Status = GSM_CALL_CallLocalEnd;
1304 break;
1305 case 0x0a:
1306 smprintf(s, "Call is being released\n");
1307 break;
1308 case 0x23:
1309 smprintf(s, "Call held\n");
1310 call.Status = GSM_CALL_CallHeld;
1311 break;
1312 case 0x25:
1313 smprintf(s, "Call resumed\n");
1314 call.Status = GSM_CALL_CallResumed;
1315 break;
1316 case 0x27:
1317 smprintf(s, "Call switched\n");
1318 /* incorrect call id in frame - 6150 5.22 */
1319 call.CallIDAvailable = false;
1320 call.Status = GSM_CALL_CallSwitched;
1321 break;
1322 case 0x29:
1323 smprintf(s, "Joining call to the conference (conference)\n");
1324 break;
1325 case 0x2A:
1326 smprintf(s, "Removing call from the conference (split)\n");
1327 break;
1328 }
1329 if (call.CallIDAvailable) smprintf(s, "Call ID : %d\n",msg.Buffer[4]);
1330 if (Data->EnableIncomingCall && s->User.IncomingCall!=NULL && call.Status != 0) {
1331 if (call.CallIDAvailable) call.CallID = msg.Buffer[4];
1332 s->User.IncomingCall(s->CurrentConfig->Device, call);
1333 }
1334 if (s->Phone.Data.RequestID == ID_CancelCall) {
1335 if (msg.Buffer[3] == 0x09) {
1336 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1337 /* when we canceled call and see frame about other
1338 * call releasing, we don't give ERR_NONE for "our"
1339 * call release command
1340 */
1341 return ERR_NEEDANOTHERANSWER;
1342 }
1343 }
1344 if (s->Phone.Data.RequestID == ID_AnswerCall) {
1345 if (msg.Buffer[3] == 0x07) {
1346 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1347 return ERR_NEEDANOTHERANSWER;
1348 }
1349 }
1350 if (s->Phone.Data.RequestID == ID_UnholdCall) {
1351 if (msg.Buffer[3] == 0x25) {
1352 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1353 return ERR_NEEDANOTHERANSWER;
1354 }
1355 }
1356 if (s->Phone.Data.RequestID == ID_HoldCall) {
1357 if (msg.Buffer[3] == 0x23) {
1358 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1359 return ERR_NEEDANOTHERANSWER;
1360 }
1361 }
1362 if (s->Phone.Data.RequestID == ID_ConferenceCall) {
1363 if (msg.Buffer[3] == 0x29) {
1364 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1365 return ERR_NEEDANOTHERANSWER;
1366 }
1367 }
1368 if (s->Phone.Data.RequestID == ID_SplitCall) {
1369 if (msg.Buffer[3] == 0x2B) {
1370 if (s->Phone.Data.CallID == msg.Buffer[4]) return ERR_NONE;
1371 return ERR_NEEDANOTHERANSWER;
1372 }
1373 }
1374 return ERR_NONE;
1375}
1376
1377static GSM_Error N6110_DeleteSMSMessage(GSM_StateMachine *s, GSM_SMSMessage *sms)
1378{
1379 unsigned char req[] = {N6110_FRAME_HEADER, 0x0a, 0x02,
1380 0x00}; /* Location */
1381
1382 if (sms->Folder!=0x00) return ERR_NOTSUPPORTED;
1383
1384 req[5]=sms->Location;
1385
1386 smprintf(s, "Deleting sms\n");
1387 return GSM_WaitFor (s, req, 6, 0x14, 4, ID_DeleteSMSMessage);
1388}
1389
1390static GSM_Error N6110_ReplySetMemory(GSM_Protocol_Message msg, GSM_StateMachine *s)
1391{
1392 smprintf(s, "Reply for writing memory\n");
1393 switch (msg.Buffer[3]) {
1394 case 0x05:
1395 smprintf(s, "Done OK\n");
1396 return ERR_NONE;
1397 case 0x06:
1398 smprintf(s, "Error\n");
1399 switch (msg.Buffer[4]) {
1400 case 0x7d:
1401 smprintf(s, "Too high location ?\n");
1402 return ERR_INVALIDLOCATION;
1403 case 0x90:
1404 smprintf(s, "Too long name...or other error\n");
1405 return ERR_NOTSUPPORTED;
1406 default:
1407 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1408 }
1409 }
1410 return ERR_UNKNOWNRESPONSE;
1411}
1412
1413static GSM_Error N6110_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1414{
1415 int current, Group, Name, Number;
1416 unsigned char req[128] = {N6110_FRAME_HEADER, 0x04,
1417 0x00, /* memory type */
1418 0x00}; /* location */
1419
1420 if (entry->Location == 0) return ERR_NOTSUPPORTED;
1421
1422 GSM_PhonebookFindDefaultNameNumberGroup(entry, &Name, &Number, &Group);
1423
1424 req[4] = NOKIA_GetMemoryType(s, entry->MemoryType,N6110_MEMORY_TYPES);
1425 req[5] = entry->Location;
1426
1427 current = 7;
1428
1429 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOPBKUNICODE)) {
1430 if (Name != -1) {
1431 req[6] = UnicodeLength(entry->Entries[Name].Text);
1432 memcpy(req+current,DecodeUnicodeString(entry->Entries[Name].Text),UnicodeLength(entry->Entries[Name].Text));
1433 current += UnicodeLength(entry->Entries[Name].Text);
1434 } else req[6] = 0;
1435 } else {
1436 if (Name != -1) {
1437 req[6] = UnicodeLength(entry->Entries[Name].Text)*2+2;
1438 memcpy(req+current,entry->Entries[Name].Text,UnicodeLength(entry->Entries[Name].Text)*2);
1439 current += UnicodeLength(entry->Entries[Name].Text)*2;
1440 } else req[6] = 0;
1441 req[current++]=0x00;
1442 req[current++]=0x00;
1443 }
1444
1445 if (Number != -1) {
1446 req[current++]=UnicodeLength(entry->Entries[Number].Text);
1447 memcpy(req+current,DecodeUnicodeString(entry->Entries[Number].Text),UnicodeLength(entry->Entries[Number].Text));
1448 current += UnicodeLength(entry->Entries[Number].Text);
1449 } else req[current++] = 0;
1450
1451 /* This allow to save 14 characters name into SIM memory, when
1452 * no caller group is selected. */
1453 if (Group == -1) {
1454 req[current++] = 0xff;
1455 } else {
1456 req[current++] = entry->Entries[Group].Number-1;
1457 }
1458
1459 smprintf(s, "Writing phonebook entry\n");
1460 return GSM_WaitFor (s, req, current, 0x03, 4, ID_SetMemory);
1461}
1462
1463static GSM_Error N6110_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
1464{
1465 GSM_MemoryEntry dwa;
1466
1467 dwa.Location = entry->Location;
1468 dwa.MemoryType = entry->MemoryType;
1469 dwa.EntriesNum = 0;
1470
1471 return N6110_SetMemory(s, &dwa);
1472}
1473
1474static GSM_Error N6110_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s)
1475{
1476 GSM_Phone_Data *Data = &s->Phone.Data;
1477 char buffer[2000];
1478 GSM_Error error;
1479 int i,end,start;
1480
1481 smprintf(s, "Ringtone received\n");
1482 switch (msg.Buffer[4]) {
1483 case 0x00:
1484 switch (Data->Ringtone->Format) {
1485 case RING_NOTETONE:
1486 memcpy(buffer,msg.Buffer,msg.Length);
1487 i=7;
1488 if (buffer[9]==0x4a && buffer[10]==0x3a) i=8;
1489 buffer[i]=0x02;
1490 error=GSM_DecodeNokiaRTTLRingtone(Data->Ringtone, buffer+i, msg.Length-i);
1491 if (error!=ERR_NONE) return ERR_EMPTY;
1492 return ERR_NONE;
1493 case RING_NOKIABINARY:
1494 i=8;
1495 while (msg.Buffer[i]!=0) {
1496 i++;
1497 if (i>msg.Length) return ERR_EMPTY;
1498 }
1499 EncodeUnicode(Data->Ringtone->Name,msg.Buffer+8,i-8);
1500 smprintf(s, "Name \"%s\"\n",DecodeUnicodeString(Data->Ringtone->Name));
1501 /* Looking for start && end */
1502 end=0;start=0;i=0;
1503 while (true) {
1504 if (start!=0) {
1505 if (msg.Buffer[i]==0x07 && msg.Buffer[i+1]==0x0b) {
1506 end=i+2; break;
1507 }
1508 if (msg.Buffer[i]==0x0e && msg.Buffer[i+1]==0x0b) {
1509 end=i+2; break;
1510 }
1511 } else {
1512 if (msg.Buffer[i]==0x02 && msg.Buffer[i+1]==0xfc && msg.Buffer[i+2]==0x09) {
1513 start = i;
1514 }
1515 }
1516 i++;
1517 if (i==msg.Length-3) return ERR_EMPTY;
1518 }
1519 /* Copying frame */
1520 memcpy(Data->Ringtone->NokiaBinary.Frame,msg.Buffer+start,end-start);
1521 Data->Ringtone->NokiaBinary.Length=end-start;
1522#ifdef DEBUG
1523 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, Data->Ringtone->NokiaBinary.Frame, Data->Ringtone->NokiaBinary.Length);
1524#endif
1525 return ERR_NONE;
1526 case RING_MIDI:
1527 return ERR_NOTSUPPORTED;
1528 }
1529 smprintf(s, "Ringtone format is %i\n",Data->Ringtone->Format);
1530 break;
1531 default:
1532 smprintf(s, "Invalid location. Too high ?\n");
1533 return ERR_INVALIDLOCATION;
1534 }
1535 return ERR_UNKNOWNRESPONSE;
1536}
1537
1538static GSM_Error N6110_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone)
1539{
1540 GSM_Error error;
1541 unsigned char req[] = {0x00, 0x01, 0x9e,
1542 0x00}; /* location */
1543
1544 if (PhoneRingtone) return ERR_NOTSUPPORTED;
1545 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_NORING)) return ERR_NOTSUPPORTED;
1546 if (Ringtone->Location == 0) return ERR_INVALIDLOCATION;
1547
1548 if (Ringtone->Format == 0x00) {
1549 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) {
1550 Ringtone->Format = RING_NOTETONE;
1551 } else {
1552 Ringtone->Format = RING_NOKIABINARY;
1553 }
1554 }
1555
1556 switch (Ringtone->Format) {
1557 case RING_NOTETONE:
1558 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
1559 break;
1560 case RING_NOKIABINARY:
1561 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_RING_SM)) return ERR_NOTSUPPORTED;
1562 break;
1563 case RING_MIDI:
1564 return ERR_NOTSUPPORTED;
1565 }
1566
1567 error=DCT3_EnableSecurity (s, 0x01);
1568 if (error!=ERR_NONE) return error;
1569
1570 req[3]=Ringtone->Location-1;
1571 s->Phone.Data.Ringtone=Ringtone;
1572 smprintf(s, "Getting (binary) ringtone\n");
1573 return GSM_WaitFor (s, req, 4, 0x40, 4, ID_GetRingtone);
1574}
1575
1576static GSM_Error N6110_ReplyGetSecurityStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1577{
1578 *s->Phone.Data.SecurityStatus = msg.Buffer[4];
1579
1580#ifdef DEBUG
1581 smprintf(s, "Security code status\n");
1582 switch(msg.Buffer[4]) {
1583 case SEC_SecurityCode: smprintf(s, "waiting for Security Code.\n"); break;
1584 case SEC_Pin : smprintf(s, "waiting for PIN.\n"); break;
1585 case SEC_Pin2 : smprintf(s, "waiting for PIN2.\n"); break;
1586 case SEC_Puk : smprintf(s, "waiting for PUK.\n"); break;
1587 case SEC_Puk2 : smprintf(s, "waiting for PUK2.\n"); break;
1588 case SEC_None : smprintf(s, "nothing to enter.\n"); break;
1589 default : smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1590 return ERR_UNKNOWNRESPONSE;
1591 }
1592#endif
1593 return ERR_NONE;
1594}
1595
1596static GSM_Error N6110_GetSecurityStatus(GSM_StateMachine *s, GSM_SecurityCodeType *Status)
1597{
1598 unsigned char req[4] = {N6110_FRAME_HEADER, 0x07};
1599
1600 s->Phone.Data.SecurityStatus=Status;
1601 smprintf(s, "Getting security code status\n");
1602 return GSM_WaitFor (s, req, 4, 0x08, 2, ID_GetSecurityStatus);
1603}
1604
1605static GSM_Error N6110_ReplyEnterSecurityCode(GSM_Protocol_Message msg, GSM_StateMachine *s)
1606{
1607 switch (msg.Buffer[3]) {
1608 case 0x0b:
1609 smprintf(s, "Security code OK\n");
1610 return ERR_NONE;
1611 case 0x0c:
1612 switch (msg.Buffer[4]) {
1613 case 0x88:
1614 smprintf(s, "Wrong code\n");
1615 return ERR_SECURITYERROR;
1616 case 0x8b:
1617 smprintf(s, "Not required\n");
1618 return ERR_NONE;
1619 default:
1620 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1621 }
1622 }
1623 return ERR_UNKNOWNRESPONSE;
1624}
1625
1626static GSM_Error N6110_EnterSecurityCode(GSM_StateMachine *s, GSM_SecurityCode Code)
1627{
1628 int len = 0;
1629 unsigned char req[15] = {N6110_FRAME_HEADER, 0x0a,
1630 0x00}; /* Type of code to enter */
1631
1632 req[4]=Code.Type;
1633
1634 len = strlen(Code.Code);
1635 memcpy(req+5,Code.Code,len);
1636 req[5+len]=0x00;
1637 req[6+len]=0x00;
1638
1639 smprintf(s, "Entering security code\n");
1640 return GSM_WaitFor (s, req, 7+len, 0x08, 4, ID_EnterSecurityCode);
1641}
1642
1643static GSM_Error N6110_ReplyGetSpeedDial(GSM_Protocol_Message msg, GSM_StateMachine *s)
1644{
1645 GSM_Phone_Data *Data = &s->Phone.Data;
1646
1647 switch (msg.Buffer[3]) {
1648 case 0x17:
1649 smprintf(s, "Speed dial received\n");
1650 switch (msg.Buffer[4]) {
1651 case 0x02:
1652 Data->SpeedDial->MemoryType = MEM_ME;
1653 smprintf(s, "ME ");
1654 break;
1655 case 0x03:
1656 Data->SpeedDial->MemoryType = MEM_SM;
1657 smprintf(s, "SIM ");
1658 break;
1659 default:
1660 smprintf(s, "ERROR: unknown %i\n",msg.Buffer[4]);
1661 return ERR_UNKNOWNRESPONSE;
1662 }
1663 Data->SpeedDial->MemoryLocation = msg.Buffer[5];
1664 if (msg.Buffer[5] == 0x00) Data->SpeedDial->MemoryLocation = Data->SpeedDial->Location;
1665 Data->SpeedDial->MemoryNumberID = 2;
1666 smprintf(s, "location %i\n",Data->SpeedDial->MemoryLocation);
1667 return ERR_NONE;
1668 case 0x18:
1669 smprintf(s, "Error getting speed dial. Invalid location\n");
1670 return ERR_INVALIDLOCATION;
1671 }
1672 return ERR_UNKNOWNRESPONSE;
1673}
1674
1675static GSM_Error N6110_GetSpeedDial(GSM_StateMachine *s, GSM_SpeedDial *SpeedDial)
1676{
1677 unsigned char req[] = {N6110_FRAME_HEADER, 0x16,
1678 0x01}; /* location */
1679
1680 req[4] = SpeedDial->Location;
1681
1682 s->Phone.Data.SpeedDial=SpeedDial;
1683 smprintf(s, "Getting speed dial\n");
1684 return GSM_WaitFor (s, req, 5, 0x03, 4, ID_GetSpeedDial);
1685}
1686
1687static GSM_Error N6110_ReplySendDTMF(GSM_Protocol_Message msg, GSM_StateMachine *s)
1688{
1689 switch (msg.Buffer[3]) {
1690 case 0x40:
1691 smprintf(s, "During sending DTMF\n");
1692 return ERR_NONE;
1693 case 0x51:
1694 smprintf(s, "DTMF sent OK\n");
1695 return ERR_NONE;
1696 }
1697 return ERR_UNKNOWNRESPONSE;
1698}
1699
1700static GSM_Error N6110_ReplyGetDisplayStatus(GSM_Protocol_Message msg, GSM_StateMachine *s)
1701{
1702 int i;
1703 GSM_Phone_Data *Data = &s->Phone.Data;
1704
1705 smprintf(s, "Display status received\n");
1706 if (Data->RequestID == ID_GetDisplayStatus) Data->DisplayFeatures->Number=0;
1707 for (i=0;i<msg.Buffer[4];i++) {
1708 if (msg.Buffer[2*i+6] == 0x02) {
1709#ifdef DEBUG
1710 switch (msg.Buffer[2*i+5]) {
1711 case 0x01: smprintf(s, "Call in progress\n"); break;
1712 case 0x02: smprintf(s, "Unknown\n"); break;
1713 case 0x03: smprintf(s, "Unread SMS\n"); break;
1714 case 0x04: smprintf(s, "Voice call\n"); break;
1715 case 0x05: smprintf(s, "Fax call active\n"); break;
1716 case 0x06: smprintf(s, "Data call active\n"); break;
1717 case 0x07: smprintf(s, "Keyboard lock\n"); break;
1718 case 0x08: smprintf(s, "SMS storage full\n"); break;
1719 }
1720#endif
1721 if (Data->RequestID == ID_GetDisplayStatus) {
1722 switch (msg.Buffer[2*i+5]) {
1723 case 0x01: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_CallActive;
1724 break;
1725 case 0x03: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_UnreadSMS;
1726 break;
1727 case 0x04: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_VoiceCall;
1728 break;
1729 case 0x05: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_FaxCall;
1730 break;
1731 case 0x06: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_DataCall;
1732 break;
1733 case 0x07: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_KeypadLocked;
1734 break;
1735 case 0x08: Data->DisplayFeatures->Feature[Data->DisplayFeatures->Number] = GSM_SMSMemoryFull;
1736 break;
1737 }
1738 if (msg.Buffer[2*i+5]!=0x02) Data->DisplayFeatures->Number++;
1739 }
1740 }
1741 }
1742 return ERR_NONE;
1743}
1744
1745static GSM_Error N6110_GetDisplayStatus(GSM_StateMachine *s, GSM_DisplayFeatures *features)
1746{
1747 unsigned char req[] = {N6110_FRAME_HEADER, 0x51};
1748
1749 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_DISPSTATUS)) return ERR_NOTSUPPORTED;
1750
1751 s->Phone.Data.DisplayFeatures = features;
1752 smprintf(s, "Getting display status\n");
1753 return GSM_WaitFor (s, req, 4, 0x0d, 4, ID_GetDisplayStatus);
1754}
1755
1756static GSM_Profile_PhoneTableValue Profile6110[] = {
1757 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x00},
1758 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x01},
1759 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x02},
1760 {Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0xff},
1761 {Profile_Lights, PROFILE_LIGHTS_OFF, 0x01,0x00},
1762 {Profile_Lights, PROFILE_LIGHTS_AUTO, 0x01,0x01},
1763 {Profile_CallAlert, PROFILE_CALLALERT_RINGING, 0x02,0x01},
1764 {Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE, 0x02,0x02},
1765 {Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x02,0x04},
1766 {Profile_CallAlert, PROFILE_CALLALERT_RINGONCE, 0x02,0x05},
1767 {Profile_CallAlert, PROFILE_CALLALERT_ASCENDING, 0x02,0x06},
1768 {Profile_CallAlert, PROFILE_CALLALERT_CALLERGROUPS,0x02,0x07},
1769 /* Ringtone ID */
1770 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x04,0x06},
1771 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x04,0x07},
1772 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x04,0x08},
1773 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x04,0x09},
1774 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x04,0x0a},
1775 {Profile_MessageTone, PROFILE_MESSAGE_NOTONE, 0x05,0x00},
1776 {Profile_MessageTone, PROFILE_MESSAGE_STANDARD, 0x05,0x01},
1777 {Profile_MessageTone, PROFILE_MESSAGE_SPECIAL, 0x05,0x02},
1778 {Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE, 0x05,0x03},
1779 {Profile_MessageTone, PROFILE_MESSAGE_ASCENDING, 0x05,0x04},
1780 {Profile_Vibration, PROFILE_VIBRATION_OFF, 0x06,0x00},
1781 {Profile_Vibration, PROFILE_VIBRATION_ON, 0x06,0x01},
1782 {Profile_WarningTone, PROFILE_WARNING_OFF, 0x07,0xff},
1783 {Profile_WarningTone, PROFILE_WARNING_ON, 0x07,0x04},
1784 /* Caller groups */
1785 {Profile_AutoAnswer, PROFILE_AUTOANSWER_OFF, 0x09,0x00},
1786 {Profile_AutoAnswer, PROFILE_AUTOANSWER_ON, 0x09,0x01},
1787 {0x00, 0x00, 0x00,0x00}
1788};
1789
1790static GSM_Profile_PhoneTableValue Profile3310[] = {
1791 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL1, 0x00,0x00},
1792 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL2, 0x00,0x01},
1793 {Profile_KeypadTone, PROFILE_KEYPAD_LEVEL3, 0x00,0x02},
1794 {Profile_KeypadTone, PROFILE_KEYPAD_OFF, 0x00,0xff},
1795 {Profile_CallAlert, PROFILE_CALLALERT_RINGING, 0x01,0x01},
1796 {Profile_CallAlert, PROFILE_CALLALERT_BEEPONCE, 0x01,0x02},
1797 {Profile_CallAlert, PROFILE_CALLALERT_OFF, 0x01,0x04},
1798 {Profile_CallAlert, PROFILE_CALLALERT_RINGONCE, 0x01,0x05},
1799 {Profile_CallAlert, PROFILE_CALLALERT_ASCENDING, 0x01,0x06},
1800 /* Ringtone ID */
1801 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL1, 0x03,0x06},
1802 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL2, 0x03,0x07},
1803 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL3, 0x03,0x08},
1804 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL4, 0x03,0x09},
1805 {Profile_RingtoneVolume, PROFILE_VOLUME_LEVEL5, 0x03,0x0a},
1806 {Profile_MessageTone, PROFILE_MESSAGE_NOTONE, 0x04,0x00},
1807 {Profile_MessageTone, PROFILE_MESSAGE_STANDARD, 0x04,0x01},
1808 {Profile_MessageTone, PROFILE_MESSAGE_SPECIAL, 0x04,0x02},
1809 {Profile_MessageTone, PROFILE_MESSAGE_BEEPONCE, 0x04,0x03},
1810 {Profile_MessageTone, PROFILE_MESSAGE_ASCENDING, 0x04,0x04},
1811 {Profile_MessageTone, PROFILE_MESSAGE_PERSONAL, 0x04,0x05},
1812 {Profile_Vibration, PROFILE_VIBRATION_OFF, 0x05,0x00},
1813 {Profile_Vibration, PROFILE_VIBRATION_ON, 0x05,0x01},
1814 {Profile_Vibration, PROFILE_VIBRATION_FIRST, 0x05,0x02},
1815 {Profile_WarningTone, PROFILE_WARNING_OFF, 0x06,0xff},
1816 {Profile_WarningTone, PROFILE_WARNING_ON, 0x06,0x04},
1817 {Profile_ScreenSaver, PROFILE_SAVER_OFF, 0x07,0x00},
1818 {Profile_ScreenSaver, PROFILE_SAVER_ON, 0x07,0x01},
1819 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_5SEC, 0x08,0x00},
1820 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_20SEC, 0x08,0x01},
1821 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_1MIN, 0x08,0x02},
1822 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_2MIN, 0x08,0x03},
1823 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_5MIN, 0x08,0x04},
1824 {Profile_ScreenSaverTime,PROFILE_SAVER_TIMEOUT_10MIN, 0x08,0x05},
1825 {0x00, 0x00, 0x00,0x00}
1826};
1827
1828static GSM_Error N6110_ReplyGetProfileFeature(GSM_Protocol_Message msg, GSM_StateMachine *s)
1829{
1830 GSM_Phone_Data *Data = &s->Phone.Data;
1831
1832 switch (msg.Buffer[3]) {
1833 case 0x14:
1834 smprintf(s, "Profile feature %02x with value %02x\n",msg.Buffer[6],msg.Buffer[8]);
1835 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1836 switch (msg.Buffer[6]) {
1837 case 0x02:
1838 smprintf(s, "Ringtone ID\n");
1839 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_RingtoneID;
1840 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8];
1841 Data->Profile->FeaturesNumber++;
1842 break;
1843 case 0x09 :
1844 smprintf(s, "screen saver number\n");
1845 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_ScreenSaverNumber;
1846 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8] + 1;
1847 Data->Profile->FeaturesNumber++;
1848 break;
1849 case 0x24:
1850 smprintf(s, "selected profile\n");
1851 if (msg.Buffer[8] + 1 == Data->Profile->Location) Data->Profile->Active = true;
1852 break;
1853 default:
1854 NOKIA_FindFeatureValue(s, Profile3310,msg.Buffer[6],msg.Buffer[8],Data,false);
1855 }
1856 return ERR_NONE;
1857 }
1858 switch (msg.Buffer[6]) {
1859 case 0x01: /* Lights */
1860 if (Data->Profile->CarKitProfile) {
1861 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1862 }
1863 break;
1864 case 0x03:
1865 smprintf(s, "Ringtone ID\n");
1866 Data->Profile->FeatureID [Data->Profile->FeaturesNumber] = Profile_RingtoneID;
1867 Data->Profile->FeatureValue [Data->Profile->FeaturesNumber] = msg.Buffer[8];
1868 Data->Profile->FeaturesNumber++;
1869 break;
1870 case 0x08: /* Caller groups */
1871 if (!IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1872 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,true);
1873 }
1874 break;
1875 case 0x09: /* Autoanswer */
1876 if (Data->Profile->CarKitProfile || Data->Profile->HeadSetProfile) {
1877 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1878 }
1879 break;
1880 case 0x2A:
1881 smprintf(s, "selected profile\n");
1882 if (msg.Buffer[8] + 1 == Data->Profile->Location) Data->Profile->Active = true;
1883 break;
1884 default:
1885 NOKIA_FindFeatureValue(s, Profile6110,msg.Buffer[6],msg.Buffer[8],Data,false);
1886 }
1887 return ERR_NONE;
1888 case 0x15:
1889 smprintf(s, "Invalid profile location\n");
1890 return ERR_INVALIDLOCATION;
1891 case 0x1b:
1892 Data->Profile->Name[0] = 0;
1893 Data->Profile->Name[1] = 0;
1894 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1895 EncodeUnicode(Data->Profile->Name,msg.Buffer+10,msg.Buffer[9]);
1896 } else {
1897 if (msg.Length > 0x0A) {
1898 CopyUnicodeString(Data->Profile->Name,msg.Buffer+10);
1899 }
1900 }
1901 smprintf(s, "Profile name: \"%s\"\n",Data->Profile->Name);
1902 Data->Profile->DefaultName = false;
1903 if (msg.Buffer[9]==0x00) Data->Profile->DefaultName = true;
1904 return ERR_NONE;
1905 }
1906 return ERR_UNKNOWNRESPONSE;
1907}
1908
1909static GSM_Error N6110_GetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1910{
1911 GSM_Error error;
1912 int i,j;
1913 unsigned char name_req[] = {N6110_FRAME_HEADER, 0x1a, 0x00};
1914 unsigned char feat_req[] = {N6110_FRAME_HEADER, 0x13, 0x01,
1915 0x00, /* Profile location */
1916 0x00}; /* Feature number */
1917
1918 s->Phone.Data.Profile=Profile;
1919
1920 smprintf(s, "Getting profile name\n");
1921 error = GSM_WaitFor (s, name_req, 5, 0x05, 4, ID_GetProfile);
1922 if (error!=ERR_NONE) return error;
1923 if (Profile->DefaultName) {
1924 NOKIA_GetDefaultProfileName(s, Profile);
1925 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1926 switch(Profile->Location) {
1927 case 1: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Personal"),strlen(GetMsg(s->msg,"Personal")));
1928 break;
1929 case 2: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Car"),strlen(GetMsg(s->msg,"Car")));
1930 break;
1931 case 3: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Headset"),strlen(GetMsg(s->msg,"Headset")));
1932 break;
1933 }
1934 }
1935 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1936 switch(Profile->Location) {
1937 case 1: EncodeUnicode(Profile->Name,GetMsg(s->msg,"General"),strlen(GetMsg(s->msg,"General")));
1938 break;
1939 case 2: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Silent"),strlen(GetMsg(s->msg,"Silent")));
1940 break;
1941 case 3: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Discreet"),strlen(GetMsg(s->msg,"Discreet")));
1942 break;
1943 case 4: EncodeUnicode(Profile->Name,GetMsg(s->msg,"Loud"),strlen(GetMsg(s->msg,"Loud")));
1944 break;
1945 case 5: EncodeUnicode(Profile->Name,GetMsg(s->msg,"My style"),strlen(GetMsg(s->msg,"My style")));
1946 break;
1947 case 6: Profile->Name[0] = 0; Profile->Name[1] = 0;
1948 break;
1949 }
1950 }
1951 }
1952
1953 Profile->FeaturesNumber = 0;
1954
1955 Profile->CarKitProfile = false;
1956 Profile->HeadSetProfile = false;
1957 if (Profile->Location == 6) Profile->CarKitProfile = true;
1958 if (Profile->Location == 7) Profile->HeadSetProfile = true;
1959 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES51)) {
1960 if (Profile->Location == 2) Profile->CarKitProfile = true;
1961 if (Profile->Location == 3) Profile->HeadSetProfile = true;
1962 }
1963 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1964 Profile->HeadSetProfile = false; //fixme
1965 Profile->CarKitProfile = false;
1966 }
1967
1968 for (i = 0x00; i <= 0x09; i++) {
1969 feat_req[5] = Profile->Location - 1;
1970 feat_req[6] = i;
1971 smprintf(s, "Getting profile feature\n");
1972 error = GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetProfile);
1973 if (error!=ERR_NONE) return error;
1974 }
1975
1976 for (i=0;i<Profile->FeaturesNumber;i++) {
1977 if (Profile->FeatureID[i] == Profile_CallAlert &&
1978 Profile->FeatureValue[i] != PROFILE_CALLALERT_CALLERGROUPS) {
1979 for (j=0;j<5;j++) Profile->CallerGroups[j] = true;
1980 }
1981 }
1982
1983 Profile->Active = false;
1984 feat_req[5] = 0;
1985 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) {
1986 feat_req[6] = 0x24;
1987 } else {
1988 feat_req[6] = 0x2A;
1989 }
1990 smprintf(s, "Getting profile feature\n");
1991 error = GSM_WaitFor (s, feat_req, 7, 0x05, 4, ID_GetProfile);
1992
1993 return error;
1994}
1995
1996static GSM_Error N6110_SetProfile(GSM_StateMachine *s, GSM_Profile *Profile)
1997{
1998 int i;
1999 bool found;
2000 unsigned char ID,Value;
2001 GSM_Error error;
2002 GSM_Profile_PhoneTableValue *ProfilePhone = Profile6110;
2003
2004 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_PROFILES33)) ProfilePhone = Profile3310;
2005
2006 for (i=0;i<Profile->FeaturesNumber;i++) {
2007 found = false;
2008 if (ProfilePhone == Profile3310) {
2009 switch (Profile->FeatureID[i]) {
2010 case Profile_RingtoneID:
2011 ID = 0x02;
2012 Value = Profile->FeatureValue[i];
2013 found = true;
2014 break;
2015 case Profile_ScreenSaverNumber:
2016 ID = 0x09;
2017 Value = Profile->FeatureValue[i];
2018 found = true;
2019 break;
2020 default:
2021 found=NOKIA_FindPhoneFeatureValue(
2022 s,
2023 ProfilePhone,
2024 Profile->FeatureID[i],Profile->FeatureValue[i],
2025 &ID,&Value);
2026 }
2027 }
2028 if (ProfilePhone == Profile6110) {
2029 switch (Profile->FeatureID[i]) {
2030 case Profile_RingtoneID:
2031 ID = 0x03;
2032 Value = Profile->FeatureValue[i];
2033 found = true;
2034 break;
2035 default:
2036 found=NOKIA_FindPhoneFeatureValue(
2037 s,
2038 ProfilePhone,
2039 Profile->FeatureID[i],Profile->FeatureValue[i],
2040 &ID,&Value);
2041 }
2042 }
2043 if (found) {
2044 error=N6110_SetProfileFeature (s,((unsigned char)(Profile->Location-1)),ID,Value);
2045 if (error!=ERR_NONE) return error;
2046 }
2047 }
2048 return ERR_NONE;
2049}
2050
2051static GSM_Error N6110_ReplyIncomingSMS(GSM_Protocol_Message msg, GSM_StateMachine *s)
2052{
2053 GSM_Phone_Data *Data = &s->Phone.Data;
2054 GSM_SMSMessage sms;
2055
2056#ifdef DEBUG
2057 smprintf(s, "SMS message received\n");
2058 sms.State = SMS_UnRead;
2059 sms.InboxFolder = true;
2060 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+7);
2061#endif
2062 if (Data->EnableIncomingSMS && s->User.IncomingSMS!=NULL) {
2063 sms.State = SMS_UnRead;
2064 sms.InboxFolder = true;
2065 DCT3_DecodeSMSFrame(s, &sms,msg.Buffer+7);
2066
2067 s->User.IncomingSMS(s->CurrentConfig->Device,sms);
2068 }
2069 return ERR_NONE;
2070}
2071
2072static GSM_Error N6110_ReplyAddCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2073{
2074 smprintf(s, "Writting calendar note: ");
2075 switch (msg.Buffer[4]) {
2076 case 0x01:
2077 smprintf(s, "OK\n");
2078 return ERR_NONE;
2079 case 0x73:
2080 case 0x7d:
2081 smprintf(s, "error\n");
2082 return ERR_UNKNOWN;
2083 case 0x81:
2084 smprintf(s,"during editing notes in phone menu\n");
2085 return ERR_INSIDEPHONEMENU;
2086 default:
2087 smprintf(s, "unknown ERROR %i\n",msg.Buffer[4]);
2088 }
2089 return ERR_UNKNOWNRESPONSE;
2090}
2091
2092static GSM_Error N6110_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2093{
2094 bool Reminder3310 = false;
2095 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location, i, current;
2096 unsigned char mychar1,mychar2;
2097 unsigned char req[200] = {N6110_FRAME_HEADER, 0x64, 0x01, 0x10,
2098 0x00, /* Length of the rest of the frame */
2099 0x00, /* Calendar note type */
2100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2101 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, 0x01};
2102
2103 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2104
2105 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
2106
2107 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52)) {
2108 switch(Note->Type) {
2109 case GSM_CAL_REMINDER: req[7]=0x01; break;
2110 case GSM_CAL_CALL : req[7]=0x02; break;
2111 case GSM_CAL_MEETING : req[7]=0x03; break;
2112 case GSM_CAL_BIRTHDAY: req[7]=0x04; break;
2113 case GSM_CAL_T_ATHL : req[7]=0x05; break;
2114 case GSM_CAL_T_BALL : req[7]=0x06; break;
2115 case GSM_CAL_T_CYCL : req[7]=0x07; break;
2116 case GSM_CAL_T_BUDO : req[7]=0x08; break;
2117 case GSM_CAL_T_DANC : req[7]=0x09; break;
2118 case GSM_CAL_T_EXTR : req[7]=0x0a; break;
2119 case GSM_CAL_T_FOOT : req[7]=0x0b; break;
2120 case GSM_CAL_T_GOLF : req[7]=0x0c; break;
2121 case GSM_CAL_T_GYM : req[7]=0x0d; break;
2122 case GSM_CAL_T_HORS : req[7]=0x0e; break;
2123 case GSM_CAL_T_HOCK : req[7]=0x0f; break;
2124 case GSM_CAL_T_RACE : req[7]=0x10; break;
2125 case GSM_CAL_T_RUGB : req[7]=0x11; break;
2126 case GSM_CAL_T_SAIL : req[7]=0x12; break;
2127 case GSM_CAL_T_STRE : req[7]=0x13; break;
2128 case GSM_CAL_T_SWIM : req[7]=0x14; break;
2129 case GSM_CAL_T_TENN : req[7]=0x15; break;
2130 case GSM_CAL_T_TRAV : req[7]=0x16; break;
2131 case GSM_CAL_T_WINT : req[7]=0x17; break;
2132 default : req[7]=0x01; break;
2133 }
2134 } else {
2135 switch(Note->Type) {
2136 case GSM_CAL_CALL : req[7]=0x02; break;
2137 case GSM_CAL_MEETING : req[7]=0x03; break;
2138 case GSM_CAL_BIRTHDAY: req[7]=0x04; break;
2139 case GSM_CAL_REMINDER:
2140 default : req[7]=0x01; break;
2141 }
2142 }
2143
2144 if (Time == -1) return ERR_UNKNOWN;
2145 NOKIA_EncodeDateTime(s, req+8, &Note->Entries[Time].Date);
2146 req[14] = Note->Entries[Time].Date.Second;
2147
2148 if (Alarm != -1) {
2149 NOKIA_EncodeDateTime(s, req+15, &Note->Entries[Alarm].Date);
2150 req[21] = Note->Entries[Alarm].Date.Second;
2151 }
2152
2153 current = 23;
2154
2155 if (Text != -1) {
2156 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52) ||
2157 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL82)) {
2158 req[22] = UnicodeLength(Note->Entries[Text].Text)*2;
2159 memcpy(req+current,Note->Entries[Text].Text,UnicodeLength(Note->Entries[Text].Text)*2);
2160 current += UnicodeLength(Note->Entries[Text].Text)*2;
2161 } else {
2162 req[22] = UnicodeLength(Note->Entries[Text].Text);
2163 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL33)) {
2164 Reminder3310 = true;
2165 if (!strcmp(s->Phone.Data.ModelInfo->model,"3310") && s->Phone.Data.VerNum<5.11) {
2166 if (Note->Type!=GSM_CAL_REMINDER) Reminder3310 = false;
2167 }
2168 if (!strcmp(s->Phone.Data.ModelInfo->model,"3330") && s->Phone.Data.VerNum<=4.50) {
2169 if (Note->Type!=GSM_CAL_REMINDER) Reminder3310 = false;
2170 }
2171 if (Reminder3310) {
2172 req[22]++; /* one additional char */
2173 req[current++] = 0x01; /* we use now subset 1 */
2174 for (i=0;i<((int)UnicodeLength(Note->Entries[Text].Text));i++) {
2175 /* Euro char */
2176 if (Note->Entries[Text].Text[i*2]==0x20 && Note->Entries[Text].Text[i*2+1]==0xAC) {
2177 req[current++] = 0xe2;
2178 req[current++] = 0x82;
2179 req[current++] = 0xac;
2180 req[23] = 0x03; /* use subset 3 */
2181 req[22]+=2; /* two additional chars */
2182 } else if (EncodeWithUTF8Alphabet(Note->Entries[Text].Text[i*2],Note->Entries[Text].Text[i*2+1],&mychar1,&mychar2)) {
2183 req[current++] = mychar1;
2184 req[current++] = mychar2;
2185 req[23] = 0x03; /* use subset 3 */
2186 req[22]++; /* one additional char */
2187 } else {
2188 current+=DecodeWithUnicodeAlphabet(((wchar_t)(Note->Entries[Text].Text[i*2]*256+Note->Entries[Text].Text[i*2+1])),req+current);
2189 }
2190 }
2191 }
2192 }
2193 if (!Reminder3310) {
2194 memcpy(req+current,DecodeUnicodeString(Note->Entries[Text].Text),UnicodeLength(Note->Entries[Text].Text));
2195 current += UnicodeLength(Note->Entries[Text].Text);
2196 }
2197 }
2198 } else req[22] = 0x00;
2199
2200 if (Note->Type == GSM_CAL_CALL) {
2201 if (Phone != -1) {
2202 req[current++] = UnicodeLength(Note->Entries[Phone].Text);
2203 memcpy(req+current,DecodeUnicodeString(Note->Entries[Phone].Text),UnicodeLength(Note->Entries[Phone].Text));
2204 current += UnicodeLength(Note->Entries[Phone].Text);
2205 } else req[current++] = 0x00;
2206 }
2207
2208 req[6] = current - 8;
2209
2210 smprintf(s, "Writing calendar note\n");
2211 return GSM_WaitFor (s, req, current, 0x13, 4, ID_SetCalendarNote);
2212}
2213
2214static GSM_Error N6110_ReplyDeleteCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2215{
2216 smprintf(s, "Deleting calendar note: ");
2217 switch (msg.Buffer[4]) {
2218 case 0x01:
2219 smprintf(s, "done OK\n");
2220 return ERR_NONE;
2221 case 0x81:
2222 smprintf(s,"during editing notes in phone menu\n");
2223 return ERR_INSIDEPHONEMENU;
2224 case 0x93:
2225 smprintf(s, "Can't be done - too high location ?\n");
2226 return ERR_INVALIDLOCATION;
2227 default:
2228 smprintf(s, "unknown ERROR %i\n",msg.Buffer[4]);
2229 return ERR_UNKNOWNRESPONSE;
2230 }
2231}
2232
2233static GSM_Error N6110_DeleteCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
2234{
2235 unsigned char req[] = {N6110_FRAME_HEADER, 0x68,
2236 0x00}; /* Location */
2237
2238 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2239
2240 req[4] = Note->Location;
2241
2242 smprintf(s, "Deleting calendar note\n");
2243 return GSM_WaitFor (s, req, 5, 0x13, 5, ID_DeleteCalendarNote);
2244}
2245
2246/* for example: "Euro_char" text */
2247static void Decode3310Subset3(int j, GSM_Protocol_Message msg, GSM_Phone_Data *Data)
2248{
2249 wchar_t wc;
2250 int len = 0;
2251 int i;
2252 bool charfound;
2253 GSM_CalendarEntry *Entry = Data->Cal;
2254
2255 i = j;
2256 while (i!=msg.Buffer[23]) {
2257 EncodeWithUnicodeAlphabet(msg.Buffer+24+i,&wc);
2258 charfound = false;
2259 if (i!=msg.Buffer[23]-2) {
2260 if (msg.Buffer[24+i] ==0xe2 && msg.Buffer[24+i+1]==0x82 &&
2261 msg.Buffer[24+i+2]==0xac) {
2262 wc = 0x20 * 256 + 0xac;
2263 i+=2;
2264 charfound = true;
2265 }
2266 }
2267 if (i!=msg.Buffer[23]-1 && !charfound) {
2268 if (msg.Buffer[24+i]>=0xc2) {
2269 wc = DecodeWithUTF8Alphabet(msg.Buffer[24+i],msg.Buffer[24+i+1]);
2270 i++;
2271 }
2272 }
2273 Entry->Entries[Entry->EntriesNum].Text[len++] = (wc >> 8) & 0xff;
2274 Entry->Entries[Entry->EntriesNum].Text[len++] = wc & 0xff;
2275 i++;
2276 }
2277 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2278 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2279}
2280
2281/* For example: "a with : above" char */
2282static void Decode3310Subset2(int j, GSM_Protocol_Message msg, GSM_Phone_Data *Data)
2283{
2284 int len = 0;
2285 int i;
2286 GSM_CalendarEntry *Entry = Data->Cal;
2287
2288 i = j;
2289 while (i!=msg.Buffer[23]) {
2290 Entry->Entries[Entry->EntriesNum].Text[len++] = 0x00;
2291 Entry->Entries[Entry->EntriesNum].Text[len++] = msg.Buffer[24+i];
2292 i++;
2293 }
2294 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2295 Entry->Entries[Entry->EntriesNum].Text[len++] = 0;
2296}
2297
2298static GSM_Error N6110_ReplyGetNextCalendar(GSM_Protocol_Message msg, GSM_StateMachine *s)
2299{
2300 int i = 0;
2301 bool SpecialSubSet = false;
2302 GSM_CalendarEntry *Entry = s->Phone.Data.Cal;
2303
2304 switch (msg.Buffer[4]) {
2305 case 0x01:
2306 smprintf(s, "Calendar note received\n");
2307 switch (msg.Buffer[8]) {
2308 case 0x01: Entry->Type = GSM_CAL_REMINDER; break;
2309 case 0x02: Entry->Type = GSM_CAL_CALL; break;
2310 case 0x03: Entry->Type = GSM_CAL_MEETING; break;
2311 case 0x04: Entry->Type = GSM_CAL_BIRTHDAY; break;
2312 case 0x05: Entry->Type = GSM_CAL_T_ATHL; break;
2313 case 0x06: Entry->Type = GSM_CAL_T_BALL; break;
2314 case 0x07: Entry->Type = GSM_CAL_T_CYCL; break;
2315 case 0x08: Entry->Type = GSM_CAL_T_BUDO; break;
2316 case 0x09: Entry->Type = GSM_CAL_T_DANC; break;
2317 case 0x0a: Entry->Type = GSM_CAL_T_EXTR; break;
2318 case 0x0b: Entry->Type = GSM_CAL_T_FOOT; break;
2319 case 0x0c: Entry->Type = GSM_CAL_T_GOLF; break;
2320 case 0x0d: Entry->Type = GSM_CAL_T_GYM; break;
2321 case 0x0e: Entry->Type = GSM_CAL_T_HORS; break;
2322 case 0x0f: Entry->Type = GSM_CAL_T_HOCK; break;
2323 case 0x10: Entry->Type = GSM_CAL_T_RACE; break;
2324 case 0x11: Entry->Type = GSM_CAL_T_RUGB; break;
2325 case 0x12: Entry->Type = GSM_CAL_T_SAIL; break;
2326 case 0x13: Entry->Type = GSM_CAL_T_STRE; break;
2327 case 0x14: Entry->Type = GSM_CAL_T_SWIM; break;
2328 case 0x15: Entry->Type = GSM_CAL_T_TENN; break;
2329 case 0x16: Entry->Type = GSM_CAL_T_TRAV; break;
2330 case 0x17: Entry->Type = GSM_CAL_T_WINT; break;
2331 default :
2332 smprintf(s, "Unknown note type %i\n",msg.Buffer[8]);
2333 return ERR_UNKNOWNRESPONSE;
2334 }
2335#ifdef DEBUG
2336 switch (msg.Buffer[8]) {
2337 case 0x01: smprintf(s, "Reminder\n"); break;
2338 case 0x02: smprintf(s, "Call\n"); break;
2339 case 0x03: smprintf(s, "Meeting\n"); break;
2340 case 0x04: smprintf(s, "Birthday\n"); break;
2341 }
2342#endif
2343 Entry->EntriesNum = 0;
2344
2345 NOKIA_DecodeDateTime(s, msg.Buffer+9, &Entry->Entries[0].Date);
2346 smprintf(s, "Time : %02i-%02i-%04i %02i:%02i:%02i\n",
2347 Entry->Entries[0].Date.Day,Entry->Entries[0].Date.Month,Entry->Entries[0].Date.Year,
2348 Entry->Entries[0].Date.Hour,Entry->Entries[0].Date.Minute,Entry->Entries[0].Date.Second);
2349 Entry->Entries[0].EntryType = CAL_START_DATETIME;
2350 Entry->EntriesNum++;
2351
2352 NOKIA_DecodeDateTime(s, msg.Buffer+16, &Entry->Entries[1].Date);
2353 if (Entry->Entries[1].Date.Year!=0) {
2354 smprintf(s, "Alarm : %02i-%02i-%04i %02i:%02i:%02i\n",
2355 Entry->Entries[1].Date.Day,Entry->Entries[1].Date.Month,Entry->Entries[1].Date.Year,
2356 Entry->Entries[1].Date.Hour,Entry->Entries[1].Date.Minute,Entry->Entries[1].Date.Second);
2357 Entry->Entries[1].EntryType = CAL_ALARM_DATETIME;
2358 Entry->EntriesNum++;
2359 } else {
2360 smprintf(s, "No alarm\n");
2361 }
2362
2363 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL52) ||
2364 IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL82)) {
2365 memcpy(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24,msg.Buffer[23]);
2366 Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23] ]=0;
2367 Entry->Entries[Entry->EntriesNum].Text[msg.Buffer[23]+1]=0;
2368 } else {
2369 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo,F_CAL33)) {
2370 /* first char is subset for 33xx and reminders */
2371 if (Entry->Type == GSM_CAL_REMINDER) {
2372 i=1;
2373 smprintf(s, "Subset %i in reminder note !\n",msg.Buffer[24]);
2374 }
2375 SpecialSubSet = true;
2376 switch (msg.Buffer[24]) {
2377 case 2 : Decode3310Subset2(i,msg,&s->Phone.Data); break;
2378 case 3 : Decode3310Subset3(i,msg,&s->Phone.Data); break;
2379 default : SpecialSubSet = false; break;
2380 }
2381 }
2382 if (!SpecialSubSet) {
2383 N6110_EncodeUnicode(s,Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+i,msg.Buffer[23]-i);
2384 }
2385 }
2386 smprintf(s, "Text \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
2387 if (msg.Buffer[23] != 0x00) {
2388 Entry->Entries[Entry->EntriesNum].EntryType = CAL_TEXT;
2389 Entry->EntriesNum++;
2390 }
2391
2392 if (Entry->Type == GSM_CAL_CALL) {
2393 EncodeUnicode(Entry->Entries[Entry->EntriesNum].Text,msg.Buffer+24+msg.Buffer[23]+1,msg.Buffer[24+msg.Buffer[23]]);
2394 smprintf(s, "Phone : \"%s\"\n",DecodeUnicodeString(Entry->Entries[Entry->EntriesNum].Text));
2395 if (msg.Buffer[24+msg.Buffer[23]] != 0x00) {
2396 Entry->Entries[Entry->EntriesNum].EntryType = CAL_PHONE;
2397 Entry->EntriesNum++;
2398 }
2399 }
2400 return ERR_NONE;
2401 case 0x93:
2402 smprintf(s, "Can't get calendar note - too high location?\n");
2403 return ERR_INVALIDLOCATION;
2404 }
2405 return ERR_UNKNOWNRESPONSE;
2406}
2407
2408static GSM_Error N6110_GetNextCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note, bool start)
2409{
2410 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location;
2411 GSM_Error error;
2412 GSM_DateTime date_time;
2413 GSM_Phone_N6110Data *Priv = &s->Phone.Data.Priv.N6110;
2414 unsigned char req[] = {N6110_FRAME_HEADER, 0x66,
2415 0x00}; /* Location */
2416
2417 if (IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_NOCALENDAR)) return ERR_NOTSUPPORTED;
2418
2419 if (start) {
2420 Priv->LastCalendarPos = 1;
2421 } else {
2422 Priv->LastCalendarPos++;
2423 }
2424
2425 Note->Location = Priv->LastCalendarPos;
2426 req[4] = Priv->LastCalendarPos;
2427
2428 s->Phone.Data.Cal=Note;
2429 smprintf(s, "Getting calendar note\n");
2430 error=GSM_WaitFor (s, req, 5, 0x13, 4, ID_GetCalendarNote);
2431
2432 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(Note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
2433 /* 2090 year is set for example in 3310 */
2434 if (error == ERR_NONE && Note->Entries[Time].Date.Year == 2090) {
2435 error=N6110_GetDateTime(s, &date_time);
2436 if (error == ERR_NONE) Note->Entries[Time].Date.Year = date_time.Year;
2437 }
2438 return error;
2439}
2440
2441GSM_Error N6110_ReplyUSSDInfo(GSM_Protocol_Message msg, GSM_StateMachine *s)
2442{
2443 unsigned char buffer[2000],buffer2[4000];
2444 int tmp;
2445
2446 tmp=GSM_UnpackEightBitsToSeven(0, 82, 82, msg.Buffer+8, buffer);
2447 msg.Buffer[tmp] = 0;
2448
2449 smprintf(s, "USSD reply: \"%s\"\n",buffer);
2450
2451 if (s->Phone.Data.EnableIncomingUSSD && s->User.IncomingUSSD!=NULL) {
2452 EncodeUnicode(buffer2,buffer,strlen(buffer));
2453 s->User.IncomingUSSD(s->CurrentConfig->Device, buffer2);
2454 }
2455
2456 return ERR_NONE;
2457}
2458
2459GSM_Error N6110_AnswerCall(GSM_StateMachine *s, int ID, bool all)
2460{
2461 GSM_Error error;
2462 unsigned char req1[] = {N6110_FRAME_HEADER, 0x42, 0x05, 0x01,
2463 0x07, 0xa2, 0x88, 0x81, 0x21, 0x15, 0x63, 0xa8,
2464 0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15,
2465 0x63, 0x80};
2466
2467 if (!all) {
2468 smprintf(s, "Answering call part 1\n");
2469 error = GSM_WaitFor (s, req1, 24, 0x01, 5, ID_AnswerCall);
2470 if (error != ERR_NONE) return error;
2471 return DCT3DCT4_AnswerCall(s,ID);
2472 }
2473
2474 return DCT3_AnswerAllCalls(s);
2475}
2476
2477static GSM_Error N6110_DialVoice(GSM_StateMachine *s, char *number, GSM_CallShowNumber ShowNumber)
2478{
2479 unsigned int pos = 4;
2480 unsigned char req[100] = {N6110_FRAME_HEADER,0x01,
2481 0x0c}; /* Length of number */
2482
2483 if (ShowNumber == GSM_CALL_DefaultNumberPresence) return DCT3_DialVoice(s,number,ShowNumber);
2484
2485 req[pos++] = strlen(number);
2486 memcpy(req+pos,number,strlen(number));
2487 pos += strlen(number);
2488 req[pos++] = 0x05; /* call type: voice - 0x05, data - 0x01 */
2489 req[pos++] = 0x01;
2490 req[pos++] = 0x01;
2491 req[pos++] = 0x05;
2492 req[pos++] = 0x81;
2493 switch (ShowNumber) {
2494 case GSM_CALL_HideNumber:
2495 req[pos++] = 0x02;
2496 break;
2497 case GSM_CALL_ShowNumber:
2498 req[pos++] = 0x03;
2499 break;
2500 case GSM_CALL_DefaultNumberPresence:
2501 req[pos++] = 0x01;
2502 break;
2503 }
2504 req[pos++] = 0x00;
2505 req[pos++] = 0x00;
2506
2507 smprintf(s, "Making voice call\n");
2508 return GSM_WaitFor (s, req, pos, 0x01, 4, ID_DialVoice);
2509}
2510
2511GSM_Error N6110_UnholdCall(GSM_StateMachine *s, int ID)
2512{
2513 unsigned char req[] = {N6110_FRAME_HEADER, 0x24, 0x00, 0x02};
2514
2515 req[4] = (unsigned char)ID;
2516 s->Phone.Data.CallID = ID;
2517
2518 smprintf(s, "Unholding call\n");
2519 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_UnholdCall);
2520}
2521
2522GSM_Error N6110_HoldCall(GSM_StateMachine *s, int ID)
2523{
2524 unsigned char req[] = {N6110_FRAME_HEADER, 0x22, 0x00, 0x00};
2525
2526 req[4] = (unsigned char)ID;
2527 s->Phone.Data.CallID = ID;
2528
2529 smprintf(s, "Unholding call\n");
2530 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_HoldCall);
2531}
2532
2533/* Joining selected call to current (and making conference) */
2534GSM_Error N6110_ConferenceCall(GSM_StateMachine *s, int ID)
2535{
2536 unsigned char req[] = {N6110_FRAME_HEADER, 0x28, 0x00, 0x01};
2537
2538 req[4] = (unsigned char)ID;
2539 s->Phone.Data.CallID = ID;
2540
2541 smprintf(s, "Conference call\n");
2542 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_ConferenceCall);
2543}
2544
2545/* Removing selected call from conference and making private call with it
2546 * (conference call is on hold) */
2547GSM_Error N6110_SplitCall(GSM_StateMachine *s, int ID)
2548{
2549 unsigned char req[] = {N6110_FRAME_HEADER, 0x2A, 0x00, 0x01};
2550
2551 req[4] = (unsigned char)ID;
2552 s->Phone.Data.CallID = ID;
2553
2554 smprintf(s, "Split call\n");
2555 return GSM_WaitFor (s, req, 6, 0x01, 4, ID_SplitCall);
2556}
2557
2558/* This probably need more investigation */
2559GSM_Error N6110_SwitchCall(GSM_StateMachine *s, int ID, bool next)
2560{
2561// unsigned char req[] = {N6110_FRAME_HEADER, 0x20}; calls info
2562 unsigned char req[] = {N6110_FRAME_HEADER, 0x26, 0x00};
2563
2564 s->Phone.Data.CallID = ID;
2565
2566 if (next) {
2567 smprintf(s, "Switch call\n");
2568 return GSM_WaitFor (s, req, 4, 0x01, 4, ID_SwitchCall);
2569 } else {
2570 req[4] = (unsigned char)ID;
2571
2572 smprintf(s, "Switch call\n");
2573 return GSM_WaitFor (s, req, 5, 0x01, 4, ID_SwitchCall);
2574 }
2575}
2576
2577/* This probably need more investigation */
2578GSM_Error N6110_TransferCall(GSM_StateMachine *s, int ID, bool next)
2579{
2580 unsigned char req[] = {N6110_FRAME_HEADER, 0x2C, 0x00};
2581
2582 s->Phone.Data.CallID = ID;
2583
2584 if (next) {
2585 smprintf(s, "Transfer call\n");
2586 return GSM_WaitFor (s, req, 4, 0x01, 4, ID_TransferCall);
2587 } else {
2588 req[4] = (unsigned char)ID;
2589
2590 smprintf(s, "Transfer call\n");
2591 return GSM_WaitFor (s, req, 5, 0x01, 4, ID_TransferCall);
2592 }
2593}
2594
2595static GSM_Reply_Function N6110ReplyFunctions[] = {
2596 {N6110_ReplyCallInfo, "\x01",0x03,0x02,ID_IncomingFrame },
2597 {N6110_ReplyCallInfo, "\x01",0x03,0x03,ID_IncomingFrame },
2598 {N6110_ReplyCallInfo, "\x01",0x03,0x04,ID_IncomingFrame },
2599 {N6110_ReplyCallInfo, "\x01",0x03,0x05,ID_IncomingFrame },
2600 {N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_AnswerCall },
2601 {N6110_ReplyCallInfo, "\x01",0x03,0x07,ID_IncomingFrame },
2602 {N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_CancelCall },
2603 {N6110_ReplyCallInfo, "\x01",0x03,0x09,ID_IncomingFrame },
2604 {N6110_ReplyCallInfo, "\x01",0x03,0x0A,ID_IncomingFrame },
2605 {N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_HoldCall },
2606 {N6110_ReplyCallInfo, "\x01",0x03,0x23,ID_IncomingFrame },
2607 {N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_UnholdCall },
2608 {N6110_ReplyCallInfo, "\x01",0x03,0x25,ID_IncomingFrame },
2609 {N6110_ReplyCallInfo, "\x01",0x03,0x27,ID_IncomingFrame },
2610 {N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_ConferenceCall },
2611 {N6110_ReplyCallInfo, "\x01",0x03,0x29,ID_IncomingFrame },
2612 {N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_SplitCall },
2613 {N6110_ReplyCallInfo, "\x01",0x03,0x2B,ID_IncomingFrame },
2614 {N6110_ReplySendDTMF, "\x01",0x03,0x40,ID_SendDTMF },
2615 {NoneReply, "\x01",0x03,0x40,ID_DialVoice },
2616 {NoneReply, "\x01",0x03,0x40,ID_IncomingFrame },
2617 {NoneReply, "\x01",0x03,0x43,ID_AnswerCall },
2618 {N6110_ReplySendDTMF, "\x01",0x03,0x51,ID_SendDTMF },
2619
2620 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x02,ID_IncomingFrame },
2621 {DCT3_ReplySendSMSMessage, "\x02",0x03,0x03,ID_IncomingFrame },
2622 {N6110_ReplyIncomingSMS, "\x02",0x03,0x10,ID_IncomingFrame },
2623#ifdef GSM_ENABLE_CELLBROADCAST
2624 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x21,ID_SetIncomingCB },
2625 {DCT3_ReplySetIncomingCB, "\x02",0x03,0x22,ID_SetIncomingCB },
2626 {DCT3_ReplyIncomingCB, "\x02",0x03,0x23,ID_IncomingFrame },
2627#endif
2628 {DCT3_ReplySetSMSC, "\x02",0x03,0x31,ID_SetSMSC },
2629 {DCT3_ReplyGetSMSC, "\x02",0x03,0x34,ID_GetSMSC },
2630 {DCT3_ReplyGetSMSC, "\x02",0x03,0x35,ID_GetSMSC },
2631
2632 {N6110_ReplyGetMemory, "\x03",0x03,0x02,ID_GetMemory },
2633 {N6110_ReplyGetMemory, "\x03",0x03,0x03,ID_GetMemory },
2634 {N6110_ReplySetMemory, "\x03",0x03,0x05,ID_SetMemory },
2635 {N6110_ReplySetMemory, "\x03",0x03,0x06,ID_SetMemory },
2636 {N6110_ReplyGetMemoryStatus, "\x03",0x03,0x08,ID_GetMemoryStatus },
2637 {N6110_ReplyGetMemoryStatus, "\x03",0x03,0x09,ID_GetMemoryStatus },
2638 {N6110_ReplyGetCallerLogo, "\x03",0x03,0x11,ID_GetBitmap },
2639 {N6110_ReplyGetCallerLogo, "\x03",0x03,0x12,ID_GetBitmap },
2640 {N6110_ReplySetCallerLogo, "\x03",0x03,0x14,ID_SetBitmap },
2641 {N6110_ReplySetCallerLogo, "\x03",0x03,0x15,ID_SetBitmap },
2642 {N6110_ReplyGetSpeedDial, "\x03",0x03,0x17,ID_GetSpeedDial },
2643 {N6110_ReplyGetSpeedDial, "\x03",0x03,0x18,ID_GetSpeedDial },
2644 /* 0x1A, 0x1B - reply set speed dial */
2645
2646 {N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetSignalQuality },
2647 {N6110_ReplyGetStatus, "\x04",0x03,0x02,ID_GetBatteryCharge },
2648
2649 {N6110_ReplySetProfileFeature, "\x05",0x03,0x11,ID_SetProfile },
2650 {N6110_ReplySetProfileFeature, "\x05",0x03,0x12,ID_SetProfile },
2651 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x14,ID_GetProfile },
2652 {N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x14,ID_GetLanguage },
2653 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x15,ID_GetProfile },
2654 {N6110_ReplyGetPhoneLanguage, "\x05",0x03,0x15,ID_GetLanguage },
2655 {N6110_ReplyGetStartup, "\x05",0x03,0x17,ID_GetBitmap },
2656 {N6110_ReplySetStartup, "\x05",0x03,0x19,ID_SetBitmap },
2657 {N6110_ReplyGetProfileFeature, "\x05",0x03,0x1b,ID_GetProfile },
2658 {N61_91_ReplySetOpLogo, "\x05",0x03,0x31,ID_SetBitmap },
2659 {N61_91_ReplySetOpLogo, "\x05",0x03,0x32,ID_SetBitmap },
2660 {N6110_ReplyGetOpLogo, "\x05",0x03,0x34,ID_GetBitmap },
2661 {N6110_ReplySetRingtone, "\x05",0x03,0x37,ID_SetRingtone },
2662 {N6110_ReplySetRingtone, "\x05",0x03,0x38,ID_SetRingtone },
2663
2664 {DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x02,ID_Divert },
2665 {DCT3DCT4_ReplyCallDivert, "\x06",0x03,0x03,ID_Divert },
2666 {N6110_ReplyUSSDInfo, "\x06",0x03,0x05,ID_IncomingFrame },
2667 {NoneReply, "\x06",0x03,0x06,ID_IncomingFrame },//incoming call divert info
2668
2669 {N6110_ReplyGetSecurityStatus, "\x08",0x03,0x08,ID_GetSecurityStatus },
2670 {N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0b,ID_EnterSecurityCode },
2671 {N6110_ReplyEnterSecurityCode, "\x08",0x03,0x0c,ID_EnterSecurityCode },
2672
2673 {DCT3_ReplySIMLogin, "\x09",0x03,0x80,ID_IncomingFrame },
2674 {DCT3_ReplySIMLogout, "\x09",0x03,0x81,ID_IncomingFrame },
2675
2676 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_GetNetworkInfo },
2677 {DCT3_ReplyGetNetworkInfo, "\x0A",0x03,0x71,ID_IncomingFrame },
2678
2679 {N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_GetDisplayStatus },
2680 {N6110_ReplyGetDisplayStatus, "\x0D",0x03,0x52,ID_IncomingFrame },
2681
2682 {DCT3_ReplySetDateTime, "\x11",0x03,0x61,ID_SetDateTime },
2683 {DCT3_ReplyGetDateTime, "\x11",0x03,0x63,ID_GetDateTime },
2684 {DCT3_ReplySetAlarm, "\x11",0x03,0x6C,ID_SetAlarm },
2685 {DCT3_ReplyGetAlarm, "\x11",0x03,0x6E,ID_GetAlarm },
2686
2687 {N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_SetCalendarNote },
2688 {N6110_ReplyAddCalendar, "\x13",0x03,0x65,ID_IncomingFrame },
2689 {N6110_ReplyGetNextCalendar, "\x13",0x03,0x67,ID_GetCalendarNote },
2690 {N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_DeleteCalendarNote },
2691 {N6110_ReplyDeleteCalendar, "\x13",0x03,0x69,ID_IncomingFrame },
2692
2693 {N6110_ReplySaveSMSMessage, "\x14",0x03,0x05,ID_SaveSMSMessage },
2694 {N6110_ReplySaveSMSMessage, "\x14",0x03,0x06,ID_SaveSMSMessage },
2695 {N6110_ReplyGetSMSMessage, "\x14",0x03,0x08,ID_GetSMSMessage },
2696 {N6110_ReplyGetSMSMessage, "\x14",0x03,0x09,ID_GetSMSMessage },
2697 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0B,ID_DeleteSMSMessage },
2698 {DCT3_ReplyDeleteSMSMessage, "\x14",0x03,0x0C,ID_DeleteSMSMessage },
2699 {N6110_ReplyGetSMSStatus, "\x14",0x03,0x37,ID_GetSMSStatus },
2700 {N6110_ReplyGetSMSStatus, "\x14",0x03,0x38,ID_GetSMSStatus },
2701
2702 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x01,ID_EnableConnectFunc },
2703 {DCT3DCT4_ReplyEnableConnectFunc, "\x3f",0x03,0x02,ID_EnableConnectFunc },
2704 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x04,ID_DisableConnectFunc },
2705 {DCT3DCT4_ReplyDisableConnectFunc,"\x3f",0x03,0x05,ID_DisableConnectFunc },
2706 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x07,ID_GetWAPBookmark },
2707 {DCT3_ReplyGetWAPBookmark, "\x3f",0x03,0x08,ID_GetWAPBookmark },
2708 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0A,ID_SetWAPBookmark },
2709 {DCT3DCT4_ReplySetWAPBookmark, "\x3f",0x03,0x0B,ID_SetWAPBookmark },
2710 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0D,ID_DeleteWAPBookmark },
2711 {DCT3DCT4_ReplyDelWAPBookmark, "\x3f",0x03,0x0E,ID_DeleteWAPBookmark },
2712 {DCT3DCT4_ReplyGetActiveConnectSet,"\x3f",0x03,0x10,ID_GetConnectSet },
2713 {DCT3DCT4_ReplySetActiveConnectSet,"\x3f",0x03,0x13,ID_SetConnectSet },
2714 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x16,ID_GetConnectSet },
2715 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x17,ID_GetConnectSet },
2716 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x19,ID_SetConnectSet },
2717 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1A,ID_SetConnectSet },
2718 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1C,ID_GetConnectSet },
2719 {DCT3_ReplyGetWAPSettings, "\x3f",0x03,0x1D,ID_GetConnectSet },
2720 {DCT3_ReplySetWAPSettings, "\x3f",0x03,0x1F,ID_SetConnectSet },
2721
2722 {DCT3_ReplyEnableSecurity, "\x40",0x02,0x64,ID_EnableSecurity },
2723 {N61_71_ReplyResetPhoneSettings, "\x40",0x02,0x65,ID_ResetPhoneSettings },
2724 {DCT3_ReplyGetIMEI, "\x40",0x02,0x66,ID_GetIMEI },
2725 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_DialVoice },
2726 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_CancelCall },
2727 {DCT3_ReplyDialCommand, "\x40",0x02,0x7C,ID_AnswerCall },
2728 {DCT3_ReplyNetmonitor, "\x40",0x02,0x7E,ID_Netmonitor },
2729 {DCT3_ReplyPlayTone, "\x40",0x02,0x8F,ID_PlayTone },
2730 {N6110_ReplyGetRingtone, "\x40",0x02,0x9E,ID_GetRingtone },
2731 {N6110_ReplySetBinRingtone, "\x40",0x02,0xA0,ID_SetRingtone },
2732 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetHardware },
2733 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xC8,ID_GetPPM },
2734 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCA,ID_GetProductCode },
2735 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetManufactureMonth},
2736 {NOKIA_ReplyGetPhoneString, "\x40",0x02,0xCC,ID_GetOriginalIMEI },
2737
2738 {N6110_ReplyGetSetPicture, "\x47",0x03,0x02,ID_GetBitmap },
2739 {N6110_ReplyGetSetPicture, "\x47",0x03,0x04,ID_SetBitmap },
2740 {N6110_ReplyGetSetPicture, "\x47",0x03,0x05,ID_SetBitmap },
2741 {N6110_ReplyGetSetPicture, "\x47",0x03,0x06,ID_GetBitmap },
2742
2743#ifndef ENABLE_LGPL
2744 {N6110_ReplyGetMagicBytes, "\x64",0x00,0x00,ID_MakeAuthentication },
2745#endif
2746
2747 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetModel },
2748 {DCT3DCT4_ReplyGetModelFirmware, "\xD2",0x02,0x00,ID_GetFirmware },
2749 {DCT3_ReplyPressKey, "\xD2",0x02,0x46,ID_PressKey },
2750 {DCT3_ReplyPressKey, "\xD2",0x02,0x47,ID_PressKey },
2751
2752 {NULL, "\x00",0x00,0x00,ID_None }
2753};
2754
2755GSM_Phone_Functions N6110Phone = {
2756 "2100|3210|3310|3330|3390|3410|3610|5110|5110i|5130|5190|5210|5510|6110|6130|6150|6190|8210|8250|8290|8850|8855|8890",
2757 N6110ReplyFunctions,
2758 N6110_Initialise,
2759 PHONE_Terminate,
2760 GSM_DispatchMessage,
2761 N6110_ShowStartInfo,
2762 NOKIA_GetManufacturer,
2763 DCT3DCT4_GetModel,
2764 DCT3DCT4_GetFirmware,
2765 DCT3_GetIMEI,
2766 DCT3_GetOriginalIMEI,
2767 DCT3_GetManufactureMonth,
2768 DCT3_GetProductCode,
2769 DCT3_GetHardware,
2770 DCT3_GetPPM,
2771 NOTSUPPORTED, /* GetSIMIMSI */
2772 N6110_GetDateTime,
2773 N6110_SetDateTime,
2774 N6110_GetAlarm,
2775 N6110_SetAlarm,
2776 NOTSUPPORTED, /* GetLocale */
2777 NOTSUPPORTED, /* SetLocale */
2778 DCT3_PressKey,
2779 DCT3_Reset,
2780 N61_71_ResetPhoneSettings,
2781 N6110_EnterSecurityCode,
2782 N6110_GetSecurityStatus,
2783 N6110_GetDisplayStatus,
2784 NOTIMPLEMENTED, /* SetAutoNetworkLogin */
2785 N6110_GetBatteryCharge,
2786 N6110_GetSignalQuality,
2787 DCT3_GetNetworkInfo,
2788 NOTSUPPORTED, /* GetCategory */
2789 NOTSUPPORTED, /* AddCategory */
2790 NOTSUPPORTED, /* GetCategoryStatus */
2791 N6110_GetMemoryStatus,
2792 N6110_GetMemory,
2793 NOTIMPLEMENTED, /* GetNextMemory */
2794 N6110_SetMemory,
2795 NOTIMPLEMENTED, /* AddMemory */
2796 N6110_DeleteMemory,
2797 NOTIMPLEMENTED, /* DeleteAllMemory */
2798 N6110_GetSpeedDial,
2799 NOTIMPLEMENTED, /* SetSpeedDial */
2800 DCT3_GetSMSC,
2801 DCT3_SetSMSC,
2802 DCT3_GetSMSStatus,
2803 N6110_GetSMSMessage,
2804 N6110_GetNextSMSMessage,
2805 N6110_SetSMS,
2806 N6110_AddSMS,
2807 N6110_DeleteSMSMessage,
2808 DCT3_SendSMSMessage,
2809 NOTSUPPORTED, /* SendSavedSMS */
2810 NOKIA_SetIncomingSMS,
2811 DCT3_SetIncomingCB,
2812 PHONE_GetSMSFolders,
2813 NOTSUPPORTED, /* AddSMSFolder */
2814 NOTSUPPORTED, /* DeleteSMSFolder */
2815 N6110_DialVoice,
2816 N6110_AnswerCall,
2817 DCT3_CancelCall,
2818 N6110_HoldCall,
2819 N6110_UnholdCall,
2820 N6110_ConferenceCall,
2821 N6110_SplitCall,
2822 N6110_TransferCall,
2823 N6110_SwitchCall,
2824 DCT3DCT4_GetCallDivert,
2825 DCT3DCT4_SetCallDivert,
2826 DCT3DCT4_CancelAllDiverts,
2827 NOKIA_SetIncomingCall,
2828 NOKIA_SetIncomingUSSD,
2829 DCT3DCT4_SendDTMF,
2830 N6110_GetRingtone,
2831 N6110_SetRingtone,
2832 NOTSUPPORTED, /* GetRingtonesInfo */
2833 NOTSUPPORTED, /* DeleteUserRingtones */
2834 DCT3_PlayTone,
2835 DCT3_GetWAPBookmark,
2836 DCT3_SetWAPBookmark,
2837 DCT3_DeleteWAPBookmark,
2838 DCT3_GetWAPSettings,
2839 DCT3_SetWAPSettings,
2840 NOTSUPPORTED, /* GetMMSSettings */
2841 NOTSUPPORTED, /* SetMMSSettings */
2842 NOTSUPPORTED, /* GetSyncMLSettings*/
2843 NOTSUPPORTED, /* SetSyncMLSettings*/
2844 NOTSUPPORTED, /* GetChatSettings */
2845 NOTSUPPORTED, /* SetChatSettings */
2846 N6110_GetBitmap,
2847 N6110_SetBitmap,
2848 NOTSUPPORTED, /* GetToDoStatus */
2849 NOTSUPPORTED, /* GetToDo */
2850 NOTSUPPORTED, /* GetNextToDo */
2851 NOTSUPPORTED, /* SetToDo */
2852 NOTSUPPORTED, /* AddToDo */
2853 NOTSUPPORTED, /* DeleteToDo */
2854 NOTSUPPORTED, /* DeleteAllToDo */
2855 NOTIMPLEMENTED, /* GetCalendarStatus */
2856 NOTIMPLEMENTED, /* GetCalendar */
2857 N6110_GetNextCalendarNote,
2858 NOTIMPLEMENTED, /* SetCalendar */
2859 N6110_AddCalendarNote,
2860 N6110_DeleteCalendarNote,
2861 NOTIMPLEMENTED, /* DeleteAllCalendar */
2862 NOTSUPPORTED, /* GetCalendarSettings */
2863 NOTSUPPORTED, /* SetCalendarSettings */
2864 NOTSUPPORTED, /* GetNote */
2865 N6110_GetProfile,
2866 N6110_SetProfile,
2867 NOTSUPPORTED, /* GetFMStation */
2868 NOTSUPPORTED, /* SetFMStation */
2869 NOTSUPPORTED, /* ClearFMStations */
2870 NOTSUPPORTED, /* GetNextFileFolder */
2871 NOTSUPPORTED, /* GetFilePart */
2872 NOTSUPPORTED, /* AddFile */
2873 NOTSUPPORTED, /* GetFileSystemStatus */
2874 NOTSUPPORTED, /* DeleteFile */
2875 NOTSUPPORTED, /* AddFolder */
2876 NOTSUPPORTED, /* GetGPRSAccessPoint */
2877 NOTSUPPORTED /* SetGPRSAccessPoint */
2878};
2879
2880#endif
2881
2882/* How should editor hadle tabs in this file? Add editor commands here.
2883 * vim: noexpandtab sw=8 ts=8 sts=8:
2884 */