7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000 Hugh Blemings & Pavel Janík ml.
10 Copyright (C) 2000 Chris Kemp
11 Copyright (C) 2001 Markus Plail, Pawe³ Kot
13 Released under the terms of the GNU GPL, see file COPYING for more details.
15 This file provides functions specific to the 7110 series.
16 See README for more details on supported mobile phones.
18 The various routines are called P7110_(whatever).
26 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.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"
37 #define snprintf _snprintf
42 static const SMSMessage_Layout nk7110_deliver = {
44 0, 21, 0, 0, 7, 0, 0, -1, 24, 23, 0, 21,
45 9, true, 25, true, 37, -1,
50 static const SMSMessage_Layout nk7110_submit = {
52 -1, 18, 18, 18, -1, 19, 20, -1, 22, 21, 18, 18,
53 6, true, 23, true, -1, -1,
58 static const SMSMessage_Layout nk7110_delivery_report = {
60 0, 0, 0, 0, 7, 0, 0, 0, 23, 22, -1, 21,
61 9, true, 24, true, 36, 43,
66 static const SMSMessage_Layout nk7110_picture = {
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 9, true, 22, true, 34, -1,
74 static SMSMessage_PhoneLayout nk7110_layout;
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 },
89 GSM_Phone phone_nokia_7110 = {
90 P7110_IncomingFunctions,
92 /* Mobile phone information */
94 "7110|6210|6250", /* Supported models */
97 GRF_Percentage, /* RF level units */
98 7, /* Max Battery Level */
99 0, /* Min Battery Level */
100 GBU_Percentage, /* Battery level units */
101 GDT_DateTime, /* Have date/time support */
102 GDT_TimeOnly, /* Alarm supports time only */
103 1, /* Alarms available - FIXME */
104 60, 96, /* Startup logo size - 7110 is fixed at init */
105 21, 78, /* Op logo size */
106 14, 72 /* Caller logo size */
111 /* FIXME - a little macro would help here... */
113 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
117 return P7110_Initialise(state);
119 return P7110_GetModel(data, state);
120 case GOP_GetRevision:
121 return P7110_GetRevision(data, state);
123 return P7110_GetIMEI(data, state);
125 return P7110_Identify(data, state);
126 case GOP_GetBatteryLevel:
127 return P7110_GetBatteryLevel(data, state);
129 return P7110_GetRFLevel(data, state);
130 case GOP_GetMemoryStatus:
131 return P7110_GetMemoryStatus(data, state);
133 return P7110_GetBitmap(data, state);
135 return P7110_SetBitmap(data, state);
136 case GOP_ReadPhonebook:
137 return P7110_ReadPhonebook(data, state);
138 case GOP_WritePhonebook:
139 return P7110_WritePhonebookLocation(data, state);
140 case GOP_GetNetworkInfo:
141 return P7110_GetNetworkInfo(data, state);
142 case GOP_GetSpeedDial:
143 return P7110_GetSpeedDial(data, state);
144 case GOP_GetSMSCenter:
145 return P7110_GetSMSCenter(data, state);
146 case GOP_GetDateTime:
147 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
149 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
150 case GOP_GetCalendarNote:
151 return P7110_GetCalendarNote(data, state);
153 return P7110_GetSMS(data, state);
155 return P7110_SendSMS(data, state);
156 /* I'm not sure yet if folder functions will be shared or local
157 case GOP_GetSMSFolders:
158 return P7110_GetSMSFolders(data, state);
159 case GOP_GetSMSFolderStatus:
160 return P7110_GetSMSFolderStatus(data, state);*/
162 return GE_NOTIMPLEMENTED;
166 /* LinkOK is always true for now... */
167 bool P7110_LinkOK = true;
169 /* Initialise is the only function allowed to 'use' state */
170 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
175 int try = 0, connected = 0;
177 /* Copy in the phone info */
178 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
181 nk7110_layout.Type = 8; /* Locate the Type of the mesage field */
182 nk7110_layout.Deliver = nk7110_deliver;
183 nk7110_layout.Submit = nk7110_submit;
184 nk7110_layout.DeliveryReport = nk7110_delivery_report;
185 nk7110_layout.Picture = nk7110_picture;
186 layout = nk7110_layout;
188 dprintf("Connecting\n");
190 switch (state->Link.ConnectionType) {
192 if (try == 0) try = 1;
194 if (try > 1) return GE_NOTSUPPORTED;
195 err = FBUS_Initialise(&(state->Link), state, 1 - try);
199 if (try > 0) return GE_NOTSUPPORTED;
200 err = PHONET_Initialise(&(state->Link), state);
203 return GE_NOTSUPPORTED;
207 if (err != GE_NONE) {
208 dprintf("Error in link initialisation: %d\n", err);
213 SM_Initialise(state);
215 /* Now test the link and get the model */
216 GSM_DataClear(&data);
218 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
221 /* Check for 7110 and alter the startup logo size */
222 if (strcmp(model, "NSE-5") == 0) {
223 state->Phone.Info.StartupLogoH = 65;
224 dprintf("7110 detected - startup logo height set to 65\n");
229 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
231 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
233 dprintf("Getting model...\n");
234 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
235 return SM_Block(state, data, 0x1b);
238 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
240 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
242 dprintf("Getting revision...\n");
243 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
244 return SM_Block(state, data, 0x1b);
247 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
249 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
251 dprintf("Getting imei...\n");
252 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
253 return SM_Block(state, data, 0x1b);
256 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
258 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
260 dprintf("Getting battery level...\n");
261 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
262 return SM_Block(state, data, 0x17);
265 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
267 switch (message[3]) {
269 if (data->BatteryLevel) {
270 *(data->BatteryUnits) = GBU_Percentage;
271 *(data->BatteryLevel) = message[5];
272 dprintf("Battery level %f\n",*(data->BatteryLevel));
276 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
282 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
284 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
286 dprintf("Getting rf level...\n");
287 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
288 return SM_Block(state, data, 0x0a);
291 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
293 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
295 dprintf("Getting Network Info...\n");
296 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
297 return SM_Block(state, data, 0x0a);
300 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
302 unsigned char *blockstart;
305 switch (message[3]) {
307 blockstart = message + 6;
308 for (i = 0; i < message[4]; i++) {
309 switch (blockstart[0]) {
310 case 0x01: /* Operator details */
311 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
312 if (data->NetworkInfo) {
313 /* Is this correct? */
314 data->NetworkInfo->CellID[0]=blockstart[4];
315 data->NetworkInfo->CellID[1]=blockstart[5];
316 data->NetworkInfo->LAC[0]=blockstart[6];
317 data->NetworkInfo->LAC[1]=blockstart[7];
318 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
319 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
320 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
321 data->NetworkInfo->NetworkCode[3] = ' ';
322 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
323 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
324 data->NetworkInfo->NetworkCode[6] = 0;
327 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
328 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
329 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
330 data->Bitmap->netcode[3] = ' ';
331 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
332 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
333 data->Bitmap->netcode[6] = 0;
334 dprintf("Operator %s ",data->Bitmap->netcode);
337 case 0x04: /* Logo */
339 dprintf("Op logo received ok ");
340 data->Bitmap->type = GSM_OperatorLogo;
341 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
342 data->Bitmap->height = blockstart[3];
343 data->Bitmap->width = blockstart[2];
344 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
345 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
349 dprintf("Unknown operator block %d\n", blockstart[0]);
352 blockstart += blockstart[1];
357 *(data->RFUnits) = GRF_Percentage;
358 *(data->RFLevel) = message[4];
359 dprintf("RF level %f\n",*(data->RFLevel));
363 dprintf("Op Logo Set OK\n");
366 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
372 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
374 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
376 dprintf("Getting memory status...\n");
377 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
378 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
379 return SM_Block(state, data, 0x03);
382 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
384 unsigned char *blockstart;
385 unsigned char blocks;
386 unsigned char subblockcount;
389 GSM_SubPhonebookEntry* subEntry = NULL;
391 PGEN_DebugMessage(messagetype, message, length);
393 switch (message[3]) {
394 case 0x04: /* Get status response */
395 if (data->MemoryStatus) {
396 if (message[5] != 0xff) {
397 data->MemoryStatus->Used = (message[16] << 8) + message[17];
398 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
399 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
401 dprintf("Unknown error getting mem status\n");
402 return GE_NOTIMPLEMENTED;
406 case 0x08: /* Read Memory response */
407 if (data->PhonebookEntry) {
408 data->PhonebookEntry->Empty = true;
409 data->PhonebookEntry->Group = 0;
410 data->PhonebookEntry->Name[0] = '\0';
411 data->PhonebookEntry->Number[0] = '\0';
412 data->PhonebookEntry->SubEntriesCount = 0;
413 data->PhonebookEntry->Date.Year = 0;
414 data->PhonebookEntry->Date.Month = 0;
415 data->PhonebookEntry->Date.Day = 0;
416 data->PhonebookEntry->Date.Hour = 0;
417 data->PhonebookEntry->Date.Minute = 0;
418 data->PhonebookEntry->Date.Second = 0;
420 if (message[6] == 0x0f) { // not found
421 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
422 dprintf("Invalid caller location\n");
423 return GE_INVALIDPHBOOKLOCATION;
425 dprintf("Unknown error getting phonebook\n");
426 return GE_NOTIMPLEMENTED;
429 dprintf("Received phonebook info\n");
430 blocks = message[17];
431 blockstart = message + 18;
434 for (i = 0; i < blocks; i++) {
435 if (data->PhonebookEntry)
436 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
437 switch(blockstart[0]) {
438 case P7110_ENTRYTYPE_POINTER: /* Pointer */
439 switch (message[11]) { /* Memory type */
440 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
441 if ((data != NULL) && (data->SpeedDial != NULL)) {
442 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
443 switch(blockstart[8]) {
445 data->SpeedDial->MemoryType = GMT_ME;
450 data->SpeedDial->MemoryType = GMT_SM;
454 data->SpeedDial->MemoryType = GMT_XX;
459 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
463 /* FIXME: is it possible? */
464 dprintf("Wrong memory type(?)\n");
469 case P7110_ENTRYTYPE_NAME: /* Name */
471 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
472 dprintf("Name: %s\n", data->Bitmap->text);
473 } else if (data->PhonebookEntry) {
474 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
475 data->PhonebookEntry->Empty = false;
476 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
479 case P7110_ENTRYTYPE_EMAIL:
480 case P7110_ENTRYTYPE_POSTAL:
481 case P7110_ENTRYTYPE_NOTE:
482 if (data->PhonebookEntry) {
483 subEntry->EntryType = blockstart[0];
484 subEntry->NumberType = 0;
485 subEntry->BlockNumber = blockstart[4];
486 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
487 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
488 dprintf(" Text: %s\n", subEntry->data.Number);
490 data->PhonebookEntry->SubEntriesCount++;
493 case P7110_ENTRYTYPE_NUMBER:
494 if (data->PhonebookEntry) {
495 subEntry->EntryType = blockstart[0];
496 subEntry->NumberType = blockstart[5];
497 subEntry->BlockNumber = blockstart[4];
498 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
499 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
500 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
501 dprintf(" Number: %s\n", subEntry->data.Number);
503 data->PhonebookEntry->SubEntriesCount++;
506 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
508 data->Bitmap->ringtone = blockstart[5];
509 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
512 case P7110_ENTRYTYPE_DATE:
513 if (data->PhonebookEntry) {
514 subEntry->EntryType=blockstart[0];
515 subEntry->NumberType=blockstart[5];
516 subEntry->BlockNumber=blockstart[4];
517 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
518 subEntry->data.Date.Month = blockstart[8];
519 subEntry->data.Date.Day = blockstart[9];
520 subEntry->data.Date.Hour = blockstart[10];
521 subEntry->data.Date.Minute = blockstart[11];
522 subEntry->data.Date.Second = blockstart[12];
523 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
524 subEntry->data.Date.Month, subEntry->data.Date.Year);
525 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
526 subEntry->data.Date.Minute, subEntry->data.Date.Second);
530 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
532 data->Bitmap->width = blockstart[5];
533 data->Bitmap->height = blockstart[6];
534 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
535 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
539 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
541 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
542 if (data->PhonebookEntry) {
543 data->PhonebookEntry->Group = blockstart[5] - 1;
544 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
548 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
551 blockstart += blockstart[3];
555 switch (message[6]) {
556 case 0x3d: return GE_PHBOOKWRITEFAILED;
557 case 0x3e: return GE_PHBOOKWRITEFAILED;
558 default: return GE_NONE;
562 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
568 /* Just as an example.... */
569 /* But note that both requests are the same type which isn't very 'proper' */
570 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
572 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
573 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
575 dprintf("Identifying...\n");
576 PNOK_GetManufacturer(data->Manufacturer);
577 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
578 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
579 SM_WaitFor(state, data, 0x1b);
580 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
581 SM_GetError(state, 0x1b);
583 /* Check that we are back at state Initialised */
584 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
588 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
590 switch (message[3]) {
593 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
594 dprintf("Received imei %s\n",data->Imei);
599 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
600 dprintf("Received model %s\n",data->Model);
602 if (data->Revision) {
603 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
604 dprintf("Received revision %s\n",data->Revision);
608 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
615 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
616 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
619 int nextfolder = 0x10;
622 switch (message[3]) {
626 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
627 dprintf("Message: %d SMS Folders received:\n", message[4]);
629 strcpy(data->SMSFolderList->Folder[1].Name, " ");
630 data->SMSFolderList->number = message[4];
632 for (j = 0; j < message[4]; j++) {
634 strcpy(data->SMSFolderList->Folder[j].Name, " ");
635 data->SMSFolderList->FolderID[j] = message[i];
636 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
638 dprintf(" Folder name: ");
640 /* search for next folder's index number, i.e. length of folder name */
641 while (message[i+1] != nextfolder && i < length) {
647 if (nextfolder == 0x28) nextfolder++;
649 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
650 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
655 /* getfolderstatus */
657 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
658 dprintf("Message: SMS Folder status received: \n" );
659 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
660 data->SMSFolder->number = (message[5] * 256) + message[5];
661 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
662 dprintf("Message: IDs of Entries : ");
663 for (i = 0; i < message[4] * 256 + message[5]; i++) {
664 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
665 dprintf("%d, ", data->SMSFolder->locations[i]);
672 for (i = 0; i < length; i ++)
673 if (isprint(message[i]))
674 dprintf("[%02x%c]", message[i], message[i]);
676 dprintf("[%02x ]", message[i]);
679 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
681 /* Number of SMS in folder */
682 data->SMSMessage->Number = message[7];
684 /* MessageType/FolderID */
685 data->SMSMessage->MemoryType = message[5];
687 /* Short Message status */
688 data->SMSMessage->Status = message[4];
689 dprintf("\tStatus: ");
690 switch (data->SMSMessage->Status) {
704 dprintf("UNKNOWN\n");
707 /* See if message# is given back by phone. If not and status is unread */
708 /* we want it, if status is not unread it's a "random" message given back */
709 /* by the phone because we want a message of which the # doesn't exist */
711 for (i = 0; i < data->SMSFolder->number; i++) {
712 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
715 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
717 DecodePDUSMS(message, data->SMSMessage, length);
721 /* get list of SMS pictures */
723 dprintf("Getting list of SMS pictures...\n");
724 for (i = 0; i < length; i ++)
725 if (isprint(message[i]))
726 dprintf("[%02x%c]", message[i], message[i]);
728 dprintf("[%02x ]", message[i]);
733 for (i = 0; i < length; i ++)
734 if (isprint(message[i]))
735 dprintf("[%02x%c]", message[i], message[i]);
737 dprintf("[%02x ]", message[i]);
739 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
745 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
747 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
748 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
751 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
756 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
761 /* just testiung picture listing */
762 req_list[4] = data->SMSMessage->MemoryType;
763 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
764 error = SM_Block(state, data, 0x14);
766 /* see if the message we want is from the last read folder, i.e. */
767 /* we don't have to get folder status again */
768 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
770 dprintf("Getting list of SMS folders...\n");
771 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
772 error = SM_Block(state, data, 0x14);
774 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
775 return GE_INVALIDMEMORYTYPE;
776 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
777 req_status[4] = data->SMSMessage->MemoryType;
779 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
780 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
781 error = SM_Block(state, data, 0x14);
784 dprintf("Getting SMS...\n");
785 req_sms[4] = data->SMSMessage->MemoryType;
786 req_sms[6] = data->SMSMessage->Number;
787 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
788 return SM_Block(state, data, 0x14);
791 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
793 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
796 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
797 return SM_Block(state, data, 0x14);
801 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
803 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
805 dprintf("Getting SMS Folders...\n");
806 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
807 return SM_Block(state, data, 0x14);
810 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
812 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
816 req[4] = data->SMSFolder->FolderID;
817 dprintf("Getting SMS Folder Status...\n");
818 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
819 return SM_Block(state, data, 0x14);
823 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
826 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
829 if (data->SMSMessage->MessageCenter.No) {
830 data->MessageCenter = &data->SMSMessage->MessageCenter;
831 P7110_GetSMSCenter(data, state);
834 length = EncodePDUSMS(data->SMSMessage, req);
835 if (!length) return GE_SMSWRONGFORMAT;
836 dprintf("Sending SMS...(%d)\n", length);
837 for (i = 0; i < length; i++) {
838 dprintf("%02x ", req[i]);
841 if (SM_SendMessage(state, length, 0x02, req) != GE_NONE) return GE_NOTREADY;
843 e = SM_Block(state, data, 0x02);
844 if (e == GE_SMSSENDOK || e == GE_SMSSENDFAILED) break;
849 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
851 GSM_Error e = GE_NONE;
854 if (!data) return GE_INTERNALERROR;
856 switch (message[3]) {
857 case P7110_SUBSMS_SMSC_RCVD:
858 dprintf("SMSC Received\n");
859 /* FIXME: Implement all these in gsm-sms.c */
860 data->MessageCenter->No = message[4];
861 data->MessageCenter->Format = message[6];
862 data->MessageCenter->Validity = message[8]; /* due to changes in format */
864 bytes = message[21] - 1;
867 sprintf(data->MessageCenter->Name, "%s", message + 33);
869 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
870 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
871 data->MessageCenter->Type = message[22];
873 if (strlen(data->MessageCenter->Recipient) == 0) {
874 sprintf(data->MessageCenter->Recipient, "(none)");
876 if (strlen(data->MessageCenter->Number) == 0) {
877 sprintf(data->MessageCenter->Number, "(none)");
879 if(strlen(data->MessageCenter->Name) == 0) {
880 sprintf(data->MessageCenter->Name, "(none)");
885 case P7110_SUBSMS_SMS_SENT:
886 dprintf("SMS sent\n");
890 case P7110_SUBSMS_SEND_FAIL:
891 dprintf("SMS sending failed\n");
892 e = GE_SMSSENDFAILED;
895 case P7110_SUBSMS_SMS_RCVD:
896 case P7110_SUBSMS_CELLBRD_OK:
897 case P7110_SUBSMS_CELLBRD_FAIL:
898 case P7110_SUBSMS_READ_CELLBRD:
899 case P7110_SUBSMS_SMSC_OK:
900 case P7110_SUBSMS_SMSC_FAIL:
901 case P7110_SUBSMS_SMSC_RCVFAIL:
902 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
903 e = GE_NOTIMPLEMENTED;
907 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
914 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
916 GSM_Error e = GE_NONE;
918 if (!data || !data->DateTime) return GE_INTERNALERROR;
919 switch (message[3]) {
920 case P7110_SUBCLO_DATE_RCVD:
921 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
922 data->DateTime->Month = message[10];
923 data->DateTime->Day = message[11];
924 data->DateTime->Hour = message[12];
925 data->DateTime->Minute = message[13];
926 data->DateTime->Second = message[14];
929 case P7110_SUBCLO_ALARM_RCVD:
931 case P7110_ALARM_ENABLED:
932 data->DateTime->AlarmEnabled = 1;
934 case P7110_ALARM_DISABLED:
935 data->DateTime->AlarmEnabled = 0;
938 data->DateTime->AlarmEnabled = -1;
939 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
944 data->DateTime->Hour = message[9];
945 data->DateTime->Minute = message[10];
949 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
956 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
961 GSM_Error e = GE_NONE;
963 if (!time || !alarm) return GE_INTERNALERROR;
965 memset(&tm_time, 0, sizeof(tm_time));
966 tm_time.tm_year = time->Year - 1900;
967 tm_time.tm_mon = time->Month - 1;
968 tm_time.tm_mday = time->Day;
969 tm_time.tm_hour = time->Hour;
970 tm_time.tm_min = time->Minute;
973 t_alarm = mktime(&tm_time);
974 t_alarm -= alarmdiff;
977 tm_alarm = localtime(&t_alarm);
979 alarm->Year = tm_alarm->tm_year + 1900;
980 alarm->Month = tm_alarm->tm_mon + 1;
981 alarm->Day = tm_alarm->tm_mday;
982 alarm->Hour = tm_alarm->tm_hour;
983 alarm->Minute = tm_alarm->tm_min;
984 alarm->Second = tm_alarm->tm_sec;
990 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
993 GSM_Error e = GE_NONE;
995 if (!c) return GE_INTERNALERROR;
997 c->Time.Hour = block[0];
998 c->Time.Minute = block[1];
999 c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1000 alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1002 if (alarmdiff != 0xffff) {
1003 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1004 c->Alarm.AlarmEnabled = 1;
1006 c->Alarm.AlarmEnabled = 0;
1012 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1014 GSM_Error e = GE_NONE;
1015 unsigned char *block;
1018 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1020 year = data->CalendarNote->Time.Year;
1021 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1022 switch (message[3]) {
1023 case P7110_SUBCAL_NOTE_RCVD:
1024 block = message + 12;
1026 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1027 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1028 data->CalendarNote->Time.Month = message[10];
1029 data->CalendarNote->Time.Day = message[11];
1030 data->CalendarNote->Time.Second = 0;
1032 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1034 switch (message[6]) {
1035 case P7110_NOTE_MEETING:
1036 data->CalendarNote->Type = GCN_MEETING;
1037 P7110_GetNoteTimes(block, data->CalendarNote);
1038 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1040 case P7110_NOTE_CALL:
1041 data->CalendarNote->Type = GCN_CALL;
1042 P7110_GetNoteTimes(block, data->CalendarNote);
1043 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1044 DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1046 case P7110_NOTE_REMINDER:
1047 data->CalendarNote->Type = GCN_REMINDER;
1048 data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1049 DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1051 case P7110_NOTE_BIRTHDAY:
1053 for (i = 0; i < 10; i++) {
1054 dprintf("(%i:0x%02x)", i, block[i]);
1058 data->CalendarNote->Type = GCN_BIRTHDAY;
1059 data->CalendarNote->Time.Year = year;
1060 data->CalendarNote->Time.Hour = 23;
1061 data->CalendarNote->Time.Minute = 59;
1062 data->CalendarNote->Time.Second = 58;
1064 alarm = ((unsigned int)block[2]) << 24;
1065 alarm += ((unsigned int)block[3]) << 16;
1066 alarm += ((unsigned int)block[4]) << 8;
1069 dprintf("alarm: %i\n", alarm);
1071 if (alarm == 0xffff) {
1072 data->CalendarNote->Alarm.AlarmEnabled = 0;
1074 data->CalendarNote->Alarm.AlarmEnabled = 1;
1077 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1079 data->CalendarNote->Time.Hour = 0;
1080 data->CalendarNote->Time.Minute = 0;
1081 data->CalendarNote->Time.Second = 0;
1082 data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1084 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1088 data->CalendarNote->Type = -1;
1094 case P7110_SUBCAL_ADD_MEETING_RESP:
1095 case P7110_SUBCAL_ADD_CALL_RESP:
1096 case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1097 case P7110_SUBCAL_ADD_REMINDER_RESP:
1098 case P7110_SUBCAL_DEL_NOTE_RESP:
1099 case P7110_SUBCAL_FREEPOS_RCVD:
1100 case P7110_SUBCAL_INFO_RCVD:
1101 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1102 e = GE_NOTIMPLEMENTED;
1105 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1112 static int GetMemoryType(GSM_MemoryType memory_type)
1116 switch (memory_type) {
1118 result = P7110_MEMORY_MT;
1121 result = P7110_MEMORY_ME;
1124 result = P7110_MEMORY_SM;
1127 result = P7110_MEMORY_FD;
1130 result = P7110_MEMORY_ON;
1133 result = P7110_MEMORY_EN;
1136 result = P7110_MEMORY_DC;
1139 result = P7110_MEMORY_RC;
1142 result = P7110_MEMORY_MC;
1145 result = P7110_MEMORY_XX;
1153 static GSM_Error P7110_DialVoice(char *Number)
1156 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1158 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1160 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1161 // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1162 // unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1163 // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1166 //req[4]=strlen(Number);
1168 //for(i=0; i < strlen(Number) ; i++)
1169 // req[5+i]=Number[i];
1171 //memcpy(req+5+strlen(Number), req_end, 10);
1173 //len=6+strlen(Number);
1178 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1182 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1183 PGEN_DebugMessage(1, req, len);
1187 // } else return GE_NOTIMPLEMENTED;
1194 return GE_NOTIMPLEMENTED;
1199 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1201 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1202 0x00, 0x10 , /* memory type */
1203 0x00, 0x00, /* location */
1206 req[11] = data->Bitmap->number + 1;
1207 dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1208 if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1209 return SM_Block(state, data, 0x03);
1212 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1217 *(block++) = size + 6;
1219 memcpy(block, buf, size);
1225 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1227 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1228 0x00, 0x10, /* memory type */
1229 0x00, 0x00, /* location */
1233 unsigned int count = 18;
1235 if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1236 (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1237 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);
1238 return GE_INVALIDIMAGESIZE;
1241 req[13] = data->Bitmap->number + 1;
1242 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1245 i = strlen(data->Bitmap->text);
1246 EncodeUnicode((string + 1), data->Bitmap->text, i);
1248 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1250 string[0] = data->Bitmap->ringtone;
1252 count += PackBlock(0x0c, 2, block++, string, req + count);
1254 string[0] = data->Bitmap->number+1;
1256 count += PackBlock(0x1e, 2, block++, string, req + count);
1257 /* Logo on/off - assume on for now */
1260 count += PackBlock(0x1c, 2, block++, string, req + count);
1262 string[0] = data->Bitmap->width;
1263 string[1] = data->Bitmap->height;
1266 string[4] = 0x7e; /* Size */
1267 memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1268 count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1269 req[17] = block - 1;
1271 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1272 return SM_Block(state, data, 0x03);
1275 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1277 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1279 dprintf("Getting startup logo...\n");
1280 if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1281 return SM_Block(state, data, 0x7a);
1284 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1286 switch (message[3]) {
1288 dprintf("Startup logo set ok\n");
1293 /* I'm sure there are blocks here but never mind! */
1294 data->Bitmap->type = GSM_StartupLogo;
1295 data->Bitmap->height = message[13];
1296 data->Bitmap->width = message[17];
1297 data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1298 memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1299 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1304 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1310 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1312 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1314 dprintf("Getting op logo...\n");
1315 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1316 return SM_Block(state, data, 0x0a);
1319 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1321 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1325 0xc0, 0x04, 0x03, 0x00 };
1329 if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1330 (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1331 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);
1332 return GE_INVALIDIMAGESIZE;
1335 req[12] = data->Bitmap->height;
1336 req[16] = data->Bitmap->width;
1337 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1338 count += data->Bitmap->size;
1339 dprintf("Setting startup logo...\n");
1341 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1342 return SM_Block(state, data, 0x7a);
1345 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1347 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1348 0x00, /* logo enabled */
1349 0x00, 0xf0, 0x00, /* network code (000 00) */
1351 0x08, /* length of rest */
1352 0x00, 0x00, /* Bitmap width / height */
1354 0x00, /* Bitmap size */
1359 if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1360 (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1361 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);
1362 return GE_INVALIDIMAGESIZE;
1365 if (strcmp(data->Bitmap->netcode,"000 00")) { /* set logo */
1366 req[5] = 0x01; // Logo enabled
1367 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1368 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1369 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1370 req[11] = 8 + data->Bitmap->size;
1371 req[12] = data->Bitmap->width;
1372 req[13] = data->Bitmap->height;
1373 req[15] = data->Bitmap->size;
1374 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1375 count += data->Bitmap->size;
1377 dprintf("Setting op logo...\n");
1378 if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1379 return SM_Block(state, data, 0x0a);
1382 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1384 switch(data->Bitmap->type) {
1385 case GSM_CallerLogo:
1386 return GetCallerBitmap(data, state);
1387 case GSM_StartupLogo:
1388 return GetStartupBitmap(data, state);
1389 case GSM_OperatorLogo:
1390 return GetOperatorBitmap(data, state);
1392 return GE_NOTIMPLEMENTED;
1396 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1398 switch(data->Bitmap->type) {
1399 case GSM_CallerLogo:
1400 return SetCallerBitmap(data, state);
1401 case GSM_StartupLogo:
1402 return SetStartupBitmap(data, state);
1403 case GSM_OperatorLogo:
1404 return SetOperatorBitmap(data, state);
1406 return GE_NOTIMPLEMENTED;
1410 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1412 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1413 0x00, 0x00, /* memory type */
1414 0x00, 0x00, /* location */
1417 int block, i, j, defaultn;
1418 unsigned int count = 18;
1419 GSM_PhonebookEntry *entry;
1421 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1422 else return GE_TRYAGAIN;
1424 req[11] = GetMemoryType(entry->MemoryType);
1425 req[12] = (entry->Location >> 8);
1426 req[13] = entry->Location & 0xff;
1428 if (*(entry->Name)) {
1430 i = strlen(entry->Name);
1431 EncodeUnicode((string + 1), entry->Name, i);
1433 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1435 string[0] = entry->Group + 1;
1437 count += PackBlock(0x1e, 2, block++, string, req + count);
1438 /* Default Number */
1440 for (i = 0; i < entry->SubEntriesCount; i++)
1441 if (entry->SubEntries[i].EntryType == GSM_Number)
1442 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1445 string[0] = entry->SubEntries[defaultn].NumberType;
1449 i = strlen(entry->SubEntries[defaultn].data.Number);
1450 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1452 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1454 /* Rest of the numbers */
1455 for (i = 0; i < entry->SubEntriesCount; i++)
1456 if (entry->SubEntries[i].EntryType == GSM_Number)
1457 if (i != defaultn) {
1458 string[0] = entry->SubEntries[i].NumberType;
1462 j = strlen(entry->SubEntries[i].data.Number);
1463 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1465 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1467 req[17] = block - 1;
1468 dprintf("Writing phonebook entry %s...\n",entry->Name);
1470 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1471 return SM_Block(state, data, 0x03);
1474 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1477 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1478 0x00, 0x00, /* memory type */ //02,05
1479 0x00, 0x00, /* location */
1482 dprintf("Reading phonebook location (%d)\n", location);
1485 req[10] = location >> 8;
1486 req[11] = location & 0xff;
1488 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1489 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1494 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1496 int memtype, location;
1498 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1499 location = data->PhonebookEntry->Location;
1501 return P7110_ReadPhonebookLL(data, state, memtype, location);
1504 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1506 int memtype, location;
1508 memtype = P7110_MEMORY_SPEEDDIALS;
1509 location = data->SpeedDial->Number;
1511 return P7110_ReadPhonebookLL(data, state, memtype, location);
1514 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1517 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1519 req[5] = data->MessageCenter->No;
1521 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1522 error = SM_Block(state, data, P7110_MSG_SMS);
1527 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1530 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1532 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1533 error = SM_Block(state, data, P7110_MSG_CLOCK);
1538 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1540 GSM_Error error = GE_NOTREADY;
1541 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1542 unsigned char date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1544 GSM_DateTime tmptime;
1546 tmpdata.DateTime = &tmptime;
1547 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1548 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1549 req[4] = data->CalendarNote->Location >> 8;
1550 req[5] = data->CalendarNote->Location & 0xff;
1551 data->CalendarNote->Time.Year = tmptime.Year;
1553 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1554 error = SM_Block(state, data, P7110_MSG_CALENDAR);