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