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.2.1 2001/11/27 22:48:37 short
21 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
23 Revision 1.1.1.2 2001/11/27 22:01:19 short
24 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
26 Revision 1.28 2001/11/27 12:25:01 pkot
29 Revision 1.27 2001/11/22 17:56:53 pkot
30 smslib update. sms sending
32 Revision 1.26 2001/11/19 17:09:59 pkot
35 Revision 1.25 2001/11/19 16:24:31 pkot
36 Grrrr... I should have check if I have fixed this typo
38 Revision 1.24 2001/11/19 15:53:16 pkot
41 Revision 1.23 2001/11/19 13:46:42 pkot
42 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
44 Revision 1.22 2001/11/17 20:18:32 pkot
45 Added dau9p connection type for 6210/7110
47 Revision 1.21 2001/11/17 16:44:07 pkot
48 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
50 Revision 1.20 2001/11/15 12:15:04 pkot
51 smslib updates. begin work on sms in 6100 series
53 Revision 1.19 2001/11/15 12:12:34 pkot
54 7110 and 6110 series phones introduce as Nokia
56 Revision 1.18 2001/11/15 12:04:06 pkot
57 Faster initialization for 6100 series (don't check for dlr3 cable)
59 Revision 1.17 2001/11/14 10:48:03 pkot
60 6210/7110 debug cleanups
62 Revision 1.16 2001/11/13 16:12:21 pkot
63 Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
65 Revision 1.15 2001/11/08 16:47:48 pkot
66 Start fiddling with 7110 and SMS
68 Revision 1.14 2001/09/09 21:45:49 machek
69 Cleanups from Ladislav Michl <ladis@psi.cz>:
71 *) do *not* internationalize debug messages
73 *) some whitespace fixes, do not use //
75 *) break is unneccessary after return
77 Revision 1.13 2001/08/16 23:59:32 pkot
78 Fixed (hopefully) timezone mismash (Sheldon Hearn)
80 Revision 1.12 2001/08/09 12:34:34 pkot
81 3330 and 6250 support - I have no idea if it does work (mygnokii)
83 Revision 1.11 2001/07/05 10:54:53 pkot
84 Solaris 2.7 fixes - should be harmless for other OSes (Michael Wiedmann)
86 Revision 1.10 2001/06/27 23:52:49 pkot
87 7110/6210 updates (Marian Jancar)
89 Revision 1.9 2001/06/10 23:49:49 pkot
90 Small fixes to hide compilation warnings and allow gnokii.c to compile
92 Revision 1.8 2001/05/24 20:47:30 chris
93 More updating of 7110 code and some of xgnokii_lowlevel changed over.
95 Revision 1.7 2001/05/07 16:24:04 pkot
96 DLR-3P temporary fix. How should I do it better?
98 Revision 1.6 2001/03/23 13:40:24 chris
99 Pavel's patch and a few fixes.
101 Revision 1.5 2001/03/22 16:17:06 chris
102 Tidy-ups and fixed gnokii/Makefile and gnokii/ChangeLog which I somehow corrupted.
104 Revision 1.4 2001/03/21 23:36:06 chris
105 Added the statemachine
106 This will break gnokii --identify and --monitor except for 6210/7110
108 Revision 1.3 2001/03/13 01:24:03 pkot
109 Code cleanup - no warnings during compilation
111 Revision 1.2 2001/03/13 01:23:18 pkot
112 Windows updates (Manfred Jonsson)
114 Revision 1.1 2001/02/21 19:57:07 chris
115 More fiddling with the directory layout
117 Revision 1.1 2001/02/16 14:29:53 chris
118 Restructure of common/. Fixed a problem in fbus-phonet.c
119 Lots of dprintfs for Marcin
120 Any size xpm can now be loaded (eg for 7110 startup logos)
121 nk7110 code detects 7110/6210 and alters startup logo size to suit
122 Moved Marcin's extended phonebook code into gnokii.c
124 Revision 1.7 2001/02/06 21:15:35 chris
125 Preliminary irda support for 7110 etc. Not well tested!
127 Revision 1.6 2001/02/03 23:56:15 chris
128 Start of work on irda support (now we just need fbus-irda.c!)
129 Proper unicode support in 7110 code (from pkot)
131 Revision 1.5 2001/02/01 15:17:31 pkot
132 Fixed --identify and added Manfred's manufacturer patch
134 Revision 1.4 2001/01/29 17:14:42 chris
135 dprintf now in misc.h (and fiddling with 7110 code)
137 Revision 1.3 2001/01/23 15:32:41 chris
138 Pavel's 'break' and 'static' corrections.
139 Work on logos for 7110.
141 Revision 1.2 2001/01/17 02:54:54 chris
142 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
143 I can now edit my phonebook in xgnokii but it is 'work in progress'.
145 Revision 1.1 2001/01/14 22:46:59 chris
146 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
154 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.h */
156 #include "gsm-common.h"
157 #include "phones/generic.h"
158 #include "phones/nk7110.h"
159 #include "links/fbus.h"
160 #include "links/fbus-phonet.h"
161 #include "phones/nokia.h"
162 #include "gsm-encoding.h"
165 #define snprintf _snprintf
170 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
171 { P7110_MSG_FOLDER, P7110_IncomingFolder },
172 { P7110_MSG_SMS, P7110_IncomingSMS },
173 { P7110_MSG_PHONEBOOK, P7110_IncomingPhonebook },
174 { P7110_MSG_NETSTATUS, P7110_IncomingNetwork },
175 { P7110_MSG_CALENDAR, P7110_IncomingCalendar },
176 { P7110_MSG_BATTERY, P7110_IncomingBattLevel },
177 { P7110_MSG_CLOCK, P7110_IncomingClock },
178 { P7110_MSG_IDENTITY, P7110_Incoming0x1b },
179 { P7110_MSG_STLOGO, P7110_IncomingStartup },
183 GSM_Phone phone_nokia_7110 = {
184 P7110_IncomingFunctions,
185 PGEN_IncomingDefault,
186 /* Mobile phone information */
188 "7110|6210|6250", /* Supported models */
189 7, /* Max RF Level */
190 0, /* Min RF Level */
191 GRF_Percentage, /* RF level units */
192 7, /* Max Battery Level */
193 0, /* Min Battery Level */
194 GBU_Percentage, /* Battery level units */
195 GDT_DateTime, /* Have date/time support */
196 GDT_TimeOnly, /* Alarm supports time only */
197 1, /* Alarms available - FIXME */
198 60, 96, /* Startup logo size - 7110 is fixed at init*/
199 21, 78, /* Op logo size */
200 14, 72 /* Caller logo size */
205 /* FIXME - a little macro would help here... */
207 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
211 return P7110_Initialise(state);
213 return P7110_GetModel(data, state);
214 case GOP_GetRevision:
215 return P7110_GetRevision(data, state);
217 return P7110_GetIMEI(data, state);
219 return P7110_Identify(data, state);
220 case GOP_GetBatteryLevel:
221 return P7110_GetBatteryLevel(data, state);
223 return P7110_GetRFLevel(data, state);
224 case GOP_GetMemoryStatus:
225 return P7110_GetMemoryStatus(data, state);
227 return P7110_GetBitmap(data, state);
229 return P7110_SetBitmap(data, state);
230 case GOP_ReadPhonebook:
231 return P7110_ReadPhonebook(data, state);
232 case GOP_WritePhonebook:
233 return P7110_WritePhonebookLocation(data, state);
234 case GOP_GetNetworkInfo:
235 return P7110_GetNetworkInfo(data, state);
236 case GOP_GetSpeedDial:
237 return P7110_GetSpeedDial(data, state);
238 case GOP_GetSMSCenter:
239 return P7110_GetSMSCenter(data, state);
240 case GOP_GetDateTime:
241 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
243 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
244 case GOP_GetCalendarNote:
245 return P7110_GetCalendarNote(data, state);
247 return P7110_GetSMS(data, state);
249 return P7110_SendSMS(data, state);
250 /* I'm not sure yet if folder functions will be shared or local
251 case GOP_GetSMSFolders:
252 return P7110_GetSMSFolders(data, state);
253 case GOP_GetSMSFolderStatus:
254 return P7110_GetSMSFolderStatus(data, state);*/
256 return GE_NOTIMPLEMENTED;
260 /* LinkOK is always true for now... */
261 bool P7110_LinkOK = true;
263 /* Initialise is the only function allowed to 'use' state */
264 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
269 int try = 0, connected = 0;
271 /* Copy in the phone info */
272 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
274 dprintf("Connecting\n");
276 switch (state->Link.ConnectionType) {
278 if (try == 0) try = 1;
280 if (try > 1) return GE_NOTSUPPORTED;
281 err = FBUS_Initialise(&(state->Link), state, 1 - try);
285 if (try > 0) return GE_NOTSUPPORTED;
286 err = PHONET_Initialise(&(state->Link), state);
289 return GE_NOTSUPPORTED;
293 if (err != GE_NONE) {
294 dprintf("Error in link initialisation: %d\n", err);
299 SM_Initialise(state);
301 /* Now test the link and get the model */
302 GSM_DataClear(&data);
304 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
307 /* Check for 7110 and alter the startup logo size */
308 if (strcmp(model, "NSE-5") == 0) {
309 state->Phone.Info.StartupLogoH = 65;
310 dprintf("7110 detected - startup logo height set to 65\n");
315 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
317 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
319 dprintf("Getting model...\n");
320 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
321 return SM_Block(state, data, 0x1b);
324 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
326 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
328 dprintf("Getting revision...\n");
329 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
330 return SM_Block(state, data, 0x1b);
333 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
335 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
337 dprintf("Getting imei...\n");
338 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
339 return SM_Block(state, data, 0x1b);
342 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
344 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
346 dprintf("Getting battery level...\n");
347 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
348 return SM_Block(state, data, 0x17);
351 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
353 switch (message[3]) {
355 if (data->BatteryLevel) {
356 *(data->BatteryUnits) = GBU_Percentage;
357 *(data->BatteryLevel) = message[5];
358 dprintf("Battery level %f\n",*(data->BatteryLevel));
362 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
368 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
370 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
372 dprintf("Getting rf level...\n");
373 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
374 return SM_Block(state, data, 0x0a);
377 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
379 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
381 dprintf("Getting Network Info...\n");
382 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
383 return SM_Block(state, data, 0x0a);
386 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
388 unsigned char *blockstart;
391 switch (message[3]) {
393 blockstart = message + 6;
394 for (i = 0; i < message[4]; i++) {
395 switch (blockstart[0]) {
396 case 0x01: /* Operator details */
397 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
398 if (data->NetworkInfo) {
399 /* Is this correct? */
400 data->NetworkInfo->CellID[0]=blockstart[4];
401 data->NetworkInfo->CellID[1]=blockstart[5];
402 data->NetworkInfo->LAC[0]=blockstart[6];
403 data->NetworkInfo->LAC[1]=blockstart[7];
404 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
405 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
406 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
407 data->NetworkInfo->NetworkCode[3] = ' ';
408 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
409 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
410 data->NetworkInfo->NetworkCode[6] = 0;
413 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
414 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
415 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
416 data->Bitmap->netcode[3] = ' ';
417 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
418 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
419 data->Bitmap->netcode[6] = 0;
420 dprintf("Operator %s ",data->Bitmap->netcode);
423 case 0x04: /* Logo */
425 dprintf("Op logo received ok ");
426 data->Bitmap->type = GSM_OperatorLogo;
427 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
428 data->Bitmap->height = blockstart[3];
429 data->Bitmap->width = blockstart[2];
430 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
431 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
435 dprintf("Unknown operator block %d\n", blockstart[0]);
438 blockstart += blockstart[1];
443 *(data->RFUnits) = GRF_Percentage;
444 *(data->RFLevel) = message[4];
445 dprintf("RF level %f\n",*(data->RFLevel));
449 dprintf("Op Logo Set OK\n");
452 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
458 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
460 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
462 dprintf("Getting memory status...\n");
463 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
464 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
465 return SM_Block(state, data, 0x03);
468 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
470 unsigned char *blockstart;
471 unsigned char blocks;
472 unsigned char subblockcount;
475 GSM_SubPhonebookEntry* subEntry = NULL;
477 PGEN_DebugMessage(messagetype, message, length);
479 switch (message[3]) {
480 case 0x04: /* Get status response */
481 if (data->MemoryStatus) {
482 if (message[5] != 0xff) {
483 data->MemoryStatus->Used = (message[16] << 8) + message[17];
484 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
485 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
487 dprintf("Unknown error getting mem status\n");
488 return GE_NOTIMPLEMENTED;
492 case 0x08: /* Read Memory response */
493 if (data->PhonebookEntry) {
494 data->PhonebookEntry->Empty = true;
495 data->PhonebookEntry->Group = 0;
496 data->PhonebookEntry->Name[0] = '\0';
497 data->PhonebookEntry->Number[0] = '\0';
498 data->PhonebookEntry->SubEntriesCount = 0;
499 data->PhonebookEntry->Date.Year = 0;
500 data->PhonebookEntry->Date.Month = 0;
501 data->PhonebookEntry->Date.Day = 0;
502 data->PhonebookEntry->Date.Hour = 0;
503 data->PhonebookEntry->Date.Minute = 0;
504 data->PhonebookEntry->Date.Second = 0;
506 if (message[6] == 0x0f) { // not found
507 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
508 dprintf("Invalid caller location\n");
509 return GE_INVALIDPHBOOKLOCATION;
511 dprintf("Unknown error getting phonebook\n");
512 return GE_NOTIMPLEMENTED;
515 dprintf("Received phonebook info\n");
516 blocks = message[17];
517 blockstart = message + 18;
520 for (i = 0; i < blocks; i++) {
521 if (data->PhonebookEntry)
522 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
523 switch(blockstart[0]) {
524 case P7110_ENTRYTYPE_POINTER: /* Pointer */
525 switch (message[11]) { /* Memory type */
526 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
527 if ((data != NULL) && (data->SpeedDial != NULL)) {
528 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
529 switch(blockstart[8]) {
531 data->SpeedDial->MemoryType = GMT_ME;
536 data->SpeedDial->MemoryType = GMT_SM;
540 data->SpeedDial->MemoryType = GMT_XX;
545 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
549 /* FIXME: is it possible? */
550 dprintf("Wrong memory type(?)\n");
555 case P7110_ENTRYTYPE_NAME: /* Name */
557 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
558 dprintf("Name: %s\n", data->Bitmap->text);
559 } else if (data->PhonebookEntry) {
560 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
561 data->PhonebookEntry->Empty = false;
562 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
565 case P7110_ENTRYTYPE_EMAIL:
566 case P7110_ENTRYTYPE_POSTAL:
567 case P7110_ENTRYTYPE_NOTE:
568 if (data->PhonebookEntry) {
569 subEntry->EntryType = blockstart[0];
570 subEntry->NumberType = 0;
571 subEntry->BlockNumber = blockstart[4];
572 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
573 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
574 dprintf(" Text: %s\n", subEntry->data.Number);
576 data->PhonebookEntry->SubEntriesCount++;
579 case P7110_ENTRYTYPE_NUMBER:
580 if (data->PhonebookEntry) {
581 subEntry->EntryType = blockstart[0];
582 subEntry->NumberType = blockstart[5];
583 subEntry->BlockNumber = blockstart[4];
584 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
585 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
586 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
587 dprintf(" Number: %s\n", subEntry->data.Number);
589 data->PhonebookEntry->SubEntriesCount++;
592 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
594 data->Bitmap->ringtone = blockstart[5];
595 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
598 case P7110_ENTRYTYPE_DATE:
599 if (data->PhonebookEntry) {
600 subEntry->EntryType=blockstart[0];
601 subEntry->NumberType=blockstart[5];
602 subEntry->BlockNumber=blockstart[4];
603 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
604 subEntry->data.Date.Month = blockstart[8];
605 subEntry->data.Date.Day = blockstart[9];
606 subEntry->data.Date.Hour = blockstart[10];
607 subEntry->data.Date.Minute = blockstart[11];
608 subEntry->data.Date.Second = blockstart[12];
609 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
610 subEntry->data.Date.Month, subEntry->data.Date.Year);
611 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
612 subEntry->data.Date.Minute, subEntry->data.Date.Second);
616 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
618 data->Bitmap->width = blockstart[5];
619 data->Bitmap->height = blockstart[6];
620 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
621 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
625 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
627 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
628 if (data->PhonebookEntry) {
629 data->PhonebookEntry->Group = blockstart[5] - 1;
630 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
634 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
637 blockstart += blockstart[3];
641 switch (message[6]) {
642 case 0x3d: return GE_PHBOOKWRITEFAILED;
643 case 0x3e: return GE_PHBOOKWRITEFAILED;
644 default: return GE_NONE;
648 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
654 /* Just as an example.... */
655 /* But note that both requests are the same type which isn't very 'proper' */
656 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
658 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
659 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
661 dprintf("Identifying...\n");
662 PNOK_GetManufacturer(data->Manufacturer);
663 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
664 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
665 SM_WaitFor(state, data, 0x1b);
666 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
667 SM_GetError(state, 0x1b);
669 /* Check that we are back at state Initialised */
670 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
674 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
676 switch (message[3]) {
679 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
680 dprintf("Received imei %s\n",data->Imei);
685 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
686 dprintf("Received model %s\n",data->Model);
688 if (data->Revision) {
689 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
690 dprintf("Received revision %s\n",data->Revision);
694 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
701 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
702 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
705 int nextfolder = 0x10;
708 switch (message[3]) {
712 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
713 dprintf("Message: %d SMS Folders received:\n", message[4]);
715 strcpy(data->SMSFolderList->Folder[1].Name, " ");
716 data->SMSFolderList->number = message[4];
718 for (j = 0; j < message[4]; j++) {
720 strcpy(data->SMSFolderList->Folder[j].Name, " ");
721 data->SMSFolderList->FolderID[j] = message[i];
722 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
724 dprintf(" Folder name: ");
726 /* search for next folder's index number, i.e. length of folder name */
727 while (message[i+1] != nextfolder && i < length) {
733 if (nextfolder == 0x28) nextfolder++;
735 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
736 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
741 /* getfolderstatus */
743 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
744 dprintf("Message: SMS Folder status received: \n" );
745 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
746 data->SMSFolder->number = (message[5] * 256) + message[5];
747 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
748 dprintf("Message: IDs of Entries : ");
749 for (i = 0; i < message[4] * 256 + message[5]; i++) {
750 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
751 dprintf("%d, ", data->SMSFolder->locations[i]);
758 for (i = 0; i < length; i ++)
759 if (isprint(message[i]))
760 dprintf("[%02x%c]", message[i], message[i]);
762 dprintf("[%02x ]", message[i]);
765 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
767 /* Number of SMS in folder */
768 data->SMSMessage->Number = message[7];
770 /* MessageType/FolderID */
771 data->SMSMessage->MemoryType = message[5];
773 /* These offsets are 6210/7110 series specific */
774 /* Short Message status */
775 data->SMSMessage->Status = message[4];
776 dprintf("\tStatus: ");
777 switch (data->SMSMessage->Status) {
791 dprintf("UNKNOWN\n");
794 /* See if message# is given back by phone. If not and status is unread */
795 /* we want it, if status is not unread it's a "random" message given back */
796 /* by the phone because we want a message of which the # doesn't exist */
798 for (i = 0; i < data->SMSFolder->number; i++) {
799 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
802 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
804 DecodePDUSMS(message + 6, data->SMSMessage, length);
808 /* get list of SMS pictures */
810 dprintf("Getting list of SMS pictures...\n");
811 for (i = 0; i < length; i ++)
812 if (isprint(message[i]))
813 dprintf("[%02x%c]", message[i], message[i]);
815 dprintf("[%02x ]", message[i]);
820 for (i = 0; i < length; i ++)
821 if (isprint(message[i]))
822 dprintf("[%02x%c]", message[i], message[i]);
824 dprintf("[%02x ]", message[i]);
826 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
832 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
834 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
835 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
838 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
843 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
848 /* just testiung picture listing */
849 req_list[4] = data->SMSMessage->MemoryType;
850 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
851 error = SM_Block(state, data, 0x14);
853 /* see if the message we want is from the last read folder, i.e. */
854 /* we don't have to get folder status again */
855 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
857 dprintf("Getting list of SMS folders...\n");
858 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
859 error = SM_Block(state, data, 0x14);
861 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
862 return GE_INVALIDMEMORYTYPE;
863 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
864 req_status[4] = data->SMSMessage->MemoryType;
866 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
867 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
868 error = SM_Block(state, data, 0x14);
871 dprintf("Getting SMS...\n");
872 req_sms[4] = data->SMSMessage->MemoryType;
873 req_sms[6] = data->SMSMessage->Number;
874 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
875 return SM_Block(state, data, 0x14);
878 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
880 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
883 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
884 return SM_Block(state, data, 0x14);
888 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
890 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
892 dprintf("Getting SMS Folders...\n");
893 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
894 return SM_Block(state, data, 0x14);
897 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
899 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
903 req[4] = data->SMSFolder->FolderID;
904 dprintf("Getting SMS Folder Status...\n");
905 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
906 return SM_Block(state, data, 0x14);
910 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
912 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
915 if (data->SMSMessage->MessageCenter.No) {
916 data->MessageCenter = &data->SMSMessage->MessageCenter;
917 P7110_GetSMSCenter(data, state);
920 length = EncodePDUSMS(data->SMSMessage, req + 6);
921 if (!length) return GE_SMSWRONGFORMAT;
922 dprintf("Sending SMS...(%d)\n", length);
923 for (i = 0; i < length + 6; i++) {
924 dprintf("%02x ", req[i]);
927 if (SM_SendMessage(state, length+6, 0x02, req) != GE_NONE) return GE_NOTREADY;
928 return SM_Block(state, data, 0x02);
931 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
933 GSM_Error e = GE_NONE;
936 if (!data) return GE_INTERNALERROR;
938 switch (message[3]) {
939 case P7110_SUBSMS_SMSC_RCVD:
940 dprintf("SMSC Received\n");
941 /* FIXME: Implement all these in gsm-sms.c */
942 data->MessageCenter->No = message[4];
943 data->MessageCenter->Format = message[6];
944 data->MessageCenter->Validity = message[8]; /* due to changes in format */
946 bytes = message[21] - 1;
949 sprintf(data->MessageCenter->Name, "%s", message + 33);
951 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
952 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
953 data->MessageCenter->Type = message[22];
955 if (strlen(data->MessageCenter->Recipient) == 0) {
956 sprintf(data->MessageCenter->Recipient, "(none)");
958 if (strlen(data->MessageCenter->Number) == 0) {
959 sprintf(data->MessageCenter->Number, "(none)");
961 if(strlen(data->MessageCenter->Name) == 0) {
962 sprintf(data->MessageCenter->Name, "(none)");
967 case P7110_SUBSMS_SMS_SENT:
968 dprintf("SMS sent\n");
972 case P7110_SUBSMS_SEND_FAIL:
973 dprintf("SMS sending failed\n");
974 e = GE_SMSSENDFAILED;
977 case P7110_SUBSMS_SMS_RCVD:
978 case P7110_SUBSMS_CELLBRD_OK:
979 case P7110_SUBSMS_CELLBRD_FAIL:
980 case P7110_SUBSMS_READ_CELLBRD:
981 case P7110_SUBSMS_SMSC_OK:
982 case P7110_SUBSMS_SMSC_FAIL:
983 case P7110_SUBSMS_SMSC_RCVFAIL:
984 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
985 e = GE_NOTIMPLEMENTED;
989 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
996 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
998 GSM_Error e = GE_NONE;
1000 if (!data || !data->DateTime) return GE_INTERNALERROR;
1001 switch (message[3]) {
1002 case P7110_SUBCLO_DATE_RCVD:
1003 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
1004 data->DateTime->Month = message[10];
1005 data->DateTime->Day = message[11];
1006 data->DateTime->Hour = message[12];
1007 data->DateTime->Minute = message[13];
1008 data->DateTime->Second = message[14];
1011 case P7110_SUBCLO_ALARM_RCVD:
1012 switch(message[8]) {
1013 case P7110_ALARM_ENABLED:
1014 data->DateTime->AlarmEnabled = 1;
1016 case P7110_ALARM_DISABLED:
1017 data->DateTime->AlarmEnabled = 0;
1020 data->DateTime->AlarmEnabled = -1;
1021 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
1026 data->DateTime->Hour = message[9];
1027 data->DateTime->Minute = message[10];
1031 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
1038 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
1042 struct tm *tm_alarm;
1043 GSM_Error e = GE_NONE;
1045 if (!time || !alarm) return GE_INTERNALERROR;
1047 memset(&tm_time, 0, sizeof(tm_time));
1048 tm_time.tm_year = time->Year - 1900;
1049 tm_time.tm_mon = time->Month - 1;
1050 tm_time.tm_mday = time->Day;
1051 tm_time.tm_hour = time->Hour;
1052 tm_time.tm_min = time->Minute;
1055 t_alarm = mktime(&tm_time);
1056 t_alarm -= alarmdiff;
1057 t_alarm += timezone;
1059 tm_alarm = localtime(&t_alarm);
1061 alarm->Year = tm_alarm->tm_year + 1900;
1062 alarm->Month = tm_alarm->tm_mon + 1;
1063 alarm->Day = tm_alarm->tm_mday;
1064 alarm->Hour = tm_alarm->tm_hour;
1065 alarm->Minute = tm_alarm->tm_min;
1066 alarm->Second = tm_alarm->tm_sec;
1072 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
1075 GSM_Error e = GE_NONE;
1077 if (!c) return GE_INTERNALERROR;
1079 c->Time.Hour = block[0];
1080 c->Time.Minute = block[1];
1081 c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1082 alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1084 if (alarmdiff != 0xffff) {
1085 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1086 c->Alarm.AlarmEnabled = 1;
1088 c->Alarm.AlarmEnabled = 0;
1094 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1096 GSM_Error e = GE_NONE;
1097 unsigned char *block;
1100 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1102 year = data->CalendarNote->Time.Year;
1103 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1104 switch (message[3]) {
1105 case P7110_SUBCAL_NOTE_RCVD:
1106 block = message + 12;
1108 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1109 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1110 data->CalendarNote->Time.Month = message[10];
1111 data->CalendarNote->Time.Day = message[11];
1112 data->CalendarNote->Time.Second = 0;
1114 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1116 switch (message[6]) {
1117 case P7110_NOTE_MEETING:
1118 data->CalendarNote->Type = GCN_MEETING;
1119 P7110_GetNoteTimes(block, data->CalendarNote);
1120 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1122 case P7110_NOTE_CALL:
1123 data->CalendarNote->Type = GCN_CALL;
1124 P7110_GetNoteTimes(block, data->CalendarNote);
1125 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1126 DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1128 case P7110_NOTE_REMINDER:
1129 data->CalendarNote->Type = GCN_REMINDER;
1130 data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1131 DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1133 case P7110_NOTE_BIRTHDAY:
1135 for (i = 0; i < 10; i++) {
1136 dprintf("(%i:0x%02x)", i, block[i]);
1140 data->CalendarNote->Type = GCN_BIRTHDAY;
1141 data->CalendarNote->Time.Year = year;
1142 data->CalendarNote->Time.Hour = 23;
1143 data->CalendarNote->Time.Minute = 59;
1144 data->CalendarNote->Time.Second = 58;
1146 alarm = ((unsigned int)block[2]) << 24;
1147 alarm += ((unsigned int)block[3]) << 16;
1148 alarm += ((unsigned int)block[4]) << 8;
1151 dprintf("alarm: %i\n", alarm);
1153 if (alarm == 0xffff) {
1154 data->CalendarNote->Alarm.AlarmEnabled = 0;
1156 data->CalendarNote->Alarm.AlarmEnabled = 1;
1159 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1161 data->CalendarNote->Time.Hour = 0;
1162 data->CalendarNote->Time.Minute = 0;
1163 data->CalendarNote->Time.Second = 0;
1164 data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1166 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1170 data->CalendarNote->Type = -1;
1176 case P7110_SUBCAL_ADD_MEETING_RESP:
1177 case P7110_SUBCAL_ADD_CALL_RESP:
1178 case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1179 case P7110_SUBCAL_ADD_REMINDER_RESP:
1180 case P7110_SUBCAL_DEL_NOTE_RESP:
1181 case P7110_SUBCAL_FREEPOS_RCVD:
1182 case P7110_SUBCAL_INFO_RCVD:
1183 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1184 e = GE_NOTIMPLEMENTED;
1187 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1194 static int GetMemoryType(GSM_MemoryType memory_type)
1198 switch (memory_type) {
1200 result = P7110_MEMORY_MT;
1203 result = P7110_MEMORY_ME;
1206 result = P7110_MEMORY_SM;
1209 result = P7110_MEMORY_FD;
1212 result = P7110_MEMORY_ON;
1215 result = P7110_MEMORY_EN;
1218 result = P7110_MEMORY_DC;
1221 result = P7110_MEMORY_RC;
1224 result = P7110_MEMORY_MC;
1227 result = P7110_MEMORY_XX;
1235 static GSM_Error P7110_DialVoice(char *Number)
1238 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1240 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1242 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1243 // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1244 // unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1245 // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1248 //req[4]=strlen(Number);
1250 //for(i=0; i < strlen(Number) ; i++)
1251 // req[5+i]=Number[i];
1253 //memcpy(req+5+strlen(Number), req_end, 10);
1255 //len=6+strlen(Number);
1260 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1264 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1265 PGEN_DebugMessage(1, req, len);
1269 // } else return GE_NOTIMPLEMENTED;
1276 return GE_NOTIMPLEMENTED;
1281 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1283 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1284 0x00, 0x10 , /* memory type */
1285 0x00, 0x00, /* location */
1288 req[11] = data->Bitmap->number + 1;
1289 dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1290 if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1291 return SM_Block(state, data, 0x03);
1294 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1299 *(block++) = size + 6;
1301 memcpy(block, buf, size);
1307 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1309 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1310 0x00, 0x10, /* memory type */
1311 0x00, 0x00, /* location */
1315 unsigned int count = 18;
1317 if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1318 (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1319 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);
1320 return GE_INVALIDIMAGESIZE;
1323 req[13] = data->Bitmap->number + 1;
1324 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1327 i = strlen(data->Bitmap->text);
1328 EncodeUnicode((string + 1), data->Bitmap->text, i);
1330 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1332 string[0] = data->Bitmap->ringtone;
1334 count += PackBlock(0x0c, 2, block++, string, req + count);
1336 string[0] = data->Bitmap->number+1;
1338 count += PackBlock(0x1e, 2, block++, string, req + count);
1339 /* Logo on/off - assume on for now */
1342 count += PackBlock(0x1c, 2, block++, string, req + count);
1344 string[0] = data->Bitmap->width;
1345 string[1] = data->Bitmap->height;
1348 string[4] = 0x7e; /* Size */
1349 memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1350 count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1351 req[17] = block - 1;
1353 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1354 return SM_Block(state, data, 0x03);
1357 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1359 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1361 dprintf("Getting startup logo...\n");
1362 if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1363 return SM_Block(state, data, 0x7a);
1366 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1368 switch (message[3]) {
1370 dprintf("Startup logo set ok\n");
1375 /* I'm sure there are blocks here but never mind! */
1376 data->Bitmap->type = GSM_StartupLogo;
1377 data->Bitmap->height = message[13];
1378 data->Bitmap->width = message[17];
1379 data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1380 memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1381 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1386 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1392 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1394 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1396 dprintf("Getting op logo...\n");
1397 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1398 return SM_Block(state, data, 0x0a);
1401 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1403 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1407 0xc0, 0x04, 0x03, 0x00 };
1411 if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1412 (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1413 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);
1414 return GE_INVALIDIMAGESIZE;
1417 req[12] = data->Bitmap->height;
1418 req[16] = data->Bitmap->width;
1419 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1420 count += data->Bitmap->size;
1421 dprintf("Setting startup logo...\n");
1423 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1424 return SM_Block(state, data, 0x7a);
1427 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1429 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1430 0x00, /* logo enabled */
1431 0x00, 0xf0, 0x00, /* network code (000 00) */
1433 0x08, /* length of rest */
1434 0x00, 0x00, /* Bitmap width / height */
1436 0x00, /* Bitmap size */
1441 if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1442 (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1443 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);
1444 return GE_INVALIDIMAGESIZE;
1447 if (strcmp(data->Bitmap->netcode,"000 00")) { /* set logo */
1448 req[5] = 0x01; // Logo enabled
1449 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1450 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1451 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1452 req[11] = 8 + data->Bitmap->size;
1453 req[12] = data->Bitmap->width;
1454 req[13] = data->Bitmap->height;
1455 req[15] = data->Bitmap->size;
1456 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1457 count += data->Bitmap->size;
1459 dprintf("Setting op logo...\n");
1460 if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1461 return SM_Block(state, data, 0x0a);
1464 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1466 switch(data->Bitmap->type) {
1467 case GSM_CallerLogo:
1468 return GetCallerBitmap(data, state);
1469 case GSM_StartupLogo:
1470 return GetStartupBitmap(data, state);
1471 case GSM_OperatorLogo:
1472 return GetOperatorBitmap(data, state);
1474 return GE_NOTIMPLEMENTED;
1478 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1480 switch(data->Bitmap->type) {
1481 case GSM_CallerLogo:
1482 return SetCallerBitmap(data, state);
1483 case GSM_StartupLogo:
1484 return SetStartupBitmap(data, state);
1485 case GSM_OperatorLogo:
1486 return SetOperatorBitmap(data, state);
1488 return GE_NOTIMPLEMENTED;
1492 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1494 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1495 0x00, 0x00, /* memory type */
1496 0x00, 0x00, /* location */
1499 int block, i, j, defaultn;
1500 unsigned int count = 18;
1501 GSM_PhonebookEntry *entry;
1503 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1504 else return GE_TRYAGAIN;
1506 req[11] = GetMemoryType(entry->MemoryType);
1507 req[12] = (entry->Location >> 8);
1508 req[13] = entry->Location & 0xff;
1510 if (*(entry->Name)) {
1512 i = strlen(entry->Name);
1513 EncodeUnicode((string + 1), entry->Name, i);
1515 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1517 string[0] = entry->Group + 1;
1519 count += PackBlock(0x1e, 2, block++, string, req + count);
1520 /* Default Number */
1522 for (i = 0; i < entry->SubEntriesCount; i++)
1523 if (entry->SubEntries[i].EntryType == GSM_Number)
1524 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1527 string[0] = entry->SubEntries[defaultn].NumberType;
1531 i = strlen(entry->SubEntries[defaultn].data.Number);
1532 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1534 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1536 /* Rest of the numbers */
1537 for (i = 0; i < entry->SubEntriesCount; i++)
1538 if (entry->SubEntries[i].EntryType == GSM_Number)
1539 if (i != defaultn) {
1540 string[0] = entry->SubEntries[i].NumberType;
1544 j = strlen(entry->SubEntries[i].data.Number);
1545 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1547 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1549 req[17] = block - 1;
1550 dprintf("Writing phonebook entry %s...\n",entry->Name);
1552 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1553 return SM_Block(state, data, 0x03);
1556 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1559 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1560 0x00, 0x00, /* memory type */ //02,05
1561 0x00, 0x00, /* location */
1564 dprintf("Reading phonebook location (%d)\n", location);
1567 req[10] = location >> 8;
1568 req[11] = location & 0xff;
1570 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1571 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1576 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1578 int memtype, location;
1580 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1581 location = data->PhonebookEntry->Location;
1583 return P7110_ReadPhonebookLL(data, state, memtype, location);
1586 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1588 int memtype, location;
1590 memtype = P7110_MEMORY_SPEEDDIALS;
1591 location = data->SpeedDial->Number;
1593 return P7110_ReadPhonebookLL(data, state, memtype, location);
1596 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1599 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1601 req[5] = data->MessageCenter->No;
1603 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1604 error = SM_Block(state, data, P7110_MSG_SMS);
1609 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1612 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1614 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1615 error = SM_Block(state, data, P7110_MSG_CLOCK);
1620 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1622 GSM_Error error = GE_NOTREADY;
1623 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1624 unsigned char date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1626 GSM_DateTime tmptime;
1628 tmpdata.DateTime = &tmptime;
1629 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1630 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1631 req[4] = data->CalendarNote->Location >> 8;
1632 req[5] = data->CalendarNote->Location & 0xff;
1633 data->CalendarNote->Time.Year = tmptime.Year;
1635 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1636 error = SM_Block(state, data, P7110_MSG_CALENDAR);