Update: orig2001_12_04_22_45 -> orig2001_12_14_20_46
[gnokii.git] / common / phones / nk7110.c
1 /*
2
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 2000 Hugh Blemings & Pavel Janík ml.
10   Copyright (C) 2000 Chris Kemp
11   Copyright (C) 2001 Markus Plail, Pawe³ Kot
12
13   Released under the terms of the GNU GPL, see file COPYING for more details.
14
15   This file provides functions specific to the 7110 series. 
16   See README for more details on supported mobile phones.
17
18   The various routines are called P7110_(whatever).
19
20 */
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25
26 #define __phones_nk7110_c  /* Turn on prototypes in phones/nk7110.h */
27 #include "misc.h"
28 #include "gsm-common.h"
29 #include "phones/generic.h"
30 #include "phones/nk7110.h"
31 #include "links/fbus.h"
32 #include "links/fbus-phonet.h"
33 #include "phones/nokia.h"
34 #include "gsm-encoding.h"
35
36 #ifdef WIN32
37 #define snprintf _snprintf
38 #endif
39
40 /* Some globals */
41
42 static const SMSMessage_Layout nk7110_deliver = {
43         true,
44         0, 21, 0, 0, 7, 0, 0, -1, 24, 23, 0, 21,
45         9, true, 25, true, 37, -1,
46         5, 4,
47         44, true
48 };
49
50 static const SMSMessage_Layout nk7110_submit = {
51         true,
52         -1, 18, 18, 18, -1, 19, 20, -1, 22, 21, 18, 18,
53         6, true, 23, true, -1, -1,
54         -1, -1,
55         42, true
56 };
57
58 static const SMSMessage_Layout nk7110_delivery_report = {
59         true,
60         0, 0, 0, 0, 7, 0, 0, 0, 23, 22, -1, 21,
61         9, true, 24, true, 36, 43,
62         5, 4,
63         23, true
64 };
65
66 static const SMSMessage_Layout nk7110_picture = {
67         true,
68         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69         9, true, 22, true, 34, -1,
70         0, 0,
71         47, true
72 };
73
74 static SMSMessage_PhoneLayout nk7110_layout;
75
76 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
77         { P7110_MSG_FOLDER,     P7110_IncomingFolder },
78         { P7110_MSG_SMS,        P7110_IncomingSMS },
79         { P7110_MSG_PHONEBOOK,  P7110_IncomingPhonebook },
80         { P7110_MSG_NETSTATUS,  P7110_IncomingNetwork },
81         { P7110_MSG_CALENDAR,   P7110_IncomingCalendar },
82         { P7110_MSG_BATTERY,    P7110_IncomingBattLevel },
83         { P7110_MSG_CLOCK,      P7110_IncomingClock },
84         { P7110_MSG_IDENTITY,   P7110_Incoming0x1b },
85         { P7110_MSG_STLOGO,     P7110_IncomingStartup },
86         { P7110_MSG_DIVERT,     P7110_IncomingCallDivert },
87         { 0, NULL }
88 };
89
90 GSM_Phone phone_nokia_7110 = {
91         P7110_IncomingFunctions,
92         PGEN_IncomingDefault,
93         /* Mobile phone information */
94         {
95                 "7110|6210|6250",      /* Supported models */
96                 7,                     /* Max RF Level */
97                 0,                     /* Min RF Level */
98                 GRF_Percentage,        /* RF level units */
99                 7,                     /* Max Battery Level */
100                 0,                     /* Min Battery Level */
101                 GBU_Percentage,        /* Battery level units */
102                 GDT_DateTime,          /* Have date/time support */
103                 GDT_TimeOnly,          /* Alarm supports time only */
104                 1,                     /* Alarms available - FIXME */
105                 60, 96,                /* Startup logo size - 7110 is fixed at init */
106                 21, 78,                /* Op logo size */
107                 14, 72                 /* Caller logo size */
108         },
109         P7110_Functions
110 };
111
112 /* FIXME - a little macro would help here... */
113
114 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
115 {
116         switch (op) {
117         case GOP_Init:
118                 return P7110_Initialise(state);
119         case GOP_GetModel:
120                 return P7110_GetModel(data, state);
121         case GOP_GetRevision:
122                 return P7110_GetRevision(data, state);
123         case GOP_GetImei:
124                 return P7110_GetIMEI(data, state);
125         case GOP_Identify:
126                 return P7110_Identify(data, state);
127         case GOP_GetBatteryLevel:
128                 return P7110_GetBatteryLevel(data, state);
129         case GOP_GetRFLevel:
130                 return P7110_GetRFLevel(data, state);
131         case GOP_GetMemoryStatus:
132                 return P7110_GetMemoryStatus(data, state);
133         case GOP_GetBitmap:
134                 return P7110_GetBitmap(data, state);
135         case GOP_SetBitmap:
136                 return P7110_SetBitmap(data, state);
137         case GOP_ReadPhonebook:
138                 return P7110_ReadPhonebook(data, state);
139         case GOP_WritePhonebook:
140                 return P7110_WritePhonebookLocation(data, state);
141         case GOP_GetNetworkInfo:
142                 return P7110_GetNetworkInfo(data, state);
143         case GOP_GetSpeedDial:
144                 return P7110_GetSpeedDial(data, state);
145         case GOP_GetSMSCenter:
146                 return P7110_GetSMSCenter(data, state);
147         case GOP_GetDateTime:
148                 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
149         case GOP_GetAlarm:
150                 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
151         case GOP_GetCalendarNote:
152                 return P7110_GetCalendarNote(data, state);
153         case GOP_GetSMS:
154                 return P7110_GetSMS(data, state);
155         case GOP_SendSMS:
156                 return P7110_SendSMS(data, state);
157         case GOP_CallDivert:
158                 return P7110_CallDivert(data, state);
159 /* I'm not sure yet if folder functions will be shared or local
160         case GOP_GetSMSFolders:
161                 return P7110_GetSMSFolders(data, state);
162         case GOP_GetSMSFolderStatus:
163         return P7110_GetSMSFolderStatus(data, state);*/
164         default:
165                 return GE_NOTIMPLEMENTED;
166         }
167 }
168
169 /* LinkOK is always true for now... */
170 bool P7110_LinkOK = true;
171
172 /* Initialise is the only function allowed to 'use' state */
173 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
174 {
175         GSM_Data data;
176         char model[10];
177         GSM_Error err;
178         int try = 0, connected = 0;
179
180         /* Copy in the phone info */
181         memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
182
183         /* SMS Layout */
184         nk7110_layout.Type = 8; /* Locate the Type of the mesage field */
185         nk7110_layout.Deliver = nk7110_deliver;
186         nk7110_layout.Submit = nk7110_submit;
187         nk7110_layout.DeliveryReport = nk7110_delivery_report;
188         nk7110_layout.Picture = nk7110_picture;
189         layout = nk7110_layout;
190
191         dprintf("Connecting\n");
192         while (!connected) {
193                 switch (state->Link.ConnectionType) {
194                 case GCT_DAU9P:
195                         if (try == 0) try = 1;
196                 case GCT_Serial:
197                         if (try > 1) return GE_NOTSUPPORTED;
198                         err = FBUS_Initialise(&(state->Link), state, 1 - try);
199                         break;
200                 case GCT_Infrared:
201                 case GCT_Irda:
202                         if (try > 0) return GE_NOTSUPPORTED;
203                         err = PHONET_Initialise(&(state->Link), state);
204                         break;
205                 default:
206                         return GE_NOTSUPPORTED;
207                         break;
208                 }
209
210                 if (err != GE_NONE) {
211                         dprintf("Error in link initialisation: %d\n", err);
212                         try++;
213                         continue;
214                 }
215
216                 SM_Initialise(state);
217
218                 /* Now test the link and get the model */
219                 GSM_DataClear(&data);
220                 data.Model = model;
221                 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
222                 else connected = 1;
223         }
224         /* Check for 7110 and alter the startup logo size */
225         if (strcmp(model, "NSE-5") == 0) {
226                 state->Phone.Info.StartupLogoH = 65;
227                 dprintf("7110 detected - startup logo height set to 65\n");
228         }
229         return GE_NONE;
230 }
231
232 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
233 {
234         unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
235   
236         dprintf("Getting model...\n");
237         if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
238         return SM_Block(state, data, 0x1b);
239 }
240
241 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
242 {
243         unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
244   
245         dprintf("Getting revision...\n");
246         if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
247         return SM_Block(state, data, 0x1b);
248 }
249
250 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
251 {
252         unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
253   
254         dprintf("Getting imei...\n");
255         if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
256         return SM_Block(state, data, 0x1b);
257 }
258
259 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
260 {
261         unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
262
263         dprintf("Getting battery level...\n");
264         if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
265         return SM_Block(state, data, 0x17);
266 }
267
268 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
269 {
270         switch (message[3]) {
271         case 0x03:
272                 if (data->BatteryLevel) { 
273                         *(data->BatteryUnits) = GBU_Percentage;
274                         *(data->BatteryLevel) = message[5];
275                         dprintf("Battery level %f\n",*(data->BatteryLevel));
276                 }
277                 break;
278         default:
279                 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
280                 return GE_UNKNOWN;
281         }
282         return GE_NONE;
283 }
284
285 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
286 {
287         unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
288
289         dprintf("Getting rf level...\n");
290         if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
291         return SM_Block(state, data, 0x0a);
292 }
293
294 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
295 {
296         unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
297
298         dprintf("Getting Network Info...\n");
299         if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
300         return SM_Block(state, data, 0x0a);
301 }
302
303 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
304 {
305         unsigned char *blockstart;
306         int i;
307         
308         switch (message[3]) {
309         case 0x71:
310                 blockstart = message + 6;
311                 for (i = 0; i < message[4]; i++) {
312                         switch (blockstart[0]) {
313                         case 0x01:  /* Operator details */
314                                 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
315                                 if (data->NetworkInfo) {
316                                         /* Is this correct? */
317                                         data->NetworkInfo->CellID[0]=blockstart[4];
318                                         data->NetworkInfo->CellID[1]=blockstart[5];
319                                         data->NetworkInfo->LAC[0]=blockstart[6];
320                                         data->NetworkInfo->LAC[1]=blockstart[7];
321                                         data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
322                                         data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
323                                         data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
324                                         data->NetworkInfo->NetworkCode[3] = ' ';
325                                         data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
326                                         data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
327                                         data->NetworkInfo->NetworkCode[6] = 0;
328                                 }
329                                 if (data->Bitmap) {
330                                         data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
331                                         data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
332                                         data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
333                                         data->Bitmap->netcode[3] = ' ';
334                                         data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
335                                         data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
336                                         data->Bitmap->netcode[6] = 0;
337                                         dprintf("Operator %s ",data->Bitmap->netcode);
338                                 }
339                                 break;
340                         case 0x04: /* Logo */
341                                 if (data->Bitmap) {
342                                         dprintf("Op logo received ok ");
343                                         data->Bitmap->type = GSM_OperatorLogo;
344                                         data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
345                                         data->Bitmap->height = blockstart[3];
346                                         data->Bitmap->width = blockstart[2];
347                                         memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
348                                         dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
349                                 }
350                                 break;
351                         default:
352                                 dprintf("Unknown operator block %d\n", blockstart[0]);
353                                 break;
354                         }
355                         blockstart += blockstart[1];
356                 }
357                 break;
358         case 0x82:
359                 if (data->RFLevel) { 
360                         *(data->RFUnits) = GRF_Percentage;
361                         *(data->RFLevel) = message[4];
362                         dprintf("RF level %f\n",*(data->RFLevel));
363                 }
364                 break;
365         case 0xa4:
366                 dprintf("Op Logo Set OK\n");
367                 break;
368         default:
369                 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
370                 return GE_UNKNOWN;
371         }
372         return GE_NONE;
373 }
374
375 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
376 {
377         unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
378       
379         dprintf("Getting memory status...\n");
380         req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
381         if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
382         return SM_Block(state, data, 0x03);
383 }
384
385 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
386 {
387         unsigned char *blockstart;
388         unsigned char blocks;
389         unsigned char subblockcount;
390         char *str;
391         int i;
392         GSM_SubPhonebookEntry* subEntry = NULL;
393
394         PGEN_DebugMessage(messagetype, message, length);
395
396         switch (message[3]) {
397         case 0x04:  /* Get status response */
398                 if (data->MemoryStatus) {
399                         if (message[5] != 0xff) {
400                                 data->MemoryStatus->Used = (message[16] << 8) + message[17];
401                                 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
402                                 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
403                         } else {
404                                 dprintf("Unknown error getting mem status\n");
405                                 return GE_NOTIMPLEMENTED;
406                         }
407                 }
408                 break;
409         case 0x08:  /* Read Memory response */
410                 if (data->PhonebookEntry) {
411                         data->PhonebookEntry->Empty = true;
412                         data->PhonebookEntry->Group = 0;
413                         data->PhonebookEntry->Name[0] = '\0';
414                         data->PhonebookEntry->Number[0] = '\0';
415                         data->PhonebookEntry->SubEntriesCount = 0;
416                         data->PhonebookEntry->Date.Year = 0;
417                         data->PhonebookEntry->Date.Month = 0;
418                         data->PhonebookEntry->Date.Day = 0;
419                         data->PhonebookEntry->Date.Hour = 0;
420                         data->PhonebookEntry->Date.Minute = 0;
421                         data->PhonebookEntry->Date.Second = 0;
422                 }
423                 if (message[6] == 0x0f) { // not found
424                         if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
425                                 dprintf("Invalid caller location\n");
426                                 return GE_INVALIDPHBOOKLOCATION;
427                         } else {
428                                 dprintf("Unknown error getting phonebook\n");
429                                 return GE_NOTIMPLEMENTED;
430                         }
431                 }
432                 dprintf("Received phonebook info\n");
433                 blocks     = message[17];        
434                 blockstart = message + 18;
435                 subblockcount = 0;
436            
437                 for (i = 0; i < blocks; i++) {
438                         if (data->PhonebookEntry)
439                                 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
440                         switch(blockstart[0]) {
441                         case P7110_ENTRYTYPE_POINTER:   /* Pointer */
442                                 switch (message[11]) {  /* Memory type */
443                                 case P7110_MEMORY_SPEEDDIALS:   /* Speed dial numbers */
444                                         if ((data != NULL) && (data->SpeedDial != NULL)) {
445                                                 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
446                                                 switch(blockstart[8]) {
447                                                 case 0x05:
448                                                         data->SpeedDial->MemoryType = GMT_ME;
449                                                         str = "phone";
450                                                         break;
451                                                 case 0x06:
452                                                         str = "SIM";
453                                                         data->SpeedDial->MemoryType = GMT_SM;
454                                                         break;
455                                                 default:
456                                                         str = "unknown";
457                                                         data->SpeedDial->MemoryType = GMT_XX;
458                                                         break;
459                                                 }
460                                         }
461                                         
462                                         dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
463                                         
464                                         break;
465                                 default:
466                                         /* FIXME: is it possible? */
467                                         dprintf("Wrong memory type(?)\n");
468                                         break;
469                                 }
470                                 
471                                 break;
472                         case P7110_ENTRYTYPE_NAME:      /* Name */
473                                 if (data->Bitmap) {
474                                         DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
475                                         dprintf("Name: %s\n", data->Bitmap->text);
476                                 } else if (data->PhonebookEntry) {
477                                         DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
478                                         data->PhonebookEntry->Empty = false;
479                                         dprintf("   Name: %s\n", data->PhonebookEntry->Name);
480                                 }
481                                 break;
482                         case P7110_ENTRYTYPE_EMAIL:
483                         case P7110_ENTRYTYPE_POSTAL:
484                         case P7110_ENTRYTYPE_NOTE:
485                                 if (data->PhonebookEntry) {
486                                         subEntry->EntryType   = blockstart[0];
487                                         subEntry->NumberType  = 0;
488                                         subEntry->BlockNumber = blockstart[4];
489                                         DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
490                                         dprintf("   Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
491                                         dprintf("   Text: %s\n", subEntry->data.Number);
492                                         subblockcount++;
493                                         data->PhonebookEntry->SubEntriesCount++;
494                                 }
495                                 break;
496                         case P7110_ENTRYTYPE_NUMBER:
497                                 if (data->PhonebookEntry) {
498                                         subEntry->EntryType   = blockstart[0];
499                                         subEntry->NumberType  = blockstart[5];
500                                         subEntry->BlockNumber = blockstart[4];
501                                         DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
502                                         if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
503                                         dprintf("   Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
504                                         dprintf(" Number: %s\n", subEntry->data.Number);                                        
505                                         subblockcount++;
506                                         data->PhonebookEntry->SubEntriesCount++;
507                                 }
508                                 break;
509                         case P7110_ENTRYTYPE_RINGTONE:  /* Ringtone */
510                                 if (data->Bitmap) {
511                                         data->Bitmap->ringtone = blockstart[5];
512                                         dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
513                                 }
514                                 break;
515                         case P7110_ENTRYTYPE_DATE:
516                                 if (data->PhonebookEntry) {
517                                         subEntry->EntryType=blockstart[0];
518                                         subEntry->NumberType=blockstart[5];
519                                         subEntry->BlockNumber=blockstart[4];
520                                         subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
521                                         subEntry->data.Date.Month  = blockstart[8];
522                                         subEntry->data.Date.Day    = blockstart[9];
523                                         subEntry->data.Date.Hour   = blockstart[10];
524                                         subEntry->data.Date.Minute = blockstart[11];
525                                         subEntry->data.Date.Second = blockstart[12];
526                                         dprintf("   Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
527                                                 subEntry->data.Date.Month, subEntry->data.Date.Year);
528                                         dprintf("   Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
529                                                 subEntry->data.Date.Minute, subEntry->data.Date.Second);
530                                         subblockcount++;
531                                 }
532                                 break;
533                         case P7110_ENTRYTYPE_LOGO:      /* Caller group logo */
534                                 if (data->Bitmap) {
535                                         data->Bitmap->width = blockstart[5];
536                                         data->Bitmap->height = blockstart[6];
537                                         data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
538                                         memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
539                                         dprintf("Bitmap\n");
540                                 }
541                                 break;
542                         case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
543                                 break;
544                         case P7110_ENTRYTYPE_GROUP:     /* Caller group number */
545                                 if (data->PhonebookEntry) {
546                                         data->PhonebookEntry->Group = blockstart[5] - 1;
547                                         dprintf("   Group: %d\n", data->PhonebookEntry->Group);
548                                 }
549                                 break;
550                         default:
551                                 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
552                                 break;
553                         }
554                         blockstart += blockstart[3];
555                 }
556                 break;
557         case 0x0c:
558                 switch (message[6]) {
559                 case 0x3d: return GE_PHBOOKWRITEFAILED;
560                 case 0x3e: return GE_PHBOOKWRITEFAILED;
561                 default: return GE_NONE;
562                 }
563                 break;  
564         default:
565                 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
566                 return GE_UNKNOWN;
567         }
568         return GE_NONE;
569 }
570
571 /* Just as an example.... */
572 /* But note that both requests are the same type which isn't very 'proper' */ 
573 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
574 {
575         unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
576         unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
577   
578         dprintf("Identifying...\n");
579         PNOK_GetManufacturer(data->Manufacturer);
580         if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
581         if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
582         SM_WaitFor(state, data, 0x1b);
583         SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
584         SM_GetError(state, 0x1b);
585         
586         /* Check that we are back at state Initialised */
587         if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
588         return GE_NONE;
589 }
590
591 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
592 {
593         switch (message[3]) {
594         case 02:
595                 if (data->Imei) { 
596                         snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
597                         dprintf("Received imei %s\n",data->Imei);
598                 }
599                 break;
600         case 04:
601                 if (data->Model) { 
602                         snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
603                         dprintf("Received model %s\n",data->Model);
604                 }
605                 if (data->Revision) { 
606                         snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
607                         dprintf("Received revision %s\n",data->Revision);
608                 }
609                 break;
610         default:
611                 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
612                 return GE_UNKNOWN;
613         }
614         return GE_NONE;
615 }
616
617
618 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
619 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
620 {
621         int i, j;
622         int nextfolder = 0x10;
623         bool found;
624
625         switch (message[3]) {
626         /* getfolders */
627         case 0x7B:
628                 i = 5;
629                 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
630                 dprintf("Message: %d SMS Folders received:\n", message[4]);
631
632                 strcpy(data->SMSFolderList->Folder[1].Name, "               ");
633                 data->SMSFolderList->number = message[4];
634       
635                 for (j = 0; j < message[4]; j++) {
636                         int len;
637                         strcpy(data->SMSFolderList->Folder[j].Name, "               ");
638                         data->SMSFolderList->FolderID[j] = message[i];
639                         dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
640                         i += 2;
641                         dprintf("   Folder name: ");
642                         len = 0;
643                         /* search for next folder's index number, i.e. length of folder name */
644                         while (message[i+1] != nextfolder && i < length) {
645                                 i += 2;
646                                 len++;
647                         }
648                         /* see nk7110.txt */
649                         nextfolder += 0x08;
650                         if (nextfolder == 0x28) nextfolder++;
651                         i -= 2 * len +1;
652                         DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
653                         dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
654                         i += 2 * len + 2;
655                 }
656                 break;
657
658         /* getfolderstatus */
659         case 0x6C:
660                 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
661                 dprintf("Message: SMS Folder status received: \n" );
662                 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
663                 data->SMSFolder->number = (message[5] * 256) + message[5];
664                 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
665                 dprintf("Message: IDs of Entries : ");
666                 for (i = 0; i < message[4] * 256 + message[5]; i++) {
667                         data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
668                         dprintf("%d, ", data->SMSFolder->locations[i]);
669                 }
670                 dprintf("\n");
671                 break;
672
673         /* getsms */    
674         case 0x08:
675                 for (i = 0; i < length; i ++)
676                         if (isprint(message[i]))
677                                 dprintf("[%02x%c]", message[i], message[i]);
678                         else
679                                 dprintf("[%02x ]", message[i]);
680                 dprintf("\n");
681
682                 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
683
684                 /* Number of SMS in folder */
685                 data->SMSMessage->Number = message[7];
686
687                 /* MessageType/FolderID */
688                 data->SMSMessage->MemoryType = message[5];
689
690                 /* Short Message status */
691                 data->SMSMessage->Status = message[4];
692                 dprintf("\tStatus: ");
693                 switch (data->SMSMessage->Status) {
694                 case SMS_Read:
695                         dprintf("READ\n");
696                         break;
697                 case SMS_Unread:
698                         dprintf("UNREAD\n");
699                         break;
700                 case SMS_Sent:
701                         dprintf("SENT\n");
702                         break;
703                 case SMS_Unsent:
704                         dprintf("UNSENT\n");
705                         break;
706                 default:
707                         dprintf("UNKNOWN\n");
708                         break;
709                 }
710                 /* See if message# is given back by phone. If not and status is unread */
711                 /* we want it, if status is not unread it's a "random" message given back */
712                 /* by the phone because we want a message of which the # doesn't exist */
713                 found = false;
714                 for (i = 0; i < data->SMSFolder->number; i++) {
715                         if (data->SMSMessage->Number == data->SMSFolder->locations[i]) 
716                                 found = true;
717                 }
718                 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
719
720                 DecodePDUSMS(message, data->SMSMessage, length);
721
722                 break;
723
724                 /* get list of SMS pictures */
725                 case 0x97:
726                 dprintf("Getting list of SMS pictures...\n");
727                 for (i = 0; i < length; i ++)
728                         if (isprint(message[i]))
729                                 dprintf("[%02x%c]", message[i], message[i]);
730                         else
731                                 dprintf("[%02x ]", message[i]);
732                 dprintf("\n");
733                 break;
734         default:
735
736                 for (i = 0; i < length; i ++)
737                         if (isprint(message[i]))
738                                 dprintf("[%02x%c]", message[i], message[i]);
739                         else
740                                 dprintf("[%02x ]", message[i]);
741                 dprintf("\n");
742                 dprintf("Message: Unknown message of type 14 : %d  length: %d\n", message[3], length);
743                 return GE_UNKNOWN;
744         }
745         return GE_NONE;
746 }
747
748 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
749 {
750         unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
751         unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b, 
752                                 0x08, // Folder ID
753                                 0x0f, 0x01};
754         unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07, 
755                                 0x08, // FolderID
756                                 0x00, 
757                                 0x01, // Location
758                                 0x01, 0x65, 0x01};
759         unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96, 
760                                          0x09, /* location */
761                                          0x0f, 0x07};
762         GSM_Error error;
763
764         /* just testiung picture listing */
765         req_list[4] = data->SMSMessage->MemoryType;
766         if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
767         error = SM_Block(state, data, 0x14);
768
769         /* see if the message we want is from the last read folder, i.e. */
770         /* we don't have to get folder status again */
771         if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
772
773                 dprintf("Getting list of SMS folders...\n");
774                 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
775                 error = SM_Block(state, data, 0x14);
776
777                 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
778                         return GE_INVALIDMEMORYTYPE;
779                 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
780                 req_status[4] = data->SMSMessage->MemoryType;
781
782                 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
783                 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
784                 error = SM_Block(state, data, 0x14);
785         }
786         
787         dprintf("Getting SMS...\n");
788         req_sms[4] = data->SMSMessage->MemoryType;
789         req_sms[6] = data->SMSMessage->Number;
790         if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
791         return SM_Block(state, data, 0x14);
792 }
793
794 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
795 {
796         unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96, 
797                                          0x09, /* location */
798                                          0x0f, 0x07};
799         if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
800         return SM_Block(state, data, 0x14);
801 }
802
803 #if 0
804 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
805 {
806         unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
807       
808         dprintf("Getting SMS Folders...\n");
809         if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
810         return SM_Block(state, data, 0x14);
811 }
812
813 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
814 {
815         unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B, 
816                                 0x08, // Folder ID
817                                 0x0F, 0x01};
818       
819         req[4] = data->SMSFolder->FolderID;
820         dprintf("Getting SMS Folder Status...\n");
821         if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
822         return SM_Block(state, data, 0x14);
823 }
824 #endif
825
826 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
827 {
828         GSM_Error e = GE_NONE;
829         unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
830         int length, i;
831
832         if (data->SMSMessage->MessageCenter.No) {
833                 data->MessageCenter = &data->SMSMessage->MessageCenter;
834                 P7110_GetSMSCenter(data, state);
835         }
836
837         length = EncodePDUSMS(data->SMSMessage, req);
838         if (!length) return GE_SMSWRONGFORMAT;
839         dprintf("Sending SMS...(%d)\n", length);
840         for (i = 0; i < length; i++) {
841                 dprintf("%02x ", req[i]);
842         }
843         dprintf("\n");
844         if (SM_SendMessage(state, length, 0x02, req) != GE_NONE) return GE_NOTREADY;
845         while (1) {
846                 e = SM_Block(state, data, 0x02);
847                 if (e == GE_SMSSENDOK || e == GE_SMSSENDFAILED) break;
848         }
849         return e;
850 }
851
852 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
853 {
854         GSM_Error       e = GE_NONE;
855         int             digits, bytes;
856
857         if (!data) return GE_INTERNALERROR;
858
859         switch (message[3]) {
860         case P7110_SUBSMS_SMSC_RCVD:
861                 dprintf("SMSC Received\n");
862                 /* FIXME: Implement all these in gsm-sms.c */
863                 data->MessageCenter->No = message[4];
864                 data->MessageCenter->Format = message[6];
865                 data->MessageCenter->Validity = message[8];  /* due to changes in format */
866                 digits = message[9];
867                 bytes = message[21] - 1;
868                 
869
870                 sprintf(data->MessageCenter->Name, "%s", message + 33);
871                 
872                 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
873                 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
874                 data->MessageCenter->Type = message[22];
875                 
876                 if (strlen(data->MessageCenter->Recipient) == 0) {
877                         sprintf(data->MessageCenter->Recipient, "(none)");
878                 }
879                 if (strlen(data->MessageCenter->Number) == 0) {
880                         sprintf(data->MessageCenter->Number, "(none)");
881                 }
882                 if(strlen(data->MessageCenter->Name) == 0) {
883                         sprintf(data->MessageCenter->Name, "(none)");
884                 }
885                 
886                 break;
887
888         case P7110_SUBSMS_SMS_SENT:
889                 dprintf("SMS sent\n");
890                 e = GE_SMSSENDOK;
891                 break;
892
893         case P7110_SUBSMS_SEND_FAIL:
894                 dprintf("SMS sending failed\n");
895                 e = GE_SMSSENDFAILED;
896                 break;
897
898         case P7110_SUBSMS_SMS_RCVD:
899         case P7110_SUBSMS_CELLBRD_OK:
900         case P7110_SUBSMS_CELLBRD_FAIL:
901         case P7110_SUBSMS_READ_CELLBRD:
902         case P7110_SUBSMS_SMSC_OK:
903         case P7110_SUBSMS_SMSC_FAIL:
904         case P7110_SUBSMS_SMSC_RCVFAIL:
905                 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
906                 e = GE_NOTIMPLEMENTED;
907                 break;
908
909         default:
910                 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
911                 e = GE_UNKNOWN;
912                 break;
913         }
914         return e;
915 }
916
917 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
918 {
919         GSM_Error       e = GE_NONE;
920
921         if (!data || !data->DateTime) return GE_INTERNALERROR;  
922         switch (message[3]) {
923         case P7110_SUBCLO_DATE_RCVD:
924                 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
925                 data->DateTime->Month = message[10];
926                 data->DateTime->Day = message[11];
927                 data->DateTime->Hour = message[12];
928                 data->DateTime->Minute = message[13];
929                 data->DateTime->Second = message[14];
930
931                 break;
932         case P7110_SUBCLO_ALARM_RCVD: 
933                 switch(message[8]) {
934                 case P7110_ALARM_ENABLED:
935                         data->DateTime->AlarmEnabled = 1;
936                         break;
937                 case P7110_ALARM_DISABLED:
938                         data->DateTime->AlarmEnabled = 0;
939                         break;
940                 default:
941                         data->DateTime->AlarmEnabled = -1;
942                         dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
943                         e = GE_UNKNOWN;
944                         break;
945                 }
946                 
947                 data->DateTime->Hour = message[9];
948                 data->DateTime->Minute = message[10];
949                 
950                 break;
951         default:
952                 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
953                 e = GE_UNKNOWN;
954                 break;
955         }
956         return e;
957 }
958
959 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
960 {
961         time_t                          t_alarm;
962         struct tm                       tm_time;
963         struct tm                       *tm_alarm;
964         GSM_Error                       e = GE_NONE;
965         
966         if (!time || !alarm) return GE_INTERNALERROR;
967         
968         memset(&tm_time, 0, sizeof(tm_time));
969         tm_time.tm_year = time->Year - 1900;
970         tm_time.tm_mon = time->Month - 1;
971         tm_time.tm_mday = time->Day;
972         tm_time.tm_hour = time->Hour;
973         tm_time.tm_min = time->Minute;
974
975         tzset();
976         t_alarm = mktime(&tm_time);
977         t_alarm -= alarmdiff;
978         t_alarm += timezone;
979
980         tm_alarm = localtime(&t_alarm);
981
982         alarm->Year = tm_alarm->tm_year + 1900;
983         alarm->Month = tm_alarm->tm_mon + 1;
984         alarm->Day = tm_alarm->tm_mday;
985         alarm->Hour = tm_alarm->tm_hour;
986         alarm->Minute = tm_alarm->tm_min;
987         alarm->Second = tm_alarm->tm_sec;
988
989         return e;
990 }
991
992
993 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
994 {
995         time_t          alarmdiff;
996         GSM_Error       e = GE_NONE;
997         
998         if (!c) return GE_INTERNALERROR;
999
1000         c->Time.Hour = block[0];
1001         c->Time.Minute = block[1];
1002         c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1003         alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1004         
1005         if (alarmdiff != 0xffff) {
1006                 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1007                 c->Alarm.AlarmEnabled = 1;
1008         } else {
1009                 c->Alarm.AlarmEnabled = 0;
1010         }
1011                 
1012         return e;
1013 }
1014
1015 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1016 {
1017         GSM_Error                       e = GE_NONE;
1018         unsigned char                   *block;
1019         int                             i, alarm, year;
1020         
1021         if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1022
1023         year =  data->CalendarNote->Time.Year;
1024         dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1025         switch (message[3]) {
1026         case P7110_SUBCAL_NOTE_RCVD:
1027                 block = message + 12;
1028                         
1029                 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1030                 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1031                 data->CalendarNote->Time.Month = message[10];
1032                 data->CalendarNote->Time.Day = message[11];
1033                 data->CalendarNote->Time.Second = 0;
1034                         
1035                 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1036                         
1037                 switch (message[6]) {
1038                 case P7110_NOTE_MEETING:
1039                         data->CalendarNote->Type = GCN_MEETING;
1040                         P7110_GetNoteTimes(block, data->CalendarNote);
1041                         DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1042                         break;
1043                 case P7110_NOTE_CALL:
1044                         data->CalendarNote->Type = GCN_CALL;
1045                         P7110_GetNoteTimes(block, data->CalendarNote);
1046                         DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1047                         DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1048                         break;
1049                 case P7110_NOTE_REMINDER:
1050                         data->CalendarNote->Type = GCN_REMINDER;
1051                         data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1052                         DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1053                         break;
1054                 case P7110_NOTE_BIRTHDAY:
1055                         
1056                         for (i = 0; i < 10; i++) {
1057                                 dprintf("(%i:0x%02x)", i, block[i]);
1058                         }
1059                         dprintf("\n");
1060                         
1061                         data->CalendarNote->Type = GCN_BIRTHDAY;
1062                         data->CalendarNote->Time.Year = year;
1063                         data->CalendarNote->Time.Hour = 23;
1064                         data->CalendarNote->Time.Minute = 59;
1065                         data->CalendarNote->Time.Second = 58;
1066                         
1067                         alarm = ((unsigned int)block[2]) << 24;
1068                         alarm += ((unsigned int)block[3]) << 16;
1069                         alarm += ((unsigned int)block[4]) << 8;
1070                         alarm += block[5];
1071                         
1072                         dprintf("alarm: %i\n", alarm);
1073                         
1074                         if (alarm == 0xffff) {
1075                                 data->CalendarNote->Alarm.AlarmEnabled = 0;
1076                         } else {
1077                                 data->CalendarNote->Alarm.AlarmEnabled = 1;
1078                         }
1079                         
1080                         P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1081                         
1082                         data->CalendarNote->Time.Hour = 0;
1083                         data->CalendarNote->Time.Minute = 0;
1084                         data->CalendarNote->Time.Second = 0;
1085                         data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1086                         
1087                         DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1088                         
1089                         break;
1090                 default:
1091                         data->CalendarNote->Type = -1;
1092                         e = GE_UNKNOWN;
1093                         break;
1094                 }
1095                 
1096                 break;
1097         case P7110_SUBCAL_ADD_MEETING_RESP:
1098         case P7110_SUBCAL_ADD_CALL_RESP:
1099         case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1100         case P7110_SUBCAL_ADD_REMINDER_RESP:
1101         case P7110_SUBCAL_DEL_NOTE_RESP:
1102         case P7110_SUBCAL_FREEPOS_RCVD:
1103         case P7110_SUBCAL_INFO_RCVD:
1104                 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1105                 e = GE_NOTIMPLEMENTED;
1106                 break;
1107         default:
1108                 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1109                 e = GE_UNKNOWN;
1110                 break;
1111         }
1112         return e;
1113 }
1114
1115 static GSM_Error P7110_CallDivert(GSM_Data *data, GSM_Statemachine *state)
1116 {
1117         unsigned short length = 0x09;
1118         char req[55] = { FBUS_FRAME_HEADER, 0x01, 0x00, /* operation */
1119                                                 0x00,
1120                                                 0x00, /* divert type */
1121                                                 0x00, /* call type */
1122                                                 0x00 };
1123         if (!data->CallDivert) return GE_UNKNOWN;
1124         switch (data->CallDivert->Operation) {
1125         case GSM_CDV_Query:
1126                 req[4] = 0x05;
1127                 break;
1128         case GSM_CDV_Register:
1129                 req[4] = 0x03;
1130                 length = 0x16;
1131                 req[8] = 0x01;
1132                 req[9] = SemiOctetPack(data->CallDivert->Number.number, req + 10, data->CallDivert->Number.type);
1133                 req[21] = data->CallDivert->Timeout;
1134                 break;
1135         case GSM_CDV_Erasure:
1136                 req[4] = 0x04;
1137                 break;
1138         default:
1139                 return GE_NOTIMPLEMENTED;
1140         }
1141         switch (data->CallDivert->CType) {
1142         case GSM_CDV_AllCalls:
1143                 break;
1144         case GSM_CDV_VoiceCalls:
1145                 req[7] = 0x0b;
1146                 break;
1147         case GSM_CDV_FaxCalls:
1148                 req[7] = 0x0d;
1149                 break;
1150         case GSM_CDV_DataCalls:
1151                 req[7] = 0x19;
1152                 break;
1153         default:
1154                 return GE_NOTIMPLEMENTED;
1155         }
1156         switch (data->CallDivert->DType) {
1157         case GSM_CDV_AllTypes:
1158                 req[6] = 0x15;
1159                 break;
1160         case GSM_CDV_Busy:
1161                 req[6] = 0x43;
1162                 break;
1163         case GSM_CDV_NoAnswer:
1164                 req[6] = 0x3d;
1165                 break;
1166         case GSM_CDV_OutOfReach:
1167                 req[6] = 0x3e;
1168                 break;
1169         default:
1170                 return GE_NOTIMPLEMENTED;
1171         }
1172         if ((data->CallDivert->DType == GSM_CDV_AllTypes) && (data->CallDivert->CType == GSM_CDV_AllCalls))
1173                 req[6] = 0x02;
1174
1175         if (SM_SendMessage(state, length, P7110_MSG_DIVERT, req) != GE_NONE) return GE_NOTREADY;
1176         return SM_WaitFor(state, data, P7110_MSG_DIVERT);
1177 }
1178
1179 static GSM_Error P7110_IncomingCallDivert(int messagetype, unsigned char *message, int length, GSM_Data *data)
1180 {
1181         int i;
1182         for (i = 0; i < length; i++) {
1183                 dprintf("%02x ", message[i]);
1184         }
1185         dprintf("\n");
1186         return GE_NONE;
1187 }
1188
1189 static int GetMemoryType(GSM_MemoryType memory_type)
1190 {
1191         int result;
1192
1193         switch (memory_type) {
1194         case GMT_MT:
1195                 result = P7110_MEMORY_MT;
1196                 break;
1197         case GMT_ME:
1198                 result = P7110_MEMORY_ME;
1199                 break;
1200         case GMT_SM:
1201                 result = P7110_MEMORY_SM;
1202                 break;
1203         case GMT_FD:
1204                 result = P7110_MEMORY_FD;
1205                 break;
1206         case GMT_ON:
1207                 result = P7110_MEMORY_ON;
1208                 break;
1209         case GMT_EN:
1210                 result = P7110_MEMORY_EN;
1211                 break;
1212         case GMT_DC:
1213                 result = P7110_MEMORY_DC;
1214                 break;
1215         case GMT_RC:
1216                 result = P7110_MEMORY_RC;
1217                 break;
1218         case GMT_MC:
1219                 result = P7110_MEMORY_MC;
1220                 break;
1221         default:
1222                 result = P7110_MEMORY_XX;
1223                 break;
1224         }
1225         return (result);
1226 }
1227
1228 #if 0
1229
1230 static GSM_Error P7110_DialVoice(char *Number)
1231 {
1232
1233   /* Doesn't work (yet) */    /* 3 2 1 5 2 30 35 */
1234
1235         // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1236
1237         unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1238         // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1239         //  unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1240         // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1241         int len = 0/*, i*/;
1242
1243         //req[4]=strlen(Number);
1244
1245         //for(i=0; i < strlen(Number) ; i++)
1246         // req[5+i]=Number[i];
1247
1248         //memcpy(req+5+strlen(Number), req_end, 10);
1249
1250         //len=6+strlen(Number);
1251
1252         //len = 4;
1253
1254         
1255         //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1256         
1257         len=17;
1258
1259         if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1260                 PGEN_DebugMessage(1, req, len);
1261 //              return GE_NONE;
1262
1263         }
1264 //      } else return GE_NOTIMPLEMENTED;
1265
1266  
1267         while(1){
1268                 link.Loop(NULL);
1269         }
1270
1271         return GE_NOTIMPLEMENTED;
1272 }
1273
1274 #endif
1275
1276 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1277 {
1278         unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1279                                   0x00, 0x10 , /* memory type */
1280                                   0x00, 0x00,  /* location */
1281                                   0x00, 0x00};
1282
1283         req[11] = data->Bitmap->number + 1;
1284         dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1285         if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1286         return SM_Block(state, data, 0x03);
1287 }
1288
1289 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1290 {
1291         *(block++) = id;
1292         *(block++) = 0;
1293         *(block++) = 0;
1294         *(block++) = size + 6;
1295         *(block++) = no;
1296         memcpy(block, buf, size);
1297         block += size;
1298         *(block++) = 0;
1299         return (size + 6);
1300 }
1301
1302 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1303 {
1304         unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1305                                   0x00, 0x10,  /* memory type */
1306                                   0x00, 0x00,  /* location */
1307                                   0x00, 0x00, 0x00};
1308         char string[500];
1309         int block, i;
1310         unsigned int count = 18;
1311
1312         if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1313             (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1314                 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n",state->Phone.Info.CallerLogoH, state->Phone.Info.CallerLogoW, data->Bitmap->height, data->Bitmap->width); 
1315             return GE_INVALIDIMAGESIZE;
1316         }       
1317
1318         req[13] = data->Bitmap->number + 1;
1319         dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1320         block = 1;
1321         /* Name */
1322         i = strlen(data->Bitmap->text);
1323         EncodeUnicode((string + 1), data->Bitmap->text, i);
1324         string[0] = i * 2;
1325         count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1326         /* Ringtone */
1327         string[0] = data->Bitmap->ringtone;
1328         string[1] = 0;
1329         count += PackBlock(0x0c, 2, block++, string, req + count);
1330         /* Number */
1331         string[0] = data->Bitmap->number+1;
1332         string[1] = 0;
1333         count += PackBlock(0x1e, 2, block++, string, req + count);
1334         /* Logo on/off - assume on for now */
1335         string[0] = 1;
1336         string[1] = 0;
1337         count += PackBlock(0x1c, 2, block++, string, req + count);
1338         /* Logo */
1339         string[0] = data->Bitmap->width;
1340         string[1] = data->Bitmap->height;
1341         string[2] = 0;
1342         string[3] = 0;
1343         string[4] = 0x7e; /* Size */
1344         memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1345         count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1346         req[17] = block - 1;
1347
1348         if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1349         return SM_Block(state, data, 0x03);
1350 }
1351
1352 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1353 {
1354         unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1355
1356         dprintf("Getting startup logo...\n");
1357         if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1358         return SM_Block(state, data, 0x7a);
1359 }
1360
1361 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1362 {
1363         switch (message[3]) {
1364         case 0xeb:
1365                 dprintf("Startup logo set ok\n");
1366                 return GE_NONE;
1367                 break;
1368         case 0xed:
1369                 if (data->Bitmap) {
1370                         /* I'm sure there are blocks here but never mind! */
1371                         data->Bitmap->type = GSM_StartupLogo;
1372                         data->Bitmap->height = message[13];
1373                         data->Bitmap->width = message[17];
1374                         data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1375                         memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1376                         dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1377                 }
1378                 return GE_NONE;
1379                 break;
1380         default:
1381                 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1382                 return GE_UNKNOWN;
1383                 break;
1384         }
1385 }
1386
1387 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1388 {
1389         unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1390
1391         dprintf("Getting op logo...\n");
1392         if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1393         return SM_Block(state, data, 0x0a);
1394 }
1395
1396 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1397 {
1398         unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1399                                    0x00,           /* Height */
1400                                    0xc0, 0x03, 0x00,
1401                                    0x00,           /* Width */
1402                                    0xc0, 0x04, 0x03, 0x00 };
1403         int count = 21;
1404
1405
1406         if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1407             (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1408                 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n",state->Phone.Info.StartupLogoH, state->Phone.Info.StartupLogoW, data->Bitmap->height, data->Bitmap->width); 
1409             return GE_INVALIDIMAGESIZE;
1410         }
1411
1412         req[12] = data->Bitmap->height;
1413         req[16] = data->Bitmap->width;
1414         memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1415         count += data->Bitmap->size;
1416         dprintf("Setting startup logo...\n");
1417
1418         if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1419         return SM_Block(state, data, 0x7a);
1420 }
1421
1422 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1423 {
1424         unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1425                                    0x00,              /* logo enabled */
1426                                    0x00, 0xf0, 0x00,  /* network code (000 00) */
1427                                    0x00 ,0x04,
1428                                    0x08,              /* length of rest */
1429                                    0x00, 0x00,        /* Bitmap width / height */
1430                                    0x00,
1431                                    0x00,              /* Bitmap size */
1432                                    0x00, 0x00
1433         };    
1434         int count = 18;
1435
1436         if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1437             (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1438                 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n",state->Phone.Info.OpLogoH, state->Phone.Info.OpLogoW, data->Bitmap->height, data->Bitmap->width); 
1439             return GE_INVALIDIMAGESIZE;
1440         }
1441
1442         if (strcmp(data->Bitmap->netcode,"000 00")) {  /* set logo */
1443                 req[5] = 0x01;      // Logo enabled
1444                 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1445                 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1446                 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1447                 req[11] = 8 + data->Bitmap->size;
1448                 req[12] = data->Bitmap->width;
1449                 req[13] = data->Bitmap->height;
1450                 req[15] = data->Bitmap->size;
1451                 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1452                 count += data->Bitmap->size;
1453         }
1454         dprintf("Setting op logo...\n");
1455         if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1456         return SM_Block(state, data, 0x0a);
1457 }
1458
1459 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1460 {
1461         switch(data->Bitmap->type) {
1462         case GSM_CallerLogo:
1463                 return GetCallerBitmap(data, state);
1464         case GSM_StartupLogo:
1465                 return GetStartupBitmap(data, state);
1466         case GSM_OperatorLogo:
1467                 return GetOperatorBitmap(data, state);
1468         default:
1469                 return GE_NOTIMPLEMENTED;
1470         }
1471 }
1472
1473 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1474 {
1475         switch(data->Bitmap->type) {
1476         case GSM_CallerLogo:
1477                 return SetCallerBitmap(data, state);
1478         case GSM_StartupLogo:
1479                 return SetStartupBitmap(data, state);
1480         case GSM_OperatorLogo:
1481                 return SetOperatorBitmap(data, state);
1482         default:
1483                 return GE_NOTIMPLEMENTED;
1484         }
1485 }
1486
1487 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1488 {
1489         unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1490                                   0x00, 0x00,  /* memory type */
1491                                   0x00, 0x00,  /* location */
1492                                   0x00, 0x00, 0x00};
1493         char string[500];
1494         int block, i, j, defaultn;
1495         unsigned int count = 18;
1496         GSM_PhonebookEntry *entry;
1497         
1498         if (data->PhonebookEntry) entry=data->PhonebookEntry;
1499         else return GE_TRYAGAIN;
1500
1501         req[11] = GetMemoryType(entry->MemoryType);
1502         req[12] = (entry->Location >> 8);
1503         req[13] = entry->Location & 0xff;
1504         block = 1;
1505         if (*(entry->Name)) {
1506                 /* Name */
1507                 i = strlen(entry->Name);
1508                 EncodeUnicode((string + 1), entry->Name, i);
1509                 string[0] = i * 2;
1510                 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1511                 /* Group */
1512                 string[0] = entry->Group + 1;
1513                 string[1] = 0;
1514                 count += PackBlock(0x1e, 2, block++, string, req + count);
1515                 /* Default Number */
1516                 defaultn = 999;
1517                 for (i = 0; i < entry->SubEntriesCount; i++)
1518                         if (entry->SubEntries[i].EntryType == GSM_Number)
1519                                 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1520                                         defaultn = i;
1521                 if (defaultn < i) {
1522                         string[0] = entry->SubEntries[defaultn].NumberType;
1523                         string[1] = 0;
1524                         string[2] = 0;
1525                         string[3] = 0;
1526                         i = strlen(entry->SubEntries[defaultn].data.Number);
1527                         EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1528                         string[4] = i * 2;
1529                         count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1530                 }
1531                 /* Rest of the numbers */
1532                 for (i = 0; i < entry->SubEntriesCount; i++)
1533                         if (entry->SubEntries[i].EntryType == GSM_Number)
1534                                 if (i != defaultn) {
1535                                         string[0] = entry->SubEntries[i].NumberType;
1536                                         string[1] = 0;
1537                                         string[2] = 0;
1538                                         string[3] = 0;
1539                                         j = strlen(entry->SubEntries[i].data.Number);
1540                                         EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1541                                         string[4] = j + 2;
1542                                         count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1543                                 } 
1544                 req[17] = block - 1;
1545                 dprintf("Writing phonebook entry %s...\n",entry->Name);
1546         }
1547         if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1548         return SM_Block(state, data, 0x03);
1549 }
1550
1551 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1552 {
1553         GSM_Error       error;
1554         unsigned char   req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1555                                         0x00, 0x00, /* memory type */ //02,05
1556                                         0x00, 0x00, /* location */
1557                                         0x00, 0x00};
1558
1559         dprintf("Reading phonebook location (%d)\n", location);
1560         
1561         req[9] = memtype;
1562         req[10] = location >> 8;
1563         req[11] = location & 0xff;
1564         
1565         if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1566         error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1567         
1568         return error;
1569 }
1570
1571 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1572 {
1573         int memtype, location;
1574         
1575         memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1576         location = data->PhonebookEntry->Location;
1577         
1578         return P7110_ReadPhonebookLL(data, state, memtype, location);
1579 }
1580
1581 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1582 {
1583         int memtype, location;
1584         
1585         memtype = P7110_MEMORY_SPEEDDIALS;
1586         location = data->SpeedDial->Number;
1587         
1588         return P7110_ReadPhonebookLL(data, state, memtype, location);
1589 }
1590
1591 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1592 {
1593         GSM_Error       error;
1594         unsigned char   req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1595         
1596         req[5] = data->MessageCenter->No;
1597         
1598         if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1599         error = SM_Block(state, data, P7110_MSG_SMS);
1600         
1601         return error;
1602 }
1603
1604 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1605 {
1606         GSM_Error       error;
1607         unsigned char   req[] = {FBUS_FRAME_HEADER, req_type};
1608         
1609         if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1610         error = SM_Block(state, data, P7110_MSG_CLOCK);
1611         
1612         return error;
1613 }
1614
1615 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1616 {
1617         GSM_Error       error = GE_NOTREADY;
1618         unsigned char   req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1619         unsigned char   date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1620         GSM_Data        tmpdata;
1621         GSM_DateTime    tmptime;
1622         
1623         tmpdata.DateTime = &tmptime;
1624         if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1625                 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1626                 req[4] = data->CalendarNote->Location >> 8;
1627                 req[5] = data->CalendarNote->Location & 0xff;
1628                 data->CalendarNote->Time.Year = tmptime.Year;
1629                 
1630                 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1631                         error = SM_Block(state, data, P7110_MSG_CALENDAR);
1632                 }
1633         }       
1634         
1635         return error;
1636 }