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 },
86 { P7110_MSG_DIVERT, P7110_IncomingCallDivert },
90 GSM_Phone phone_nokia_7110 = {
91 P7110_IncomingFunctions,
93 /* Mobile phone information */
95 "7110|6210|6250", /* Supported models */
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 */
112 /* FIXME - a little macro would help here... */
114 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
118 return P7110_Initialise(state);
120 return P7110_GetModel(data, state);
121 case GOP_GetRevision:
122 return P7110_GetRevision(data, state);
124 return P7110_GetIMEI(data, state);
126 return P7110_Identify(data, state);
127 case GOP_GetBatteryLevel:
128 return P7110_GetBatteryLevel(data, state);
130 return P7110_GetRFLevel(data, state);
131 case GOP_GetMemoryStatus:
132 return P7110_GetMemoryStatus(data, state);
134 return P7110_GetBitmap(data, state);
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);
150 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
151 case GOP_GetCalendarNote:
152 return P7110_GetCalendarNote(data, state);
154 return P7110_GetSMS(data, state);
156 return P7110_SendSMS(data, state);
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);*/
165 return GE_NOTIMPLEMENTED;
169 /* LinkOK is always true for now... */
170 bool P7110_LinkOK = true;
172 /* Initialise is the only function allowed to 'use' state */
173 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
178 int try = 0, connected = 0;
180 /* Copy in the phone info */
181 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
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;
191 dprintf("Connecting\n");
193 switch (state->Link.ConnectionType) {
195 if (try == 0) try = 1;
197 if (try > 1) return GE_NOTSUPPORTED;
198 err = FBUS_Initialise(&(state->Link), state, 1 - try);
202 if (try > 0) return GE_NOTSUPPORTED;
203 err = PHONET_Initialise(&(state->Link), state);
206 return GE_NOTSUPPORTED;
210 if (err != GE_NONE) {
211 dprintf("Error in link initialisation: %d\n", err);
216 SM_Initialise(state);
218 /* Now test the link and get the model */
219 GSM_DataClear(&data);
221 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
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");
232 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
234 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
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);
241 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
243 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
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);
250 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
252 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
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);
259 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
261 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
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);
268 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
270 switch (message[3]) {
272 if (data->BatteryLevel) {
273 *(data->BatteryUnits) = GBU_Percentage;
274 *(data->BatteryLevel) = message[5];
275 dprintf("Battery level %f\n",*(data->BatteryLevel));
279 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
285 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
287 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
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);
294 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
296 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
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);
303 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
305 unsigned char *blockstart;
308 switch (message[3]) {
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;
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);
340 case 0x04: /* Logo */
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);
352 dprintf("Unknown operator block %d\n", blockstart[0]);
355 blockstart += blockstart[1];
360 *(data->RFUnits) = GRF_Percentage;
361 *(data->RFLevel) = message[4];
362 dprintf("RF level %f\n",*(data->RFLevel));
366 dprintf("Op Logo Set OK\n");
369 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
375 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
377 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
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);
385 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
387 unsigned char *blockstart;
388 unsigned char blocks;
389 unsigned char subblockcount;
392 GSM_SubPhonebookEntry* subEntry = NULL;
394 PGEN_DebugMessage(messagetype, message, length);
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]);
404 dprintf("Unknown error getting mem status\n");
405 return GE_NOTIMPLEMENTED;
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;
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;
428 dprintf("Unknown error getting phonebook\n");
429 return GE_NOTIMPLEMENTED;
432 dprintf("Received phonebook info\n");
433 blocks = message[17];
434 blockstart = message + 18;
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]) {
448 data->SpeedDial->MemoryType = GMT_ME;
453 data->SpeedDial->MemoryType = GMT_SM;
457 data->SpeedDial->MemoryType = GMT_XX;
462 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
466 /* FIXME: is it possible? */
467 dprintf("Wrong memory type(?)\n");
472 case P7110_ENTRYTYPE_NAME: /* Name */
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);
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);
493 data->PhonebookEntry->SubEntriesCount++;
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);
506 data->PhonebookEntry->SubEntriesCount++;
509 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
511 data->Bitmap->ringtone = blockstart[5];
512 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
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);
533 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
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);
542 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
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);
551 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
554 blockstart += blockstart[3];
558 switch (message[6]) {
559 case 0x3d: return GE_PHBOOKWRITEFAILED;
560 case 0x3e: return GE_PHBOOKWRITEFAILED;
561 default: return GE_NONE;
565 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
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)
575 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
576 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
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);
586 /* Check that we are back at state Initialised */
587 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
591 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
593 switch (message[3]) {
596 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
597 dprintf("Received imei %s\n",data->Imei);
602 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
603 dprintf("Received model %s\n",data->Model);
605 if (data->Revision) {
606 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
607 dprintf("Received revision %s\n",data->Revision);
611 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
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)
622 int nextfolder = 0x10;
625 switch (message[3]) {
629 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
630 dprintf("Message: %d SMS Folders received:\n", message[4]);
632 strcpy(data->SMSFolderList->Folder[1].Name, " ");
633 data->SMSFolderList->number = message[4];
635 for (j = 0; j < message[4]; j++) {
637 strcpy(data->SMSFolderList->Folder[j].Name, " ");
638 data->SMSFolderList->FolderID[j] = message[i];
639 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
641 dprintf(" Folder name: ");
643 /* search for next folder's index number, i.e. length of folder name */
644 while (message[i+1] != nextfolder && i < length) {
650 if (nextfolder == 0x28) nextfolder++;
652 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
653 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
658 /* getfolderstatus */
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]);
675 for (i = 0; i < length; i ++)
676 if (isprint(message[i]))
677 dprintf("[%02x%c]", message[i], message[i]);
679 dprintf("[%02x ]", message[i]);
682 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
684 /* Number of SMS in folder */
685 data->SMSMessage->Number = message[7];
687 /* MessageType/FolderID */
688 data->SMSMessage->MemoryType = message[5];
690 /* Short Message status */
691 data->SMSMessage->Status = message[4];
692 dprintf("\tStatus: ");
693 switch (data->SMSMessage->Status) {
707 dprintf("UNKNOWN\n");
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 */
714 for (i = 0; i < data->SMSFolder->number; i++) {
715 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
718 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
720 DecodePDUSMS(message, data->SMSMessage, length);
724 /* get list of SMS pictures */
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]);
731 dprintf("[%02x ]", message[i]);
736 for (i = 0; i < length; i ++)
737 if (isprint(message[i]))
738 dprintf("[%02x%c]", message[i], message[i]);
740 dprintf("[%02x ]", message[i]);
742 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
748 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
750 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
751 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
754 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
759 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
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);
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) {
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);
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;
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);
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);
794 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
796 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
799 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
800 return SM_Block(state, data, 0x14);
804 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
806 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
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);
813 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
815 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
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);
826 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
828 GSM_Error e = GE_NONE;
829 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
832 if (data->SMSMessage->MessageCenter.No) {
833 data->MessageCenter = &data->SMSMessage->MessageCenter;
834 P7110_GetSMSCenter(data, state);
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]);
844 if (SM_SendMessage(state, length, 0x02, req) != GE_NONE) return GE_NOTREADY;
846 e = SM_Block(state, data, 0x02);
847 if (e == GE_SMSSENDOK || e == GE_SMSSENDFAILED) break;
852 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
854 GSM_Error e = GE_NONE;
857 if (!data) return GE_INTERNALERROR;
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 */
867 bytes = message[21] - 1;
870 sprintf(data->MessageCenter->Name, "%s", message + 33);
872 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
873 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
874 data->MessageCenter->Type = message[22];
876 if (strlen(data->MessageCenter->Recipient) == 0) {
877 sprintf(data->MessageCenter->Recipient, "(none)");
879 if (strlen(data->MessageCenter->Number) == 0) {
880 sprintf(data->MessageCenter->Number, "(none)");
882 if(strlen(data->MessageCenter->Name) == 0) {
883 sprintf(data->MessageCenter->Name, "(none)");
888 case P7110_SUBSMS_SMS_SENT:
889 dprintf("SMS sent\n");
893 case P7110_SUBSMS_SEND_FAIL:
894 dprintf("SMS sending failed\n");
895 e = GE_SMSSENDFAILED;
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;
910 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
917 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
919 GSM_Error e = GE_NONE;
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];
932 case P7110_SUBCLO_ALARM_RCVD:
934 case P7110_ALARM_ENABLED:
935 data->DateTime->AlarmEnabled = 1;
937 case P7110_ALARM_DISABLED:
938 data->DateTime->AlarmEnabled = 0;
941 data->DateTime->AlarmEnabled = -1;
942 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
947 data->DateTime->Hour = message[9];
948 data->DateTime->Minute = message[10];
952 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
959 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
964 GSM_Error e = GE_NONE;
966 if (!time || !alarm) return GE_INTERNALERROR;
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;
976 t_alarm = mktime(&tm_time);
977 t_alarm -= alarmdiff;
980 tm_alarm = localtime(&t_alarm);
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;
993 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
996 GSM_Error e = GE_NONE;
998 if (!c) return GE_INTERNALERROR;
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];
1005 if (alarmdiff != 0xffff) {
1006 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1007 c->Alarm.AlarmEnabled = 1;
1009 c->Alarm.AlarmEnabled = 0;
1015 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1017 GSM_Error e = GE_NONE;
1018 unsigned char *block;
1021 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
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;
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;
1035 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
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]);
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]);
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]);
1054 case P7110_NOTE_BIRTHDAY:
1056 for (i = 0; i < 10; i++) {
1057 dprintf("(%i:0x%02x)", i, block[i]);
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;
1067 alarm = ((unsigned int)block[2]) << 24;
1068 alarm += ((unsigned int)block[3]) << 16;
1069 alarm += ((unsigned int)block[4]) << 8;
1072 dprintf("alarm: %i\n", alarm);
1074 if (alarm == 0xffff) {
1075 data->CalendarNote->Alarm.AlarmEnabled = 0;
1077 data->CalendarNote->Alarm.AlarmEnabled = 1;
1080 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
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];
1087 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1091 data->CalendarNote->Type = -1;
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;
1108 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1115 static GSM_Error P7110_CallDivert(GSM_Data *data, GSM_Statemachine *state)
1117 unsigned short length = 0x09;
1118 char req[55] = { FBUS_FRAME_HEADER, 0x01, 0x00, /* operation */
1120 0x00, /* divert type */
1121 0x00, /* call type */
1123 if (!data->CallDivert) return GE_UNKNOWN;
1124 switch (data->CallDivert->Operation) {
1128 case GSM_CDV_Register:
1132 req[9] = SemiOctetPack(data->CallDivert->Number.number, req + 10, data->CallDivert->Number.type);
1133 req[21] = data->CallDivert->Timeout;
1135 case GSM_CDV_Erasure:
1139 return GE_NOTIMPLEMENTED;
1141 switch (data->CallDivert->CType) {
1142 case GSM_CDV_AllCalls:
1144 case GSM_CDV_VoiceCalls:
1147 case GSM_CDV_FaxCalls:
1150 case GSM_CDV_DataCalls:
1154 return GE_NOTIMPLEMENTED;
1156 switch (data->CallDivert->DType) {
1157 case GSM_CDV_AllTypes:
1163 case GSM_CDV_NoAnswer:
1166 case GSM_CDV_OutOfReach:
1170 return GE_NOTIMPLEMENTED;
1172 if ((data->CallDivert->DType == GSM_CDV_AllTypes) && (data->CallDivert->CType == GSM_CDV_AllCalls))
1175 if (SM_SendMessage(state, length, P7110_MSG_DIVERT, req) != GE_NONE) return GE_NOTREADY;
1176 return SM_WaitFor(state, data, P7110_MSG_DIVERT);
1179 static GSM_Error P7110_IncomingCallDivert(int messagetype, unsigned char *message, int length, GSM_Data *data)
1182 for (i = 0; i < length; i++) {
1183 dprintf("%02x ", message[i]);
1189 static int GetMemoryType(GSM_MemoryType memory_type)
1193 switch (memory_type) {
1195 result = P7110_MEMORY_MT;
1198 result = P7110_MEMORY_ME;
1201 result = P7110_MEMORY_SM;
1204 result = P7110_MEMORY_FD;
1207 result = P7110_MEMORY_ON;
1210 result = P7110_MEMORY_EN;
1213 result = P7110_MEMORY_DC;
1216 result = P7110_MEMORY_RC;
1219 result = P7110_MEMORY_MC;
1222 result = P7110_MEMORY_XX;
1230 static GSM_Error P7110_DialVoice(char *Number)
1233 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1235 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
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};
1243 //req[4]=strlen(Number);
1245 //for(i=0; i < strlen(Number) ; i++)
1246 // req[5+i]=Number[i];
1248 //memcpy(req+5+strlen(Number), req_end, 10);
1250 //len=6+strlen(Number);
1255 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1259 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1260 PGEN_DebugMessage(1, req, len);
1264 // } else return GE_NOTIMPLEMENTED;
1271 return GE_NOTIMPLEMENTED;
1276 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1278 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1279 0x00, 0x10 , /* memory type */
1280 0x00, 0x00, /* location */
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);
1289 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1294 *(block++) = size + 6;
1296 memcpy(block, buf, size);
1302 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1304 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1305 0x00, 0x10, /* memory type */
1306 0x00, 0x00, /* location */
1310 unsigned int count = 18;
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;
1318 req[13] = data->Bitmap->number + 1;
1319 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1322 i = strlen(data->Bitmap->text);
1323 EncodeUnicode((string + 1), data->Bitmap->text, i);
1325 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1327 string[0] = data->Bitmap->ringtone;
1329 count += PackBlock(0x0c, 2, block++, string, req + count);
1331 string[0] = data->Bitmap->number+1;
1333 count += PackBlock(0x1e, 2, block++, string, req + count);
1334 /* Logo on/off - assume on for now */
1337 count += PackBlock(0x1c, 2, block++, string, req + count);
1339 string[0] = data->Bitmap->width;
1340 string[1] = data->Bitmap->height;
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;
1348 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1349 return SM_Block(state, data, 0x03);
1352 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1354 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
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);
1361 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1363 switch (message[3]) {
1365 dprintf("Startup logo set ok\n");
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);
1381 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1387 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1389 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
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);
1396 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1398 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1402 0xc0, 0x04, 0x03, 0x00 };
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;
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");
1418 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1419 return SM_Block(state, data, 0x7a);
1422 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1424 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1425 0x00, /* logo enabled */
1426 0x00, 0xf0, 0x00, /* network code (000 00) */
1428 0x08, /* length of rest */
1429 0x00, 0x00, /* Bitmap width / height */
1431 0x00, /* Bitmap size */
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;
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;
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);
1459 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
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);
1469 return GE_NOTIMPLEMENTED;
1473 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
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);
1483 return GE_NOTIMPLEMENTED;
1487 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1489 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1490 0x00, 0x00, /* memory type */
1491 0x00, 0x00, /* location */
1494 int block, i, j, defaultn;
1495 unsigned int count = 18;
1496 GSM_PhonebookEntry *entry;
1498 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1499 else return GE_TRYAGAIN;
1501 req[11] = GetMemoryType(entry->MemoryType);
1502 req[12] = (entry->Location >> 8);
1503 req[13] = entry->Location & 0xff;
1505 if (*(entry->Name)) {
1507 i = strlen(entry->Name);
1508 EncodeUnicode((string + 1), entry->Name, i);
1510 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1512 string[0] = entry->Group + 1;
1514 count += PackBlock(0x1e, 2, block++, string, req + count);
1515 /* Default Number */
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))
1522 string[0] = entry->SubEntries[defaultn].NumberType;
1526 i = strlen(entry->SubEntries[defaultn].data.Number);
1527 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1529 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
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;
1539 j = strlen(entry->SubEntries[i].data.Number);
1540 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1542 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1544 req[17] = block - 1;
1545 dprintf("Writing phonebook entry %s...\n",entry->Name);
1547 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1548 return SM_Block(state, data, 0x03);
1551 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1554 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1555 0x00, 0x00, /* memory type */ //02,05
1556 0x00, 0x00, /* location */
1559 dprintf("Reading phonebook location (%d)\n", location);
1562 req[10] = location >> 8;
1563 req[11] = location & 0xff;
1565 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1566 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1571 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1573 int memtype, location;
1575 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1576 location = data->PhonebookEntry->Location;
1578 return P7110_ReadPhonebookLL(data, state, memtype, location);
1581 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1583 int memtype, location;
1585 memtype = P7110_MEMORY_SPEEDDIALS;
1586 location = data->SpeedDial->Number;
1588 return P7110_ReadPhonebookLL(data, state, memtype, location);
1591 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1594 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1596 req[5] = data->MessageCenter->No;
1598 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1599 error = SM_Block(state, data, P7110_MSG_SMS);
1604 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1607 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1609 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1610 error = SM_Block(state, data, P7110_MSG_CLOCK);
1615 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
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};
1621 GSM_DateTime tmptime;
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;
1630 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1631 error = SM_Block(state, data, P7110_MSG_CALENDAR);