7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000 Hugh Blemings & Pavel JanÃk ml.
10 Copytight (C) 2000 Chris Kemp
12 Released under the terms of the GNU GPL, see file COPYING for more details.
14 This file provides functions specific to the 7110 series.
15 See README for more details on supported mobile phones.
17 The various routines are called P7110_(whatever).
20 Revision 1.1.1.2 2001/11/27 22:01:19 short
21 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
23 Revision 1.28 2001/11/27 12:25:01 pkot
26 Revision 1.27 2001/11/22 17:56:53 pkot
27 smslib update. sms sending
29 Revision 1.26 2001/11/19 17:09:59 pkot
32 Revision 1.25 2001/11/19 16:24:31 pkot
33 Grrrr... I should have check if I have fixed this typo
35 Revision 1.24 2001/11/19 15:53:16 pkot
38 Revision 1.23 2001/11/19 13:46:42 pkot
39 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
41 Revision 1.22 2001/11/17 20:18:32 pkot
42 Added dau9p connection type for 6210/7110
44 Revision 1.21 2001/11/17 16:44:07 pkot
45 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
47 Revision 1.20 2001/11/15 12:15:04 pkot
48 smslib updates. begin work on sms in 6100 series
50 Revision 1.19 2001/11/15 12:12:34 pkot
51 7110 and 6110 series phones introduce as Nokia
53 Revision 1.18 2001/11/15 12:04:06 pkot
54 Faster initialization for 6100 series (don't check for dlr3 cable)
56 Revision 1.17 2001/11/14 10:48:03 pkot
57 6210/7110 debug cleanups
59 Revision 1.16 2001/11/13 16:12:21 pkot
60 Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
62 Revision 1.15 2001/11/08 16:47:48 pkot
63 Start fiddling with 7110 and SMS
65 Revision 1.14 2001/09/09 21:45:49 machek
66 Cleanups from Ladislav Michl <ladis@psi.cz>:
68 *) do *not* internationalize debug messages
70 *) some whitespace fixes, do not use //
72 *) break is unneccessary after return
74 Revision 1.13 2001/08/16 23:59:32 pkot
75 Fixed (hopefully) timezone mismash (Sheldon Hearn)
77 Revision 1.12 2001/08/09 12:34:34 pkot
78 3330 and 6250 support - I have no idea if it does work (mygnokii)
80 Revision 1.11 2001/07/05 10:54:53 pkot
81 Solaris 2.7 fixes - should be harmless for other OSes (Michael Wiedmann)
83 Revision 1.10 2001/06/27 23:52:49 pkot
84 7110/6210 updates (Marian Jancar)
86 Revision 1.9 2001/06/10 23:49:49 pkot
87 Small fixes to hide compilation warnings and allow gnokii.c to compile
89 Revision 1.8 2001/05/24 20:47:30 chris
90 More updating of 7110 code and some of xgnokii_lowlevel changed over.
92 Revision 1.7 2001/05/07 16:24:04 pkot
93 DLR-3P temporary fix. How should I do it better?
95 Revision 1.6 2001/03/23 13:40:24 chris
96 Pavel's patch and a few fixes.
98 Revision 1.5 2001/03/22 16:17:06 chris
99 Tidy-ups and fixed gnokii/Makefile and gnokii/ChangeLog which I somehow corrupted.
101 Revision 1.4 2001/03/21 23:36:06 chris
102 Added the statemachine
103 This will break gnokii --identify and --monitor except for 6210/7110
105 Revision 1.3 2001/03/13 01:24:03 pkot
106 Code cleanup - no warnings during compilation
108 Revision 1.2 2001/03/13 01:23:18 pkot
109 Windows updates (Manfred Jonsson)
111 Revision 1.1 2001/02/21 19:57:07 chris
112 More fiddling with the directory layout
114 Revision 1.1 2001/02/16 14:29:53 chris
115 Restructure of common/. Fixed a problem in fbus-phonet.c
116 Lots of dprintfs for Marcin
117 Any size xpm can now be loaded (eg for 7110 startup logos)
118 nk7110 code detects 7110/6210 and alters startup logo size to suit
119 Moved Marcin's extended phonebook code into gnokii.c
121 Revision 1.7 2001/02/06 21:15:35 chris
122 Preliminary irda support for 7110 etc. Not well tested!
124 Revision 1.6 2001/02/03 23:56:15 chris
125 Start of work on irda support (now we just need fbus-irda.c!)
126 Proper unicode support in 7110 code (from pkot)
128 Revision 1.5 2001/02/01 15:17:31 pkot
129 Fixed --identify and added Manfred's manufacturer patch
131 Revision 1.4 2001/01/29 17:14:42 chris
132 dprintf now in misc.h (and fiddling with 7110 code)
134 Revision 1.3 2001/01/23 15:32:41 chris
135 Pavel's 'break' and 'static' corrections.
136 Work on logos for 7110.
138 Revision 1.2 2001/01/17 02:54:54 chris
139 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
140 I can now edit my phonebook in xgnokii but it is 'work in progress'.
142 Revision 1.1 2001/01/14 22:46:59 chris
143 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
151 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.h */
153 #include "gsm-common.h"
154 #include "phones/generic.h"
155 #include "phones/nk7110.h"
156 #include "links/fbus.h"
157 #include "links/fbus-phonet.h"
158 #include "phones/nokia.h"
159 #include "gsm-encoding.h"
162 #define snprintf _snprintf
167 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
168 { P7110_MSG_FOLDER, P7110_IncomingFolder },
169 { P7110_MSG_SMS, P7110_IncomingSMS },
170 { P7110_MSG_PHONEBOOK, P7110_IncomingPhonebook },
171 { P7110_MSG_NETSTATUS, P7110_IncomingNetwork },
172 { P7110_MSG_CALENDAR, P7110_IncomingCalendar },
173 { P7110_MSG_BATTERY, P7110_IncomingBattLevel },
174 { P7110_MSG_CLOCK, P7110_IncomingClock },
175 { P7110_MSG_IDENTITY, P7110_Incoming0x1b },
176 { P7110_MSG_STLOGO, P7110_IncomingStartup },
180 GSM_Phone phone_nokia_7110 = {
181 P7110_IncomingFunctions,
182 PGEN_IncomingDefault,
183 /* Mobile phone information */
185 "7110|6210|6250", /* Supported models */
186 7, /* Max RF Level */
187 0, /* Min RF Level */
188 GRF_Percentage, /* RF level units */
189 7, /* Max Battery Level */
190 0, /* Min Battery Level */
191 GBU_Percentage, /* Battery level units */
192 GDT_DateTime, /* Have date/time support */
193 GDT_TimeOnly, /* Alarm supports time only */
194 1, /* Alarms available - FIXME */
195 60, 96, /* Startup logo size - 7110 is fixed at init*/
196 21, 78, /* Op logo size */
197 14, 72 /* Caller logo size */
202 /* FIXME - a little macro would help here... */
204 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
208 return P7110_Initialise(state);
210 return P7110_GetModel(data, state);
211 case GOP_GetRevision:
212 return P7110_GetRevision(data, state);
214 return P7110_GetIMEI(data, state);
216 return P7110_Identify(data, state);
217 case GOP_GetBatteryLevel:
218 return P7110_GetBatteryLevel(data, state);
220 return P7110_GetRFLevel(data, state);
221 case GOP_GetMemoryStatus:
222 return P7110_GetMemoryStatus(data, state);
224 return P7110_GetBitmap(data, state);
226 return P7110_SetBitmap(data, state);
227 case GOP_ReadPhonebook:
228 return P7110_ReadPhonebook(data, state);
229 case GOP_WritePhonebook:
230 return P7110_WritePhonebookLocation(data, state);
231 case GOP_GetNetworkInfo:
232 return P7110_GetNetworkInfo(data, state);
233 case GOP_GetSpeedDial:
234 return P7110_GetSpeedDial(data, state);
235 case GOP_GetSMSCenter:
236 return P7110_GetSMSCenter(data, state);
237 case GOP_GetDateTime:
238 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
240 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
241 case GOP_GetCalendarNote:
242 return P7110_GetCalendarNote(data, state);
244 return P7110_GetSMS(data, state);
246 return P7110_SendSMS(data, state);
247 /* I'm not sure yet if folder functions will be shared or local
248 case GOP_GetSMSFolders:
249 return P7110_GetSMSFolders(data, state);
250 case GOP_GetSMSFolderStatus:
251 return P7110_GetSMSFolderStatus(data, state);*/
253 return GE_NOTIMPLEMENTED;
257 /* LinkOK is always true for now... */
258 bool P7110_LinkOK = true;
260 /* Initialise is the only function allowed to 'use' state */
261 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
266 int try = 0, connected = 0;
268 /* Copy in the phone info */
269 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
271 dprintf("Connecting\n");
273 switch (state->Link.ConnectionType) {
275 if (try == 0) try = 1;
277 if (try > 1) return GE_NOTSUPPORTED;
278 err = FBUS_Initialise(&(state->Link), state, 1 - try);
282 if (try > 0) return GE_NOTSUPPORTED;
283 err = PHONET_Initialise(&(state->Link), state);
286 return GE_NOTSUPPORTED;
290 if (err != GE_NONE) {
291 dprintf("Error in link initialisation: %d\n", err);
296 SM_Initialise(state);
298 /* Now test the link and get the model */
299 GSM_DataClear(&data);
301 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
304 /* Check for 7110 and alter the startup logo size */
305 if (strcmp(model, "NSE-5") == 0) {
306 state->Phone.Info.StartupLogoH = 65;
307 dprintf("7110 detected - startup logo height set to 65\n");
312 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
314 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
316 dprintf("Getting model...\n");
317 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
318 return SM_Block(state, data, 0x1b);
321 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
323 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
325 dprintf("Getting revision...\n");
326 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
327 return SM_Block(state, data, 0x1b);
330 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
332 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
334 dprintf("Getting imei...\n");
335 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
336 return SM_Block(state, data, 0x1b);
339 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
341 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
343 dprintf("Getting battery level...\n");
344 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
345 return SM_Block(state, data, 0x17);
348 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
350 switch (message[3]) {
352 if (data->BatteryLevel) {
353 *(data->BatteryUnits) = GBU_Percentage;
354 *(data->BatteryLevel) = message[5];
355 dprintf("Battery level %f\n",*(data->BatteryLevel));
359 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
365 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
367 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
369 dprintf("Getting rf level...\n");
370 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
371 return SM_Block(state, data, 0x0a);
374 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
376 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
378 dprintf("Getting Network Info...\n");
379 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
380 return SM_Block(state, data, 0x0a);
383 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
385 unsigned char *blockstart;
388 switch (message[3]) {
390 blockstart = message + 6;
391 for (i = 0; i < message[4]; i++) {
392 switch (blockstart[0]) {
393 case 0x01: /* Operator details */
394 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
395 if (data->NetworkInfo) {
396 /* Is this correct? */
397 data->NetworkInfo->CellID[0]=blockstart[4];
398 data->NetworkInfo->CellID[1]=blockstart[5];
399 data->NetworkInfo->LAC[0]=blockstart[6];
400 data->NetworkInfo->LAC[1]=blockstart[7];
401 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
402 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
403 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
404 data->NetworkInfo->NetworkCode[3] = ' ';
405 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
406 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
407 data->NetworkInfo->NetworkCode[6] = 0;
410 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
411 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
412 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
413 data->Bitmap->netcode[3] = ' ';
414 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
415 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
416 data->Bitmap->netcode[6] = 0;
417 dprintf("Operator %s ",data->Bitmap->netcode);
420 case 0x04: /* Logo */
422 dprintf("Op logo received ok ");
423 data->Bitmap->type = GSM_OperatorLogo;
424 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
425 data->Bitmap->height = blockstart[3];
426 data->Bitmap->width = blockstart[2];
427 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
428 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
432 dprintf("Unknown operator block %d\n", blockstart[0]);
435 blockstart += blockstart[1];
440 *(data->RFUnits) = GRF_Percentage;
441 *(data->RFLevel) = message[4];
442 dprintf("RF level %f\n",*(data->RFLevel));
446 dprintf("Op Logo Set OK\n");
449 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
455 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
457 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
459 dprintf("Getting memory status...\n");
460 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
461 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
462 return SM_Block(state, data, 0x03);
465 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
467 unsigned char *blockstart;
468 unsigned char blocks;
469 unsigned char subblockcount;
472 GSM_SubPhonebookEntry* subEntry = NULL;
474 PGEN_DebugMessage(messagetype, message, length);
476 switch (message[3]) {
477 case 0x04: /* Get status response */
478 if (data->MemoryStatus) {
479 if (message[5] != 0xff) {
480 data->MemoryStatus->Used = (message[16] << 8) + message[17];
481 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
482 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
484 dprintf("Unknown error getting mem status\n");
485 return GE_NOTIMPLEMENTED;
489 case 0x08: /* Read Memory response */
490 if (data->PhonebookEntry) {
491 data->PhonebookEntry->Empty = true;
492 data->PhonebookEntry->Group = 0;
493 data->PhonebookEntry->Name[0] = '\0';
494 data->PhonebookEntry->Number[0] = '\0';
495 data->PhonebookEntry->SubEntriesCount = 0;
496 data->PhonebookEntry->Date.Year = 0;
497 data->PhonebookEntry->Date.Month = 0;
498 data->PhonebookEntry->Date.Day = 0;
499 data->PhonebookEntry->Date.Hour = 0;
500 data->PhonebookEntry->Date.Minute = 0;
501 data->PhonebookEntry->Date.Second = 0;
503 if (message[6] == 0x0f) { // not found
504 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
505 dprintf("Invalid caller location\n");
506 return GE_INVALIDPHBOOKLOCATION;
508 dprintf("Unknown error getting phonebook\n");
509 return GE_NOTIMPLEMENTED;
512 dprintf("Received phonebook info\n");
513 blocks = message[17];
514 blockstart = message + 18;
517 for (i = 0; i < blocks; i++) {
518 if (data->PhonebookEntry)
519 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
520 switch(blockstart[0]) {
521 case P7110_ENTRYTYPE_POINTER: /* Pointer */
522 switch (message[11]) { /* Memory type */
523 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
524 if ((data != NULL) && (data->SpeedDial != NULL)) {
525 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
526 switch(blockstart[8]) {
528 data->SpeedDial->MemoryType = GMT_ME;
533 data->SpeedDial->MemoryType = GMT_SM;
537 data->SpeedDial->MemoryType = GMT_XX;
542 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
546 /* FIXME: is it possible? */
547 dprintf("Wrong memory type(?)\n");
552 case P7110_ENTRYTYPE_NAME: /* Name */
554 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
555 dprintf("Name: %s\n", data->Bitmap->text);
556 } else if (data->PhonebookEntry) {
557 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
558 data->PhonebookEntry->Empty = false;
559 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
562 case P7110_ENTRYTYPE_EMAIL:
563 case P7110_ENTRYTYPE_POSTAL:
564 case P7110_ENTRYTYPE_NOTE:
565 if (data->PhonebookEntry) {
566 subEntry->EntryType = blockstart[0];
567 subEntry->NumberType = 0;
568 subEntry->BlockNumber = blockstart[4];
569 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
570 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
571 dprintf(" Text: %s\n", subEntry->data.Number);
573 data->PhonebookEntry->SubEntriesCount++;
576 case P7110_ENTRYTYPE_NUMBER:
577 if (data->PhonebookEntry) {
578 subEntry->EntryType = blockstart[0];
579 subEntry->NumberType = blockstart[5];
580 subEntry->BlockNumber = blockstart[4];
581 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
582 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
583 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
584 dprintf(" Number: %s\n", subEntry->data.Number);
586 data->PhonebookEntry->SubEntriesCount++;
589 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
591 data->Bitmap->ringtone = blockstart[5];
592 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
595 case P7110_ENTRYTYPE_DATE:
596 if (data->PhonebookEntry) {
597 subEntry->EntryType=blockstart[0];
598 subEntry->NumberType=blockstart[5];
599 subEntry->BlockNumber=blockstart[4];
600 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
601 subEntry->data.Date.Month = blockstart[8];
602 subEntry->data.Date.Day = blockstart[9];
603 subEntry->data.Date.Hour = blockstart[10];
604 subEntry->data.Date.Minute = blockstart[11];
605 subEntry->data.Date.Second = blockstart[12];
606 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
607 subEntry->data.Date.Month, subEntry->data.Date.Year);
608 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
609 subEntry->data.Date.Minute, subEntry->data.Date.Second);
613 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
615 data->Bitmap->width = blockstart[5];
616 data->Bitmap->height = blockstart[6];
617 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
618 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
622 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
624 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
625 if (data->PhonebookEntry) {
626 data->PhonebookEntry->Group = blockstart[5] - 1;
627 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
631 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
634 blockstart += blockstart[3];
638 switch (message[6]) {
639 case 0x3d: return GE_PHBOOKWRITEFAILED;
640 case 0x3e: return GE_PHBOOKWRITEFAILED;
641 default: return GE_NONE;
645 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
651 /* Just as an example.... */
652 /* But note that both requests are the same type which isn't very 'proper' */
653 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
655 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
656 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
658 dprintf("Identifying...\n");
659 PNOK_GetManufacturer(data->Manufacturer);
660 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
661 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
662 SM_WaitFor(state, data, 0x1b);
663 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
664 SM_GetError(state, 0x1b);
666 /* Check that we are back at state Initialised */
667 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
671 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
673 switch (message[3]) {
676 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
677 dprintf("Received imei %s\n",data->Imei);
682 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
683 dprintf("Received model %s\n",data->Model);
685 if (data->Revision) {
686 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
687 dprintf("Received revision %s\n",data->Revision);
691 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
698 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
699 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
702 int nextfolder = 0x10;
705 switch (message[3]) {
709 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
710 dprintf("Message: %d SMS Folders received:\n", message[4]);
712 strcpy(data->SMSFolderList->Folder[1].Name, " ");
713 data->SMSFolderList->number = message[4];
715 for (j = 0; j < message[4]; j++) {
717 strcpy(data->SMSFolderList->Folder[j].Name, " ");
718 data->SMSFolderList->FolderID[j] = message[i];
719 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
721 dprintf(" Folder name: ");
723 /* search for next folder's index number, i.e. length of folder name */
724 while (message[i+1] != nextfolder && i < length) {
730 if (nextfolder == 0x28) nextfolder++;
732 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
733 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
738 /* getfolderstatus */
740 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
741 dprintf("Message: SMS Folder status received: \n" );
742 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
743 data->SMSFolder->number = (message[5] * 256) + message[5];
744 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
745 dprintf("Message: IDs of Entries : ");
746 for (i = 0; i < message[4] * 256 + message[5]; i++) {
747 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
748 dprintf("%d, ", data->SMSFolder->locations[i]);
755 for (i = 0; i < length; i ++)
756 if (isprint(message[i]))
757 dprintf("[%02x%c]", message[i], message[i]);
759 dprintf("[%02x ]", message[i]);
762 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
764 /* Number of SMS in folder */
765 data->SMSMessage->Number = message[7];
767 /* MessageType/FolderID */
768 data->SMSMessage->MemoryType = message[5];
770 /* These offsets are 6210/7110 series specific */
771 /* Short Message status */
772 data->SMSMessage->Status = message[4];
773 dprintf("\tStatus: ");
774 switch (data->SMSMessage->Status) {
788 dprintf("UNKNOWN\n");
791 /* See if message# is given back by phone. If not and status is unread */
792 /* we want it, if status is not unread it's a "random" message given back */
793 /* by the phone because we want a message of which the # doesn't exist */
795 for (i = 0; i < data->SMSFolder->number; i++) {
796 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
799 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
801 DecodePDUSMS(message + 6, data->SMSMessage, length);
805 /* get list of SMS pictures */
807 dprintf("Getting list of SMS pictures...\n");
808 for (i = 0; i < length; i ++)
809 if (isprint(message[i]))
810 dprintf("[%02x%c]", message[i], message[i]);
812 dprintf("[%02x ]", message[i]);
817 for (i = 0; i < length; i ++)
818 if (isprint(message[i]))
819 dprintf("[%02x%c]", message[i], message[i]);
821 dprintf("[%02x ]", message[i]);
823 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
829 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
831 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
832 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
835 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
840 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
845 /* just testiung picture listing */
846 req_list[4] = data->SMSMessage->MemoryType;
847 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
848 error = SM_Block(state, data, 0x14);
850 /* see if the message we want is from the last read folder, i.e. */
851 /* we don't have to get folder status again */
852 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
854 dprintf("Getting list of SMS folders...\n");
855 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
856 error = SM_Block(state, data, 0x14);
858 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
859 return GE_INVALIDMEMORYTYPE;
860 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
861 req_status[4] = data->SMSMessage->MemoryType;
863 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
864 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
865 error = SM_Block(state, data, 0x14);
868 dprintf("Getting SMS...\n");
869 req_sms[4] = data->SMSMessage->MemoryType;
870 req_sms[6] = data->SMSMessage->Number;
871 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
872 return SM_Block(state, data, 0x14);
875 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
877 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
880 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
881 return SM_Block(state, data, 0x14);
885 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
887 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
889 dprintf("Getting SMS Folders...\n");
890 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
891 return SM_Block(state, data, 0x14);
894 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
896 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
900 req[4] = data->SMSFolder->FolderID;
901 dprintf("Getting SMS Folder Status...\n");
902 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
903 return SM_Block(state, data, 0x14);
907 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
909 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
912 if (data->SMSMessage->MessageCenter.No) {
913 data->MessageCenter = &data->SMSMessage->MessageCenter;
914 P7110_GetSMSCenter(data, state);
917 length = EncodePDUSMS(data->SMSMessage, req + 6);
918 if (!length) return GE_SMSWRONGFORMAT;
919 dprintf("Sending SMS...(%d)\n", length);
920 for (i = 0; i < length + 6; i++) {
921 dprintf("%02x ", req[i]);
924 if (SM_SendMessage(state, length+6, 0x02, req) != GE_NONE) return GE_NOTREADY;
925 return SM_Block(state, data, 0x02);
928 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
930 GSM_Error e = GE_NONE;
933 if (!data) return GE_INTERNALERROR;
935 switch (message[3]) {
936 case P7110_SUBSMS_SMSC_RCVD:
937 dprintf("SMSC Received\n");
938 /* FIXME: Implement all these in gsm-sms.c */
939 data->MessageCenter->No = message[4];
940 data->MessageCenter->Format = message[6];
941 data->MessageCenter->Validity = message[8]; /* due to changes in format */
943 bytes = message[21] - 1;
946 sprintf(data->MessageCenter->Name, "%s", message + 33);
948 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
949 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
950 data->MessageCenter->Type = message[22];
952 if (strlen(data->MessageCenter->Recipient) == 0) {
953 sprintf(data->MessageCenter->Recipient, "(none)");
955 if (strlen(data->MessageCenter->Number) == 0) {
956 sprintf(data->MessageCenter->Number, "(none)");
958 if(strlen(data->MessageCenter->Name) == 0) {
959 sprintf(data->MessageCenter->Name, "(none)");
964 case P7110_SUBSMS_SMS_SENT:
965 dprintf("SMS sent\n");
969 case P7110_SUBSMS_SEND_FAIL:
970 dprintf("SMS sending failed\n");
971 e = GE_SMSSENDFAILED;
974 case P7110_SUBSMS_SMS_RCVD:
975 case P7110_SUBSMS_CELLBRD_OK:
976 case P7110_SUBSMS_CELLBRD_FAIL:
977 case P7110_SUBSMS_READ_CELLBRD:
978 case P7110_SUBSMS_SMSC_OK:
979 case P7110_SUBSMS_SMSC_FAIL:
980 case P7110_SUBSMS_SMSC_RCVFAIL:
981 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
982 e = GE_NOTIMPLEMENTED;
986 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
993 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
995 GSM_Error e = GE_NONE;
997 if (!data || !data->DateTime) return GE_INTERNALERROR;
998 switch (message[3]) {
999 case P7110_SUBCLO_DATE_RCVD:
1000 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
1001 data->DateTime->Month = message[10];
1002 data->DateTime->Day = message[11];
1003 data->DateTime->Hour = message[12];
1004 data->DateTime->Minute = message[13];
1005 data->DateTime->Second = message[14];
1008 case P7110_SUBCLO_ALARM_RCVD:
1009 switch(message[8]) {
1010 case P7110_ALARM_ENABLED:
1011 data->DateTime->AlarmEnabled = 1;
1013 case P7110_ALARM_DISABLED:
1014 data->DateTime->AlarmEnabled = 0;
1017 data->DateTime->AlarmEnabled = -1;
1018 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
1023 data->DateTime->Hour = message[9];
1024 data->DateTime->Minute = message[10];
1028 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
1035 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
1039 struct tm *tm_alarm;
1040 GSM_Error e = GE_NONE;
1042 if (!time || !alarm) return GE_INTERNALERROR;
1044 memset(&tm_time, 0, sizeof(tm_time));
1045 tm_time.tm_year = time->Year - 1900;
1046 tm_time.tm_mon = time->Month - 1;
1047 tm_time.tm_mday = time->Day;
1048 tm_time.tm_hour = time->Hour;
1049 tm_time.tm_min = time->Minute;
1052 t_alarm = mktime(&tm_time);
1053 t_alarm -= alarmdiff;
1054 t_alarm += timezone;
1056 tm_alarm = localtime(&t_alarm);
1058 alarm->Year = tm_alarm->tm_year + 1900;
1059 alarm->Month = tm_alarm->tm_mon + 1;
1060 alarm->Day = tm_alarm->tm_mday;
1061 alarm->Hour = tm_alarm->tm_hour;
1062 alarm->Minute = tm_alarm->tm_min;
1063 alarm->Second = tm_alarm->tm_sec;
1069 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
1072 GSM_Error e = GE_NONE;
1074 if (!c) return GE_INTERNALERROR;
1076 c->Time.Hour = block[0];
1077 c->Time.Minute = block[1];
1078 c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1079 alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1081 if (alarmdiff != 0xffff) {
1082 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1083 c->Alarm.AlarmEnabled = 1;
1085 c->Alarm.AlarmEnabled = 0;
1091 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1093 GSM_Error e = GE_NONE;
1094 unsigned char *block;
1097 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1099 year = data->CalendarNote->Time.Year;
1100 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1101 switch (message[3]) {
1102 case P7110_SUBCAL_NOTE_RCVD:
1103 block = message + 12;
1105 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1106 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1107 data->CalendarNote->Time.Month = message[10];
1108 data->CalendarNote->Time.Day = message[11];
1109 data->CalendarNote->Time.Second = 0;
1111 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1113 switch (message[6]) {
1114 case P7110_NOTE_MEETING:
1115 data->CalendarNote->Type = GCN_MEETING;
1116 P7110_GetNoteTimes(block, data->CalendarNote);
1117 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1119 case P7110_NOTE_CALL:
1120 data->CalendarNote->Type = GCN_CALL;
1121 P7110_GetNoteTimes(block, data->CalendarNote);
1122 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1123 DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1125 case P7110_NOTE_REMINDER:
1126 data->CalendarNote->Type = GCN_REMINDER;
1127 data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1128 DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1130 case P7110_NOTE_BIRTHDAY:
1132 for (i = 0; i < 10; i++) {
1133 dprintf("(%i:0x%02x)", i, block[i]);
1137 data->CalendarNote->Type = GCN_BIRTHDAY;
1138 data->CalendarNote->Time.Year = year;
1139 data->CalendarNote->Time.Hour = 23;
1140 data->CalendarNote->Time.Minute = 59;
1141 data->CalendarNote->Time.Second = 58;
1143 alarm = ((unsigned int)block[2]) << 24;
1144 alarm += ((unsigned int)block[3]) << 16;
1145 alarm += ((unsigned int)block[4]) << 8;
1148 dprintf("alarm: %i\n", alarm);
1150 if (alarm == 0xffff) {
1151 data->CalendarNote->Alarm.AlarmEnabled = 0;
1153 data->CalendarNote->Alarm.AlarmEnabled = 1;
1156 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1158 data->CalendarNote->Time.Hour = 0;
1159 data->CalendarNote->Time.Minute = 0;
1160 data->CalendarNote->Time.Second = 0;
1161 data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1163 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1167 data->CalendarNote->Type = -1;
1173 case P7110_SUBCAL_ADD_MEETING_RESP:
1174 case P7110_SUBCAL_ADD_CALL_RESP:
1175 case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1176 case P7110_SUBCAL_ADD_REMINDER_RESP:
1177 case P7110_SUBCAL_DEL_NOTE_RESP:
1178 case P7110_SUBCAL_FREEPOS_RCVD:
1179 case P7110_SUBCAL_INFO_RCVD:
1180 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1181 e = GE_NOTIMPLEMENTED;
1184 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1191 static int GetMemoryType(GSM_MemoryType memory_type)
1195 switch (memory_type) {
1197 result = P7110_MEMORY_MT;
1200 result = P7110_MEMORY_ME;
1203 result = P7110_MEMORY_SM;
1206 result = P7110_MEMORY_FD;
1209 result = P7110_MEMORY_ON;
1212 result = P7110_MEMORY_EN;
1215 result = P7110_MEMORY_DC;
1218 result = P7110_MEMORY_RC;
1221 result = P7110_MEMORY_MC;
1224 result = P7110_MEMORY_XX;
1232 static GSM_Error P7110_DialVoice(char *Number)
1235 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1237 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1239 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1240 // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1241 // unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1242 // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1245 //req[4]=strlen(Number);
1247 //for(i=0; i < strlen(Number) ; i++)
1248 // req[5+i]=Number[i];
1250 //memcpy(req+5+strlen(Number), req_end, 10);
1252 //len=6+strlen(Number);
1257 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1261 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1262 PGEN_DebugMessage(1, req, len);
1266 // } else return GE_NOTIMPLEMENTED;
1273 return GE_NOTIMPLEMENTED;
1278 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1280 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1281 0x00, 0x10 , /* memory type */
1282 0x00, 0x00, /* location */
1285 req[11] = data->Bitmap->number + 1;
1286 dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1287 if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1288 return SM_Block(state, data, 0x03);
1291 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1296 *(block++) = size + 6;
1298 memcpy(block, buf, size);
1304 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1306 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1307 0x00, 0x10, /* memory type */
1308 0x00, 0x00, /* location */
1312 unsigned int count = 18;
1314 if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1315 (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1316 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);
1317 return GE_INVALIDIMAGESIZE;
1320 req[13] = data->Bitmap->number + 1;
1321 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1324 i = strlen(data->Bitmap->text);
1325 EncodeUnicode((string + 1), data->Bitmap->text, i);
1327 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1329 string[0] = data->Bitmap->ringtone;
1331 count += PackBlock(0x0c, 2, block++, string, req + count);
1333 string[0] = data->Bitmap->number+1;
1335 count += PackBlock(0x1e, 2, block++, string, req + count);
1336 /* Logo on/off - assume on for now */
1339 count += PackBlock(0x1c, 2, block++, string, req + count);
1341 string[0] = data->Bitmap->width;
1342 string[1] = data->Bitmap->height;
1345 string[4] = 0x7e; /* Size */
1346 memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1347 count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1348 req[17] = block - 1;
1350 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1351 return SM_Block(state, data, 0x03);
1354 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1356 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1358 dprintf("Getting startup logo...\n");
1359 if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1360 return SM_Block(state, data, 0x7a);
1363 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1365 switch (message[3]) {
1367 dprintf("Startup logo set ok\n");
1372 /* I'm sure there are blocks here but never mind! */
1373 data->Bitmap->type = GSM_StartupLogo;
1374 data->Bitmap->height = message[13];
1375 data->Bitmap->width = message[17];
1376 data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1377 memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1378 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1383 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1389 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1391 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1393 dprintf("Getting op logo...\n");
1394 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1395 return SM_Block(state, data, 0x0a);
1398 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1400 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1404 0xc0, 0x04, 0x03, 0x00 };
1408 if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1409 (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1410 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);
1411 return GE_INVALIDIMAGESIZE;
1414 req[12] = data->Bitmap->height;
1415 req[16] = data->Bitmap->width;
1416 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1417 count += data->Bitmap->size;
1418 dprintf("Setting startup logo...\n");
1420 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1421 return SM_Block(state, data, 0x7a);
1424 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1426 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1427 0x00, /* logo enabled */
1428 0x00, 0xf0, 0x00, /* network code (000 00) */
1430 0x08, /* length of rest */
1431 0x00, 0x00, /* Bitmap width / height */
1433 0x00, /* Bitmap size */
1438 if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1439 (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1440 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);
1441 return GE_INVALIDIMAGESIZE;
1444 if (strcmp(data->Bitmap->netcode,"000 00")) { /* set logo */
1445 req[5] = 0x01; // Logo enabled
1446 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1447 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1448 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1449 req[11] = 8 + data->Bitmap->size;
1450 req[12] = data->Bitmap->width;
1451 req[13] = data->Bitmap->height;
1452 req[15] = data->Bitmap->size;
1453 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1454 count += data->Bitmap->size;
1456 dprintf("Setting op logo...\n");
1457 if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1458 return SM_Block(state, data, 0x0a);
1461 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1463 switch(data->Bitmap->type) {
1464 case GSM_CallerLogo:
1465 return GetCallerBitmap(data, state);
1466 case GSM_StartupLogo:
1467 return GetStartupBitmap(data, state);
1468 case GSM_OperatorLogo:
1469 return GetOperatorBitmap(data, state);
1471 return GE_NOTIMPLEMENTED;
1475 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1477 switch(data->Bitmap->type) {
1478 case GSM_CallerLogo:
1479 return SetCallerBitmap(data, state);
1480 case GSM_StartupLogo:
1481 return SetStartupBitmap(data, state);
1482 case GSM_OperatorLogo:
1483 return SetOperatorBitmap(data, state);
1485 return GE_NOTIMPLEMENTED;
1489 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1491 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1492 0x00, 0x00, /* memory type */
1493 0x00, 0x00, /* location */
1496 int block, i, j, defaultn;
1497 unsigned int count = 18;
1498 GSM_PhonebookEntry *entry;
1500 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1501 else return GE_TRYAGAIN;
1503 req[11] = GetMemoryType(entry->MemoryType);
1504 req[12] = (entry->Location >> 8);
1505 req[13] = entry->Location & 0xff;
1507 if (*(entry->Name)) {
1509 i = strlen(entry->Name);
1510 EncodeUnicode((string + 1), entry->Name, i);
1512 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1514 string[0] = entry->Group + 1;
1516 count += PackBlock(0x1e, 2, block++, string, req + count);
1517 /* Default Number */
1519 for (i = 0; i < entry->SubEntriesCount; i++)
1520 if (entry->SubEntries[i].EntryType == GSM_Number)
1521 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1524 string[0] = entry->SubEntries[defaultn].NumberType;
1528 i = strlen(entry->SubEntries[defaultn].data.Number);
1529 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1531 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1533 /* Rest of the numbers */
1534 for (i = 0; i < entry->SubEntriesCount; i++)
1535 if (entry->SubEntries[i].EntryType == GSM_Number)
1536 if (i != defaultn) {
1537 string[0] = entry->SubEntries[i].NumberType;
1541 j = strlen(entry->SubEntries[i].data.Number);
1542 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1544 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1546 req[17] = block - 1;
1547 dprintf("Writing phonebook entry %s...\n",entry->Name);
1549 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1550 return SM_Block(state, data, 0x03);
1553 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1556 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1557 0x00, 0x00, /* memory type */ //02,05
1558 0x00, 0x00, /* location */
1561 dprintf("Reading phonebook location (%d)\n", location);
1564 req[10] = location >> 8;
1565 req[11] = location & 0xff;
1567 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1568 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1573 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1575 int memtype, location;
1577 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1578 location = data->PhonebookEntry->Location;
1580 return P7110_ReadPhonebookLL(data, state, memtype, location);
1583 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1585 int memtype, location;
1587 memtype = P7110_MEMORY_SPEEDDIALS;
1588 location = data->SpeedDial->Number;
1590 return P7110_ReadPhonebookLL(data, state, memtype, location);
1593 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1596 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1598 req[5] = data->MessageCenter->No;
1600 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1601 error = SM_Block(state, data, P7110_MSG_SMS);
1606 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1609 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1611 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1612 error = SM_Block(state, data, P7110_MSG_CLOCK);
1617 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1619 GSM_Error error = GE_NOTREADY;
1620 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1621 unsigned char date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1623 GSM_DateTime tmptime;
1625 tmpdata.DateTime = &tmptime;
1626 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1627 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1628 req[4] = data->CalendarNote->Location >> 8;
1629 req[5] = data->CalendarNote->Location & 0xff;
1630 data->CalendarNote->Time.Year = tmptime.Year;
1632 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1633 error = SM_Block(state, data, P7110_MSG_CALENDAR);