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 2001/11/25 21:59:13 short
21 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
23 Revision 1.27 2001/11/22 17:56:53 pkot
24 smslib update. sms sending
26 Revision 1.26 2001/11/19 17:09:59 pkot
29 Revision 1.25 2001/11/19 16:24:31 pkot
30 Grrrr... I should have check if I have fixed this typo
32 Revision 1.24 2001/11/19 15:53:16 pkot
35 Revision 1.23 2001/11/19 13:46:42 pkot
36 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
38 Revision 1.22 2001/11/17 20:18:32 pkot
39 Added dau9p connection type for 6210/7110
41 Revision 1.21 2001/11/17 16:44:07 pkot
42 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
44 Revision 1.20 2001/11/15 12:15:04 pkot
45 smslib updates. begin work on sms in 6100 series
47 Revision 1.19 2001/11/15 12:12:34 pkot
48 7110 and 6110 series phones introduce as Nokia
50 Revision 1.18 2001/11/15 12:04:06 pkot
51 Faster initialization for 6100 series (don't check for dlr3 cable)
53 Revision 1.17 2001/11/14 10:48:03 pkot
54 6210/7110 debug cleanups
56 Revision 1.16 2001/11/13 16:12:21 pkot
57 Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
59 Revision 1.15 2001/11/08 16:47:48 pkot
60 Start fiddling with 7110 and SMS
62 Revision 1.14 2001/09/09 21:45:49 machek
63 Cleanups from Ladislav Michl <ladis@psi.cz>:
65 *) do *not* internationalize debug messages
67 *) some whitespace fixes, do not use //
69 *) break is unneccessary after return
71 Revision 1.13 2001/08/16 23:59:32 pkot
72 Fixed (hopefully) timezone mismash (Sheldon Hearn)
74 Revision 1.12 2001/08/09 12:34:34 pkot
75 3330 and 6250 support - I have no idea if it does work (mygnokii)
77 Revision 1.11 2001/07/05 10:54:53 pkot
78 Solaris 2.7 fixes - should be harmless for other OSes (Michael Wiedmann)
80 Revision 1.10 2001/06/27 23:52:49 pkot
81 7110/6210 updates (Marian Jancar)
83 Revision 1.9 2001/06/10 23:49:49 pkot
84 Small fixes to hide compilation warnings and allow gnokii.c to compile
86 Revision 1.8 2001/05/24 20:47:30 chris
87 More updating of 7110 code and some of xgnokii_lowlevel changed over.
89 Revision 1.7 2001/05/07 16:24:04 pkot
90 DLR-3P temporary fix. How should I do it better?
92 Revision 1.6 2001/03/23 13:40:24 chris
93 Pavel's patch and a few fixes.
95 Revision 1.5 2001/03/22 16:17:06 chris
96 Tidy-ups and fixed gnokii/Makefile and gnokii/ChangeLog which I somehow corrupted.
98 Revision 1.4 2001/03/21 23:36:06 chris
99 Added the statemachine
100 This will break gnokii --identify and --monitor except for 6210/7110
102 Revision 1.3 2001/03/13 01:24:03 pkot
103 Code cleanup - no warnings during compilation
105 Revision 1.2 2001/03/13 01:23:18 pkot
106 Windows updates (Manfred Jonsson)
108 Revision 1.1 2001/02/21 19:57:07 chris
109 More fiddling with the directory layout
111 Revision 1.1 2001/02/16 14:29:53 chris
112 Restructure of common/. Fixed a problem in fbus-phonet.c
113 Lots of dprintfs for Marcin
114 Any size xpm can now be loaded (eg for 7110 startup logos)
115 nk7110 code detects 7110/6210 and alters startup logo size to suit
116 Moved Marcin's extended phonebook code into gnokii.c
118 Revision 1.7 2001/02/06 21:15:35 chris
119 Preliminary irda support for 7110 etc. Not well tested!
121 Revision 1.6 2001/02/03 23:56:15 chris
122 Start of work on irda support (now we just need fbus-irda.c!)
123 Proper unicode support in 7110 code (from pkot)
125 Revision 1.5 2001/02/01 15:17:31 pkot
126 Fixed --identify and added Manfred's manufacturer patch
128 Revision 1.4 2001/01/29 17:14:42 chris
129 dprintf now in misc.h (and fiddling with 7110 code)
131 Revision 1.3 2001/01/23 15:32:41 chris
132 Pavel's 'break' and 'static' corrections.
133 Work on logos for 7110.
135 Revision 1.2 2001/01/17 02:54:54 chris
136 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
137 I can now edit my phonebook in xgnokii but it is 'work in progress'.
139 Revision 1.1 2001/01/14 22:46:59 chris
140 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
148 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.h */
150 #include "gsm-common.h"
151 #include "phones/generic.h"
152 #include "phones/nk7110.h"
153 #include "links/fbus.h"
154 #include "links/fbus-phonet.h"
155 #include "phones/nokia.h"
156 #include "gsm-encoding.h"
159 #define snprintf _snprintf
164 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
165 { P7110_MSG_FOLDER, P7110_IncomingFolder },
166 { P7110_MSG_SMS, P7110_IncomingSMS },
167 { P7110_MSG_PHONEBOOK, P7110_IncomingPhonebook },
168 { P7110_MSG_NETSTATUS, P7110_IncomingNetwork },
169 { P7110_MSG_CALENDAR, P7110_IncomingCalendar },
170 { P7110_MSG_BATTERY, P7110_IncomingBattLevel },
171 { P7110_MSG_CLOCK, P7110_IncomingClock },
172 { P7110_MSG_IDENTITY, P7110_Incoming0x1b },
173 { P7110_MSG_STLOGO, P7110_IncomingStartup },
177 GSM_Phone phone_nokia_7110 = {
178 P7110_IncomingFunctions,
179 PGEN_IncomingDefault,
180 /* Mobile phone information */
182 "7110|6210|6250", /* Supported models */
183 7, /* Max RF Level */
184 0, /* Min RF Level */
185 GRF_Percentage, /* RF level units */
186 7, /* Max Battery Level */
187 0, /* Min Battery Level */
188 GBU_Percentage, /* Battery level units */
189 GDT_DateTime, /* Have date/time support */
190 GDT_TimeOnly, /* Alarm supports time only */
191 1, /* Alarms available - FIXME */
192 60, 96, /* Startup logo size - 7110 is fixed at init*/
193 21, 78, /* Op logo size */
194 14, 72 /* Caller logo size */
199 /* FIXME - a little macro would help here... */
201 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
205 return P7110_Initialise(state);
207 return P7110_GetModel(data, state);
208 case GOP_GetRevision:
209 return P7110_GetRevision(data, state);
211 return P7110_GetIMEI(data, state);
213 return P7110_Identify(data, state);
214 case GOP_GetBatteryLevel:
215 return P7110_GetBatteryLevel(data, state);
217 return P7110_GetRFLevel(data, state);
218 case GOP_GetMemoryStatus:
219 return P7110_GetMemoryStatus(data, state);
221 return P7110_GetBitmap(data, state);
223 return P7110_SetBitmap(data, state);
224 case GOP_ReadPhonebook:
225 return P7110_ReadPhonebook(data, state);
226 case GOP_WritePhonebook:
227 return P7110_WritePhonebookLocation(data, state);
228 case GOP_GetNetworkInfo:
229 return P7110_GetNetworkInfo(data, state);
230 case GOP_GetSpeedDial:
231 return P7110_GetSpeedDial(data, state);
232 case GOP_GetSMSCenter:
233 return P7110_GetSMSCenter(data, state);
234 case GOP_GetDateTime:
235 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
237 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
238 case GOP_GetCalendarNote:
239 return P7110_GetCalendarNote(data, state);
241 return P7110_GetSMS(data, state);
243 return P7110_SendSMS(data, state);
244 /* I'm not sure yet if folder functions will be shared or local
245 case GOP_GetSMSFolders:
246 return P7110_GetSMSFolders(data, state);
247 case GOP_GetSMSFolderStatus:
248 return P7110_GetSMSFolderStatus(data, state);*/
250 return GE_NOTIMPLEMENTED;
254 /* LinkOK is always true for now... */
255 bool P7110_LinkOK = true;
257 /* Initialise is the only function allowed to 'use' state */
258 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
263 int try = 0, connected = 0;
265 /* Copy in the phone info */
266 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
268 dprintf("Connecting\n");
270 switch (state->Link.ConnectionType) {
272 if (try == 0) try = 1;
274 if (try > 1) return GE_NOTSUPPORTED;
275 err = FBUS_Initialise(&(state->Link), state, 1 - try);
279 if (try > 0) return GE_NOTSUPPORTED;
280 err = PHONET_Initialise(&(state->Link), state);
283 return GE_NOTSUPPORTED;
287 if (err != GE_NONE) {
288 dprintf("Error in link initialisation: %d\n", err);
293 SM_Initialise(state);
295 /* Now test the link and get the model */
296 GSM_DataClear(&data);
298 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
301 /* Check for 7110 and alter the startup logo size */
302 if (strcmp(model, "NSE-5") == 0) {
303 state->Phone.Info.StartupLogoH = 65;
304 dprintf("7110 detected - startup logo height set to 65\n");
309 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
311 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
313 dprintf("Getting model...\n");
314 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
315 return SM_Block(state, data, 0x1b);
318 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
320 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
322 dprintf("Getting revision...\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_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
329 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
331 dprintf("Getting imei...\n");
332 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
333 return SM_Block(state, data, 0x1b);
336 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
338 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
340 dprintf("Getting battery level...\n");
341 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
342 return SM_Block(state, data, 0x17);
345 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
347 switch (message[3]) {
349 if (data->BatteryLevel) {
350 *(data->BatteryUnits) = GBU_Percentage;
351 *(data->BatteryLevel) = message[5];
352 dprintf("Battery level %f\n",*(data->BatteryLevel));
356 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
362 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
364 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
366 dprintf("Getting rf level...\n");
367 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
368 return SM_Block(state, data, 0x0a);
371 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
373 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
375 dprintf("Getting Network Info...\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_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
382 unsigned char *blockstart;
385 switch (message[3]) {
387 blockstart = message + 6;
388 for (i = 0; i < message[4]; i++) {
389 switch (blockstart[0]) {
390 case 0x01: /* Operator details */
391 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
392 if (data->NetworkInfo) {
393 /* Is this correct? */
394 data->NetworkInfo->CellID[0]=blockstart[4];
395 data->NetworkInfo->CellID[1]=blockstart[5];
396 data->NetworkInfo->LAC[0]=blockstart[6];
397 data->NetworkInfo->LAC[1]=blockstart[7];
398 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
399 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
400 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
401 data->NetworkInfo->NetworkCode[3] = ' ';
402 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
403 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
404 data->NetworkInfo->NetworkCode[6] = 0;
407 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
408 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
409 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
410 data->Bitmap->netcode[3] = ' ';
411 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
412 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
413 data->Bitmap->netcode[6] = 0;
414 dprintf("Operator %s ",data->Bitmap->netcode);
417 case 0x04: /* Logo */
419 dprintf("Op logo received ok ");
420 data->Bitmap->type = GSM_OperatorLogo;
421 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
422 data->Bitmap->height = blockstart[3];
423 data->Bitmap->width = blockstart[2];
424 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
425 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
429 dprintf("Unknown operator block %d\n", blockstart[0]);
432 blockstart += blockstart[1];
437 *(data->RFUnits) = GRF_Percentage;
438 *(data->RFLevel) = message[4];
439 dprintf("RF level %f\n",*(data->RFLevel));
443 dprintf("Op Logo Set OK\n");
446 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
452 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
454 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
456 dprintf("Getting memory status...\n");
457 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
458 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
459 return SM_Block(state, data, 0x03);
462 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
464 unsigned char *blockstart;
465 unsigned char blocks;
466 unsigned char subblockcount;
469 GSM_SubPhonebookEntry* subEntry = NULL;
471 PGEN_DebugMessage(messagetype, message, length);
473 switch (message[3]) {
474 case 0x04: /* Get status response */
475 if (data->MemoryStatus) {
476 if (message[5] != 0xff) {
477 data->MemoryStatus->Used = (message[16] << 8) + message[17];
478 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
479 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
481 dprintf("Unknown error getting mem status\n");
482 return GE_NOTIMPLEMENTED;
486 case 0x08: /* Read Memory response */
487 if (data->PhonebookEntry) {
488 data->PhonebookEntry->Empty = true;
489 data->PhonebookEntry->Group = 0;
490 data->PhonebookEntry->Name[0] = '\0';
491 data->PhonebookEntry->Number[0] = '\0';
492 data->PhonebookEntry->SubEntriesCount = 0;
493 data->PhonebookEntry->Date.Year = 0;
494 data->PhonebookEntry->Date.Month = 0;
495 data->PhonebookEntry->Date.Day = 0;
496 data->PhonebookEntry->Date.Hour = 0;
497 data->PhonebookEntry->Date.Minute = 0;
498 data->PhonebookEntry->Date.Second = 0;
500 if (message[6] == 0x0f) { // not found
501 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
502 dprintf("Invalid caller location\n");
503 return GE_INVALIDPHBOOKLOCATION;
505 dprintf("Unknown error getting phonebook\n");
506 return GE_NOTIMPLEMENTED;
509 dprintf("Received phonebook info\n");
510 blocks = message[17];
511 blockstart = message + 18;
514 for (i = 0; i < blocks; i++) {
515 if (data->PhonebookEntry)
516 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
517 switch(blockstart[0]) {
518 case P7110_ENTRYTYPE_POINTER: /* Pointer */
519 switch (message[11]) { /* Memory type */
520 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
521 if ((data != NULL) && (data->SpeedDial != NULL)) {
522 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
523 switch(blockstart[8]) {
525 data->SpeedDial->MemoryType = GMT_ME;
530 data->SpeedDial->MemoryType = GMT_SM;
534 data->SpeedDial->MemoryType = GMT_XX;
539 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
543 /* FIXME: is it possible? */
544 dprintf("Wrong memory type(?)\n");
549 case P7110_ENTRYTYPE_NAME: /* Name */
551 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
552 dprintf("Name: %s\n", data->Bitmap->text);
553 } else if (data->PhonebookEntry) {
554 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
555 data->PhonebookEntry->Empty = false;
556 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
559 case P7110_ENTRYTYPE_EMAIL:
560 case P7110_ENTRYTYPE_POSTAL:
561 case P7110_ENTRYTYPE_NOTE:
562 if (data->PhonebookEntry) {
563 subEntry->EntryType = blockstart[0];
564 subEntry->NumberType = 0;
565 subEntry->BlockNumber = blockstart[4];
566 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
567 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
568 dprintf(" Text: %s\n", subEntry->data.Number);
570 data->PhonebookEntry->SubEntriesCount++;
573 case P7110_ENTRYTYPE_NUMBER:
574 if (data->PhonebookEntry) {
575 subEntry->EntryType = blockstart[0];
576 subEntry->NumberType = blockstart[5];
577 subEntry->BlockNumber = blockstart[4];
578 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
579 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
580 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
581 dprintf(" Number: %s\n", subEntry->data.Number);
583 data->PhonebookEntry->SubEntriesCount++;
586 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
588 data->Bitmap->ringtone = blockstart[5];
589 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
592 case P7110_ENTRYTYPE_DATE:
593 if (data->PhonebookEntry) {
594 subEntry->EntryType=blockstart[0];
595 subEntry->NumberType=blockstart[5];
596 subEntry->BlockNumber=blockstart[4];
597 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
598 subEntry->data.Date.Month = blockstart[8];
599 subEntry->data.Date.Day = blockstart[9];
600 subEntry->data.Date.Hour = blockstart[10];
601 subEntry->data.Date.Minute = blockstart[11];
602 subEntry->data.Date.Second = blockstart[12];
603 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
604 subEntry->data.Date.Month, subEntry->data.Date.Year);
605 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
606 subEntry->data.Date.Minute, subEntry->data.Date.Second);
610 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
612 data->Bitmap->width = blockstart[5];
613 data->Bitmap->height = blockstart[6];
614 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
615 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
619 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
621 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
622 if (data->PhonebookEntry) {
623 data->PhonebookEntry->Group = blockstart[5] - 1;
624 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
628 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
631 blockstart += blockstart[3];
635 switch (message[6]) {
636 case 0x3d: return GE_PHBOOKWRITEFAILED;
637 case 0x3e: return GE_PHBOOKWRITEFAILED;
638 default: return GE_NONE;
642 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
648 /* Just as an example.... */
649 /* But note that both requests are the same type which isn't very 'proper' */
650 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
652 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
653 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
655 dprintf("Identifying...\n");
656 PNOK_GetManufacturer(data->Manufacturer);
657 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
658 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
659 SM_WaitFor(state, data, 0x1b);
660 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
661 SM_GetError(state, 0x1b);
663 /* Check that we are back at state Initialised */
664 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
668 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
670 switch (message[3]) {
673 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
674 dprintf("Received imei %s\n",data->Imei);
679 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
680 dprintf("Received model %s\n",data->Model);
682 if (data->Revision) {
683 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
684 dprintf("Received revision %s\n",data->Revision);
688 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
695 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
696 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
699 int nextfolder = 0x10;
702 switch (message[3]) {
706 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
707 dprintf("Message: %d SMS Folders received:\n", message[4]);
709 strcpy(data->SMSFolderList->Folder[1].Name, " ");
710 data->SMSFolderList->number = message[4];
712 for (j = 0; j < message[4]; j++) {
714 strcpy(data->SMSFolderList->Folder[j].Name, " ");
715 data->SMSFolderList->FolderID[j] = message[i];
716 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
718 dprintf(" Folder name: ");
720 /* search for next folder's index number, i.e. length of folder name */
721 while (message[i+1] != nextfolder && i < length) {
727 if (nextfolder == 0x28) nextfolder++;
729 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
730 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
735 /* getfolderstatus */
737 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
738 dprintf("Message: SMS Folder status received: \n" );
739 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
740 data->SMSFolder->number = (message[5] * 256) + message[5];
741 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
742 dprintf("Message: IDs of Entries : ");
743 for (i = 0; i < message[4] * 256 + message[5]; i++) {
744 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
745 dprintf("%d, ", data->SMSFolder->locations[i]);
752 for (i = 0; i < length; i ++)
753 if (isprint(message[i]))
754 dprintf("[%02x%c]", message[i], message[i]);
756 dprintf("[%02x ]", message[i]);
759 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
761 /* Number of SMS in folder */
762 data->SMSMessage->Number = message[7];
764 /* MessageType/FolderID */
765 data->SMSMessage->MemoryType = message[5];
767 /* These offsets are 6210/7110 series specific */
768 /* Short Message status */
769 data->SMSMessage->Status = message[4];
770 dprintf("\tStatus: ");
771 switch (data->SMSMessage->Status) {
785 dprintf("UNKNOWN\n");
788 /* See if message# is given back by phone. If not and status is unread */
789 /* we want it, if status is not unread it's a "random" message given back */
790 /* by the phone because we want a message of which the # doesn't exist */
792 for (i = 0; i < data->SMSFolder->number; i++) {
793 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
796 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
798 DecodePDUSMS(message + 6, data->SMSMessage, length);
802 /* get list of SMS pictures */
804 dprintf("Getting list of SMS pictures...\n");
805 for (i = 0; i < length; i ++)
806 if (isprint(message[i]))
807 dprintf("[%02x%c]", message[i], message[i]);
809 dprintf("[%02x ]", message[i]);
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]);
820 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
826 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
828 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
829 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
832 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
837 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
842 /* just testiung picture listing */
843 req_list[4] = data->SMSMessage->MemoryType;
844 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
845 error = SM_Block(state, data, 0x14);
847 /* see if the message we want is from the last read folder, i.e. */
848 /* we don't have to get folder status again */
849 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
851 dprintf("Getting list of SMS folders...\n");
852 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
853 error = SM_Block(state, data, 0x14);
855 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
856 return GE_INVALIDMEMORYTYPE;
857 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
858 req_status[4] = data->SMSMessage->MemoryType;
860 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
861 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
862 error = SM_Block(state, data, 0x14);
865 dprintf("Getting SMS...\n");
866 req_sms[4] = data->SMSMessage->MemoryType;
867 req_sms[6] = data->SMSMessage->Number;
868 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
869 return SM_Block(state, data, 0x14);
872 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
874 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
877 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
878 return SM_Block(state, data, 0x14);
882 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
884 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
886 dprintf("Getting SMS Folders...\n");
887 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
888 return SM_Block(state, data, 0x14);
891 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
893 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
897 req[4] = data->SMSFolder->FolderID;
898 dprintf("Getting SMS Folder Status...\n");
899 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
900 return SM_Block(state, data, 0x14);
904 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
906 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
907 unsigned char smsc_req[] = {FBUS_FRAME_HEADER, 0x33, 0x64, 0x00};
910 if (data->SMSMessage->MessageCenter.No) {
911 data->MessageCenter = &data->SMSMessage->MessageCenter;
912 P7110_GetSMSCenter(data, state);
913 // SM_SendMessage(state, 6, 0x02, smsc_req);
914 // SM_Block(state, data, 0x02);
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;
931 int digits, bytes, i;
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);