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.12.1 2001/11/27 23:34:48 short
21 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
23 Revision 1.1.1.1.8.1 2001/11/27 23:06:09 short
24 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
26 Revision 1.1.1.1.2.1 2001/11/27 22:48:37 short
27 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
29 Revision 1.1.1.2 2001/11/27 22:01:19 short
30 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
32 Revision 1.28 2001/11/27 12:25:01 pkot
35 Revision 1.27 2001/11/22 17:56:53 pkot
36 smslib update. sms sending
38 Revision 1.26 2001/11/19 17:09:59 pkot
41 Revision 1.25 2001/11/19 16:24:31 pkot
42 Grrrr... I should have check if I have fixed this typo
44 Revision 1.24 2001/11/19 15:53:16 pkot
47 Revision 1.23 2001/11/19 13:46:42 pkot
48 reading unread SMS in 6210 from Inbox. Folder updates (Markus Plail)
50 Revision 1.22 2001/11/17 20:18:32 pkot
51 Added dau9p connection type for 6210/7110
53 Revision 1.21 2001/11/17 16:44:07 pkot
54 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
56 Revision 1.20 2001/11/15 12:15:04 pkot
57 smslib updates. begin work on sms in 6100 series
59 Revision 1.19 2001/11/15 12:12:34 pkot
60 7110 and 6110 series phones introduce as Nokia
62 Revision 1.18 2001/11/15 12:04:06 pkot
63 Faster initialization for 6100 series (don't check for dlr3 cable)
65 Revision 1.17 2001/11/14 10:48:03 pkot
66 6210/7110 debug cleanups
68 Revision 1.16 2001/11/13 16:12:21 pkot
69 Preparing libsms to get to work. 6210/7110 SMS and SMS Folder updates
71 Revision 1.15 2001/11/08 16:47:48 pkot
72 Start fiddling with 7110 and SMS
74 Revision 1.14 2001/09/09 21:45:49 machek
75 Cleanups from Ladislav Michl <ladis@psi.cz>:
77 *) do *not* internationalize debug messages
79 *) some whitespace fixes, do not use //
81 *) break is unneccessary after return
83 Revision 1.13 2001/08/16 23:59:32 pkot
84 Fixed (hopefully) timezone mismash (Sheldon Hearn)
86 Revision 1.12 2001/08/09 12:34:34 pkot
87 3330 and 6250 support - I have no idea if it does work (mygnokii)
89 Revision 1.11 2001/07/05 10:54:53 pkot
90 Solaris 2.7 fixes - should be harmless for other OSes (Michael Wiedmann)
92 Revision 1.10 2001/06/27 23:52:49 pkot
93 7110/6210 updates (Marian Jancar)
95 Revision 1.9 2001/06/10 23:49:49 pkot
96 Small fixes to hide compilation warnings and allow gnokii.c to compile
98 Revision 1.8 2001/05/24 20:47:30 chris
99 More updating of 7110 code and some of xgnokii_lowlevel changed over.
101 Revision 1.7 2001/05/07 16:24:04 pkot
102 DLR-3P temporary fix. How should I do it better?
104 Revision 1.6 2001/03/23 13:40:24 chris
105 Pavel's patch and a few fixes.
107 Revision 1.5 2001/03/22 16:17:06 chris
108 Tidy-ups and fixed gnokii/Makefile and gnokii/ChangeLog which I somehow corrupted.
110 Revision 1.4 2001/03/21 23:36:06 chris
111 Added the statemachine
112 This will break gnokii --identify and --monitor except for 6210/7110
114 Revision 1.3 2001/03/13 01:24:03 pkot
115 Code cleanup - no warnings during compilation
117 Revision 1.2 2001/03/13 01:23:18 pkot
118 Windows updates (Manfred Jonsson)
120 Revision 1.1 2001/02/21 19:57:07 chris
121 More fiddling with the directory layout
123 Revision 1.1 2001/02/16 14:29:53 chris
124 Restructure of common/. Fixed a problem in fbus-phonet.c
125 Lots of dprintfs for Marcin
126 Any size xpm can now be loaded (eg for 7110 startup logos)
127 nk7110 code detects 7110/6210 and alters startup logo size to suit
128 Moved Marcin's extended phonebook code into gnokii.c
130 Revision 1.7 2001/02/06 21:15:35 chris
131 Preliminary irda support for 7110 etc. Not well tested!
133 Revision 1.6 2001/02/03 23:56:15 chris
134 Start of work on irda support (now we just need fbus-irda.c!)
135 Proper unicode support in 7110 code (from pkot)
137 Revision 1.5 2001/02/01 15:17:31 pkot
138 Fixed --identify and added Manfred's manufacturer patch
140 Revision 1.4 2001/01/29 17:14:42 chris
141 dprintf now in misc.h (and fiddling with 7110 code)
143 Revision 1.3 2001/01/23 15:32:41 chris
144 Pavel's 'break' and 'static' corrections.
145 Work on logos for 7110.
147 Revision 1.2 2001/01/17 02:54:54 chris
148 More 7110 work. Use with care! (eg it is not possible to delete phonebook entries)
149 I can now edit my phonebook in xgnokii but it is 'work in progress'.
151 Revision 1.1 2001/01/14 22:46:59 chris
152 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
160 #define __phones_nk7110_c /* Turn on prototypes in phones/nk7110.h */
162 #include "gsm-common.h"
163 #include "phones/generic.h"
164 #include "phones/nk7110.h"
165 #include "links/fbus.h"
166 #include "links/fbus-phonet.h"
167 #include "phones/nokia.h"
168 #include "gsm-encoding.h"
171 #define snprintf _snprintf
176 static GSM_IncomingFunctionType P7110_IncomingFunctions[] = {
177 { P7110_MSG_FOLDER, P7110_IncomingFolder },
178 { P7110_MSG_SMS, P7110_IncomingSMS },
179 { P7110_MSG_PHONEBOOK, P7110_IncomingPhonebook },
180 { P7110_MSG_NETSTATUS, P7110_IncomingNetwork },
181 { P7110_MSG_CALENDAR, P7110_IncomingCalendar },
182 { P7110_MSG_BATTERY, P7110_IncomingBattLevel },
183 { P7110_MSG_CLOCK, P7110_IncomingClock },
184 { P7110_MSG_IDENTITY, P7110_Incoming0x1b },
185 { P7110_MSG_STLOGO, P7110_IncomingStartup },
189 GSM_Phone phone_nokia_7110 = {
190 P7110_IncomingFunctions,
191 PGEN_IncomingDefault,
192 /* Mobile phone information */
194 "7110|6210|6250", /* Supported models */
195 7, /* Max RF Level */
196 0, /* Min RF Level */
197 GRF_Percentage, /* RF level units */
198 7, /* Max Battery Level */
199 0, /* Min Battery Level */
200 GBU_Percentage, /* Battery level units */
201 GDT_DateTime, /* Have date/time support */
202 GDT_TimeOnly, /* Alarm supports time only */
203 1, /* Alarms available - FIXME */
204 60, 96, /* Startup logo size - 7110 is fixed at init*/
205 21, 78, /* Op logo size */
206 14, 72 /* Caller logo size */
211 /* FIXME - a little macro would help here... */
213 static GSM_Error P7110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
217 return P7110_Initialise(state);
219 return P7110_GetModel(data, state);
220 case GOP_GetRevision:
221 return P7110_GetRevision(data, state);
223 return P7110_GetIMEI(data, state);
225 return P7110_Identify(data, state);
226 case GOP_GetBatteryLevel:
227 return P7110_GetBatteryLevel(data, state);
229 return P7110_GetRFLevel(data, state);
230 case GOP_GetMemoryStatus:
231 return P7110_GetMemoryStatus(data, state);
233 return P7110_GetBitmap(data, state);
235 return P7110_SetBitmap(data, state);
236 case GOP_ReadPhonebook:
237 return P7110_ReadPhonebook(data, state);
238 case GOP_WritePhonebook:
239 return P7110_WritePhonebookLocation(data, state);
240 case GOP_GetNetworkInfo:
241 return P7110_GetNetworkInfo(data, state);
242 case GOP_GetSpeedDial:
243 return P7110_GetSpeedDial(data, state);
244 case GOP_GetSMSCenter:
245 return P7110_GetSMSCenter(data, state);
246 case GOP_GetDateTime:
247 return P7110_GetClock(P7110_SUBCLO_GET_DATE, data, state);
249 return P7110_GetClock(P7110_SUBCLO_GET_ALARM, data, state);
250 case GOP_GetCalendarNote:
251 return P7110_GetCalendarNote(data, state);
253 return P7110_GetSMS(data, state);
255 return P7110_SendSMS(data, state);
256 /* I'm not sure yet if folder functions will be shared or local
257 case GOP_GetSMSFolders:
258 return P7110_GetSMSFolders(data, state);
259 case GOP_GetSMSFolderStatus:
260 return P7110_GetSMSFolderStatus(data, state);*/
262 return GE_NOTIMPLEMENTED;
266 /* LinkOK is always true for now... */
267 bool P7110_LinkOK = true;
269 /* Initialise is the only function allowed to 'use' state */
270 static GSM_Error P7110_Initialise(GSM_Statemachine *state)
275 int try = 0, connected = 0;
277 /* Copy in the phone info */
278 memcpy(&(state->Phone), &phone_nokia_7110, sizeof(GSM_Phone));
280 dprintf("Connecting\n");
282 switch (state->Link.ConnectionType) {
284 if (try == 0) try = 1;
286 if (try > 1) return GE_NOTSUPPORTED;
287 err = FBUS_Initialise(&(state->Link), state, 1 - try);
291 if (try > 0) return GE_NOTSUPPORTED;
292 err = PHONET_Initialise(&(state->Link), state);
295 return GE_NOTSUPPORTED;
299 if (err != GE_NONE) {
300 dprintf("Error in link initialisation: %d\n", err);
305 SM_Initialise(state);
307 /* Now test the link and get the model */
308 GSM_DataClear(&data);
310 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
313 /* Check for 7110 and alter the startup logo size */
314 if (strcmp(model, "NSE-5") == 0) {
315 state->Phone.Info.StartupLogoH = 65;
316 dprintf("7110 detected - startup logo height set to 65\n");
321 static GSM_Error P7110_GetModel(GSM_Data *data, GSM_Statemachine *state)
323 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
325 dprintf("Getting model...\n");
326 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
327 return SM_Block(state, data, 0x1b);
330 static GSM_Error P7110_GetRevision(GSM_Data *data, GSM_Statemachine *state)
332 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
334 dprintf("Getting revision...\n");
335 if (SM_SendMessage(state, 6, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
336 return SM_Block(state, data, 0x1b);
339 static GSM_Error P7110_GetIMEI(GSM_Data *data, GSM_Statemachine *state)
341 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
343 dprintf("Getting imei...\n");
344 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
345 return SM_Block(state, data, 0x1b);
348 static GSM_Error P7110_GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
350 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
352 dprintf("Getting battery level...\n");
353 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
354 return SM_Block(state, data, 0x17);
357 static GSM_Error P7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, GSM_Data *data)
359 switch (message[3]) {
361 if (data->BatteryLevel) {
362 *(data->BatteryUnits) = GBU_Percentage;
363 *(data->BatteryLevel) = message[5];
364 dprintf("Battery level %f\n",*(data->BatteryLevel));
368 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
374 static GSM_Error P7110_GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
376 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
378 dprintf("Getting rf level...\n");
379 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
380 return SM_Block(state, data, 0x0a);
383 static GSM_Error P7110_GetNetworkInfo(GSM_Data *data, GSM_Statemachine *state)
385 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
387 dprintf("Getting Network Info...\n");
388 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
389 return SM_Block(state, data, 0x0a);
392 static GSM_Error P7110_IncomingNetwork(int messagetype, unsigned char *message, int length, GSM_Data *data)
394 unsigned char *blockstart;
397 switch (message[3]) {
399 blockstart = message + 6;
400 for (i = 0; i < message[4]; i++) {
401 switch (blockstart[0]) {
402 case 0x01: /* Operator details */
403 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
404 if (data->NetworkInfo) {
405 /* Is this correct? */
406 data->NetworkInfo->CellID[0]=blockstart[4];
407 data->NetworkInfo->CellID[1]=blockstart[5];
408 data->NetworkInfo->LAC[0]=blockstart[6];
409 data->NetworkInfo->LAC[1]=blockstart[7];
410 data->NetworkInfo->NetworkCode[0] = '0' + (blockstart[8] & 0x0f);
411 data->NetworkInfo->NetworkCode[1] = '0' + (blockstart[8] >> 4);
412 data->NetworkInfo->NetworkCode[2] = '0' + (blockstart[9] & 0x0f);
413 data->NetworkInfo->NetworkCode[3] = ' ';
414 data->NetworkInfo->NetworkCode[4] = '0' + (blockstart[10] & 0x0f);
415 data->NetworkInfo->NetworkCode[5] = '0' + (blockstart[10] >> 4);
416 data->NetworkInfo->NetworkCode[6] = 0;
419 data->Bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
420 data->Bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
421 data->Bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
422 data->Bitmap->netcode[3] = ' ';
423 data->Bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
424 data->Bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
425 data->Bitmap->netcode[6] = 0;
426 dprintf("Operator %s ",data->Bitmap->netcode);
429 case 0x04: /* Logo */
431 dprintf("Op logo received ok ");
432 data->Bitmap->type = GSM_OperatorLogo;
433 data->Bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
434 data->Bitmap->height = blockstart[3];
435 data->Bitmap->width = blockstart[2];
436 memcpy(data->Bitmap->bitmap, blockstart + 8, data->Bitmap->size);
437 dprintf("Logo (%dx%d) ", data->Bitmap->height, data->Bitmap->width);
441 dprintf("Unknown operator block %d\n", blockstart[0]);
444 blockstart += blockstart[1];
449 *(data->RFUnits) = GRF_Percentage;
450 *(data->RFLevel) = message[4];
451 dprintf("RF level %f\n",*(data->RFLevel));
455 dprintf("Op Logo Set OK\n");
458 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
464 static GSM_Error P7110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
466 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
468 dprintf("Getting memory status...\n");
469 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
470 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
471 return SM_Block(state, data, 0x03);
474 static GSM_Error P7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, GSM_Data *data)
476 unsigned char *blockstart;
477 unsigned char blocks;
478 unsigned char subblockcount;
481 GSM_SubPhonebookEntry* subEntry = NULL;
483 PGEN_DebugMessage(messagetype, message, length);
485 switch (message[3]) {
486 case 0x04: /* Get status response */
487 if (data->MemoryStatus) {
488 if (message[5] != 0xff) {
489 data->MemoryStatus->Used = (message[16] << 8) + message[17];
490 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
491 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
493 dprintf("Unknown error getting mem status\n");
494 return GE_NOTIMPLEMENTED;
498 case 0x08: /* Read Memory response */
499 if (data->PhonebookEntry) {
500 data->PhonebookEntry->Empty = true;
501 data->PhonebookEntry->Group = 0;
502 data->PhonebookEntry->Name[0] = '\0';
503 data->PhonebookEntry->Number[0] = '\0';
504 data->PhonebookEntry->SubEntriesCount = 0;
505 data->PhonebookEntry->Date.Year = 0;
506 data->PhonebookEntry->Date.Month = 0;
507 data->PhonebookEntry->Date.Day = 0;
508 data->PhonebookEntry->Date.Hour = 0;
509 data->PhonebookEntry->Date.Minute = 0;
510 data->PhonebookEntry->Date.Second = 0;
512 if (message[6] == 0x0f) { // not found
513 if (message[10] == 0x34 || message[10] == 0x33 || message[10] == 0x30) {
514 dprintf("Invalid caller location\n");
515 return GE_INVALIDPHBOOKLOCATION;
517 dprintf("Unknown error getting phonebook\n");
518 return GE_NOTIMPLEMENTED;
521 dprintf("Received phonebook info\n");
522 blocks = message[17];
523 blockstart = message + 18;
526 for (i = 0; i < blocks; i++) {
527 if (data->PhonebookEntry)
528 subEntry = &data->PhonebookEntry->SubEntries[subblockcount];
529 switch(blockstart[0]) {
530 case P7110_ENTRYTYPE_POINTER: /* Pointer */
531 switch (message[11]) { /* Memory type */
532 case P7110_MEMORY_SPEEDDIALS: /* Speed dial numbers */
533 if ((data != NULL) && (data->SpeedDial != NULL)) {
534 data->SpeedDial->Location = (((unsigned int)blockstart[6]) << 8) + blockstart[7];
535 switch(blockstart[8]) {
537 data->SpeedDial->MemoryType = GMT_ME;
542 data->SpeedDial->MemoryType = GMT_SM;
546 data->SpeedDial->MemoryType = GMT_XX;
551 dprintf("Speed dial pointer: %i in %s\n", data->SpeedDial->Location, str);
555 /* FIXME: is it possible? */
556 dprintf("Wrong memory type(?)\n");
561 case P7110_ENTRYTYPE_NAME: /* Name */
563 DecodeUnicode(data->Bitmap->text, (blockstart + 6), blockstart[5] / 2);
564 dprintf("Name: %s\n", data->Bitmap->text);
565 } else if (data->PhonebookEntry) {
566 DecodeUnicode(data->PhonebookEntry->Name, (blockstart + 6), blockstart[5] / 2);
567 data->PhonebookEntry->Empty = false;
568 dprintf(" Name: %s\n", data->PhonebookEntry->Name);
571 case P7110_ENTRYTYPE_EMAIL:
572 case P7110_ENTRYTYPE_POSTAL:
573 case P7110_ENTRYTYPE_NOTE:
574 if (data->PhonebookEntry) {
575 subEntry->EntryType = blockstart[0];
576 subEntry->NumberType = 0;
577 subEntry->BlockNumber = blockstart[4];
578 DecodeUnicode(subEntry->data.Number, (blockstart + 6), blockstart[5] / 2);
579 dprintf(" Type: %d (%02x)\n", subEntry->EntryType, subEntry->EntryType);
580 dprintf(" Text: %s\n", subEntry->data.Number);
582 data->PhonebookEntry->SubEntriesCount++;
585 case P7110_ENTRYTYPE_NUMBER:
586 if (data->PhonebookEntry) {
587 subEntry->EntryType = blockstart[0];
588 subEntry->NumberType = blockstart[5];
589 subEntry->BlockNumber = blockstart[4];
590 DecodeUnicode(subEntry->data.Number, (blockstart + 10), blockstart[9] / 2);
591 if (!subblockcount) strcpy(data->PhonebookEntry->Number, subEntry->data.Number);
592 dprintf(" Type: %d (%02x)\n", subEntry->NumberType, subEntry->NumberType);
593 dprintf(" Number: %s\n", subEntry->data.Number);
595 data->PhonebookEntry->SubEntriesCount++;
598 case P7110_ENTRYTYPE_RINGTONE: /* Ringtone */
600 data->Bitmap->ringtone = blockstart[5];
601 dprintf("Ringtone no. %d\n", data->Bitmap->ringtone);
604 case P7110_ENTRYTYPE_DATE:
605 if (data->PhonebookEntry) {
606 subEntry->EntryType=blockstart[0];
607 subEntry->NumberType=blockstart[5];
608 subEntry->BlockNumber=blockstart[4];
609 subEntry->data.Date.Year=(blockstart[6] << 8) + blockstart[7];
610 subEntry->data.Date.Month = blockstart[8];
611 subEntry->data.Date.Day = blockstart[9];
612 subEntry->data.Date.Hour = blockstart[10];
613 subEntry->data.Date.Minute = blockstart[11];
614 subEntry->data.Date.Second = blockstart[12];
615 dprintf(" Date: %02u.%02u.%04u\n", subEntry->data.Date.Day,
616 subEntry->data.Date.Month, subEntry->data.Date.Year);
617 dprintf(" Time: %02u:%02u:%02u\n", subEntry->data.Date.Hour,
618 subEntry->data.Date.Minute, subEntry->data.Date.Second);
622 case P7110_ENTRYTYPE_LOGO: /* Caller group logo */
624 data->Bitmap->width = blockstart[5];
625 data->Bitmap->height = blockstart[6];
626 data->Bitmap->size = (data->Bitmap->width * data->Bitmap->height) / 8;
627 memcpy(data->Bitmap->bitmap, blockstart + 10, data->Bitmap->size);
631 case P7110_ENTRYTYPE_LOGOSWITCH:/* Logo on/off */
633 case P7110_ENTRYTYPE_GROUP: /* Caller group number */
634 if (data->PhonebookEntry) {
635 data->PhonebookEntry->Group = blockstart[5] - 1;
636 dprintf(" Group: %d\n", data->PhonebookEntry->Group);
640 dprintf("Unknown phonebook block %02x\n", blockstart[0]);
643 blockstart += blockstart[3];
647 switch (message[6]) {
648 case 0x3d: return GE_PHBOOKWRITEFAILED;
649 case 0x3e: return GE_PHBOOKWRITEFAILED;
650 default: return GE_NONE;
654 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
660 /* Just as an example.... */
661 /* But note that both requests are the same type which isn't very 'proper' */
662 static GSM_Error P7110_Identify(GSM_Data *data, GSM_Statemachine *state)
664 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
665 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
667 dprintf("Identifying...\n");
668 PNOK_GetManufacturer(data->Manufacturer);
669 if (SM_SendMessage(state, 4, 0x1b, req) != GE_NONE) return GE_NOTREADY;
670 if (SM_SendMessage(state, 6, 0x1b, req2) != GE_NONE) return GE_NOTREADY;
671 SM_WaitFor(state, data, 0x1b);
672 SM_Block(state, data, 0x1b); /* waits for all requests - returns req2 error */
673 SM_GetError(state, 0x1b);
675 /* Check that we are back at state Initialised */
676 if (SM_Loop(state,0)!=Initialised) return GE_UNKNOWN;
680 static GSM_Error P7110_Incoming0x1b(int messagetype, unsigned char *message, int length, GSM_Data *data)
682 switch (message[3]) {
685 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
686 dprintf("Received imei %s\n",data->Imei);
691 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
692 dprintf("Received model %s\n",data->Model);
694 if (data->Revision) {
695 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
696 dprintf("Received revision %s\n",data->Revision);
700 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
707 /* handle messages of type 0x14 (SMS Handling, Folders, Logos.. */
708 static GSM_Error P7110_IncomingFolder(int messagetype, unsigned char *message, int length, GSM_Data *data)
711 int nextfolder = 0x10;
714 switch (message[3]) {
718 memset(data->SMSFolderList, 0, sizeof(SMS_FolderList));
719 dprintf("Message: %d SMS Folders received:\n", message[4]);
721 strcpy(data->SMSFolderList->Folder[1].Name, " ");
722 data->SMSFolderList->number = message[4];
724 for (j = 0; j < message[4]; j++) {
726 strcpy(data->SMSFolderList->Folder[j].Name, " ");
727 data->SMSFolderList->FolderID[j] = message[i];
728 dprintf("Folder Index: %d", data->SMSFolderList->FolderID[j]);
730 dprintf(" Folder name: ");
732 /* search for next folder's index number, i.e. length of folder name */
733 while (message[i+1] != nextfolder && i < length) {
739 if (nextfolder == 0x28) nextfolder++;
741 DecodeUnicode(data->SMSFolderList->Folder[j].Name, message + i, len);
742 dprintf("%s\n", data->SMSFolderList->Folder[j].Name);
747 /* getfolderstatus */
749 memset(data->SMSFolder, 0, sizeof(SMS_Folder));
750 dprintf("Message: SMS Folder status received: \n" );
751 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
752 data->SMSFolder->number = (message[5] * 256) + message[5];
753 dprintf("Message: Number of Entries: %i\n" , data->SMSFolder->number);
754 dprintf("Message: IDs of Entries : ");
755 for (i = 0; i < message[4] * 256 + message[5]; i++) {
756 data->SMSFolder->locations[i] = message[6+(i*2)] * 256 + message[(i*2)+7];
757 dprintf("%d, ", data->SMSFolder->locations[i]);
764 for (i = 0; i < length; i ++)
765 if (isprint(message[i]))
766 dprintf("[%02x%c]", message[i], message[i]);
768 dprintf("[%02x ]", message[i]);
771 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
773 /* Number of SMS in folder */
774 data->SMSMessage->Number = message[7];
776 /* MessageType/FolderID */
777 data->SMSMessage->MemoryType = message[5];
779 /* These offsets are 6210/7110 series specific */
780 /* Short Message status */
781 data->SMSMessage->Status = message[4];
782 dprintf("\tStatus: ");
783 switch (data->SMSMessage->Status) {
797 dprintf("UNKNOWN\n");
800 /* See if message# is given back by phone. If not and status is unread */
801 /* we want it, if status is not unread it's a "random" message given back */
802 /* by the phone because we want a message of which the # doesn't exist */
804 for (i = 0; i < data->SMSFolder->number; i++) {
805 if (data->SMSMessage->Number == data->SMSFolder->locations[i])
808 if (found==false && data->SMSMessage->Status != SMS_Unread) return GE_INVALIDSMSLOCATION;
810 DecodePDUSMS(message + 6, data->SMSMessage, length);
814 /* get list of SMS pictures */
816 dprintf("Getting list of SMS pictures...\n");
817 for (i = 0; i < length; i ++)
818 if (isprint(message[i]))
819 dprintf("[%02x%c]", message[i], message[i]);
821 dprintf("[%02x ]", message[i]);
826 for (i = 0; i < length; i ++)
827 if (isprint(message[i]))
828 dprintf("[%02x%c]", message[i], message[i]);
830 dprintf("[%02x ]", message[i]);
832 dprintf("Message: Unknown message of type 14 : %d length: %d\n", message[3], length);
838 static GSM_Error P7110_GetSMS(GSM_Data *data, GSM_Statemachine *state)
840 unsigned char req_folders[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
841 unsigned char req_status[] = {FBUS_FRAME_HEADER, 0x6b,
844 unsigned char req_sms[] = {FBUS_FRAME_HEADER, 0x07,
849 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
854 /* just testiung picture listing */
855 req_list[4] = data->SMSMessage->MemoryType;
856 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
857 error = SM_Block(state, data, 0x14);
859 /* see if the message we want is from the last read folder, i.e. */
860 /* we don't have to get folder status again */
861 if (data->SMSMessage->MemoryType != data->SMSFolder->FolderID) {
863 dprintf("Getting list of SMS folders...\n");
864 if (SM_SendMessage(state, 6, 0x14, req_folders) != GE_NONE) return GE_NOTREADY;
865 error = SM_Block(state, data, 0x14);
867 if (data->SMSMessage->MemoryType > data->SMSFolderList->FolderID[data->SMSFolderList->number-1])
868 return GE_INVALIDMEMORYTYPE;
869 data->SMSFolder->FolderID = data->SMSMessage->MemoryType;
870 req_status[4] = data->SMSMessage->MemoryType;
872 dprintf("Getting entries for SMS folder %i...\n", data->SMSMessage->MemoryType);
873 if (SM_SendMessage(state, 7, 0x14, req_status) != GE_NONE) return GE_NOTREADY;
874 error = SM_Block(state, data, 0x14);
877 dprintf("Getting SMS...\n");
878 req_sms[4] = data->SMSMessage->MemoryType;
879 req_sms[6] = data->SMSMessage->Number;
880 if (SM_SendMessage(state, 10, 0x14, req_sms) != GE_NONE) return GE_NOTREADY;
881 return SM_Block(state, data, 0x14);
884 static GSM_Error P7110_GetPicture(GSM_Data *data, GSM_Statemachine *state)
886 unsigned char req_list[] = {FBUS_FRAME_HEADER, 0x96,
889 if (SM_SendMessage(state, 7, 0x14, req_list) != GE_NONE) return GE_NOTREADY;
890 return SM_Block(state, data, 0x14);
894 static GSM_Error P7110_GetSMSFolders(GSM_Data *data, GSM_Statemachine *state)
896 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7A, 0x00, 0x00};
898 dprintf("Getting SMS Folders...\n");
899 if (SM_SendMessage(state, 6, 0x14, req) != GE_NONE) return GE_NOTREADY;
900 return SM_Block(state, data, 0x14);
903 static GSM_Error P7110_GetSMSFolderStatus(GSM_Data *data, GSM_Statemachine *state)
905 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
909 req[4] = data->SMSFolder->FolderID;
910 dprintf("Getting SMS Folder Status...\n");
911 if (SM_SendMessage(state, 7, 0x14, req) != GE_NONE) return GE_NOTREADY;
912 return SM_Block(state, data, 0x14);
916 static GSM_Error P7110_SendSMS(GSM_Data *data, GSM_Statemachine *state)
918 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
921 if (data->SMSMessage->MessageCenter.No) {
922 data->MessageCenter = &data->SMSMessage->MessageCenter;
923 P7110_GetSMSCenter(data, state);
926 length = EncodePDUSMS(data->SMSMessage, req + 6);
927 if (!length) return GE_SMSWRONGFORMAT;
928 dprintf("Sending SMS...(%d)\n", length);
929 for (i = 0; i < length + 6; i++) {
930 dprintf("%02x ", req[i]);
933 if (SM_SendMessage(state, length+6, 0x02, req) != GE_NONE) return GE_NOTREADY;
934 return SM_Block(state, data, 0x02);
937 static GSM_Error P7110_IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
939 GSM_Error e = GE_NONE;
942 if (!data) return GE_INTERNALERROR;
944 switch (message[3]) {
945 case P7110_SUBSMS_SMSC_RCVD:
946 dprintf("SMSC Received\n");
947 /* FIXME: Implement all these in gsm-sms.c */
948 data->MessageCenter->No = message[4];
949 data->MessageCenter->Format = message[6];
950 data->MessageCenter->Validity = message[8]; /* due to changes in format */
952 bytes = message[21] - 1;
955 sprintf(data->MessageCenter->Name, "%s", message + 33);
957 strcpy(data->MessageCenter->Recipient, GetBCDNumber(message+9));
958 strcpy(data->MessageCenter->Number, GetBCDNumber(message+21));
959 data->MessageCenter->Type = message[22];
961 if (strlen(data->MessageCenter->Recipient) == 0) {
962 sprintf(data->MessageCenter->Recipient, "(none)");
964 if (strlen(data->MessageCenter->Number) == 0) {
965 sprintf(data->MessageCenter->Number, "(none)");
967 if(strlen(data->MessageCenter->Name) == 0) {
968 sprintf(data->MessageCenter->Name, "(none)");
973 case P7110_SUBSMS_SMS_SENT:
974 dprintf("SMS sent\n");
978 case P7110_SUBSMS_SEND_FAIL:
979 dprintf("SMS sending failed\n");
980 e = GE_SMSSENDFAILED;
983 case P7110_SUBSMS_SMS_RCVD:
984 case P7110_SUBSMS_CELLBRD_OK:
985 case P7110_SUBSMS_CELLBRD_FAIL:
986 case P7110_SUBSMS_READ_CELLBRD:
987 case P7110_SUBSMS_SMSC_OK:
988 case P7110_SUBSMS_SMSC_FAIL:
989 case P7110_SUBSMS_SMSC_RCVFAIL:
990 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], P7110_MSG_SMS);
991 e = GE_NOTIMPLEMENTED;
995 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", P7110_MSG_SMS, message[3]);
1002 static GSM_Error P7110_IncomingClock(int messagetype, unsigned char *message, int length, GSM_Data *data)
1004 GSM_Error e = GE_NONE;
1006 if (!data || !data->DateTime) return GE_INTERNALERROR;
1007 switch (message[3]) {
1008 case P7110_SUBCLO_DATE_RCVD:
1009 data->DateTime->Year = (((unsigned int)message[8]) << 8) + message[9];
1010 data->DateTime->Month = message[10];
1011 data->DateTime->Day = message[11];
1012 data->DateTime->Hour = message[12];
1013 data->DateTime->Minute = message[13];
1014 data->DateTime->Second = message[14];
1017 case P7110_SUBCLO_ALARM_RCVD:
1018 switch(message[8]) {
1019 case P7110_ALARM_ENABLED:
1020 data->DateTime->AlarmEnabled = 1;
1022 case P7110_ALARM_DISABLED:
1023 data->DateTime->AlarmEnabled = 0;
1026 data->DateTime->AlarmEnabled = -1;
1027 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
1032 data->DateTime->Hour = message[9];
1033 data->DateTime->Minute = message[10];
1037 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", P7110_MSG_CLOCK, message[3]);
1044 GSM_Error P7110_GetNoteAlarm(int alarmdiff, GSM_DateTime *time, GSM_DateTime *alarm)
1048 struct tm *tm_alarm;
1049 GSM_Error e = GE_NONE;
1051 if (!time || !alarm) return GE_INTERNALERROR;
1053 memset(&tm_time, 0, sizeof(tm_time));
1054 tm_time.tm_year = time->Year - 1900;
1055 tm_time.tm_mon = time->Month - 1;
1056 tm_time.tm_mday = time->Day;
1057 tm_time.tm_hour = time->Hour;
1058 tm_time.tm_min = time->Minute;
1061 t_alarm = mktime(&tm_time);
1062 t_alarm -= alarmdiff;
1063 t_alarm += timezone;
1065 tm_alarm = localtime(&t_alarm);
1067 alarm->Year = tm_alarm->tm_year + 1900;
1068 alarm->Month = tm_alarm->tm_mon + 1;
1069 alarm->Day = tm_alarm->tm_mday;
1070 alarm->Hour = tm_alarm->tm_hour;
1071 alarm->Minute = tm_alarm->tm_min;
1072 alarm->Second = tm_alarm->tm_sec;
1078 GSM_Error P7110_GetNoteTimes(unsigned char *block, GSM_CalendarNote *c)
1081 GSM_Error e = GE_NONE;
1083 if (!c) return GE_INTERNALERROR;
1085 c->Time.Hour = block[0];
1086 c->Time.Minute = block[1];
1087 c->Recurance = ((((unsigned int)block[4]) << 8) + block[5]) * 60;
1088 alarmdiff = (((unsigned int)block[2]) << 8) + block[3];
1090 if (alarmdiff != 0xffff) {
1091 P7110_GetNoteAlarm(alarmdiff * 60, &(c->Time), &(c->Alarm));
1092 c->Alarm.AlarmEnabled = 1;
1094 c->Alarm.AlarmEnabled = 0;
1100 static GSM_Error P7110_IncomingCalendar(int messagetype, unsigned char *message, int length, GSM_Data *data)
1102 GSM_Error e = GE_NONE;
1103 unsigned char *block;
1106 if (!data || !data->CalendarNote) return GE_INTERNALERROR;
1108 year = data->CalendarNote->Time.Year;
1109 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1110 switch (message[3]) {
1111 case P7110_SUBCAL_NOTE_RCVD:
1112 block = message + 12;
1114 data->CalendarNote->Location = (((unsigned int)message[4]) << 8) + message[5];
1115 data->CalendarNote->Time.Year = (((unsigned int)message[8]) << 8) + message[9];
1116 data->CalendarNote->Time.Month = message[10];
1117 data->CalendarNote->Time.Day = message[11];
1118 data->CalendarNote->Time.Second = 0;
1120 dprintf("Year: %i\n", data->CalendarNote->Time.Year);
1122 switch (message[6]) {
1123 case P7110_NOTE_MEETING:
1124 data->CalendarNote->Type = GCN_MEETING;
1125 P7110_GetNoteTimes(block, data->CalendarNote);
1126 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1128 case P7110_NOTE_CALL:
1129 data->CalendarNote->Type = GCN_CALL;
1130 P7110_GetNoteTimes(block, data->CalendarNote);
1131 DecodeUnicode(data->CalendarNote->Text, (block + 8), block[6]);
1132 DecodeUnicode(data->CalendarNote->Phone, (block + 8 + block[6] * 2), block[7]);
1134 case P7110_NOTE_REMINDER:
1135 data->CalendarNote->Type = GCN_REMINDER;
1136 data->CalendarNote->Recurance = ((((unsigned int)block[0]) << 8) + block[1]) * 60;
1137 DecodeUnicode(data->CalendarNote->Text, (block + 4), block[2]);
1139 case P7110_NOTE_BIRTHDAY:
1141 for (i = 0; i < 10; i++) {
1142 dprintf("(%i:0x%02x)", i, block[i]);
1146 data->CalendarNote->Type = GCN_BIRTHDAY;
1147 data->CalendarNote->Time.Year = year;
1148 data->CalendarNote->Time.Hour = 23;
1149 data->CalendarNote->Time.Minute = 59;
1150 data->CalendarNote->Time.Second = 58;
1152 alarm = ((unsigned int)block[2]) << 24;
1153 alarm += ((unsigned int)block[3]) << 16;
1154 alarm += ((unsigned int)block[4]) << 8;
1157 dprintf("alarm: %i\n", alarm);
1159 if (alarm == 0xffff) {
1160 data->CalendarNote->Alarm.AlarmEnabled = 0;
1162 data->CalendarNote->Alarm.AlarmEnabled = 1;
1165 P7110_GetNoteAlarm(alarm, &(data->CalendarNote->Time), &(data->CalendarNote->Alarm));
1167 data->CalendarNote->Time.Hour = 0;
1168 data->CalendarNote->Time.Minute = 0;
1169 data->CalendarNote->Time.Second = 0;
1170 data->CalendarNote->Time.Year = (((unsigned int)block[6]) << 8) + block[7];
1172 DecodeUnicode(data->CalendarNote->Text, (block + 10), block[9]);
1176 data->CalendarNote->Type = -1;
1182 case P7110_SUBCAL_ADD_MEETING_RESP:
1183 case P7110_SUBCAL_ADD_CALL_RESP:
1184 case P7110_SUBCAL_ADD_BIRTHDAY_RESP:
1185 case P7110_SUBCAL_ADD_REMINDER_RESP:
1186 case P7110_SUBCAL_DEL_NOTE_RESP:
1187 case P7110_SUBCAL_FREEPOS_RCVD:
1188 case P7110_SUBCAL_INFO_RCVD:
1189 dprintf("Subtype 0x%02x of type 0x%02x (calendar handling) not implemented\n", message[3], P7110_MSG_CALENDAR);
1190 e = GE_NOTIMPLEMENTED;
1193 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", P7110_MSG_CALENDAR, message[3]);
1200 static int GetMemoryType(GSM_MemoryType memory_type)
1204 switch (memory_type) {
1206 result = P7110_MEMORY_MT;
1209 result = P7110_MEMORY_ME;
1212 result = P7110_MEMORY_SM;
1215 result = P7110_MEMORY_FD;
1218 result = P7110_MEMORY_ON;
1221 result = P7110_MEMORY_EN;
1224 result = P7110_MEMORY_DC;
1227 result = P7110_MEMORY_RC;
1230 result = P7110_MEMORY_MC;
1233 result = P7110_MEMORY_XX;
1241 static GSM_Error P7110_DialVoice(char *Number)
1244 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
1246 // unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
1248 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
1249 // unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
1250 // unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
1251 // unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1254 //req[4]=strlen(Number);
1256 //for(i=0; i < strlen(Number) ; i++)
1257 // req[5+i]=Number[i];
1259 //memcpy(req+5+strlen(Number), req_end, 10);
1261 //len=6+strlen(Number);
1266 //PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
1270 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100)==GE_NONE) {
1271 PGEN_DebugMessage(1, req, len);
1275 // } else return GE_NOTIMPLEMENTED;
1282 return GE_NOTIMPLEMENTED;
1287 static GSM_Error GetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1289 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1290 0x00, 0x10 , /* memory type */
1291 0x00, 0x00, /* location */
1294 req[11] = data->Bitmap->number + 1;
1295 dprintf("Getting caller(%d) logo...\n",data->Bitmap->number);
1296 if (SM_SendMessage(state, 14, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1297 return SM_Block(state, data, 0x03);
1300 inline unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
1305 *(block++) = size + 6;
1307 memcpy(block, buf, size);
1313 static GSM_Error SetCallerBitmap(GSM_Data *data, GSM_Statemachine *state)
1315 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1316 0x00, 0x10, /* memory type */
1317 0x00, 0x00, /* location */
1321 unsigned int count = 18;
1323 if ((data->Bitmap->width!=state->Phone.Info.CallerLogoW) ||
1324 (data->Bitmap->height!=state->Phone.Info.CallerLogoH )) {
1325 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);
1326 return GE_INVALIDIMAGESIZE;
1329 req[13] = data->Bitmap->number + 1;
1330 dprintf("Setting caller(%d) bitmap...\n",data->Bitmap->number);
1333 i = strlen(data->Bitmap->text);
1334 EncodeUnicode((string + 1), data->Bitmap->text, i);
1336 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1338 string[0] = data->Bitmap->ringtone;
1340 count += PackBlock(0x0c, 2, block++, string, req + count);
1342 string[0] = data->Bitmap->number+1;
1344 count += PackBlock(0x1e, 2, block++, string, req + count);
1345 /* Logo on/off - assume on for now */
1348 count += PackBlock(0x1c, 2, block++, string, req + count);
1350 string[0] = data->Bitmap->width;
1351 string[1] = data->Bitmap->height;
1354 string[4] = 0x7e; /* Size */
1355 memcpy(string + 5, data->Bitmap->bitmap, data->Bitmap->size);
1356 count += PackBlock(0x1b, data->Bitmap->size + 5, block++, string, req + count);
1357 req[17] = block - 1;
1359 if (SM_SendMessage(state, count, 0x03, req)!=GE_NONE) return GE_NOTREADY;
1360 return SM_Block(state, data, 0x03);
1363 static GSM_Error GetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1365 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
1367 dprintf("Getting startup logo...\n");
1368 if (SM_SendMessage(state, 5, 0x7a, req)!=GE_NONE) return GE_NOTREADY;
1369 return SM_Block(state, data, 0x7a);
1372 static GSM_Error P7110_IncomingStartup(int messagetype, unsigned char *message, int length, GSM_Data *data)
1374 switch (message[3]) {
1376 dprintf("Startup logo set ok\n");
1381 /* I'm sure there are blocks here but never mind! */
1382 data->Bitmap->type = GSM_StartupLogo;
1383 data->Bitmap->height = message[13];
1384 data->Bitmap->width = message[17];
1385 data->Bitmap->size=((data->Bitmap->height/8)+(data->Bitmap->height%8>0))*data->Bitmap->width; /* Can't see this coded anywhere */
1386 memcpy(data->Bitmap->bitmap, message+22, data->Bitmap->size);
1387 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->Bitmap->height, data->Bitmap->width);
1392 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
1398 static GSM_Error GetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1400 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
1402 dprintf("Getting op logo...\n");
1403 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1404 return SM_Block(state, data, 0x0a);
1407 static GSM_Error SetStartupBitmap(GSM_Data *data, GSM_Statemachine *state)
1409 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
1413 0xc0, 0x04, 0x03, 0x00 };
1417 if ((data->Bitmap->width!=state->Phone.Info.StartupLogoW) ||
1418 (data->Bitmap->height!=state->Phone.Info.StartupLogoH )) {
1419 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);
1420 return GE_INVALIDIMAGESIZE;
1423 req[12] = data->Bitmap->height;
1424 req[16] = data->Bitmap->width;
1425 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1426 count += data->Bitmap->size;
1427 dprintf("Setting startup logo...\n");
1429 if (SM_SendMessage(state, count, 0x7a, req) != GE_NONE) return GE_NOTREADY;
1430 return SM_Block(state, data, 0x7a);
1433 static GSM_Error SetOperatorBitmap(GSM_Data *data, GSM_Statemachine *state)
1435 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
1436 0x00, /* logo enabled */
1437 0x00, 0xf0, 0x00, /* network code (000 00) */
1439 0x08, /* length of rest */
1440 0x00, 0x00, /* Bitmap width / height */
1442 0x00, /* Bitmap size */
1447 if ((data->Bitmap->width!=state->Phone.Info.OpLogoW) ||
1448 (data->Bitmap->height!=state->Phone.Info.OpLogoH )) {
1449 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);
1450 return GE_INVALIDIMAGESIZE;
1453 if (strcmp(data->Bitmap->netcode,"000 00")) { /* set logo */
1454 req[5] = 0x01; // Logo enabled
1455 req[6] = ((data->Bitmap->netcode[1] & 0x0f) << 4) | (data->Bitmap->netcode[0] & 0x0f);
1456 req[7] = 0xf0 | (data->Bitmap->netcode[2] & 0x0f);
1457 req[8] = ((data->Bitmap->netcode[5] & 0x0f) << 4) | (data->Bitmap->netcode[4] & 0x0f);
1458 req[11] = 8 + data->Bitmap->size;
1459 req[12] = data->Bitmap->width;
1460 req[13] = data->Bitmap->height;
1461 req[15] = data->Bitmap->size;
1462 memcpy(req + count, data->Bitmap->bitmap, data->Bitmap->size);
1463 count += data->Bitmap->size;
1465 dprintf("Setting op logo...\n");
1466 if (SM_SendMessage(state, count, 0x0a, req) != GE_NONE) return GE_NOTREADY;
1467 return SM_Block(state, data, 0x0a);
1470 static GSM_Error P7110_GetBitmap(GSM_Data *data, GSM_Statemachine *state)
1472 switch(data->Bitmap->type) {
1473 case GSM_CallerLogo:
1474 return GetCallerBitmap(data, state);
1475 case GSM_StartupLogo:
1476 return GetStartupBitmap(data, state);
1477 case GSM_OperatorLogo:
1478 return GetOperatorBitmap(data, state);
1480 return GE_NOTIMPLEMENTED;
1484 static GSM_Error P7110_SetBitmap(GSM_Data *data, GSM_Statemachine *state)
1486 switch(data->Bitmap->type) {
1487 case GSM_CallerLogo:
1488 return SetCallerBitmap(data, state);
1489 case GSM_StartupLogo:
1490 return SetStartupBitmap(data, state);
1491 case GSM_OperatorLogo:
1492 return SetOperatorBitmap(data, state);
1494 return GE_NOTIMPLEMENTED;
1498 static GSM_Error P7110_WritePhonebookLocation(GSM_Data *data, GSM_Statemachine *state)
1500 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
1501 0x00, 0x00, /* memory type */
1502 0x00, 0x00, /* location */
1505 int block, i, j, defaultn;
1506 unsigned int count = 18;
1507 GSM_PhonebookEntry *entry;
1509 if (data->PhonebookEntry) entry=data->PhonebookEntry;
1510 else return GE_TRYAGAIN;
1512 req[11] = GetMemoryType(entry->MemoryType);
1513 req[12] = (entry->Location >> 8);
1514 req[13] = entry->Location & 0xff;
1516 if (*(entry->Name)) {
1518 i = strlen(entry->Name);
1519 EncodeUnicode((string + 1), entry->Name, i);
1521 count += PackBlock(0x07, i * 2 + 1, block++, string, req + count);
1523 string[0] = entry->Group + 1;
1525 count += PackBlock(0x1e, 2, block++, string, req + count);
1526 /* Default Number */
1528 for (i = 0; i < entry->SubEntriesCount; i++)
1529 if (entry->SubEntries[i].EntryType == GSM_Number)
1530 if (!strcmp(entry->Number, entry->SubEntries[i].data.Number))
1533 string[0] = entry->SubEntries[defaultn].NumberType;
1537 i = strlen(entry->SubEntries[defaultn].data.Number);
1538 EncodeUnicode((string + 5), entry->SubEntries[defaultn].data.Number, i);
1540 count += PackBlock(0x0b, i * 2 + 5, block++, string, req + count);
1542 /* Rest of the numbers */
1543 for (i = 0; i < entry->SubEntriesCount; i++)
1544 if (entry->SubEntries[i].EntryType == GSM_Number)
1545 if (i != defaultn) {
1546 string[0] = entry->SubEntries[i].NumberType;
1550 j = strlen(entry->SubEntries[i].data.Number);
1551 EncodeUnicode((string + 5), entry->SubEntries[i].data.Number, j);
1553 count += PackBlock(0x0b, j * 2 + 5, block++, string, req + count);
1555 req[17] = block - 1;
1556 dprintf("Writing phonebook entry %s...\n",entry->Name);
1558 if (SM_SendMessage(state, count, 0x03, req) != GE_NONE) return GE_NOTREADY;
1559 return SM_Block(state, data, 0x03);
1562 static GSM_Error P7110_ReadPhonebookLL(GSM_Data *data, GSM_Statemachine *state, int memtype, int location)
1565 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
1566 0x00, 0x00, /* memory type */ //02,05
1567 0x00, 0x00, /* location */
1570 dprintf("Reading phonebook location (%d)\n", location);
1573 req[10] = location >> 8;
1574 req[11] = location & 0xff;
1576 if (SM_SendMessage(state, 14, P7110_MSG_PHONEBOOK, req) != GE_NONE) return GE_NOTREADY;
1577 error = SM_Block(state, data, P7110_MSG_PHONEBOOK);
1582 static GSM_Error P7110_ReadPhonebook(GSM_Data *data, GSM_Statemachine *state)
1584 int memtype, location;
1586 memtype = GetMemoryType(data->PhonebookEntry->MemoryType);
1587 location = data->PhonebookEntry->Location;
1589 return P7110_ReadPhonebookLL(data, state, memtype, location);
1592 static GSM_Error P7110_GetSpeedDial(GSM_Data *data, GSM_Statemachine *state)
1594 int memtype, location;
1596 memtype = P7110_MEMORY_SPEEDDIALS;
1597 location = data->SpeedDial->Number;
1599 return P7110_ReadPhonebookLL(data, state, memtype, location);
1602 static GSM_Error P7110_GetSMSCenter(GSM_Data *data, GSM_Statemachine *state)
1605 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1607 req[5] = data->MessageCenter->No;
1609 if (SM_SendMessage(state, 6, P7110_MSG_SMS, req) != GE_NONE) return GE_NOTREADY;
1610 error = SM_Block(state, data, P7110_MSG_SMS);
1615 static GSM_Error P7110_GetClock(char req_type, GSM_Data *data, GSM_Statemachine *state)
1618 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1620 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, req) != GE_NONE) return GE_NOTREADY;
1621 error = SM_Block(state, data, P7110_MSG_CLOCK);
1626 static GSM_Error P7110_GetCalendarNote(GSM_Data *data, GSM_Statemachine *state)
1628 GSM_Error error = GE_NOTREADY;
1629 unsigned char req[] = {FBUS_FRAME_HEADER, P7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1630 unsigned char date[] = {FBUS_FRAME_HEADER, P7110_SUBCLO_GET_DATE};
1632 GSM_DateTime tmptime;
1634 tmpdata.DateTime = &tmptime;
1635 if (SM_SendMessage(state, 4, P7110_MSG_CLOCK, date) == GE_NONE) {
1636 SM_Block(state, &tmpdata, P7110_MSG_CLOCK);
1637 req[4] = data->CalendarNote->Location >> 8;
1638 req[5] = data->CalendarNote->Location & 0xff;
1639 data->CalendarNote->Time.Year = tmptime.Year;
1641 if(SM_SendMessage(state, 6, P7110_MSG_CALENDAR, req) == GE_NONE) {
1642 error = SM_Block(state, data, P7110_MSG_CALENDAR);