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.1.8.1 2001/11/27 23:06:09 short
21 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
23 Revision 1.1.1.1.2.1 2001/11/27 22:48:37 short
24 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
26 Revision 1.1.1.2 2001/11/27 22:01:19 short
27 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
29 Revision 1.28 2001/11/27 12:25:01 pkot
32 Revision 1.27 2001/11/22 17:56:53 pkot
33 smslib update. sms sending
35 Revision 1.26 2001/11/19 17:09:59 pkot
38 Revision 1.25 2001/11/19 16:24:31 pkot
39 Grrrr... I should have check if I have fixed this typo
41 Revision 1.24 2001/11/19 15:53:16 pkot
44 Revision 1.23 2001/11/19 13:46:42 pkot
45 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
47 Revision 1.22 2001/11/17 20:18:32 pkot
48 Added dau9p connection type for 6210/7110
50 Revision 1.21 2001/11/17 16:44:07 pkot
51 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
53 Revision 1.20 2001/11/15 12:15:04 pkot
54 smslib updates. begin work on sms in 6100 series
56 Revision 1.19 2001/11/15 12:12:34 pkot
57 7110 and 6110 series phones introduce as Nokia
59 Revision 1.18 2001/11/15 12:04:06 pkot
60 Faster initialization for 6100 series (don't check for dlr3 cable)
62 Revision 1.17 2001/11/14 10:48:03 pkot
63 6210/7110 debug cleanups
65 Revision 1.16 2001/11/13 16:12:21 pkot
66 Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
68 Revision 1.15 2001/11/08 16:47:48 pkot
69 Start fiddling with 7110 and SMS
71 Revision 1.14 2001/09/09 21:45:49 machek
72 Cleanups from Ladislav Michl <ladis@psi.cz>:
74 *) do *not* internationalize debug messages
76 *) some whitespace fixes, do not use //
78 *) break is unneccessary after return
80 Revision 1.13 2001/08/16 23:59:32 pkot
81 Fixed (hopefully) timezone mismash (Sheldon Hearn)
83 Revision 1.12 2001/08/09 12:34:34 pkot
84 3330 and 6250 support - I have no idea if it does work (mygnokii)
86 Revision 1.11 2001/07/05 10:54:53 pkot
87 Solaris 2.7 fixes - should be harmless for other OSes (Michael Wiedmann)
89 Revision 1.10 2001/06/27 23:52:49 pkot
90 7110/6210 updates (Marian Jancar)
92 Revision 1.9 2001/06/10 23:49:49 pkot
93 Small fixes to hide compilation warnings and allow gnokii.c to compile
95 Revision 1.8 2001/05/24 20:47:30 chris
96 More updating of 7110 code and some of xgnokii_lowlevel changed over.
98 Revision 1.7 2001/05/07 16:24:04 pkot
99 DLR-3P temporary fix. How should I do it better?
101 Revision 1.6 2001/03/23 13:40:24 chris
102 Pavel's patch and a few fixes.
104 Revision 1.5 2001/03/22 16:17:06 chris
105 Tidy-ups and fixed gnokii/Makefile and gnokii/ChangeLog which I somehow corrupted.
107 Revision 1.4 2001/03/21 23:36:06 chris
108 Added the statemachine
109 This will break gnokii --identify and --monitor except for 6210/7110
111 Revision 1.3 2001/03/13 01:24:03 pkot
112 Code cleanup - no warnings during compilation
114 Revision 1.2 2001/03/13 01:23:18 pkot
115 Windows updates (Manfred Jonsson)
117 Revision 1.1 2001/02/21 19:57:07 chris
118 More fiddling with the directory layout
120 Revision 1.1 2001/02/16 14:29:53 chris
121 Restructure of common/. Fixed a problem in fbus-phonet.c
122 Lots of dprintfs for Marcin
123 Any size xpm can now be loaded (eg for 7110 startup logos)
124 nk7110 code detects 7110/6210 and alters startup logo size to suit
125 Moved Marcin's extended phonebook code into gnokii.c
127 Revision 1.7 2001/02/06 21:15:35 chris
128 Preliminary irda support for 7110 etc. Not well tested!
130 Revision 1.6 2001/02/03 23:56:15 chris
131 Start of work on irda support (now we just need fbus-irda.c!)
132 Proper unicode support in 7110 code (from pkot)
134 Revision 1.5 2001/02/01 15:17:31 pkot
135 Fixed --identify and added Manfred's manufacturer patch
137 Revision 1.4 2001/01/29 17:14:42 chris
138 dprintf now in misc.h (and fiddling with 7110 code)
140 Revision 1.3 2001/01/23 15:32:41 chris
141 Pavel's 'break' and 'static' corrections.
142 Work on logos for 7110.
144 Revision 1.2 2001/01/17 02:54:54 chris
145 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
146 I can now edit my phonebook in xgnokii but it is 'work in progress'.
148 Revision 1.1 2001/01/14 22:46:59 chris
149 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
157 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.h */
159 #include "gsm-common.h"
160 #include "phones/generic.h"
161 #include "phones/nk7110.h"
162 #include "links/fbus.h"
163 #include "links/fbus-phonet.h"
164 #include "phones/nokia.h"
165 #include "gsm-encoding.h"
168 #define snprintf _snprintf
173 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
174 { P7110_MSG_FOLDER, P7110_IncomingFolder },
175 { P7110_MSG_SMS, P7110_IncomingSMS },
176 { P7110_MSG_PHONEBOOK, P7110_IncomingPhonebook },
177 { P7110_MSG_NETSTATUS, P7110_IncomingNetwork },
178 { P7110_MSG_CALENDAR, P7110_IncomingCalendar },
179 { P7110_MSG_BATTERY, P7110_IncomingBattLevel },
180 { P7110_MSG_CLOCK, P7110_IncomingClock },
181 { P7110_MSG_IDENTITY, P7110_Incoming0x1b },
182 { P7110_MSG_STLOGO, P7110_IncomingStartup },
186 GSM_Phone phone_nokia_7110 = {
187 P7110_IncomingFunctions,
188 PGEN_IncomingDefault,
189 /* Mobile phone information */
191 "7110|6210|6250", /* Supported models */
192 7, /* Max RF Level */
193 0, /* Min RF Level */
194 GRF_Percentage, /* RF level units */
195 7, /* Max Battery Level */
196 0, /* Min Battery Level */
197 GBU_Percentage, /* Battery level units */
198 GDT_DateTime, /* Have date/time support */
199 GDT_TimeOnly, /* Alarm supports time only */
200 1, /* Alarms available - FIXME */
201 60, 96, /* Startup logo size - 7110 is fixed at init*/
202 21, 78, /* Op logo size */
203 14, 72 /* Caller logo size */
208 /* FIXME - a little macro would help here... */
210 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
214 return P7110_Initialise(state);
216 return P7110_GetModel(data, state);
217 case GOP_GetRevision:
218 return P7110_GetRevision(data, state);
220 return P7110_GetIMEI(data, state);
222 return P7110_Identify(data, state);
223 case GOP_GetBatteryLevel:
224 return P7110_GetBatteryLevel(data, state);
226 return P7110_GetRFLevel(data, state);
227 case GOP_GetMemoryStatus:
228 return P7110_GetMemoryStatus(data, state);
230 return P7110_GetBitmap(data, state);
232 return P7110_SetBitmap(data, state);
233 case GOP_ReadPhonebook:
234 return P7110_ReadPhonebook(data, state);
235 case GOP_WritePhonebook:
236 return P7110_WritePhonebookLocation(data, state);
237 case GOP_GetNetworkInfo:
238 return P7110_GetNetworkInfo(data, state);
239 case GOP_GetSpeedDial:
240 return P7110_GetSpeedDial(data, state);
241 case GOP_GetSMSCenter:
242 return P7110_GetSMSCenter(data, state);
243 case GOP_GetDateTime:
244 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
246 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
247 case GOP_GetCalendarNote:
248 return P7110_GetCalendarNote(data, state);
250 return P7110_GetSMS(data, state);
252 return P7110_SendSMS(data, state);
253 /* I'm not sure yet if folder functions will be shared or local
254 case GOP_GetSMSFolders:
255 return P7110_GetSMSFolders(data, state);
256 case GOP_GetSMSFolderStatus:
257 return P7110_GetSMSFolderStatus(data, state);*/
259 return GE_NOTIMPLEMENTED;
263 /* LinkOK is always true for now... */
264 bool P7110_LinkOK = true;
266 /* Initialise is the only function allowed to 'use' state */
267 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
272 int try = 0, connected = 0;
274 /* Copy in the phone info */
275 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
277 dprintf("Connecting\n");
279 switch (state->Link.ConnectionType) {
281 if (try == 0) try = 1;
283 if (try > 1) return GE_NOTSUPPORTED;
284 err = FBUS_Initialise(&(state->Link), state, 1 - try);
288 if (try > 0) return GE_NOTSUPPORTED;
289 err = PHONET_Initialise(&(state->Link), state);
292 return GE_NOTSUPPORTED;
296 if (err != GE_NONE) {
297 dprintf("Error in link initialisation: %d\n", err);
302 SM_Initialise(state);
304 /* Now test the link and get the model */
305 GSM_DataClear(&data);
307 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
310 /* Check for 7110 and alter the startup logo size */
311 if (strcmp(model, "NSE-5") == 0) {
312 state->Phone.Info.StartupLogoH = 65;
313 dprintf("7110 detected - startup logo height set to 65\n");
318 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
320 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
322 dprintf("Getting model...\n");
323 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
324 return SM_Block(state, data, 0x1b);
327 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
329 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
331 dprintf("Getting revision...\n");
332 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
333 return SM_Block(state, data, 0x1b);
336 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
338 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
340 dprintf("Getting imei...\n");
341 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
342 return SM_Block(state, data, 0x1b);
345 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
347 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
349 dprintf("Getting battery level...\n");
350 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
351 return SM_Block(state, data, 0x17);
354 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
356 switch (message[3]) {
358 if (data->BatteryLevel) {
359 *(data->BatteryUnits) = GBU_Percentage;
360 *(data->BatteryLevel) = message[5];
361 dprintf("Battery level %f\n",*(data->BatteryLevel));
365 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
371 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
373 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
375 dprintf("Getting rf level...\n");
376 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
377 return SM_Block(state, data, 0x0a);
380 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
382 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
384 dprintf("Getting Network Info...\n");
385 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
386 return SM_Block(state, data, 0x0a);
389 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
391 unsigned char *blockstart;
394 switch (message[3]) {
396 blockstart = message + 6;
397 for (i = 0; i < message[4]; i++) {
398 switch (blockstart[0]) {
399 case 0x01: /* Operator details */
400 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
401 if (data->NetworkInfo) {
402 /* Is this correct? */
403 data->NetworkInfo->CellID[0]=blockstart[4];
404 data->NetworkInfo->CellID[1]=blockstart[5];
405 data->NetworkInfo->LAC[0]=blockstart[6];
406 data->NetworkInfo->LAC[1]=blockstart[7];
407 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
408 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
409 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
410 data->NetworkInfo->NetworkCode[3] = ' ';
411 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
412 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
413 data->NetworkInfo->NetworkCode[6] = 0;
416 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
417 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
418 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
419 data->Bitmap->netcode[3] = ' ';
420 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
421 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
422 data->Bitmap->netcode[6] = 0;
423 dprintf("Operator %s ",data->Bitmap->netcode);
426 case 0x04: /* Logo */
428 dprintf("Op logo received ok ");
429 data->Bitmap->type = GSM_OperatorLogo;
430 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
431 data->Bitmap->height = blockstart[3];
432 data->Bitmap->width = blockstart[2];
433 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
434 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
438 dprintf("Unknown operator block %d\n", blockstart[0]);
441 blockstart += blockstart[1];
446 *(data->RFUnits) = GRF_Percentage;
447 *(data->RFLevel) = message[4];
448 dprintf("RF level %f\n",*(data->RFLevel));
452 dprintf("Op Logo Set OK\n");
455 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
461 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
463 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
465 dprintf("Getting memory status...\n");
466 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
467 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
468 return SM_Block(state, data, 0x03);
471 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
473 unsigned char *blockstart;
474 unsigned char blocks;
475 unsigned char subblockcount;
478 GSM_SubPhonebookEntry* subEntry = NULL;
480 PGEN_DebugMessage(messagetype, message, length);
482 switch (message[3]) {
483 case 0x04: /* Get status response */
484 if (data->MemoryStatus) {
485 if (message[5] != 0xff) {
486 data->MemoryStatus->Used = (message[16] << 8) + message[17];
487 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
488 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
490 dprintf("Unknown error getting mem status\n");
491 return GE_NOTIMPLEMENTED;
495 case 0x08: /* Read Memory response */
496 if (data->PhonebookEntry) {
497 data->PhonebookEntry->Empty = true;
498 data->PhonebookEntry->Group = 0;
499 data->PhonebookEntry->Name[0] = '\0';
500 data->PhonebookEntry->Number[0] = '\0';
501 data->PhonebookEntry->SubEntriesCount = 0;
502 data->PhonebookEntry->Date.Year = 0;
503 data->PhonebookEntry->Date.Month = 0;
504 data->PhonebookEntry->Date.Day = 0;
505 data->PhonebookEntry->Date.Hour = 0;
506 data->PhonebookEntry->Date.Minute = 0;
507 data->PhonebookEntry->Date.Second = 0;
509 if (message[6] == 0x0f) { // not found
510 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
511 dprintf("Invalid caller location\n");
512 return GE_INVALIDPHBOOKLOCATION;
514 dprintf("Unknown error getting phonebook\n");
515 return GE_NOTIMPLEMENTED;
518 dprintf("Received phonebook info\n");
519 blocks = message[17];
520 blockstart = message + 18;
523 for (i = 0; i < blocks; i++) {
524 if (data->PhonebookEntry)
525 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
526 switch(blockstart[0]) {
527 case P7110_ENTRYTYPE_POINTER: /* Pointer */
528 switch (message[11]) { /* Memory type */
529 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
530 if ((data != NULL) && (data->SpeedDial != NULL)) {
531 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
532 switch(blockstart[8]) {
534 data->SpeedDial->MemoryType = GMT_ME;
539 data->SpeedDial->MemoryType = GMT_SM;
543 data->SpeedDial->MemoryType = GMT_XX;
548 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
552 /* FIXME: is it possible? */
553 dprintf("Wrong memory type(?)\n");
558 case P7110_ENTRYTYPE_NAME: /* Name */
560 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
561 dprintf("Name: %s\n", data->Bitmap->text);
562 } else if (data->PhonebookEntry) {
563 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
564 data->PhonebookEntry->Empty = false;
565 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
568 case P7110_ENTRYTYPE_EMAIL:
569 case P7110_ENTRYTYPE_POSTAL:
570 case P7110_ENTRYTYPE_NOTE:
571 if (data->PhonebookEntry) {
572 subEntry->EntryType = blockstart[0];
573 subEntry->NumberType = 0;
574 subEntry->BlockNumber = blockstart[4];
575 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
576 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
577 dprintf(" Text: %s\n", subEntry->data.Number);
579 data->PhonebookEntry->SubEntriesCount++;
582 case P7110_ENTRYTYPE_NUMBER:
583 if (data->PhonebookEntry) {
584 subEntry->EntryType = blockstart[0];
585 subEntry->NumberType = blockstart[5];
586 subEntry->BlockNumber = blockstart[4];
587 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
588 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
589 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
590 dprintf(" Number: %s\n", subEntry->data.Number);
592 data->PhonebookEntry->SubEntriesCount++;
595 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
597 data->Bitmap->ringtone = blockstart[5];
598 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
601 case P7110_ENTRYTYPE_DATE:
602 if (data->PhonebookEntry) {
603 subEntry->EntryType=blockstart[0];
604 subEntry->NumberType=blockstart[5];
605 subEntry->BlockNumber=blockstart[4];
606 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
607 subEntry->data.Date.Month = blockstart[8];
608 subEntry->data.Date.Day = blockstart[9];
609 subEntry->data.Date.Hour = blockstart[10];
610 subEntry->data.Date.Minute = blockstart[11];
611 subEntry->data.Date.Second = blockstart[12];
612 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
613 subEntry->data.Date.Month, subEntry->data.Date.Year);
614 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
615 subEntry->data.Date.Minute, subEntry->data.Date.Second);
619 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
621 data->Bitmap->width = blockstart[5];
622 data->Bitmap->height = blockstart[6];
623 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
624 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
628 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
630 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
631 if (data->PhonebookEntry) {
632 data->PhonebookEntry->Group = blockstart[5] - 1;
633 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
637 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
640 blockstart += blockstart[3];
644 switch (message[6]) {
645 case 0x3d: return GE_PHBOOKWRITEFAILED;
646 case 0x3e: return GE_PHBOOKWRITEFAILED;
647 default: return GE_NONE;
651 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
657 /* Just as an example.... */
658 /* But note that both requests are the same type which isn't very 'proper' */
659 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
661 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
662 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
664 dprintf("Identifying...\n");
665 PNOK_GetManufacturer(data->Manufacturer);
666 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
667 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
668 SM_WaitFor(state, data, 0x1b);
669 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
670 SM_GetError(state, 0x1b);
672 /* Check that we are back at state Initialised */
673 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
677 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
679 switch (message[3]) {
682 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
683 dprintf("Received imei %s\n",data->Imei);
688 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
689 dprintf("Received model %s\n",data->Model);
691 if (data->Revision) {
692 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
693 dprintf("Received revision %s\n",data->Revision);
697 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
704 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
705 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
708 int nextfolder = 0x10;
711 switch (message[3]) {
715 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
716 dprintf("Message: %d SMS Folders received:\n", message[4]);
718 strcpy(data->SMSFolderList->Folder[1].Name, " ");
719 data->SMSFolderList->number = message[4];
721 for (j = 0; j < message[4]; j++) {
723 strcpy(data->SMSFolderList->Folder[j].Name, " ");
724 data->SMSFolderList->FolderID[j] = message[i];
725 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
727 dprintf(" Folder name: ");
729 /* search for next folder's index number, i.e. length of folder name */
730 while (message[i+1] != nextfolder && i < length) {
736 if (nextfolder == 0x28) nextfolder++;
738 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
739 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
744 /* getfolderstatus */
746 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
747 dprintf("Message: SMS Folder status received: \n" );
748 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
749 data->SMSFolder->number = (message[5] * 256) + message[5];
750 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
751 dprintf("Message: IDs of Entries : ");
752 for (i = 0; i < message[4] * 256 + message[5]; i++) {
753 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
754 dprintf("%d, ", data->SMSFolder->locations[i]);
761 for (i = 0; i < length; i ++)
762 if (isprint(message[i]))
763 dprintf("[%02x%c]", message[i], message[i]);
765 dprintf("[%02x ]", message[i]);
768 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
770 /* Number of SMS in folder */
771 data->SMSMessage->Number = message[7];
773 /* MessageType/FolderID */
774 data->SMSMessage->MemoryType = message[5];
776 /* These offsets are 6210/7110 series specific */
777 /* Short Message status */
778 data->SMSMessage->Status = message[4];
779 dprintf("\tStatus: ");
780 switch (data->SMSMessage->Status) {
794 dprintf("UNKNOWN\n");
797 /* See if message# is given back by phone. If not and status is unread */
798 /* we want it, if status is not unread it's a "random" message given back */
799 /* by the phone because we want a message of which the # doesn't exist */
801 for (i = 0; i < data->SMSFolder->number; i++) {
802 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
805 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
807 DecodePDUSMS(message + 6, data->SMSMessage, length);
811 /* get list of SMS pictures */
813 dprintf("Getting list of SMS pictures...\n");
814 for (i = 0; i < length; i ++)
815 if (isprint(message[i]))
816 dprintf("[%02x%c]", message[i], message[i]);
818 dprintf("[%02x ]", message[i]);
823 for (i = 0; i < length; i ++)
824 if (isprint(message[i]))
825 dprintf("[%02x%c]", message[i], message[i]);
827 dprintf("[%02x ]", message[i]);
829 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
835 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
837 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
838 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
841 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
846 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
851 /* just testiung picture listing */
852 req_list[4] = data->SMSMessage->MemoryType;
853 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
854 error = SM_Block(state, data, 0x14);
856 /* see if the message we want is from the last read folder, i.e. */
857 /* we don't have to get folder status again */
858 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
860 dprintf("Getting list of SMS folders...\n");
861 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
862 error = SM_Block(state, data, 0x14);
864 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
865 return GE_INVALIDMEMORYTYPE;
866 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
867 req_status[4] = data->SMSMessage->MemoryType;
869 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
870 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
871 error = SM_Block(state, data, 0x14);
874 dprintf("Getting SMS...\n");
875 req_sms[4] = data->SMSMessage->MemoryType;
876 req_sms[6] = data->SMSMessage->Number;
877 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
878 return SM_Block(state, data, 0x14);
881 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
883 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
886 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
887 return SM_Block(state, data, 0x14);
891 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
893 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
895 dprintf("Getting SMS Folders...\n");
896 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
897 return SM_Block(state, data, 0x14);
900 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
902 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
906 req[4] = data->SMSFolder->FolderID;
907 dprintf("Getting SMS Folder Status...\n");
908 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
909 return SM_Block(state, data, 0x14);
913 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
915 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
918 if (data->SMSMessage->MessageCenter.No) {
919 data->MessageCenter = &data->SMSMessage->MessageCenter;
920 P7110_GetSMSCenter(data, state);
923 length = EncodePDUSMS(data->SMSMessage, req + 6);
924 if (!length) return GE_SMSWRONGFORMAT;
925 dprintf("Sending SMS...(%d)\n", length);
926 for (i = 0; i < length + 6; i++) {
927 dprintf("%02x ", req[i]);
930 if (SM_SendMessage(state, length+6, 0x02, req) != GE_NONE) return GE_NOTREADY;
931 return SM_Block(state, data, 0x02);
934 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
936 GSM_Error e = GE_NONE;
939 if (!data) return GE_INTERNALERROR;
941 switch (message[3]) {
942 case P7110_SUBSMS_SMSC_RCVD:
943 dprintf("SMSC Received\n");
944 /* FIXME: Implement all these in gsm-sms.c */
945 data->MessageCenter->No = message[4];
946 data->MessageCenter->Format = message[6];
947 data->MessageCenter->Validity = message[8]; /* due to changes in format */
949 bytes = message[21] - 1;
952 sprintf(data->MessageCenter->Name, "%s", message + 33);
954 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
955 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
956 data->MessageCenter->Type = message[22];
958 if (strlen(data->MessageCenter->Recipient) == 0) {
959 sprintf(data->MessageCenter->Recipient, "(none)");
961 if (strlen(data->MessageCenter->Number) == 0) {
962 sprintf(data->MessageCenter->Number, "(none)");
964 if(strlen(data->MessageCenter->Name) == 0) {
965 sprintf(data->MessageCenter->Name, "(none)");
970 case P7110_SUBSMS_SMS_SENT:
971 dprintf("SMS sent\n");
975 case P7110_SUBSMS_SEND_FAIL:
976 dprintf("SMS sending failed\n");
977 e = GE_SMSSENDFAILED;
980 case P7110_SUBSMS_SMS_RCVD:
981 case P7110_SUBSMS_CELLBRD_OK:
982 case P7110_SUBSMS_CELLBRD_FAIL:
983 case P7110_SUBSMS_READ_CELLBRD:
984 case P7110_SUBSMS_SMSC_OK:
985 case P7110_SUBSMS_SMSC_FAIL:
986 case P7110_SUBSMS_SMSC_RCVFAIL:
987 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
988 e = GE_NOTIMPLEMENTED;
992 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
999 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
1001 GSM_Error e = GE_NONE;
1003 if (!data || !data->DateTime) return GE_INTERNALERROR;
1004 switch (message[3]) {
1005 case P7110_SUBCLO_DATE_RCVD:
1006 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
1007 data->DateTime->Month = message[10];
1008 data->DateTime->Day = message[11];
1009 data->DateTime->Hour = message[12];
1010 data->DateTime->Minute = message[13];
1011 data->DateTime->Second = message[14];
1014 case P7110_SUBCLO_ALARM_RCVD:
1015 switch(message[8]) {
1016 case P7110_ALARM_ENABLED:
1017 data->DateTime->AlarmEnabled = 1;
1019 case P7110_ALARM_DISABLED:
1020 data->DateTime->AlarmEnabled = 0;
1023 data->DateTime->AlarmEnabled = -1;
1024 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
1029 data->DateTime->Hour = message[9];
1030 data->DateTime->Minute = message[10];
1034 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
1041 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
1045 struct tm *tm_alarm;
1046 GSM_Error e = GE_NONE;
1048 if (!time || !alarm) return GE_INTERNALERROR;
1050 memset(&tm_time, 0, sizeof(tm_time));
1051 tm_time.tm_year = time->Year - 1900;
1052 tm_time.tm_mon = time->Month - 1;
1053 tm_time.tm_mday = time->Day;
1054 tm_time.tm_hour = time->Hour;
1055 tm_time.tm_min = time->Minute;
1058 t_alarm = mktime(&tm_time);
1059 t_alarm -= alarmdiff;
1060 t_alarm += timezone;
1062 tm_alarm = localtime(&t_alarm);
1064 alarm->Year = tm_alarm->tm_year + 1900;
1065 alarm->Month = tm_alarm->tm_mon + 1;
1066 alarm->Day = tm_alarm->tm_mday;
1067 alarm->Hour = tm_alarm->tm_hour;
1068 alarm->Minute = tm_alarm->tm_min;
1069 alarm->Second = tm_alarm->tm_sec;
1075 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
1078 GSM_Error e = GE_NONE;
1080 if (!c) return GE_INTERNALERROR;
1082 c->Time.Hour = block[0];
1083 c->Time.Minute = block[1];
1084 c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1085 alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1087 if (alarmdiff != 0xffff) {
1088 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1089 c->Alarm.AlarmEnabled = 1;
1091 c->Alarm.AlarmEnabled = 0;
1097 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1099 GSM_Error e = GE_NONE;
1100 unsigned char *block;
1103 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1105 year = data->CalendarNote->Time.Year;
1106 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1107 switch (message[3]) {
1108 case P7110_SUBCAL_NOTE_RCVD:
1109 block = message + 12;
1111 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1112 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1113 data->CalendarNote->Time.Month = message[10];
1114 data->CalendarNote->Time.Day = message[11];
1115 data->CalendarNote->Time.Second = 0;
1117 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1119 switch (message[6]) {
1120 case P7110_NOTE_MEETING:
1121 data->CalendarNote->Type = GCN_MEETING;
1122 P7110_GetNoteTimes(block, data->CalendarNote);
1123 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1125 case P7110_NOTE_CALL:
1126 data->CalendarNote->Type = GCN_CALL;
1127 P7110_GetNoteTimes(block, data->CalendarNote);
1128 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1129 DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1131 case P7110_NOTE_REMINDER:
1132 data->CalendarNote->Type = GCN_REMINDER;
1133 data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1134 DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1136 case P7110_NOTE_BIRTHDAY:
1138 for (i = 0; i < 10; i++) {
1139 dprintf("(%i:0x%02x)", i, block[i]);
1143 data->CalendarNote->Type = GCN_BIRTHDAY;
1144 data->CalendarNote->Time.Year = year;
1145 data->CalendarNote->Time.Hour = 23;
1146 data->CalendarNote->Time.Minute = 59;
1147 data->CalendarNote->Time.Second = 58;
1149 alarm = ((unsigned int)block[2]) << 24;
1150 alarm += ((unsigned int)block[3]) << 16;
1151 alarm += ((unsigned int)block[4]) << 8;
1154 dprintf("alarm: %i\n", alarm);
1156 if (alarm == 0xffff) {
1157 data->CalendarNote->Alarm.AlarmEnabled = 0;
1159 data->CalendarNote->Alarm.AlarmEnabled = 1;
1162 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1164 data->CalendarNote->Time.Hour = 0;
1165 data->CalendarNote->Time.Minute = 0;
1166 data->CalendarNote->Time.Second = 0;
1167 data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1169 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1173 data->CalendarNote->Type = -1;
1179 case P7110_SUBCAL_ADD_MEETING_RESP:
1180 case P7110_SUBCAL_ADD_CALL_RESP:
1181 case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1182 case P7110_SUBCAL_ADD_REMINDER_RESP:
1183 case P7110_SUBCAL_DEL_NOTE_RESP:
1184 case P7110_SUBCAL_FREEPOS_RCVD:
1185 case P7110_SUBCAL_INFO_RCVD:
1186 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1187 e = GE_NOTIMPLEMENTED;
1190 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1197 static int GetMemoryType(GSM_MemoryType memory_type)
1201 switch (memory_type) {
1203 result = P7110_MEMORY_MT;
1206 result = P7110_MEMORY_ME;
1209 result = P7110_MEMORY_SM;
1212 result = P7110_MEMORY_FD;
1215 result = P7110_MEMORY_ON;
1218 result = P7110_MEMORY_EN;
1221 result = P7110_MEMORY_DC;
1224 result = P7110_MEMORY_RC;
1227 result = P7110_MEMORY_MC;
1230 result = P7110_MEMORY_XX;
1238 static GSM_Error P7110_DialVoice(char *Number)
1241 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1243 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1245 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1246 // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1247 // unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1248 // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1251 //req[4]=strlen(Number);
1253 //for(i=0; i < strlen(Number) ; i++)
1254 // req[5+i]=Number[i];
1256 //memcpy(req+5+strlen(Number), req_end, 10);
1258 //len=6+strlen(Number);
1263 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1267 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1268 PGEN_DebugMessage(1, req, len);
1272 // } else return GE_NOTIMPLEMENTED;
1279 return GE_NOTIMPLEMENTED;
1284 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1286 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1287 0x00, 0x10 , /* memory type */
1288 0x00, 0x00, /* location */
1291 req[11] = data->Bitmap->number + 1;
1292 dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1293 if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1294 return SM_Block(state, data, 0x03);
1297 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1302 *(block++) = size + 6;
1304 memcpy(block, buf, size);
1310 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1312 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1313 0x00, 0x10, /* memory type */
1314 0x00, 0x00, /* location */
1318 unsigned int count = 18;
1320 if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1321 (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1322 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);
1323 return GE_INVALIDIMAGESIZE;
1326 req[13] = data->Bitmap->number + 1;
1327 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1330 i = strlen(data->Bitmap->text);
1331 EncodeUnicode((string + 1), data->Bitmap->text, i);
1333 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1335 string[0] = data->Bitmap->ringtone;
1337 count += PackBlock(0x0c, 2, block++, string, req + count);
1339 string[0] = data->Bitmap->number+1;
1341 count += PackBlock(0x1e, 2, block++, string, req + count);
1342 /* Logo on/off - assume on for now */
1345 count += PackBlock(0x1c, 2, block++, string, req + count);
1347 string[0] = data->Bitmap->width;
1348 string[1] = data->Bitmap->height;
1351 string[4] = 0x7e; /* Size */
1352 memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1353 count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1354 req[17] = block - 1;
1356 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1357 return SM_Block(state, data, 0x03);
1360 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1362 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1364 dprintf("Getting startup logo...\n");
1365 if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1366 return SM_Block(state, data, 0x7a);
1369 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1371 switch (message[3]) {
1373 dprintf("Startup logo set ok\n");
1378 /* I'm sure there are blocks here but never mind! */
1379 data->Bitmap->type = GSM_StartupLogo;
1380 data->Bitmap->height = message[13];
1381 data->Bitmap->width = message[17];
1382 data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1383 memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1384 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1389 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1395 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1397 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1399 dprintf("Getting op logo...\n");
1400 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1401 return SM_Block(state, data, 0x0a);
1404 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1406 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1410 0xc0, 0x04, 0x03, 0x00 };
1414 if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1415 (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1416 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);
1417 return GE_INVALIDIMAGESIZE;
1420 req[12] = data->Bitmap->height;
1421 req[16] = data->Bitmap->width;
1422 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1423 count += data->Bitmap->size;
1424 dprintf("Setting startup logo...\n");
1426 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1427 return SM_Block(state, data, 0x7a);
1430 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1432 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1433 0x00, /* logo enabled */
1434 0x00, 0xf0, 0x00, /* network code (000 00) */
1436 0x08, /* length of rest */
1437 0x00, 0x00, /* Bitmap width / height */
1439 0x00, /* Bitmap size */
1444 if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1445 (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1446 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);
1447 return GE_INVALIDIMAGESIZE;
1450 if (strcmp(data->Bitmap->netcode,"000 00")) { /* set logo */
1451 req[5] = 0x01; // Logo enabled
1452 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1453 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1454 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1455 req[11] = 8 + data->Bitmap->size;
1456 req[12] = data->Bitmap->width;
1457 req[13] = data->Bitmap->height;
1458 req[15] = data->Bitmap->size;
1459 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1460 count += data->Bitmap->size;
1462 dprintf("Setting op logo...\n");
1463 if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1464 return SM_Block(state, data, 0x0a);
1467 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1469 switch(data->Bitmap->type) {
1470 case GSM_CallerLogo:
1471 return GetCallerBitmap(data, state);
1472 case GSM_StartupLogo:
1473 return GetStartupBitmap(data, state);
1474 case GSM_OperatorLogo:
1475 return GetOperatorBitmap(data, state);
1477 return GE_NOTIMPLEMENTED;
1481 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1483 switch(data->Bitmap->type) {
1484 case GSM_CallerLogo:
1485 return SetCallerBitmap(data, state);
1486 case GSM_StartupLogo:
1487 return SetStartupBitmap(data, state);
1488 case GSM_OperatorLogo:
1489 return SetOperatorBitmap(data, state);
1491 return GE_NOTIMPLEMENTED;
1495 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1497 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1498 0x00, 0x00, /* memory type */
1499 0x00, 0x00, /* location */
1502 int block, i, j, defaultn;
1503 unsigned int count = 18;
1504 GSM_PhonebookEntry *entry;
1506 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1507 else return GE_TRYAGAIN;
1509 req[11] = GetMemoryType(entry->MemoryType);
1510 req[12] = (entry->Location >> 8);
1511 req[13] = entry->Location & 0xff;
1513 if (*(entry->Name)) {
1515 i = strlen(entry->Name);
1516 EncodeUnicode((string + 1), entry->Name, i);
1518 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1520 string[0] = entry->Group + 1;
1522 count += PackBlock(0x1e, 2, block++, string, req + count);
1523 /* Default Number */
1525 for (i = 0; i < entry->SubEntriesCount; i++)
1526 if (entry->SubEntries[i].EntryType == GSM_Number)
1527 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1530 string[0] = entry->SubEntries[defaultn].NumberType;
1534 i = strlen(entry->SubEntries[defaultn].data.Number);
1535 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1537 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1539 /* Rest of the numbers */
1540 for (i = 0; i < entry->SubEntriesCount; i++)
1541 if (entry->SubEntries[i].EntryType == GSM_Number)
1542 if (i != defaultn) {
1543 string[0] = entry->SubEntries[i].NumberType;
1547 j = strlen(entry->SubEntries[i].data.Number);
1548 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1550 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1552 req[17] = block - 1;
1553 dprintf("Writing phonebook entry %s...\n",entry->Name);
1555 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1556 return SM_Block(state, data, 0x03);
1559 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1562 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1563 0x00, 0x00, /* memory type */ //02,05
1564 0x00, 0x00, /* location */
1567 dprintf("Reading phonebook location (%d)\n", location);
1570 req[10] = location >> 8;
1571 req[11] = location & 0xff;
1573 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1574 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1579 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1581 int memtype, location;
1583 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1584 location = data->PhonebookEntry->Location;
1586 return P7110_ReadPhonebookLL(data, state, memtype, location);
1589 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1591 int memtype, location;
1593 memtype = P7110_MEMORY_SPEEDDIALS;
1594 location = data->SpeedDial->Number;
1596 return P7110_ReadPhonebookLL(data, state, memtype, location);
1599 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1602 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1604 req[5] = data->MessageCenter->No;
1606 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1607 error = SM_Block(state, data, P7110_MSG_SMS);
1612 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1615 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1617 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1618 error = SM_Block(state, data, P7110_MSG_CLOCK);
1623 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1625 GSM_Error error = GE_NOTREADY;
1626 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1627 unsigned char date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1629 GSM_DateTime tmptime;
1631 tmpdata.DateTime = &tmptime;
1632 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1633 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1634 req[4] = data->CalendarNote->Location >> 8;
1635 req[5] = data->CalendarNote->Location & 0xff;
1636 data->CalendarNote->Time.Year = tmptime.Year;
1638 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1639 error = SM_Block(state, data, P7110_MSG_CALENDAR);