Found in "gnokii-working" directory, some November-patches version
[gnokii.git] / common / fbus-6110.c
1 /*
2
3   $Id$
4   
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13   This file provides an API for accessing functions on the 6110 and similar
14   phones. See README for more details on supported mobile phones.
15
16   The various routines are called FB61 (whatever) as a concatenation of FBUS
17   and 6110.
18
19   $Log$
20   Revision 1.1.1.2  2002/04/03 00:07:54  short
21   Found in "gnokii-working" directory, some November-patches version
22
23   Revision 1.136  2001/08/20 23:27:37  pkot
24   Add hardware shakehand to the link layer (Manfred Jonsson)
25
26   Revision 1.135  2001/08/09 12:34:33  pkot
27   3330 and 6250 support - I have no idea if it does work (mygnokii)
28
29   Revision 1.134  2001/06/10 11:24:57  machek
30   Kill "slash star" inside comment.
31
32   Revision 1.133  2001/03/19 23:43:46  pkot
33   Solaris/ *BSD '#if defined' cleanup
34
35   Revision 1.132  2001/03/13 01:23:17  pkot
36   Windows updates (Manfred Jonsson)
37
38   Revision 1.131  2001/03/13 01:21:38  pkot
39   *BSD updates (Bert Driehuis)
40
41   Revision 1.130  2001/02/28 21:30:52  machek
42   Return data in GBF_Arbitrary if we can't handle units requested.
43
44   Revision 1.129  2001/02/21 19:56:55  chris
45   More fiddling with the directory layout
46
47   Revision 1.128  2001/02/17 22:40:48  chris
48   ATA support
49
50   Revision 1.127  2001/02/06 21:15:34  chris
51   Preliminary irda support for 7110 etc.  Not well tested!
52
53   Revision 1.126  2001/02/06 14:35:55  pkot
54   Few more cleanups on authentication
55
56   Revision 1.125  2001/02/03 23:56:12  chris
57   Start of work on irda support (now we just need fbus-irda.c!)
58   Proper unicode support in 7110 code (from pkot)
59
60   Revision 1.124  2001/02/01 15:17:27  pkot
61   Fixed --identify and added Manfred's manufacturer patch
62
63   Revision 1.123  2001/01/31 12:49:00  pkot
64   Many cleanups in fbus-6110 code.
65   3210/3310 really work now.
66
67   Revision 1.122  2001/01/23 15:32:35  chris
68   Pavel's 'break' and 'static' corrections.
69   Work on logos for 7110.
70
71   Revision 1.121  2001/01/15 17:00:45  pkot
72   Initial keypress sequence support. Disable compilation warning
73
74   Revision 1.120  2001/01/14 22:46:56  chris
75   Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
76
77   Revision 1.119  2001/01/10 16:32:16  pkot
78   Documentation updates.
79   FreeBSD fix for 3810 code.
80   Added possibility for deleting SMS just after reading it in gnokii.
81   2110 code updates.
82   Many cleanups.
83
84   Revision 1.118  2001/01/08 15:11:36  pkot
85   Documentation updates.
86   Fixed some bugs and removed FIXMEs.
87   We need to move some stuff from configure.in to aclocal.m4
88
89   Revision 1.117  2000/12/21 15:13:46  pkot
90   Fixed functions converting ascii to and from PDU
91
92   Revision 1.116  2000/12/19 16:27:16  pkot
93   Added 'static' word to variable declarations in common/fbus-6110.c and Makefile fix. (thanks to Pavel Machek)
94
95 */
96
97 /* "Turn on" prototypes in fbus-6110.h */
98
99 #define __fbus_6110_c 
100
101 /* System header files */
102
103 #include <stdio.h>
104 #include <string.h>
105 #include <stdlib.h>
106  
107 #ifdef WIN32
108
109 #include <windows.h>
110 #include "win32/winserial.h"
111
112 #undef IN
113 #undef OUT
114
115 #define WRITEPHONE(a, b, c) WriteCommBlock(b, c)
116 #define sleep(x) Sleep((x) * 1000)
117 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
118 extern HANDLE hPhone;
119
120 #else
121
122 #define WRITEPHONE(a, b, c) device_write(b, c)
123 #include <unistd.h>
124 #include <termios.h>
125 #include <fcntl.h>
126 #include <ctype.h>
127 #include <signal.h>
128 #include <sys/ioctl.h>
129 #include <sys/types.h>
130 #include <sys/time.h>
131 #include <pthread.h>
132 #include <errno.h>
133 #include "device.h"
134 #include "devices/unixserial.h"
135
136 #endif
137
138 /* Various header file */
139
140 #include "config.h"
141 #include "misc.h"
142 #include "gsm-common.h"
143 #include "fbus-6110.h"
144 #include "fbus-6110-auth.h"
145 #include "gsm-ringtones.h"
146 #include "gsm-networks.h"
147 #include "phones/generic.h"
148 #include "phones/nokia.h"
149
150 /* Global variables used by code in gsm-api.c to expose the functions
151    supported by this model of phone. */
152
153 bool FB61_LinkOK;
154
155 #if __unices__
156 /* fd opened in device.c */
157 extern int device_portfd;
158 #endif
159
160 #ifdef WIN32
161
162 void FB61_InitializeLink();
163
164 #endif
165
166 /* Here we initialise model specific functions. */
167
168 GSM_Functions FB61_Functions = {
169         FB61_Initialise,
170         FB61_Terminate,
171         FB61_GetMemoryLocation,
172         FB61_WritePhonebookLocation,
173         FB61_GetSpeedDial,
174         FB61_SetSpeedDial,
175         FB61_GetMemoryStatus,
176         FB61_GetSMSStatus,
177         FB61_GetSMSCenter,
178         FB61_SetSMSCenter,
179         FB61_GetSMSMessage,
180         FB61_DeleteSMSMessage,
181         FB61_SendSMSMessage,
182         FB61_SaveSMSMessage,
183         FB61_GetRFLevel,
184         FB61_GetBatteryLevel,
185         FB61_GetPowerSource,
186         FB61_GetDisplayStatus,
187         FB61_EnterSecurityCode,
188         FB61_GetSecurityCodeStatus,
189         FB61_GetIMEI,
190         FB61_GetRevision,
191         FB61_GetModel,
192         PNOK_GetManufacturer,
193         FB61_GetDateTime,
194         FB61_SetDateTime,
195         FB61_GetAlarm,
196         FB61_SetAlarm,
197         FB61_DialVoice,
198         FB61_DialData,
199         FB61_GetIncomingCallNr,
200         FB61_GetNetworkInfo,
201         FB61_GetCalendarNote,
202         FB61_WriteCalendarNote,
203         FB61_DeleteCalendarNote,
204         FB61_NetMonitor,
205         FB61_SendDTMF,
206         FB61_GetBitmap,
207         FB61_SetBitmap,
208         FB61_SetRingTone,
209         FB61_Reset,
210         FB61_GetProfile,
211         FB61_SetProfile,
212         FB61_SendRLPFrame,
213         FB61_CancelCall,
214         FB61_EnableDisplayOutput,
215         FB61_DisableDisplayOutput,
216         FB61_EnableCellBroadcast,
217         FB61_DisableCellBroadcast,
218         FB61_ReadCellBroadcast,
219         UNIMPLEMENTED,
220         UNIMPLEMENTED,
221         FB61_AnswerCall
222 };
223
224 /* Mobile phone information */
225
226 GSM_Information FB61_Information = {
227         "6110|6130|6150|6190|5110|5130|5190|3210|3310|3330", /* Supported models */
228         4,                     /* Max RF Level */
229         0,                     /* Min RF Level */
230         GRF_Arbitrary,         /* RF level units */
231         4,                     /* Max Battery Level */
232         0,                     /* Min Battery Level */
233         GBU_Arbitrary,         /* Battery level units */
234         GDT_DateTime,          /* Have date/time support */
235         GDT_TimeOnly,            /* Alarm supports time only */
236         1,                     /* Only one alarm available */
237         48, 84,                /* Startup logo size */
238         14, 72,                /* Op logo size */
239         14, 72                 /* Caller logo size */
240 };
241
242 const char *FB61_MemoryType_String [] = {
243         "",     /* 0x00 */
244         "MT", /* 0x01 */
245         "ME", /* 0x02 */
246         "SM", /* 0x03 */
247         "FD", /* 0x04 */
248         "ON", /* 0x05 */
249         "EN", /* 0x06 */
250         "DC", /* 0x07 */
251         "RC", /* 0x08 */
252         "MC", /* 0x09 */
253 };
254
255 /* Local variables */
256
257
258 char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH];
259
260 /* This is the connection type used in gnokii. */
261
262 GSM_ConnectionType CurrentConnectionType;
263
264 int BufferCount;
265
266 u8 MessageBuffer[FB61_MAX_RECEIVE_LENGTH * 6];
267
268 u16 MessageLength;
269 u8 MessageType, MessageDestination, MessageSource, MessageUnknown;
270 u8 MessagesSent=0, AcksReceived=0;
271
272 /* Magic bytes from the phone. */
273
274 unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };
275 GSM_Error CurrentMagicError = GE_BUSY;
276
277 enum FB61_RX_States RX_State;
278 bool RX_Multiple = false;
279
280 u8        RequestSequenceNumber = 0x00;
281 bool      RequestTerminate;
282 bool      DisableKeepalive = false;
283 int       InitLength;
284 u8        CallSequenceNumber; /* Used to disconnect the call */
285
286 #ifndef WIN32
287
288 pthread_t Thread;
289 # if __unices__
290 pthread_t selThread;
291 # endif
292
293 #endif
294
295 /* Local variables used by get/set phonebook entry code. Buffer is used as a
296    source or destination for phonebook data and other functions... Error is
297    set to GE_NONE by calling function, set to GE_COMPLETE or an error code by
298    handler routines as appropriate. */
299                                    
300 static GSM_PhonebookEntry *CurrentPhonebookEntry;
301 static GSM_Error          CurrentPhonebookError;
302
303 static GSM_SpeedDial      *CurrentSpeedDialEntry;
304 static GSM_Error          CurrentSpeedDialError;
305
306 static GSM_SMSMessage     *CurrentSMSMessage;
307 static GSM_Error          CurrentSMSMessageError;
308
309 static GSM_MemoryStatus   *CurrentMemoryStatus;
310 static GSM_Error          CurrentMemoryStatusError;
311
312 static GSM_NetworkInfo    *CurrentNetworkInfo = NULL;
313 static GSM_Error          CurrentNetworkInfoError;
314
315 static GSM_SMSStatus      *CurrentSMSStatus;
316 static GSM_Error          CurrentSMSStatusError;
317
318 static GSM_MessageCenter  *CurrentMessageCenter;
319 static GSM_Error          CurrentMessageCenterError;
320
321 static int                *CurrentSecurityCodeStatus;
322 static GSM_Error          CurrentSecurityCodeError;
323
324 static GSM_DateTime       *CurrentDateTime;
325 static GSM_Error          CurrentDateTimeError;
326
327 static GSM_DateTime       *CurrentAlarm;
328 static GSM_Error          CurrentAlarmError;
329
330 static GSM_CalendarNote   *CurrentCalendarNote;
331 static GSM_Error          CurrentCalendarNoteError;
332
333 static GSM_Error          CurrentSetDateTimeError;
334 static GSM_Error          CurrentSetAlarmError;
335
336 static int                CurrentRFLevel,
337         CurrentBatteryLevel,
338         CurrentPowerSource;
339
340 static int                DisplayStatus;
341 static GSM_Error          DisplayStatusError;
342
343 static char               *CurrentNetmonitor;
344 static GSM_Error          CurrentNetmonitorError;
345
346 static GSM_Bitmap         *GetBitmap=NULL;
347 static GSM_Error          GetBitmapError;
348
349 static GSM_Error          SetBitmapError;
350
351 static GSM_Profile        *CurrentProfile;
352 static GSM_Error          CurrentProfileError;
353
354 static GSM_Error          CurrentDisplayOutputError;
355
356 static GSM_CBMessage      *CurrentCBMessage;
357 static GSM_Error          CurrentCBError;
358
359 static GSM_Error          CurrentPhoneInfoError;
360
361 static unsigned char      IMEI[FB61_MAX_IMEI_LENGTH];
362 static unsigned char      Revision[FB61_MAX_REVISION_LENGTH];
363 static unsigned char      Model[FB61_MAX_MODEL_LENGTH];
364
365 static char               CurrentIncomingCall[20] = " ";
366
367 /* Pointer to callback function in user code to be called when RLP frames
368    are received. */
369
370 void               (*RLP_RXCallback)(RLP_F96Frame *frame);
371
372 /* Pointer to a callback function used to return changes to a calls status */
373 /* This saves unreliable polling */
374 void (*CallPassup)(char c);
375
376 #ifdef WIN32
377 /* called repeatedly from a separate thread */
378 void FB61_KeepAliveProc()
379 {
380         if (!DisableKeepalive)
381                 FB61_TX_SendStatusRequest();
382         Sleep(2000);
383 }
384 #endif
385
386 /* Initialise variables and state machine. */
387
388 GSM_Error FB61_Initialise(char *port_device, char *initlength,
389                           GSM_ConnectionType connection,
390                           void (*rlp_callback)(RLP_F96Frame *frame))
391 {
392         int rtn;
393
394         RequestTerminate = false;
395         FB61_LinkOK = false;
396         RLP_RXCallback = rlp_callback;
397         CallPassup = NULL;
398
399         strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
400
401         InitLength = atoi(initlength);
402         if (!strcmp(initlength, "default") || (InitLength == 0)) {
403                 InitLength = 250;       /* This is the usual value, lower may work. */
404         }
405
406         CurrentConnectionType = connection;
407
408         /* Create and start main thread. */
409
410 #ifdef WIN32
411         DisableKeepalive = true;
412         rtn = ! OpenConnection(PortDevice, FB61_RX_StateMachine, FB61_KeepAliveProc);
413         if (rtn == 0) {
414                 FB61_InitializeLink(); /* makes more sense to do this in 'this' thread */
415                 DisableKeepalive = false;
416         }
417 #else
418         rtn = pthread_create(&Thread, NULL, (void *)FB61_ThreadLoop, (void *)NULL);
419 #endif
420
421         if (rtn != 0)
422                 return (GE_INTERNALERROR);
423
424         return (GE_NONE);
425 }
426
427 #if __unices__
428 /* thread for handling incoming data */
429 void FB61_SelectLoop()
430 {
431         int err;
432         fd_set readfds;
433         struct timeval timeout;
434
435         FD_ZERO(&readfds);
436         FD_SET(device_portfd, &readfds);
437         /* set timeout to 15 seconds */
438         timeout.tv_sec=15;
439         timeout.tv_usec=0;
440         while (!RequestTerminate) {
441                 err = select(device_portfd + 1, &readfds, NULL, NULL, &timeout);
442                 /* call singal handler to process incoming data */
443                 if ( err > 0 ) FB61_SigHandler(0);
444                 else if (err == -1) perror("Error in SelectLoop");
445         }
446 }
447 #endif
448
449   
450 /* This function send the status request to the phone. */
451
452 GSM_Error FB61_TX_SendStatusRequest(void)
453 {
454         /* The status request is of the type 0x04. It's subtype is 0x01. If you have
455            another subtypes and it's meaning - just inform Pavel, please. */
456         unsigned char request[] = {FB61_FRAME_HEADER, 0x01};
457         FB61_TX_SendMessage(4, 0x04, request);
458         return (GE_NONE);
459 }
460
461 /* This function translates GMT_MemoryType to FB61_MEMORY_xx */
462
463 int FB61_GetMemoryType(GSM_MemoryType memory_type)
464 {
465         int result;
466         switch (memory_type) {
467         case GMT_MT: result = FB61_MEMORY_MT; break;
468         case GMT_ME: result = FB61_MEMORY_ME; break;
469         case GMT_SM: result = FB61_MEMORY_SM; break;
470         case GMT_FD: result = FB61_MEMORY_FD; break;
471         case GMT_ON: result = FB61_MEMORY_ON; break;
472         case GMT_EN: result = FB61_MEMORY_EN; break;
473         case GMT_DC: result = FB61_MEMORY_DC; break;
474         case GMT_RC: result = FB61_MEMORY_RC; break;
475         case GMT_MC: result = FB61_MEMORY_MC; break;
476         default:     result = FB61_MEMORY_XX; break;
477         }
478         return (result);
479 }
480
481 /* This function is used to get storage status from the phone. It currently
482    supports two different memory areas - internal and SIM. */
483
484 static GSM_Error 
485 wait_on(volatile GSM_Error *what, int timeout)
486 {
487         *what = GE_BUSY;
488         while (timeout && (*what == GE_BUSY)) {
489                 if (!--timeout)
490                         return GE_TIMEOUT;
491                 usleep(100000);
492         }
493         return *what;
494 }
495
496 #define WAIT_ON(x, y) \
497         { \
498                 GSM_Error res = wait_on(x, y); \
499                 if (res != GE_NONE) \
500                         return res; \
501         }
502
503 #define WAIT_ON1(x, y) \
504         { \
505                 GSM_Error res = wait_on(x, y); \
506                 if (res != GE_NONE) \
507                         return; \
508         }
509
510 static GSM_Error FB61_GetPhoneInfo()
511 {
512         unsigned char req[] = { FB61_FRAME_HEADER, 0x03, 0x00 };
513         FB61_TX_SendMessage(5, 0xd1, req);
514         return (wait_on(&CurrentPhoneInfoError, 20));
515 }
516
517 GSM_Error FB61_AnswerCall(char s)
518 {
519         unsigned char req0[] = { FB61_FRAME_HEADER, 0x42,0x05,0x01,0x07,                                 0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
520                             0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80};
521         unsigned char req[] = { FB61_FRAME_HEADER, 0x06, 0x00, 0x00};
522         req[4]=s;
523         dprintf("Answering call %d\n\r",s);
524         FB61_TX_SendMessage(sizeof(req0), 0x01, req0);
525         sleep(1);
526         FB61_TX_SendMessage(sizeof(req), 0x01, req);
527         return (wait_on(&CurrentPhoneInfoError, 20));
528 }
529
530 GSM_Error FB61_GetMemoryStatus(GSM_MemoryStatus *Status)
531 {
532         unsigned char req[] = { FB61_FRAME_HEADER, 0x07 /* MemoryStatus request */, 0x00 /* MemoryType */ };
533         CurrentMemoryStatus = Status;
534         req[4] = FB61_GetMemoryType(Status->MemoryType);
535         FB61_TX_SendMessage(5, 0x03, req);
536         return wait_on(&CurrentMemoryStatusError, 20);
537 }
538
539 GSM_Error FB61_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
540 {
541         unsigned char req[] = { FB61_FRAME_HEADER, 0x70 };
542         CurrentNetworkInfo = NetworkInfo;
543         FB61_TX_SendMessage(4, 0x0a, req);
544         return wait_on(&CurrentNetworkInfoError, 20);
545 }
546
547 GSM_Error FB61_EnableDisplayOutput(void)
548 {
549         unsigned char req[] = { FB61_FRAME_HEADER, 0x53, 0x01};
550         FB61_TX_SendMessage(5, 0x0d, req);
551         return wait_on(&CurrentDisplayOutputError, 20);
552 }
553  
554 GSM_Error FB61_DisableDisplayOutput(void)
555 {
556         unsigned char req[] = { FB61_FRAME_HEADER, 0x53, 0x02};
557         FB61_TX_SendMessage(5, 0x0d, req);
558         return wait_on(&CurrentDisplayOutputError, 20);
559 }
560
561 GSM_Error FB61_GetProfile(GSM_Profile *Profile)
562 {
563         int i;
564         /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
565         char model[64];
566         unsigned char name_req[] = { FB61_FRAME_HEADER, 0x1a, 0x00};
567         unsigned char feat_req[] = { FB61_FRAME_HEADER, 0x13, 0x01, 0x00, 0x00};
568
569         CurrentProfile = Profile;
570
571         name_req[4] = Profile->Number;
572         feat_req[5] = Profile->Number;
573         FB61_TX_SendMessage(5, 0x05, name_req);
574
575         WAIT_ON(&CurrentProfileError, 20);
576
577         for (i = 0x00; i <= 0x09; i++) {
578                 CurrentProfileError = GE_BUSY;
579                 feat_req[6] = i;
580                 FB61_TX_SendMessage(7, 0x05, feat_req);
581                 WAIT_ON(&CurrentProfileError, 20);
582         }
583
584         if (Profile->DefaultName > -1)
585         {
586                 while (FB61_GetModel(model)  != GE_NONE)
587                         sleep(1);
588
589                 /*For N5110*/
590                 /*FIX ME: It should be set for N5130 and 3210 too*/
591                 if (!strcmp(model,"NSE-1")) {
592                         switch (Profile->DefaultName) {
593                         case 0x00: sprintf(Profile->Name, "Personal"); break;
594                         case 0x01: sprintf(Profile->Name, "Car"); break;
595                         case 0x02: sprintf(Profile->Name, "Headset"); break;
596                         default:   sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName); break;
597                         }
598                 } else {
599                         switch (Profile->DefaultName) {
600                         case 0x00: sprintf(Profile->Name, "General"); break;
601                         case 0x01: sprintf(Profile->Name, "Silent"); break;
602                         case 0x02: sprintf(Profile->Name, "Meeting"); break;
603                         case 0x03: sprintf(Profile->Name, "Outdoor"); break;
604                         case 0x04: sprintf(Profile->Name, "Pager"); break;
605                         case 0x05: sprintf(Profile->Name, "Car"); break;
606                         case 0x06: sprintf(Profile->Name, "Headset"); break;
607                         default: sprintf(Profile->Name, "Unknown (%i)", Profile->DefaultName); break;
608                         }
609                 }
610         }
611         return (GE_NONE);
612 }
613
614 GSM_Error FB61_SetProfile(GSM_Profile *Profile)
615 {
616         int i;
617         unsigned char name_req[40] = { FB61_FRAME_HEADER, 0x1c, 0x01, 0x03, 0x00, 0x00, 0x00};
618         unsigned char feat_req[] = { FB61_FRAME_HEADER, 0x10, 0x01, 0x00, 0x00, 0x00};
619
620         name_req[7] = Profile->Number;
621         name_req[8] = strlen(Profile->Name);
622         name_req[6] = name_req[8] + 2;
623
624         for (i = 0; i < name_req[8]; i++)
625                 name_req[9 + i] = Profile->Name[i];
626
627         FB61_TX_SendMessage(name_req[8] + 9, 0x05, name_req);
628         WAIT_ON(&CurrentProfileError, 30);
629
630         feat_req[5] = Profile->Number;
631         for (i = 0x00; i <= 0x09; i++) {
632                 feat_req[6] = i;
633                 switch (feat_req[6]) {
634                 case 0x00: feat_req[7] = Profile->KeypadTone; break;
635                 case 0x01: feat_req[7] = Profile->Lights; break;
636                 case 0x02: feat_req[7] = Profile->CallAlert; break;
637                 case 0x03: feat_req[7] = Profile->Ringtone; break;
638                 case 0x04: feat_req[7] = Profile->Volume; break;
639                 case 0x05: feat_req[7] = Profile->MessageTone; break;
640                 case 0x06: feat_req[7] = Profile->Vibration; break;
641                 case 0x07: feat_req[7] = Profile->WarningTone; break;
642                 case 0x08: feat_req[7] = Profile->CallerGroups; break;
643                 case 0x09: feat_req[7] = Profile->AutomaticAnswer; break;
644                 }
645
646                 FB61_TX_SendMessage(8, 0x05, feat_req);
647                 WAIT_ON(&CurrentProfileError, 20);
648         }
649
650         return (GE_NONE);
651 }
652
653 bool FB61_SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
654 {
655         u8 req[60] = { 0x00, 0xd9 };
656         /* Discontinuos transmission (DTX).  See section 5.6 of GSM 04.22 version 7.0.1. */
657        
658         if (out_dtx) req[1] = 0x01;
659         memcpy(req + 2, (u8 *) frame, 32);
660         return (FB61_TX_SendFrame(32, 0xf0, req));
661 }
662
663
664 GSM_Error FB61_GetCalendarNote(GSM_CalendarNote *CalendarNote)
665 {
666         unsigned char req[5] = { FB61_FRAME_HEADER, 0x66, 0x00 };
667         req[4] = CalendarNote->Location;
668         CurrentCalendarNote = CalendarNote;
669         CurrentCalendarNoteError = GE_BUSY;
670         FB61_TX_SendMessage(5, 0x13, req);
671         return wait_on(&CurrentCalendarNoteError, 20);
672 }
673
674 GSM_Error FB61_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
675 {
676         unsigned char req[200] = { FB61_FRAME_HEADER,
677                                    0x64, 0x01, 0x10,
678                                    0x00, /* Length of the rest of the frame. */
679                                    0x00, /* The type of calendar note */
680                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
682         };
683         int i, current;
684
685         req[7] = CalendarNote->Type;
686
687         req[8]  = CalendarNote->Time.Year / 256;
688         req[9]  = CalendarNote->Time.Year % 256;
689         req[10] = CalendarNote->Time.Month;
690         req[11] = CalendarNote->Time.Day;
691         req[12] = CalendarNote->Time.Hour;
692         req[13] = CalendarNote->Time.Minute;
693         req[14] = CalendarNote->Time.Timezone;
694
695         if (CalendarNote->Alarm.Year) {
696                 req[15] = CalendarNote->Alarm.Year / 256;
697                 req[16] = CalendarNote->Alarm.Year % 256;
698                 req[17] = CalendarNote->Alarm.Month;
699                 req[18] = CalendarNote->Alarm.Day;
700                 req[19] = CalendarNote->Alarm.Hour;
701                 req[20] = CalendarNote->Alarm.Minute;
702                 req[21] = CalendarNote->Alarm.Timezone;
703         }
704
705         req[22] = strlen(CalendarNote->Text);
706
707         current = 23;
708
709         for (i=0; i<strlen(CalendarNote->Text); i++)
710                 req[current++] = CalendarNote->Text[i];
711
712         req[current++] = strlen(CalendarNote->Phone);
713
714         for (i=0; i<strlen(CalendarNote->Phone); i++)
715                 req[current++] = CalendarNote->Phone[i];
716
717         CurrentCalendarNote = CalendarNote;
718         CurrentCalendarNoteError = GE_BUSY;
719
720         FB61_TX_SendMessage(current, 0x13, req);
721         return wait_on(&CurrentCalendarNoteError, 20);
722 }
723
724 GSM_Error FB61_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
725 {
726         unsigned char req[] = { FB61_FRAME_HEADER, 0x68, 0x00 };
727         req[4] = CalendarNote->Location;
728         CurrentCalendarNoteError = GE_BUSY;
729         FB61_TX_SendMessage(5, 0x13, req);
730         return wait_on(&CurrentCalendarNoteError, 20);
731 }
732
733 /* Init ir for win32 is made in winserial.c */
734 #ifndef WIN32
735
736 void FB61_InitIR(void)
737 {
738         int i;
739         unsigned char init_char     = FB61_SYNC_BYTE;
740         unsigned char end_init_char = FB61_IR_END_INIT_BYTE;
741   
742         for ( i = 0; i < 32; i++ )
743                 device_write(&init_char, 1);
744
745         device_write(&end_init_char, 1);
746         usleep(100000);
747 }
748
749 bool FB61_InitIR115200(void)
750 {
751         int PortFD;
752         u8 connect_seq[] = {FB61_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
753
754         bool ret         = true;
755         u8 nr_read       = 0;
756         u8 in_buffer[255];
757         struct timeval timeout;
758         fd_set ready;
759         int no_timeout   = 0;
760         int i;
761         int done         = 0;
762
763         /* send the connection sequence to phone */
764         FB61_TX_SendMessage(7, 0x02, connect_seq);
765
766         /* Wait for 1 sec. */
767         timeout.tv_sec  = 1;
768         timeout.tv_usec = 0;
769
770         PortFD = device_getfd();
771
772         do {
773                 FD_ZERO(&ready);
774                 FD_SET(PortFD, &ready);
775                 no_timeout = select(PortFD + 1, &ready, NULL, NULL, &timeout);
776                 if ( FD_ISSET(PortFD, &ready) ) {
777                         nr_read = read(PortFD, in_buffer, 1);
778                         if ( nr_read >= 1 ) {
779                                 for (i = 0; i < nr_read; i++) {
780                                         if ( in_buffer[i] == FB61_IR_FRAME_ID ) {
781                                                 done = 1;
782                                                 ret = true;
783                                                 break;
784                                         }
785                                 }
786                         } else {
787                                 done = 1;
788                                 ret = false;
789                         }
790                 }
791
792                 if (!no_timeout) {
793                         dprintf(_("Timeout in IR-mode\n"));
794                         done = 1;
795                         ret = false;
796                 }
797         } while (!done);
798   
799         return (ret);
800 }
801
802 /* This function is used to open the IR connection with the phone. */
803
804 bool FB61_OpenIR(void)
805 {
806         int result;
807         bool ret = false;
808         u8 i = 0;
809
810 #if __unices__
811         int rtn;
812 #else
813         struct sigaction sig_io;  
814
815         /* Set up and install handler before enabling async IO on port. */
816   
817         sig_io.sa_handler = FB61_SigHandler;
818         sig_io.sa_flags = 0;
819         sigaction (SIGIO, &sig_io, NULL);
820 #endif
821
822         /* Open device. */
823   
824         result = device_open(PortDevice, false, true, false, GCT_Infrared);
825
826         if (!result) {
827                 perror(_("Couldn't open FB61 infrared device"));
828                 return false;
829         }
830
831 #if __unices__
832         /* create a thread to handle incoming data from mobile phone */
833         rtn = pthread_create(&selThread, NULL, (void*)FB61_SelectLoop, (void*)NULL);
834         if (rtn != 0) return false;
835 #endif
836
837         device_changespeed(9600);
838         FB61_InitIR();
839         device_changespeed(115200);
840         ret = FB61_InitIR115200();
841         if (!ret) {
842                 for ( i = 0; i < 4 ; i++) {
843                         usleep (500000);
844                         device_changespeed(9600);
845                         FB61_InitIR();
846                         device_changespeed(115200);
847                         ret = FB61_InitIR115200();
848                         if (ret) break;
849                 }
850         }
851   
852         return (ret);
853 }
854
855 static void FB61_Authentication()
856 {
857         unsigned char connect1[] = {FB61_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
858         unsigned char connect2[] = {FB61_FRAME_HEADER, 0x20, 0x02};
859         unsigned char connect3[] = {FB61_FRAME_HEADER, 0x0d, 0x01, 0x00, 0x02};
860         unsigned char connect4[] = {FB61_FRAME_HEADER, 0x10};
861
862         unsigned char magic_connect[] = {FB61_FRAME_HEADER,
863                                          0x12,
864
865                                          /* The real magic goes here ... These bytes are filled in with the
866                                             external function FB61_GetNokiaAuth(). */
867
868                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
870
871                                          /* NOKIA&GNOKII Accessory */
872
873                                          0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x26, 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x20,
874                                          0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79,
875   
876                                          0x00, 0x00, 0x00, 0x00};
877
878         usleep(100); FB61_GetPhoneInfo(); usleep(100);
879
880         if (*Model && (GetPhoneModel(Model)->flags & PM_AUTHENTICATION)) {
881                 FB61_TX_SendMessage(7, 0x02, connect1);
882                 usleep(100); FB61_TX_SendMessage(5, 0x02, connect2);
883                 usleep(100); FB61_TX_SendMessage(7, 0x02, connect3);
884                 usleep(100); FB61_TX_SendMessage(4, 0x64, connect4);
885
886                 WAIT_ON1(&CurrentMagicError, 50);
887
888                 FB61_GetNokiaAuth(IMEI, MagicBytes, magic_connect+4);
889
890                 FB61_TX_SendMessage(45, 0x64, magic_connect);
891         }
892
893         return;
894 }
895
896 /* This is the main loop for the FB61 functions. When FB61_Initialise is
897    called a thread is created to run this loop. This loop is exited when the
898    application calls the FB61_Terminate function. */
899 void FB61_ThreadLoop(void)
900 {
901         unsigned char init_char = 0x55;
902         int count, idle_timer;
903
904         CurrentPhonebookEntry = NULL;  
905
906         if ( CurrentConnectionType == GCT_Infrared ) {
907                 dprintf(_("Starting IR mode...!\n"));
908                 if (FB61_OpenIR() != true) {
909                         FB61_LinkOK = false;
910                         while (!RequestTerminate)
911                                 usleep (100000);
912                         return;
913                 }
914
915         } else { /* CurrentConnectionType == GCT_Serial */
916
917                 /* Try to open serial port, if we fail we sit here and don't proceed to the
918                    main loop. */
919    
920                 if (FB61_OpenSerial() != true) {
921                         FB61_LinkOK = false;
922       
923                         /* Fail so sit here till calling code works out there is a problem. */
924       
925                         while (!RequestTerminate)
926                                 usleep (100000);
927       
928                         return;
929                 }
930         }
931
932         /* Initialise link with phone or what have you */
933
934         /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
935            empirical. */
936
937         for (count = 0; count < InitLength; count ++) {
938                 usleep(100);
939                 WRITEPHONE(PortFD, &init_char, 1);
940         }
941
942         FB61_TX_SendStatusRequest();
943
944         FB61_Authentication();
945
946         /* FIXME: we should implement better support for ringtones and the utility
947            to set ringtones. */
948
949         // FB61_SendRingtoneRTTTL("/tmp/barbie.txt");
950
951         idle_timer = 0;
952
953         /* Now enter main loop */
954
955         while (!RequestTerminate) {
956                 if (idle_timer == 0) {
957                         /* Dont send keepalive and status packets when doing other transactions. */
958                         if (!DisableKeepalive) FB61_TX_SendStatusRequest();
959                         idle_timer = 20;
960                 } else
961                         idle_timer--;
962
963                 usleep(100000);         /* Avoid becoming a "busy" loop. */
964         }
965 }
966 #endif /* WIN32 */
967
968 #ifdef WIN32
969 void FB61_InitializeLink()
970 {
971         int count;
972         DCB        dcb;
973
974         unsigned char init_char = 0x55;
975         /* Daxer */
976         unsigned char end_init_char = 0xc1;
977
978         /* Daxer Added for infared support */
979         if ( CurrentConnectionType == GCT_Infrared ) {
980                 dcb.DCBlength = sizeof(DCB);
981
982                 GetCommState(hPhone, &dcb);
983                 dcb.BaudRate = CBR_9600;
984                 SetCommState(hPhone, &dcb);
985         }
986
987         /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
988            empirical. */
989
990         for (count = 0; count < 32; count ++) {
991                 usleep(100);
992                 WRITEPHONE(PortFD, &init_char, 1);
993         }
994
995         WRITEPHONE(PortFD, &end_init_char, 1);
996
997         if ( CurrentConnectionType == GCT_Infrared ) {
998                 dcb.BaudRate = CBR_115200;
999                 SetCommState(hPhone, &dcb);
1000         }
1001  
1002         FB61_TX_SendStatusRequest();
1003
1004         FB61_Authentication();
1005 }
1006 #endif
1007
1008 /* Applications should call FB61_Terminate to shut down the FB61 thread and
1009    close the serial port. */
1010
1011 void FB61_Terminate(void)
1012 {
1013         /* Request termination of thread */
1014         RequestTerminate = true;
1015
1016 #ifndef WIN32
1017         /* Now wait for thread to terminate. */
1018         pthread_join(Thread, NULL);
1019
1020         /* Close serial port. */
1021         device_close();
1022
1023 #else
1024         CloseConnection();
1025 #endif
1026 }
1027
1028 GSM_Error FB61_GetRFLevel(GSM_RFUnits *units, float *level)
1029 {
1030         /* FIXME - these values are from 3810 code, may be incorrect.  Map from
1031            values returned in status packet to the the values returned by the AT+CSQ
1032            command. */
1033         float   csq_map[5] = {0, 8, 16, 24, 31};
1034         int timeout = 10;
1035         int rf_level;
1036
1037         CurrentRFLevel = -1;
1038
1039         FB61_TX_SendStatusRequest();
1040
1041         /* Wait for timeout or other error. */
1042
1043         while (timeout && (CurrentRFLevel == -1)) {
1044                 if (!--timeout)
1045                         return (GE_TIMEOUT);
1046                 usleep (100000);
1047         }
1048
1049         /* Make copy in case it changes. */
1050         rf_level = CurrentRFLevel;
1051
1052         if (rf_level == -1)
1053                 return (GE_NOLINK);
1054
1055   /* Now convert between the different units we support. */
1056
1057   /* Arbitrary units. */
1058         if (*units == GRF_Arbitrary) {
1059                 *level = rf_level;
1060                 return (GE_NONE);
1061         }
1062
1063         /* CSQ units. */
1064         if (*units == GRF_CSQ) {
1065
1066                 if (rf_level <= 4)
1067                         *level = csq_map[rf_level];
1068                 else
1069                         *level = 99; /* Unknown/undefined */
1070
1071                 return (GE_NONE);
1072         }
1073
1074         *units = GRF_Arbitrary;
1075         *level = rf_level;
1076         return (GE_NONE);
1077 }
1078
1079 GSM_Error FB61_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1080 {
1081         int timeout = 10;
1082         int batt_level;
1083
1084         CurrentBatteryLevel = -1;
1085
1086         FB61_TX_SendStatusRequest();
1087
1088         /* Wait for timeout or other error. */
1089         while (timeout && (CurrentBatteryLevel == -1)) {
1090                 if (!--timeout)
1091                         return (GE_TIMEOUT);
1092                 usleep (100000);
1093         }
1094
1095         /* Take copy in case it changes. */
1096         batt_level = CurrentBatteryLevel;
1097
1098         if (batt_level != -1) {
1099                 /* Only units we handle at present are GBU_Arbitrary */
1100                 *units = GBU_Arbitrary;
1101                 *level = batt_level;
1102                 return (GE_NONE);
1103         } else return (GE_NOLINK);
1104 }
1105
1106 GSM_Error FB61_GetPowerSource(GSM_PowerSource *source)
1107 {
1108         int timeout = 10;
1109         CurrentPowerSource=-1;
1110
1111         FB61_TX_SendStatusRequest();
1112
1113         /* Wait for timeout or other error. */
1114         while (timeout && (CurrentPowerSource == -1)) {
1115                 if (!--timeout)
1116                         return (GE_TIMEOUT);
1117                 usleep (100000);
1118         }
1119
1120         if (CurrentPowerSource != -1) {
1121                 *source = CurrentPowerSource;
1122                 return (GE_NONE);
1123         } else return (GE_NOLINK);
1124 }
1125
1126 GSM_Error FB61_GetDisplayStatus(int *Status)
1127 {
1128         unsigned char req[4]={ FB61_FRAME_HEADER, 0x51 };
1129         FB61_TX_SendMessage(4, 0x0d, req);
1130         WAIT_ON(&DisplayStatusError, 10);
1131         *Status = DisplayStatus;
1132         return (GE_NONE);
1133 }
1134
1135 GSM_Error FB61_DialVoice(char *Number)
1136 {
1137         unsigned char req[64] = {FB61_FRAME_HEADER, 0x01};
1138         unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
1139         int i = 0;
1140
1141         req[4] = strlen(Number);
1142         for(i = 0; i < strlen(Number) ; i++)
1143                 req[5+i] = Number[i];
1144         memcpy(req + 5 + strlen(Number), req_end, 10);
1145         FB61_TX_SendMessage(13 + strlen(Number), 0x01, req);
1146
1147         return(GE_NONE);
1148 }
1149
1150 /* Dial a data call - type specifies request to use: 
1151      type 0 should normally be used
1152      type 1 should be used when calling a digital line - corresponds to ats35=0
1153      Maybe one day we'll know what they mean!
1154 */
1155
1156 GSM_Error FB61_DialData(char *Number, char type, void (* callpassup)(char c))
1157 {
1158         unsigned char req[100]   = { FB61_FRAME_HEADER, 0x01 };
1159         unsigned char *req_end;
1160         unsigned char req_end0[] = { 0x01,  /* make a data call = type 0x01 */
1161                                      0x02,0x01,0x05,0x81,0x01,0x00,0x00,0x01,0x02,0x0a,
1162                                      0x07,0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00 };
1163         unsigned char req_end1[] = { 0x01,
1164                                      0x02,0x01,0x05,0x81,0x01,0x00,0x00,0x01,0x02,0x0a,
1165                                      0x07,0xa1,0x88,0x89,0x21,0x15,0x63,0xa0,0x00,0x06,
1166                                      0x88,0x90,0x21,0x48,0x40,0xbb };
1167         unsigned char req2[]     = { FB61_FRAME_HEADER, 0x42,0x05,0x01,
1168                                      0x07,0xa2,0xc8,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
1169                                      0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80,0x01,0x60 };
1170         unsigned char req3[]     = { FB61_FRAME_HEADER, 0x42,0x05,0x01,
1171                                      0x07,0xa2,0x88,0x81,0x21,0x15,0x63,0xa8,0x00,0x00,
1172                                      0x07,0xa3,0xb8,0x81,0x20,0x15,0x63,0x80 };
1173         unsigned char req4[]     = { FB61_FRAME_HEADER, 0x42,0x05,0x81,
1174                                      0x07,0xa1,0x88,0x89,0x21,0x15,0x63,0xa0,0x00,0x06,
1175                                      0x88,0x90,0x21,0x48,0x40,0xbb,0x07,0xa3,0xb8,0x81,
1176                                      0x20,0x15,0x63,0x80 };
1177
1178         int i = 0;
1179         u8 size;
1180
1181         CallPassup=callpassup;
1182
1183         switch (type) {
1184         case 0:
1185                 req_end = req_end0;
1186                 size = sizeof(req_end0);
1187                 break;
1188         case 1:
1189                 FB61_TX_SendMessage(sizeof(req3), 0x01, req3);
1190                 FB61_TX_SendMessage(sizeof(req4), 0x01, req4);
1191                 req_end = req_end1;
1192                 size = sizeof(req_end1);
1193                 break;
1194         case -1:   /* Just used to set the call passup */
1195                 return GE_NONE;
1196                 break;
1197         default:
1198                 req_end = req_end0;
1199                 size = sizeof(req_end0);
1200                 break;
1201         }
1202
1203         req[4] = strlen(Number);
1204
1205         for(i = 0; i < strlen(Number) ; i++)
1206                 req[5+i] = Number[i];
1207
1208         memcpy(req + 5 + strlen(Number), req_end, size);
1209
1210         FB61_TX_SendMessage(5 + size + strlen(Number), 0x01, req);
1211         if (type != 1) FB61_TX_SendMessage(26, 0x01, req2);
1212
1213         return (GE_NONE);
1214 }
1215
1216 GSM_Error FB61_GetIncomingCallNr(char *Number)
1217 {
1218         if (*CurrentIncomingCall != ' ') {
1219                 strcpy(Number, CurrentIncomingCall);
1220                 return GE_NONE;
1221         } else return GE_BUSY;
1222 }
1223
1224 GSM_Error FB61_CancelCall(void)
1225 {
1226         unsigned char req[] = { FB61_FRAME_HEADER, 0x08, 0x00, 0x85};
1227   
1228         req[4] = CallSequenceNumber;
1229         FB61_TX_SendMessage(6, 0x01, req);
1230   
1231         return GE_NONE;
1232 }  
1233   
1234 GSM_Error FB61_EnterSecurityCode(GSM_SecurityCode SecurityCode)
1235 {
1236         unsigned char req[15] = { FB61_FRAME_HEADER, 0x0a /* Enter code request. */, 0x00 /* Type of the entered code. */ };
1237         int i = 0;
1238         req[4] = SecurityCode.Type;
1239         for (i = 0; i < strlen(SecurityCode.Code); i++)
1240                 req[5+i] = SecurityCode.Code[i];
1241         req[5+strlen(SecurityCode.Code)] = 0x00;
1242         req[6+strlen(SecurityCode.Code)] = 0x00;
1243         FB61_TX_SendMessage(7+strlen(SecurityCode.Code), 0x08, req);
1244         return wait_on(&CurrentSecurityCodeError, 20);
1245 }
1246
1247 GSM_Error FB61_GetSecurityCodeStatus(int *Status)
1248 {
1249         unsigned char req[4] = { FB61_FRAME_HEADER, 0x07 };
1250         CurrentSecurityCodeStatus=Status;
1251         FB61_TX_SendMessage(4, 0x08, req);
1252         return wait_on(&CurrentSecurityCodeError, 20);
1253 }
1254
1255 GSM_Error FB61_GetDateTime(GSM_DateTime *date_time)
1256 {
1257         unsigned char req[] = {FB61_FRAME_HEADER, 0x62};
1258         CurrentDateTime = date_time;
1259         FB61_TX_SendMessage(4, 0x11, req);
1260         return wait_on(&CurrentDateTimeError, 5);
1261 }
1262
1263 GSM_Error FB61_GetAlarm(int alarm_number, GSM_DateTime *date_time)
1264 {
1265         unsigned char req[] = {FB61_FRAME_HEADER, 0x6d};
1266         CurrentAlarm = date_time;
1267         FB61_TX_SendMessage(4, 0x11, req);
1268         return wait_on(&CurrentAlarmError, 5);
1269 }
1270
1271 /* This function sends to the mobile phone a request for the SMS Center */
1272
1273 GSM_Error FB61_GetSMSCenter(GSM_MessageCenter *MessageCenter)
1274 {
1275         unsigned char req[10] = { FB61_FRAME_HEADER, 0x33, 0x64, 0x00 /* SMS Center Number. */ };
1276         req[5] = MessageCenter->No;
1277         CurrentMessageCenter = MessageCenter;
1278         FB61_TX_SendMessage(6, 0x02, req);
1279         return wait_on(&CurrentMessageCenterError, 10);
1280 }
1281
1282 /* This function set the SMS Center profile on the phone. */
1283
1284 GSM_Error FB61_SetSMSCenter(GSM_MessageCenter *MessageCenter)
1285 {
1286         unsigned char req[64] = { FB61_FRAME_HEADER, 0x30, 0x64,
1287                                   0x00, /* SMS Center Number. */
1288                                   0x00, /* Unknown. */
1289                                   0x00, /* SMS Message Format. */
1290                                   0x00, /* Unknown. */
1291                                   0x00, /* Validity. */
1292                                   0,0,0,0,0,0,0,0,0,0,0,0, /* Unknown. */
1293                                   0,0,0,0,0,0,0,0,0,0,0,0 /* Message Center Number. */
1294                                   /* Message Center Name. */
1295         };
1296         req[5] = MessageCenter->No;
1297         req[7] = MessageCenter->Format;
1298         req[9] = MessageCenter->Validity;
1299
1300         req[22] = SemiOctetPack(MessageCenter->Number, req+23);
1301         if (req[22] % 2) req[22]++;
1302         req[22] = req[22] / 2 + 1;
1303
1304         sprintf(req+34, "%s", MessageCenter->Name);
1305
1306         CurrentMessageCenter = MessageCenter;
1307         CurrentMessageCenterError = GE_BUSY;
1308
1309         FB61_TX_SendMessage(35+strlen(MessageCenter->Name), 0x02, req);
1310         return wait_on(&CurrentMessageCenterError,20);
1311 }
1312
1313 GSM_Error FB61_GetSMSStatus(GSM_SMSStatus *Status)
1314 {
1315         unsigned char req[] = {FB61_FRAME_HEADER, 0x36, 0x64};
1316         CurrentSMSStatus = Status;
1317         FB61_TX_SendMessage(5, 0x14, req);
1318         return wait_on(&CurrentSMSStatusError,20);
1319 }
1320
1321 GSM_Error FB61_GetIMEI(char *imei)
1322 {
1323         if (*IMEI) {
1324                 strncpy (imei, IMEI, FB61_MAX_IMEI_LENGTH);
1325                 return (GE_NONE);
1326         } else return (GE_TRYAGAIN);
1327 }
1328
1329 GSM_Error FB61_GetRevision(char *revision)
1330 {
1331         if (*Revision) {
1332                 strncpy (revision, Revision, FB61_MAX_REVISION_LENGTH);
1333                 return (GE_NONE);
1334         } else return (GE_TRYAGAIN);
1335 }
1336
1337 GSM_Error FB61_GetModel(char *model)
1338 {
1339         if (*Model) {
1340                 strncpy (model, Model, FB61_MAX_MODEL_LENGTH);
1341                 return (GE_NONE);
1342         } else return (GE_TRYAGAIN);
1343 }
1344
1345 GSM_Error FB61_SetDateTime(GSM_DateTime *date_time)
1346 {
1347         unsigned char req[] = { FB61_FRAME_HEADER,
1348                                 0x60, /* set-time subtype */
1349                                 0x01, 0x01, 0x07, /* unknown */
1350                                 0x00, 0x00, /* Year (0x07cf = 1999) */
1351                                 0x00, 0x00, /* Month Day */
1352                                 0x00, 0x00, /* Hours Minutes */
1353                                 0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */
1354         };
1355         req[7] = date_time->Year / 256;
1356         req[8] = date_time->Year % 256;
1357         req[9] = date_time->Month;
1358         req[10] = date_time->Day;
1359         req[11] = date_time->Hour;
1360         req[12] = date_time->Minute;
1361
1362         FB61_TX_SendMessage(14, 0x11, req);
1363         return wait_on(&CurrentSetDateTimeError, 20);
1364 }
1365
1366 /* FIXME: we should also allow to set the alarm off :-) */
1367
1368 GSM_Error FB61_SetAlarm(int alarm_number, GSM_DateTime *date_time)
1369 {
1370         unsigned char req[] = { FB61_FRAME_HEADER,
1371                                 0x6b, /* set-alarm subtype */
1372                                 0x01, 0x20, 0x03, /* unknown */
1373                                 0x02,       /* should be alarm on/off, but it don't works */
1374                                 0x00, 0x00, /* Hours Minutes */
1375                                 0x00 /* Unknown, but not seconds - try 59 and wait 1 sec. */
1376         };
1377         req[8] = date_time->Hour;
1378         req[9] = date_time->Minute;
1379
1380         FB61_TX_SendMessage(11, 0x11, req);
1381         return wait_on(&CurrentSetAlarmError, 20);
1382 }
1383
1384 /* Routine to get specifed phone book location.  Designed to be called by
1385    application.  Will block until location is retrieved or a timeout/error
1386    occurs. */
1387
1388 GSM_Error FB61_GetMemoryLocation(GSM_PhonebookEntry *entry)
1389 {
1390         unsigned char req[] = {FB61_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00};
1391
1392         CurrentPhonebookEntry = entry;
1393         req[4] = FB61_GetMemoryType(entry->MemoryType);
1394         req[5] = entry->Location;
1395         FB61_TX_SendMessage(7, 0x03, req);
1396         return wait_on(&CurrentPhonebookError, 20);
1397 }
1398
1399 /* Routine to write phonebook location in phone. Designed to be called by
1400    application code. Will block until location is written or timeout
1401    occurs. */
1402
1403 GSM_Error FB61_WritePhonebookLocation(GSM_PhonebookEntry *entry)
1404 {
1405         unsigned char req[128] = { FB61_FRAME_HEADER, 0x04, 0x00, 0x00 };
1406         int i = 0, current = 0;
1407
1408         req[4] = FB61_GetMemoryType(entry->MemoryType);
1409         req[5] = entry->Location;
1410
1411         req[6] = strlen(entry->Name);
1412
1413         current = 7;
1414
1415         for (i = 0; i<strlen(entry->Name); i++)
1416                 req[current+i] = entry->Name[i];
1417
1418         current += strlen(entry->Name);
1419
1420         req[current++] = strlen(entry->Number);
1421
1422         for (i = 0; i < strlen(entry->Number); i++)
1423                 req[current+i] = entry->Number[i];
1424
1425         current += strlen(entry->Number);
1426
1427         /* Jano: This allow to save 14 characters name into SIM memory, when
1428            No Group is selected. */
1429
1430         if (entry->Group == 5)
1431                 req[current++] = 0xff;
1432         else
1433                 req[current++] = entry->Group;
1434
1435         FB61_TX_SendMessage(current, 3, req);
1436         return wait_on(&CurrentPhonebookError, 50);
1437 }
1438
1439 GSM_Error FB61_NetMonitor(unsigned char mode, char *Screen)
1440 {
1441         unsigned char req1[] = { 0x00, 0x01, 0x64, 0x01 };
1442         unsigned char req2[] = { 0x00, 0x01, 0x7e, 0x00 };
1443
1444         CurrentNetmonitor = Screen;
1445         FB61_TX_SendMessage(4, 0x40, req1);
1446         req2[3] = mode;
1447         FB61_TX_SendMessage(4, 0x40, req2);
1448         return wait_on(&CurrentNetmonitorError, 20);
1449 }
1450
1451 GSM_Error FB61_SendDTMF(char *String)
1452 {
1453         unsigned char req[64] = { FB61_FRAME_HEADER, 0x50, 0x00 /* Length of DTMF string. */ };
1454         u8 length=strlen(String);
1455
1456         req[4] = length;
1457         sprintf(req+5, "%s", String);
1458         FB61_TX_SendMessage(5+length, 0x01, req);
1459         return (GE_NONE);
1460 }
1461
1462 GSM_Error FB61_GetSpeedDial(GSM_SpeedDial *entry)
1463 {
1464         unsigned char req[10] = { FB61_FRAME_HEADER, 0x16, 0x00  /* The number of speed dial. */ };
1465         CurrentSpeedDialEntry = entry;
1466         req[4] = entry->Number;
1467         FB61_TX_SendMessage(5, 0x03, req);
1468         return wait_on(&CurrentSpeedDialError, 20);
1469 }
1470
1471 GSM_Error FB61_SetSpeedDial(GSM_SpeedDial *entry)
1472 {
1473         unsigned char req[7] = { FB61_FRAME_HEADER, 0x19, 0x00 /* Number */, 0x00 /* Memory Type */, 0x00  /* Location */ };
1474         req[4] = entry->Number;
1475         req[5] = entry->MemoryType;
1476         req[6] = entry->Location;
1477         FB61_TX_SendMessage(7, 0x03, req);
1478         return wait_on(&CurrentSpeedDialError, 20);
1479 }
1480
1481 GSM_Error FB61_GetSMSMessage(GSM_SMSMessage *message)
1482 {
1483         unsigned char req[10] = { FB61_FRAME_HEADER, 0x07, 0x02 /* Unknown */, 0x00 /* Location */, 0x01, 0x64};
1484         int timeout = 60;
1485
1486         /* State machine code writes data to these variables when it comes in. */
1487
1488         CurrentSMSMessage = message;
1489         CurrentSMSMessageError = GE_BUSY;
1490         req[5] = message->Location;
1491         FB61_TX_SendMessage(8, 0x02, req);
1492
1493         while (timeout && (CurrentSMSMessageError == GE_BUSY || CurrentSMSMessageError == GE_SMSWAITING)) {
1494                 if (!--timeout)
1495                         return (GE_TIMEOUT);
1496                 usleep (100000);
1497         }
1498         return (CurrentSMSMessageError);
1499 }
1500
1501 GSM_Error FB61_DeleteSMSMessage(GSM_SMSMessage *message)
1502 {
1503         unsigned char req[] = {FB61_FRAME_HEADER, 0x0a, 0x02, 0x00};
1504         CurrentSMSMessageError = GE_BUSY;
1505         req[5] = message->Location;
1506         FB61_TX_SendMessage(6, 0x14, req);
1507         return wait_on(&CurrentSMSMessageError, 50);
1508 }
1509
1510 /* The second argument is the size of the data in octets,
1511    excluding User Data Header - important only for 8bit data */
1512 GSM_Error FB61_SendSMSMessage(GSM_SMSMessage *SMS)
1513 {
1514         GSM_Error error;
1515
1516         unsigned char req[256] = {
1517                 FB61_FRAME_HEADER,
1518                 0x01, 0x02, 0x00, /* SMS send request*/
1519                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* SMS center, the rest is unused */
1520                 0x11, /*  0 - TP-Reply-Path (9.2.3.17)
1521                           0 - TP-TP-User-Data-Header-Indicator (9.2.3.23)
1522                           x - TP-Status-Report-Request (9.2.3.5)
1523                           0 - no delivery report (default for gnokii)
1524                           1 - request for delivry report
1525                           xx - TP validity period (9.2.3.3, see also 9.2.3.12)
1526                           00 - not present
1527                           10 - relative format (default for gnokii)
1528                           01 - enhanced format
1529                           11 - absolute format
1530                           no support for this field yet
1531                           0 - TP-Reject-Duplicates (9.2.3.25)
1532                           01 - TP-Message-Type-Indicator (9.2.3.1) - SMS_SUBMIT */
1533                 0x00, /* TP-Message-Reference (9.2.3.6) */
1534                 0x00, /* TP-Protocol-Identifier (9.2.3.9) */
1535                 0x00, /* TP-Data-Coding-Scheme (9.2.3.10, GSM 03.38) */
1536                 0x00, /* TP-User-Data-Length (9.2.3.16) */
1537                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* destination */
1538                 0xa9, /* SMS validity: b0=1h 47=6h a7=24h a9=72h ad=1week */
1539                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1540         };
1541
1542         int size, offset;
1543
1544         /* First of all we should get SMSC number */
1545         if (SMS->MessageCenter.No) {
1546                 error = FB61_GetSMSCenter(&SMS->MessageCenter);
1547                 if (error != GE_NONE)
1548                         return error;
1549                 SMS->MessageCenter.No = 0;
1550         }
1551         dprintf(_("Sending SMS to %s via message center %s\n"), SMS->Destination, SMS->MessageCenter.Number);
1552
1553         if (SMS->UDHPresent) {
1554                 /* offset - length of the user data header */
1555                 offset = 1 + SMS->UDH[0];
1556                 /* we copy the udh and set the mask for the indicator */
1557                 memcpy(req + 42, SMS->UDH, offset);
1558                 req[18] |= 0x40;
1559         } else {
1560                 offset = 0;
1561                 /* such messages should be sent as concatenated */
1562                 if (strlen(SMS->MessageText) > GSM_MAX_SMS_LENGTH)
1563                         return(GE_SMSTOOLONG);
1564         }
1565
1566         /* size is the length of the data in octets including udh */
1567         /* req[22] is:
1568            - integer representation of the number od octets within the user data when UD is coded using 8bit data
1569            - the sum of the number of septets in UDH including any padding and number of septets in UD in other case
1570         */
1571
1572         size = offset;
1573   
1574         /* offset now denotes UDH length */
1575         if (SMS->EightBit) {
1576                 memcpy(req + 42 + offset, SMS->MessageText, SMS->MessageTextLength);
1577                 /* the mask for the 8-bit data */
1578                 req[21] |= 0xf4;
1579                 size += SMS->MessageTextLength;
1580                 req[22] = size;
1581         } else {
1582                 size += PackSevenBitsToEight((7-offset)%7, SMS->MessageText, req + 42 + offset);
1583                 req[22] = (offset*8 +6/*round-up*/)/7 +strlen(SMS->MessageText)*7;
1584         }
1585
1586         CurrentSMSMessageError=GE_BUSY;
1587
1588         req[6] = SemiOctetPack(SMS->MessageCenter.Number, req+7);
1589         if (req[6] % 2) req[6]++;
1590
1591         req[6] = req[6] / 2 + 1;
1592
1593         /* Mask for request for delivery report from SMSC */
1594         if (SMS->Type == GST_DR) req[18] |= 0x20;
1595  
1596         /* Message Class */
1597         switch (SMS->Class) {
1598         case 0: req[21] |= 0xf0; break;
1599         case 1: req[21] |= 0xf1; break;
1600         case 2: req[21] |= 0xf2; break;
1601         case 3: req[21] |= 0xf3; break;
1602         default: break;
1603         }
1604   
1605         /* Mask for compression */
1606         /* FIXME: support for compression */
1607         /* See GSM 03.42 */
1608 /*  if (SMS->Compression) req[21] = req[21] | 0x20; */
1609
1610         req[23] = SemiOctetPack(SMS->Destination, req+24);
1611
1612         /* TP-Validity Period handling */
1613         req[35] = SMS_Validity_to_VP(SMS->Validity);
1614
1615         FB61_TX_SendMessage(42+size, 0x02, req);
1616         return wait_on(&CurrentSMSMessageError, 70);
1617 }
1618
1619 /* FIXME: UDH & EightBit not implemented yet */
1620 GSM_Error FB61_SaveSMSMessage(GSM_SMSMessage *SMS)
1621 {
1622         unsigned char req[256] = {
1623                 FB61_FRAME_HEADER,
1624                 0x04, 0x05, 0x02, 0x00, 0x02, /* SMS save request*/
1625                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* SMS center, the rest is unused */
1626                 0x11, /*  0 - TP-Reply-Path (9.2.3.17)
1627                           0 - TP-TP-User-Data-Header-Indicator (9.2.3.23)
1628                           x - TP-Status-Report-Request (9.2.3.5)
1629                           0 - no delivery report (default for gnokii)
1630                           1 - request for delivry report
1631                           xx - TP validity period (9.2.3.3, see also 9.2.3.12)
1632                           00 - not present
1633                           10 - relative format (default for gnokii)
1634                           01 - enhanced format
1635                           11 - absolute format
1636                           no support for this field yet
1637                           0 - TP-Reject-Duplicates (9.2.3.25)
1638                           01 - TP-Message-Type-Indicator (9.2.3.1) - SMS_SUBMIT */
1639                 0x00, /* TP-Message-Reference (9.2.3.6) */
1640                 0x00, /* TP-Protocol-Identifier (9.2.3.9) */
1641                 0x00, /* TP-Data-Coding-Scheme (9.2.3.10, GSM 03.38) */
1642                 0x00, /* TP-User-Data-Length (9.2.3.16) */
1643                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* destination */
1644                 0xa9, /* SMS validity: b0=1h 47=6h a7=24h a9=72h ad=1week */
1645                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1646         };
1647
1648         int size, offset;
1649
1650         if (SMS->Status == GSS_NOTSENTREAD)
1651                 req[4] |= 0x02;
1652
1653         if (SMS->Location)
1654                 req[6] = SMS->Location;
1655
1656         offset = 0;
1657         /* such messages should be sent as concatenated */
1658         if (strlen(SMS->MessageText) > GSM_MAX_SMS_LENGTH)
1659                 return(GE_SMSTOOLONG);
1660
1661         /* size is the length of the data in octets including udh */
1662         /* req[24] is:
1663            - integer representation of the number od octets within the user data when UD is coded using 8bit data
1664            - the sum of the number of septets in UDH including any padding and number of septets in UD in other case
1665         */
1666   
1667         /* offset now denotes UDH length */
1668         size = PackSevenBitsToEight((7-offset)%7, SMS->MessageText, req + 44 + offset);
1669         size += offset;
1670
1671         req[24] = (offset*8 + ((7-offset)%7)) / 7 + strlen(SMS->MessageText);
1672
1673         FB61_TX_SendMessage(44+size, 0x14, req);
1674         return wait_on(&CurrentSMSMessageError, 70);
1675 }
1676
1677 /* Enable and disable Cell Broadcasting */
1678
1679 GSM_Error FB61_EnableCellBroadcast(void)
1680 {
1681         unsigned char req[] = {FB61_FRAME_HEADER, 0x20, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01};
1682         CurrentCBError = GE_BUSY;
1683
1684         CurrentCBMessage = (GSM_CBMessage *)malloc(sizeof (GSM_CBMessage));
1685         CurrentCBMessage->Channel = 0;
1686         CurrentCBMessage->New = false;
1687         strcpy (CurrentCBMessage->Message,"");
1688         FB61_TX_SendMessage(10, 0x02, req);
1689         return wait_on(&CurrentCBError, 20);
1690 }
1691
1692 GSM_Error FB61_DisableCellBroadcast(void) /* Should work, but not tested fully */
1693 {
1694         unsigned char req[] = {FB61_FRAME_HEADER, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; /*VERIFY*/
1695         FB61_TX_SendMessage(10, 0x02, req);
1696         return wait_on(&CurrentCBError, 20);
1697 }
1698
1699 GSM_Error FB61_ReadCellBroadcast(GSM_CBMessage *Message)
1700 {
1701         if (CurrentCBMessage != NULL) {
1702                 if (CurrentCBMessage->New == true) {
1703                         Message->Channel = CurrentCBMessage->Channel;
1704                         strcpy(Message->Message,CurrentCBMessage->Message);
1705                         CurrentCBMessage->New = false;
1706                         return (GE_NONE);
1707                 }
1708         }
1709         return (GE_NONEWCBRECEIVED);
1710 }
1711
1712 /* Send a bitmap or welcome-note */
1713
1714 GSM_Error FB61_SetBitmap(GSM_Bitmap *Bitmap)
1715 {
1716         unsigned char req[600] = { FB61_FRAME_HEADER };
1717         u16 count = 3;
1718         u8 textlen;
1719
1720         switch (Bitmap->type) {
1721         case GSM_WelcomeNoteText:
1722                 req[count++] = 0x18;
1723                 req[count++] = 0x01; /* Only one block */
1724                 req[count++] = 0x02; /* Welcome text */
1725                 req[count++] = textlen = strlen(Bitmap->text);
1726                 memcpy(req+count, Bitmap->text, textlen);
1727       
1728                 count += textlen;
1729                 FB61_TX_SendMessage(count, 0x05, req);
1730                 break;
1731
1732         case GSM_DealerNoteText:
1733                 req[count++] = 0x18;
1734                 req[count++] = 0x01; /* Only one block */
1735                 req[count++] = 0x03; /* Dealer Welcome Note */
1736                 req[count++] = textlen = strlen(Bitmap->text);
1737                 memcpy(req+count, Bitmap->text, textlen);
1738       
1739                 count += textlen;
1740                 FB61_TX_SendMessage(count, 0x05, req);
1741                 break;
1742
1743         case GSM_StartupLogo:
1744                 req[count++] = 0x18;
1745                 req[count++] = 0x01; /* Only one block */
1746                 req[count++] = 0x01;
1747                 req[count++] = Bitmap->height;
1748                 req[count++] = Bitmap->width;
1749                 memcpy(req+count, Bitmap->bitmap, Bitmap->size);
1750                 count += Bitmap->size;
1751                 FB61_TX_SendMessage(count, 0x05, req);
1752                 break;
1753
1754         case GSM_OperatorLogo:
1755                 req[count++] = 0x30;  /* Store Op Logo */
1756                 req[count++] = 0x01;  /* Location */
1757                 req[count++] = ((Bitmap->netcode[1] & 0x0f) << 4) | (Bitmap->netcode[0] & 0x0f);
1758                 req[count++] = 0xf0 | (Bitmap->netcode[2] & 0x0f);
1759                 req[count++] = ((Bitmap->netcode[5] & 0x0f) << 4) | (Bitmap->netcode[4] & 0x0f);
1760                 req[count++] = (Bitmap->size+4) >> 8;
1761                 req[count++] = (Bitmap->size+4)%0xff;
1762                 req[count++] = 0x00;  /* Infofield */
1763                 req[count++] = Bitmap->width;
1764                 req[count++] = Bitmap->height;
1765                 req[count++] = 0x01;  /* Just BW */    
1766                 memcpy(req+count, Bitmap->bitmap, Bitmap->size);
1767                 FB61_TX_SendMessage(count+Bitmap->size, 0x05, req);
1768                 break;
1769
1770         case GSM_CallerLogo:
1771                 req[count++] = 0x13;
1772                 req[count++] = Bitmap->number;
1773                 req[count++] = strlen(Bitmap->text);
1774                 memcpy(req+count, Bitmap->text, req[count-1]);
1775                 count += req[count-1];
1776                 req[count++]= Bitmap->ringtone;
1777                 req[count++]= 0x01;  /* Graphic on. You can use other values as well:
1778                                         0x00 - Off
1779                                         0x01 - On
1780                                         0x02 - View Graphics
1781                                         0x03 - Send Graphics
1782                                         0x04 - Send via IR
1783                                         You can even set it higher but Nokia phones (my
1784                                         6110 at least) will not show you the name of this
1785                                         item in menu ;-)) Nokia is really joking here. */
1786                 req[count++] = (Bitmap->size + 4) >> 8;
1787                 req[count++] = (Bitmap->size + 4) % 0xff;
1788                 req[count++] = 0x00;  /* Future extensions! */
1789                 req[count++] = Bitmap->width;
1790                 req[count++] = Bitmap->height;
1791                 req[count++] = 0x01;  /* Just BW */
1792                 memcpy(req+count, Bitmap->bitmap, Bitmap->size);
1793                 FB61_TX_SendMessage(count+Bitmap->size, 0x03, req);
1794                 break;
1795
1796         case GSM_PictureImage:
1797                 return (GE_NOTIMPLEMENTED);
1798                 break;
1799
1800         case GSM_None:
1801                 break;
1802         }
1803         return wait_on(&SetBitmapError, 70);
1804 }
1805
1806 /* Get a bitmap from the phone */
1807
1808 GSM_Error FB61_GetBitmap(GSM_Bitmap *Bitmap)
1809 {
1810         unsigned char req[10] = { FB61_FRAME_HEADER };
1811         u8 count = 3;
1812         int timeout = 10;
1813
1814         GetBitmap = Bitmap;
1815         GetBitmapError = GE_BUSY;
1816  
1817         /* This is needed to avoid the packet being interrupted */
1818         /* Remove when multipacket code is implemented fully */
1819
1820         DisableKeepalive = true;
1821
1822         while (timeout && (MessagesSent != AcksReceived)) {
1823                 usleep(100000);
1824                 timeout--;
1825         }
1826
1827         /* We'll assume that nothing more will be received after 1 sec */
1828
1829         MessagesSent = AcksReceived;
1830
1831         switch (GetBitmap->type) {
1832         case GSM_StartupLogo:
1833                 req[count++] = 0x16;
1834                 FB61_TX_SendMessage(count, 0x05, req);
1835                 break;
1836         case GSM_WelcomeNoteText:
1837                 req[count++] = 0x16;
1838                 FB61_TX_SendMessage(count, 0x05, req);
1839                 break;
1840         case GSM_DealerNoteText:
1841                 req[count++] = 0x16;
1842                 FB61_TX_SendMessage(count, 0x05, req);
1843                 break;  
1844         case GSM_OperatorLogo:
1845                 req[count++] = 0x33;
1846                 req[count++] = 0x01; /* Location 1 */
1847                 FB61_TX_SendMessage(count, 0x05, req);
1848                 break;
1849         case GSM_CallerLogo:
1850                 req[count++] = 0x10;
1851                 req[count++] = Bitmap->number;
1852                 FB61_TX_SendMessage(count, 0x03, req);
1853                 break;
1854         default:
1855                 break;
1856         }
1857
1858         /* 5secs for the command to complete */
1859   
1860         WAIT_ON(&GetBitmapError, 50);
1861
1862         DisableKeepalive = false;
1863         GetBitmap = NULL;
1864         return (GetBitmapError);
1865 }
1866
1867
1868 GSM_Error FB61_SetRingTone(GSM_Ringtone *ringtone)
1869 {
1870         char package[GSM_MAX_RINGTONE_PACKAGE_LENGTH+10] =
1871         { 0x0c, 0x01, /* FBUS RingTone header */
1872           /* Next bytes are from Smart Messaging Specification version 2.0.0 */
1873           0x06,       /* User Data Header Length */
1874           0x05,       /* IEI FIXME: What is this? */
1875           0x04,       /* IEDL FIXME: What is this? */
1876           0x15, 0x81, /* Destination port */
1877           0x15, 0x81  /* Originator port, only
1878                          to fill in the two
1879                          bytes :-) */
1880         };
1881         int size = GSM_MAX_RINGTONE_PACKAGE_LENGTH;
1882         GSM_PackRingtone(ringtone, package+9, &size);
1883         package[size+9] = 0x01;
1884         FB61_TX_SendMessage((size+10), 0x12, package);
1885         return (GE_NONE);
1886 }
1887
1888 GSM_Error FB61_Reset(unsigned char type)
1889 {
1890         unsigned char req[4] = { 0x00,0x01,0x64,0x03 };
1891         req[3] = type;
1892         FB61_TX_SendMessage(4, 0x40, req);
1893         return (GE_NONE);
1894 }
1895
1896 #ifndef WIN32
1897
1898 void FB61_DumpSerial(void)
1899 {
1900         int PortFD;
1901         unsigned int Flags=0;
1902
1903         PortFD = device_getfd();
1904         ioctl(PortFD, TIOCMGET, &Flags);
1905
1906         dprintf(_("Serial flags dump:\n"));
1907         dprintf(_("DTR is %s.\n"), Flags&TIOCM_DTR?_("up"):_("down"));
1908         dprintf(_("RTS is %s.\n"), Flags&TIOCM_RTS?_("up"):_("down"));
1909         dprintf(_("CAR is %s.\n"), Flags&TIOCM_CAR?_("up"):_("down"));
1910         dprintf(_("CTS is %s.\n"), Flags&TIOCM_CTS?_("up"):_("down"));
1911         dprintf("\n");
1912 }
1913
1914 /* This functions set up the Nokia DAU-9P MBus Cable NSE-3 which is probably
1915    dual MBUS/FBUS to FBUS communication. If we skip this step we can
1916    communicate with the phone, but the phone sends us some garbagge (0x18 0x00
1917    ...).
1918
1919    This was brought to my attention by people with original cable. My cable is
1920    FBUS only so I borrow the original cable from my friend and solve
1921    it. Thanks to Cobus, Juan and people on the mailing list.
1922
1923    Colin wrote:
1924
1925    The data suite cable has some electronics built into the connector. This of
1926    course needs a power supply of some sorts to operate properly.
1927
1928    In this case power is drawn off the handshaking lines of the PC. DTR has to
1929    be set and RTS have to be cleared, thus if you use a terminal program (that
1930    does not set the handshaking lines to these conditions) you will get weird
1931    results. It will not set them like this since if Request To Send (RTS) is
1932    not set the other party will not send any data (in hardware handshaking)
1933    and if DTS is not set (handshaking = none) the cable will not receive
1934    power. */
1935
1936 /* FIXME: In this function we use ioctls - can people with different OSes than
1937    my (Linux) tell me if it works for them? */
1938
1939 void FB61_SetFBUS(void)
1940 {
1941 #ifdef DEBUG
1942         FB61_DumpSerial();  
1943         dprintf(_("Setting FBUS communication...\n"));
1944 #endif
1945
1946         /* clearing the RTS bit and setting the DTR bit*/
1947         device_setdtrrts(1, 0);
1948
1949 #ifdef DEBUG
1950         FB61_DumpSerial();  
1951 #endif /* DEBUG */
1952 }
1953
1954 /* Called by initialisation code to open comm port in asynchronous mode. */
1955
1956 bool FB61_OpenSerial(void)
1957 {
1958         int result;
1959   
1960 #if __unices__
1961         int rtn;
1962 #else
1963         struct sigaction sig_io;
1964
1965         /* Set up and install handler before enabling async IO on port. */
1966
1967         sig_io.sa_handler = FB61_SigHandler;
1968         sig_io.sa_flags = 0;
1969         sigaction (SIGIO, &sig_io, NULL);
1970 #endif
1971
1972         /* Open device. */
1973
1974         result = device_open(PortDevice, false, true, false, GCT_Serial);
1975
1976         if (!result) {
1977                 perror(_("Couldn't open FB61 device"));
1978                 return false;
1979         }
1980
1981 #if __unices__
1982         /* create a thread to handle incoming data from mobile phone */
1983         rtn = pthread_create(&selThread, NULL, (void*)FB61_SelectLoop, (void*)NULL);
1984         if (rtn != 0) return false;
1985 #endif
1986
1987         device_changespeed(115200);
1988         FB61_SetFBUS();
1989         return (true);
1990 }
1991
1992 void FB61_SigHandler(int status)
1993 {
1994         unsigned char buffer[255];
1995         int count, res;
1996         res = device_read(buffer, 255);
1997         for (count = 0; count < res ; count ++)
1998                 FB61_RX_StateMachine(buffer[count]);
1999 }
2000 #endif /* WIN32 */
2001
2002 char *FB61_GetPackedDateTime(u8 *Number)
2003 {
2004         static char Buffer[20] = "";
2005
2006         sprintf(Buffer, "%d%d-", Number[0] & 0xf, Number[0] >> 4);
2007         sprintf(Buffer, "%s%d%d-", Buffer, Number[1] & 0xf, Number[1] >> 4);
2008         sprintf(Buffer, "%s%d%d ", Buffer, Number[2] & 0xf, Number[2] >> 4);
2009         sprintf(Buffer, "%s%d%d:", Buffer, Number[3] & 0xf, Number[3] >> 4);
2010         sprintf(Buffer, "%s%d%d:", Buffer, Number[4] & 0xf, Number[4] >> 4);
2011         sprintf(Buffer, "%s%d%d",  Buffer, Number[5] & 0xf, Number[5] >> 4);
2012   
2013         return Buffer;
2014 }
2015
2016 enum FB61_RX_States FB61_RX_DispatchMessage(void)
2017 {
2018         int i, tmp, count, offset, off, length;
2019         unsigned char output[160];
2020         bool supported;
2021
2022         if (RX_Multiple) return FB61_RX_Sync;
2023
2024 #ifdef DEBUG
2025         /* Do not debug Ack and RLP frames to detail. */
2026
2027         if (MessageType != FB61_FRTYPE_ACK && MessageType != 0xf1)
2028                 FB61_RX_DisplayMessage();
2029 #endif /* DEBUG */
2030
2031         /* Switch on the basis of the message type byte */
2032         switch (MessageType) {
2033         case 0x01:    /* Call information */
2034                 switch (MessageBuffer[3]) {
2035                         /* Unknown message - it has been seen after the 0x07 message (call
2036                            answered). Probably it has similar meaning. If you can solve
2037                            this - just mail me. Pavel Janík ml.
2038
2039                            The message looks like this:
2040
2041                            Msg Destination: PC
2042                            Msg Source: Phone
2043                            Msg Type: 01
2044                            Msg Unknown: 00
2045                            Msg Len: 0e
2046
2047                            Phone: [01 ][08 ][00 ] is the header of the frame
2048
2049                            [03 ] is the call message subtype
2050
2051                            [05 ] is the call sequence number
2052
2053                            [05 ] unknown 
2054
2055                            [00 ][01 ][03 ][02 ][91][00] are unknown but has been
2056                            seen in the Incoming call message (just after the
2057                            caller's name from the phonebook). But never change
2058                            between phone calls :-(
2059                         */
2060
2061                 case 0x02: /* This may mean sequence number of 'just made' call - CK */
2062                         dprintf(_("Message: Call message, type 0x02:"));
2063                         dprintf(_("   Exact meaning not known yet, sorry :-(\n"));
2064                         break;
2065
2066                 case 0x03: /* Possibly call OK */
2067 /* JD: I think that this means "call in progress" (incomming or outgoing) */
2068                         dprintf(_("Message: Call message, type 0x03:"));
2069                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2070                         dprintf(_("   Exact meaning not known yet, sorry :-(\n"));
2071                         CallSequenceNumber = MessageBuffer[4];
2072                         CurrentIncomingCall[0] = 'D';
2073                         if (CallPassup) CallPassup('D');
2074                         break;
2075
2076                         /* Remote end has gone away before you answer the call.  Probably your
2077                            mother-in-law or banker (which is worse?) ... */
2078                 case 0x04:
2079                         dprintf(_("Message: Remote end hang up.\n"));
2080                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2081                         CurrentIncomingCall[0] = ' ';
2082                         if (CallPassup) CallPassup(' ');
2083                         break;
2084
2085                 case 0x05: /* Incoming call alert */
2086                         dprintf(_("Message: Incoming call alert:\n"));
2087                         /* We can have more then one call ringing - we can distinguish between
2088                            them */
2089                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2090                         dprintf(_("   Number: "));
2091                         count = MessageBuffer[6];
2092                         for (tmp = 0; tmp < count; tmp++)
2093                                 dprintf("%c", MessageBuffer[7+tmp]);
2094                         dprintf("\n");
2095                         dprintf(_("   Name: "));
2096                         for (tmp = 0; tmp < MessageBuffer[7+count]; tmp++)
2097                                 dprintf("%c", MessageBuffer[8+count+tmp]);
2098                         dprintf("\n");
2099                         count = MessageBuffer[6];
2100                         CurrentIncomingCall[0] = 0;
2101                         for (tmp = 0; tmp < count; tmp++)
2102                                 sprintf(CurrentIncomingCall, "%s%c", CurrentIncomingCall, MessageBuffer[7+tmp]);
2103                         if (CallPassup) CallPassup(MessageBuffer[4]);
2104                         break;
2105
2106                         /* Call answered. Probably your girlfriend...*/
2107                 case 0x07:
2108                         dprintf(_("Message: Call answered.\n"));
2109                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2110                         break;
2111
2112                         /* Call ended. Girlfriend is girlfriend, but time is money :-) */
2113                 case 0x09:
2114                         dprintf(_("Message: Call ended by your phone.\n"));
2115                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2116                         break;
2117
2118                         /* This message has been seen with the message of subtype 0x09
2119                            after I hang the call.
2120
2121                            Msg Destination: PC
2122                            Msg Source: Phone
2123                            Msg Type: 01
2124                            Msg Unknown: 00
2125                            Msg Len: 08
2126                            Phone: [01 ][08 ][00 ][0a ][04 ][87 ][01 ][42B][1a ][c2 ]
2127
2128                            What is the meaning of 87? Can you spell some magic light into
2129                            this issue?
2130
2131                         */
2132
2133                 case 0x0a: /* Probably means call over - CK */
2134                         dprintf(_("Message: Call message, type 0x0a:"));
2135                         dprintf(_("   Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2136                         dprintf(_("   Exact meaning not known yet, sorry :-(\n"));
2137
2138                         CurrentIncomingCall[0] = ' ';
2139                         if (CallPassup) CallPassup(' ');
2140                         break;
2141
2142                 default:
2143                         dprintf(_("Message: Unknown message of type 0x01\n"));
2144                         break;
2145                 }
2146                 break;
2147
2148                 /* SMS handling */
2149
2150         case 0x02:
2151                 switch (MessageBuffer[3]) {
2152                 case 0x02: /* SMS message correctly sent to the network */
2153                         dprintf(_("Message: SMS Message correctly sent.\n"));
2154                         CurrentSMSMessageError = GE_SMSSENDOK;
2155                         break;
2156
2157                 case 0x03: /* SMS message send to the network failed */
2158                         dprintf(_("Message: Sending SMS Message failed.\n"));
2159                         CurrentSMSMessageError = GE_SMSSENDFAILED;
2160                         break;
2161
2162                 case 0x10:
2163                         dprintf(_("Message: SMS Message Received\n"));
2164                         dprintf(_("   SMS center number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer+7));
2165
2166                         MessageBuffer[23] = (MessageBuffer[23]+1)/2+1;
2167
2168                         dprintf(_("   Remote number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer+23));
2169                         dprintf(_("   Date: %s\n"), FB61_GetPackedDateTime(MessageBuffer+35));
2170                         dprintf(_("   SMS: "));
2171
2172                         tmp = UnpackEightBitsToSeven(0, MessageLength - 42 - 2, MessageBuffer[22], MessageBuffer + 42, output);
2173
2174                         for (i = 0; i < tmp; i++) dprintf("%c", GSM_Default_Alphabet[output[i]]);
2175
2176                         dprintf("\n");
2177                         break;
2178
2179                 case 0x21:
2180                         dprintf(_("Message: Cell Broadcast enabled/disabled successfully.\n"));
2181                         CurrentCBError = GE_NONE;
2182                         break;
2183
2184                 case 0x23:
2185                         CurrentCBMessage->Channel = MessageBuffer[7];
2186                         CurrentCBMessage->New = true;
2187                         tmp=UnpackEightBitsToSeven(0, 82, 82, MessageBuffer+10, output);
2188
2189                         dprintf(_("Message: CB received.\n")); fflush (stdout);
2190                         dprintf(_("Message: channel number %i\n"),MessageBuffer[7]);
2191                         for (i=0; i<tmp;i++)
2192                                 dprintf("%c", GSM_Default_Alphabet[output[i]]);
2193
2194                         dprintf("\n");
2195                         for (i = 0; i < tmp; i++)
2196                                 CurrentCBMessage->Message[i] = GSM_Default_Alphabet[output[i]];
2197
2198                         break;
2199
2200   
2201                 case 0x31:
2202                         dprintf(_("Message: SMS Center correctly set.\n"));
2203                         CurrentMessageCenterError = GE_NONE;
2204                         break;
2205
2206                 case 0x34:
2207
2208                         CurrentMessageCenter->No = MessageBuffer[4];
2209                         CurrentMessageCenter->Format = MessageBuffer[6];
2210                         CurrentMessageCenter->Validity = MessageBuffer[8];
2211                         sprintf(CurrentMessageCenter->Name, "%s", MessageBuffer+33);
2212                         sprintf(CurrentMessageCenter->Number, "%s", SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer+21));
2213
2214                         dprintf(_("Message: SMS Center received:\n"));
2215                         dprintf(_("   %d. SMS Center name is %s\n"), CurrentMessageCenter->No, CurrentMessageCenter->Name);
2216                         dprintf(_("   SMS Center number is %s\n"), CurrentMessageCenter->Number);
2217                         dprintf(_("   SMS Center message format is "));
2218
2219                         switch (CurrentMessageCenter->Format) {
2220                         case GSMF_Text:   dprintf(_("Text"));    break;
2221                         case GSMF_Paging: dprintf(_("Paging"));  break;
2222                         case GSMF_Fax:    dprintf(_("Fax"));     break;
2223                         case GSMF_Email:  dprintf(_("Email"));   break;
2224                         default:          dprintf(_("Unknown")); break;
2225                         }
2226
2227                         dprintf("\n");
2228
2229                         dprintf(_("   SMS Center message validity is "));
2230
2231                         switch (CurrentMessageCenter->Validity) {
2232                         case GSMV_1_Hour:    dprintf(_("1 hour"));       break;
2233                         case GSMV_6_Hours:   dprintf(_("6 hours"));      break;
2234                         case GSMV_24_Hours:  dprintf(_("24 hours"));     break;
2235                         case GSMV_72_Hours:  dprintf(_("72 hours"));     break;
2236                         case GSMV_1_Week:    dprintf(_("1 week"));       break;
2237                         case GSMV_Max_Time:  dprintf(_("Maximum time")); break;
2238                         default:             dprintf(_("Unknown"));      break;
2239                         }
2240                         dprintf("\n");
2241                         CurrentMessageCenterError = GE_NONE;
2242                         break;
2243
2244                 case 0x35:
2245                         /* Nokia 6110 has support for three SMS centers with numbers 1, 2 and
2246                            3. Each request for SMS Center without one of these numbers
2247                            fail. */
2248                         dprintf(_("Message: SMS Center error received:\n"));
2249                         dprintf(_("   The request for SMS Center failed.\n"));
2250
2251                         /* FIXME: appropriate error. */
2252                         CurrentMessageCenterError = GE_INTERNALERROR;
2253                         break;  
2254
2255                 default:
2256                         dprintf(_("Unknown message!\n"));
2257                         break;
2258                 }
2259
2260                 break;
2261
2262                 /* Phonebook handling */
2263
2264         case 0x03:
2265
2266                 switch (MessageBuffer[3]) {
2267
2268                 case 0x02:
2269
2270                         CurrentPhonebookEntry->Empty = true;
2271
2272                         count = MessageBuffer[5];
2273                         dprintf(_("Message: Phonebook entry received:\n"));
2274                         dprintf(_("   Name: "));
2275                         for (tmp = 0; tmp < count; tmp++)
2276                                 dprintf("%c", MessageBuffer[6+tmp]);
2277                         dprintf("\n");
2278
2279                         memcpy(CurrentPhonebookEntry->Name, MessageBuffer + 6, count);
2280                         CurrentPhonebookEntry->Name[count] = 0x00;
2281                         CurrentPhonebookEntry->Empty = false;
2282
2283                         i = 7 + count;
2284                         count = MessageBuffer[6+count];
2285
2286                         dprintf(_("   Number: "));
2287                         for (tmp = 0; tmp < count; tmp++)
2288                                 dprintf("%c", MessageBuffer[i+tmp]);
2289                         dprintf("\n");
2290
2291                         memcpy(CurrentPhonebookEntry->Number, MessageBuffer + i, count);
2292                         CurrentPhonebookEntry->Number[count] = 0x00;
2293                         CurrentPhonebookEntry->Group = MessageBuffer[i+count];
2294       
2295                         CurrentPhonebookEntry->Date.Year = MessageBuffer[i+count+2] * 256 + MessageBuffer[i+count+3];
2296                         CurrentPhonebookEntry->Date.Month = MessageBuffer[i+count+4];
2297                         CurrentPhonebookEntry->Date.Day = MessageBuffer[i+count+5];
2298                         CurrentPhonebookEntry->Date.Hour = MessageBuffer[i+count+6];
2299                         CurrentPhonebookEntry->Date.Minute = MessageBuffer[i+count+7];
2300                         CurrentPhonebookEntry->Date.Second = MessageBuffer[i+count+8];
2301
2302                         dprintf(_("   Date: "));
2303                         dprintf("%02u-%02u-%04u\n", CurrentPhonebookEntry->Date.Day, CurrentPhonebookEntry->Date.Month, CurrentPhonebookEntry->Date.Year);
2304                         dprintf(_("   Time: "));
2305                         dprintf("%02u-%02u-%02u\n", CurrentPhonebookEntry->Date.Hour, CurrentPhonebookEntry->Date.Minute, CurrentPhonebookEntry->Date.Second);
2306
2307                         /* Signal no error to calling code. */
2308
2309                         CurrentPhonebookError = GE_NONE;
2310
2311                         break;
2312
2313                 case 0x03:
2314                         dprintf(_("Message: Phonebook read entry error received:\n"));
2315                         switch (MessageBuffer[4]) {
2316                         case 0x7d:
2317                                 dprintf(_("   Invalid memory type!\n"));
2318                                 CurrentPhonebookError = GE_INVALIDMEMORYTYPE;
2319                                 break;
2320                         default:
2321                                 dprintf(_("   Unknown error!\n"));
2322                                 CurrentPhonebookError = GE_INTERNALERROR;
2323                                 break;
2324                         }
2325                         break;
2326
2327                 case 0x05:
2328                         dprintf(_("Message: Phonebook written correctly.\n"));
2329                         CurrentPhonebookError = GE_NONE;
2330                         break;
2331
2332                 case 0x06:
2333                         switch (MessageBuffer[4]) {
2334
2335                                 /* FIXME: other errors? When I send the phonebook with index of 350 it
2336                                    still report error 0x7d :-( */
2337
2338                         case 0x7d:
2339                                 dprintf(_("Message: Phonebook not written - name is too long.\n"));
2340                                 CurrentPhonebookError = GE_PHBOOKNAMETOOLONG;
2341                                 break;
2342
2343                         default:
2344                                 dprintf(_("   Unknown error!\n"));
2345                                 CurrentPhonebookError = GE_INTERNALERROR;
2346                                 break;
2347                         }
2348
2349                         break;
2350
2351                 case 0x08:
2352                         dprintf(_("Message: Memory status received:\n"));
2353                         dprintf(_("   Memory Type: %s\n"), FB61_MemoryType_String[MessageBuffer[4]]);
2354                         dprintf(_("   Used: %d\n"), MessageBuffer[6]);
2355                         dprintf(_("   Free: %d\n"), MessageBuffer[5]);
2356                         CurrentMemoryStatus->Used = MessageBuffer[6];
2357                         CurrentMemoryStatus->Free = MessageBuffer[5];
2358                         CurrentMemoryStatusError = GE_NONE;
2359                         break;
2360
2361                 case 0x09:
2362                         switch (MessageBuffer[4]) {
2363                         case 0x6f:
2364                                 dprintf(_("Message: Memory status error, phone is probably powered off.\n"));
2365                                 CurrentMemoryStatusError = GE_TIMEOUT;
2366                                 break;
2367
2368                         case 0x7d:
2369                                 dprintf(_("Message: Memory status error, memory type not supported by phone model.\n"));
2370                                 CurrentMemoryStatusError = GE_INTERNALERROR;
2371                                 break;
2372
2373                         case 0x8d:
2374                                 dprintf(_("Message: Memory status error, waiting for security code.\n"));
2375                                 CurrentMemoryStatusError = GE_INVALIDSECURITYCODE;
2376                                 break;
2377
2378                         default:
2379                                 dprintf(_("Message: Unknown Memory status error, subtype (MessageBuffer[4]) = %02x\n"),MessageBuffer[4]);
2380                                 break;
2381                         }
2382
2383                         break;
2384     
2385                 case 0x11:   /* Get group data */
2386       
2387                         /* [ID],[name_len],[name].,[ringtone],[graphicon],[lenhi],[lenlo],[bitmap] */
2388  
2389                         if (GetBitmap != NULL) {
2390                                 count = MessageBuffer[5];
2391                                 memcpy(GetBitmap->text, MessageBuffer+6, count);
2392                                 GetBitmap->text[count] = 0;
2393
2394                                 dprintf(_("Message: Caller group logo etc.\n"));
2395                                 dprintf(_("Caller group name: %s\n"), GetBitmap->text);
2396
2397                                 count += 6;
2398                                 GetBitmap->ringtone = MessageBuffer[count++];
2399                                 count++;
2400                                 GetBitmap->size = MessageBuffer[count++]<<8;
2401                                 GetBitmap->size += MessageBuffer[count++];
2402                                 count++;
2403                                 GetBitmap->width = MessageBuffer[count++];
2404                                 GetBitmap->height = MessageBuffer[count++];
2405                                 count++;
2406                                 tmp = GetBitmap->height * GetBitmap->width / 8;
2407                                 if (GetBitmap->size > tmp) GetBitmap->size = tmp;
2408                                 memcpy(GetBitmap->bitmap, MessageBuffer+count, GetBitmap->size);
2409                                 GetBitmapError = GE_NONE;
2410                         }
2411                         else {
2412                                 dprintf(_("Message: Caller group data received but not requested!\n"));
2413                         }
2414                         break;
2415
2416                 case 0x12:   /* Get group data error */
2417                         GetBitmapError = GE_UNKNOWN;   
2418                         dprintf(_("Message: Error attempting to get caller group data.\n"));
2419                         break;
2420       
2421                 case 0x14:   /* Set group data OK */
2422                         SetBitmapError = GE_NONE;      
2423                         dprintf(_("Message: Caller group data set correctly.\n"));
2424                         break;
2425
2426                 case 0x15:   /* Set group data error */
2427                         SetBitmapError = GE_UNKNOWN;      
2428                         dprintf(_("Message: Error attempting to set caller group data\n"));
2429                         break;  
2430
2431                 case 0x17:
2432                         CurrentSpeedDialEntry->MemoryType = MessageBuffer[4];
2433                         CurrentSpeedDialEntry->Location = MessageBuffer[5];
2434                         dprintf(_("Message: Speed dial entry received:\n"));
2435                         dprintf(_("   Location: %d\n"), CurrentSpeedDialEntry->Location);
2436                         dprintf(_("   MemoryType: %s\n"), FB61_MemoryType_String[CurrentSpeedDialEntry->MemoryType]);
2437                         dprintf(_("   Number: %d\n"), CurrentSpeedDialEntry->Number);
2438                         CurrentSpeedDialError = GE_NONE;
2439                         break;
2440
2441                 case 0x18:
2442                         dprintf(_("Message: Speed dial entry error\n"));
2443                         CurrentSpeedDialError = GE_INVALIDSPEEDDIALLOCATION;
2444                         break;
2445
2446                 case 0x1a:
2447                         dprintf(_("Message: Speed dial entry set.\n"));
2448                         CurrentSpeedDialError = GE_NONE;
2449                         break;
2450
2451                 case 0x1b:
2452                         dprintf(_("Message: Speed dial entry setting error.\n"));
2453                         CurrentSpeedDialError = GE_INVALIDSPEEDDIALLOCATION;
2454                         break;
2455
2456                 default:
2457                         dprintf(_("Message: Unknown message of type 0x03\n"));
2458                         break;
2459                 }
2460
2461                 break;
2462
2463                 /* Phone status */
2464           
2465         case 0x04:
2466                 switch (MessageBuffer[3]) {
2467                 case 0x02:
2468                         dprintf(_("Message: Phone status received:\n"));
2469                         dprintf(_("   Mode: "));
2470                         switch (MessageBuffer[4]) {
2471                         case 0x01: dprintf(_("registered within the network\n")); break;
2472                                 /* I was really amazing why is there a hole in the type of 0x02, now I
2473                                    know... */
2474                         case 0x02: dprintf(_("call in progress\n")); /* ringing or already answered call */ break;
2475                         case 0x03: dprintf(_("waiting for security code\n")); break;
2476                         case 0x04: dprintf(_("powered off\n")); break;
2477                         default: dprintf(_("unknown\n")); break;
2478                         }
2479                         dprintf(_("   Power source: "));
2480                         switch (MessageBuffer[7]) {
2481                         case 0x01: dprintf(_("AC/DC\n")); break;
2482                         case 0x02: dprintf(_("battery\n")); break;
2483                         default: dprintf(_("unknown\n")); break;
2484                         }
2485                         dprintf(_("   Battery Level: %d\n"), MessageBuffer[8]);
2486                         dprintf(_("   Signal strength: %d\n"), MessageBuffer[5]);
2487
2488                         CurrentRFLevel = MessageBuffer[5];
2489                         CurrentBatteryLevel = MessageBuffer[8];
2490                         CurrentPowerSource = MessageBuffer[7];
2491                         break;
2492
2493                 default:
2494                         dprintf(_("Message: Unknown message of type 0x04\n"));
2495                         break;
2496                 }
2497
2498                 break;
2499   
2500                 /* Startup Logo, Operator Logo and Profiles. */
2501
2502         case 0x05:
2503                 switch (MessageBuffer[3]) {
2504                 case 0x11:   /* Profile feature change result */
2505                         dprintf(_("Message: Profile feature change result.\n"));
2506                         CurrentProfileError = GE_NONE;
2507                         break;
2508
2509                 case 0x14:   /* Profile feature */
2510                         switch (MessageBuffer[6]) {
2511                         case 0x00:
2512                                 CurrentProfile->KeypadTone = MessageBuffer[8];
2513                                 break;
2514                         case 0x01:
2515                                 CurrentProfile->Lights = MessageBuffer[8];
2516                                 break;
2517                         case 0x02:
2518                                 CurrentProfile->CallAlert = MessageBuffer[8];
2519                                 break;
2520                         case 0x03:
2521                                 CurrentProfile->Ringtone = MessageBuffer[8];
2522                                 break;
2523                         case 0x04:
2524                                 CurrentProfile->Volume = MessageBuffer[8];
2525                                 break;
2526                         case 0x05:
2527                                 CurrentProfile->MessageTone = MessageBuffer[8];
2528                                 break;
2529                         case 0x06:
2530                                 CurrentProfile->Vibration = MessageBuffer[8];
2531                                 break;
2532                         case 0x07:
2533                                 CurrentProfile->WarningTone = MessageBuffer[8];
2534                                 break;
2535                         case 0x08:
2536                                 CurrentProfile->CallerGroups = MessageBuffer[8];
2537                                 break;
2538                         case 0x09:
2539                                 CurrentProfile->AutomaticAnswer = MessageBuffer[8];
2540                                 break;
2541                         }
2542
2543                         CurrentProfileError = GE_NONE;
2544                         break;
2545
2546                 case 0x17:   /* Startup Logo */
2547                         dprintf(_("Message: Startup Logo, welcome note and dealer welcome note received.\n"));
2548                         if (GetBitmap != NULL) {
2549                                 supported = false;
2550                                 count = 5;
2551                                 for (tmp = 0; tmp < MessageBuffer[4]; tmp++){
2552                                         switch (MessageBuffer[count++]) {
2553                                         case 0x01:
2554                                                 if (GetBitmap->type == GSM_StartupLogo) {
2555                                                         GetBitmap->height = MessageBuffer[count++];
2556                                                         GetBitmap->width = MessageBuffer[count++];
2557                                                         GetBitmap->size = GetBitmap->height * GetBitmap->width / 8;
2558                                                         length = GetBitmap->size;
2559                                                         memcpy(GetBitmap->bitmap, MessageBuffer + count, length);
2560                                                 } else {
2561                                                         length = MessageBuffer[count++];
2562                                                         length = length * MessageBuffer[count++] / 8;
2563                                                 }
2564                                                 count += length;
2565                                                 dprintf(_("Startup logo supported - "));
2566                                                 if (length != 0) dprintf(_("currently set\n"));
2567                                                 else dprintf(_("currently empty\n"));
2568                                                 if (GetBitmap->type == GSM_StartupLogo) supported = true;
2569                                                 break;
2570                                         case 0x02:
2571                                                 length = MessageBuffer[count];
2572                                                 if (GetBitmap->type == GSM_WelcomeNoteText) {
2573                                                         memcpy(GetBitmap->text, MessageBuffer + count + 1, length);
2574                                                         GetBitmap->text[length] = 0;
2575                                                 }
2576                                                 dprintf(_("Startup Text supported - "));
2577                                                 if (length != 0) {
2578                                                         dprintf(_("currently set to \""));
2579                                                         for (i = 0; i < length; i++) dprintf(_("%c"), MessageBuffer[count+1+i]);
2580                                                         dprintf(_("\"\n"));
2581                                                 } else {
2582                                                         dprintf(_("currently empty\n"));
2583                                                 }
2584                                                 count += length + 1;
2585                                                 if (GetBitmap->type == GSM_WelcomeNoteText) supported = true;
2586                                                 break;
2587                                         case 0x03:
2588                                                 length = MessageBuffer[count];
2589                                                 if (GetBitmap->type == GSM_DealerNoteText) {
2590                                                         memcpy(GetBitmap->text, MessageBuffer + count + 1, length);
2591                                                         GetBitmap->text[length] = 0;
2592                                                 }
2593                                                 dprintf(_("Dealer Welcome supported - "));
2594                                                 if (length != 0) {
2595                                                         dprintf(_("currently set to \""));
2596                                                         for (i = 0;i < length; i++) dprintf(_("%c"), MessageBuffer[count+1+i]);
2597                                                         dprintf(_("\"\n"));
2598                                                 } else dprintf(_("currently empty\n"));
2599                                                 count += length + 1;
2600                                                 if (GetBitmap->type==GSM_DealerNoteText) supported = true;
2601                                                 break;
2602                                         }
2603                                 }
2604                                 if (supported) GetBitmapError = GE_NONE;
2605                                 else GetBitmapError = GE_NOTSUPPORTED;
2606                         } else dprintf(_("Message: Startup logo received but not requested!\n"));
2607                         break;
2608
2609                 case 0x19:   /* Set startup OK */
2610                         SetBitmapError = GE_NONE;
2611                         dprintf(_("Message: Startup logo, welcome note or dealer welcome note correctly set.\n"));
2612                         break;      
2613
2614                 case 0x1b:   /* Incoming profile name */
2615                         if (MessageBuffer[9] == 0x00)
2616                                 CurrentProfile->DefaultName = MessageBuffer[8];
2617                         else {
2618                                 CurrentProfile->DefaultName = -1;
2619                                 sprintf(CurrentProfile->Name, MessageBuffer + 10, MessageBuffer[9]);
2620                                 CurrentProfile->Name[MessageBuffer[9]] = '\0';
2621                         }
2622                         CurrentProfileError = GE_NONE;
2623                         break;
2624
2625                 case 0x1d:   /* Profile name set result */
2626                         CurrentProfileError = GE_NONE;
2627                         break;
2628
2629                 case 0x31:   /* Set Operator Logo OK */
2630                         dprintf(_("Message: Operator logo correctly set.\n"));
2631                         SetBitmapError = GE_NONE;      
2632                         break;
2633       
2634                 case 0x32:   /* Set Operator Logo Error */
2635                         SetBitmapError = GE_UNKNOWN;
2636                         dprintf(_("Message: Error setting operator logo!\n"));
2637                         break;
2638
2639                 case 0x34:  /* Operator Logo */
2640                         /* [location],[netcode x 3],[lenhi],[lenlo],[bitmap] */
2641                         if (GetBitmap != NULL) {
2642                                 count = 5;  /* Location ignored. */
2643                                 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
2644                                 GetBitmap->netcode[0] = '0' + (MessageBuffer[count] & 0x0f);
2645                                 GetBitmap->netcode[1] = '0' + (MessageBuffer[count++] >> 4);
2646                                 GetBitmap->netcode[2] = '0' + (MessageBuffer[count++] & 0x0f);
2647                                 GetBitmap->netcode[3] = ' ';
2648                                 GetBitmap->netcode[4] = '0' + (MessageBuffer[count] & 0x0f);
2649                                 GetBitmap->netcode[5] = '0' + (MessageBuffer[count++] >> 4);
2650                                 GetBitmap->netcode[6] = 0;
2651                                 dprintf(_("Message: Operator Logo for %s (%s) network received.\n"),
2652                                         GetBitmap->netcode,
2653                                         GSM_GetNetworkName(GetBitmap->netcode));
2654                                 GetBitmap->size = MessageBuffer[count++] << 8;
2655                                 GetBitmap->size += MessageBuffer[count++];
2656                                 count++;
2657                                 GetBitmap->width = MessageBuffer[count++];
2658                                 GetBitmap->height = MessageBuffer[count++];
2659                                 count++;
2660                                 tmp = GetBitmap->height * GetBitmap->width / 8;
2661                                 if (GetBitmap->size > tmp) GetBitmap->size = tmp;
2662                                 memcpy(GetBitmap->bitmap, MessageBuffer + count, GetBitmap->size);
2663                                 GetBitmapError = GE_NONE;
2664                         }
2665                         else dprintf(_("Message: Operator logo received but not requested!\n"));
2666                         break;
2667       
2668                 case 0x35:  /* Get op logo error */
2669                         dprintf(_("Message: Error getting operator logo!\n"));
2670                         GetBitmapError = GE_UNKNOWN; 
2671                         break;
2672                 }
2673                 break;
2674
2675                 /* Security code requests */
2676
2677         case 0x08:
2678                 switch(MessageBuffer[3]) {
2679                 case 0x08:
2680                         *CurrentSecurityCodeStatus = MessageBuffer[4];
2681                         dprintf(_("Message: Security Code status received: "));
2682                         switch(*CurrentSecurityCodeStatus) {
2683                         case GSCT_SecurityCode: dprintf(_("waiting for Security Code.\n")); break;
2684                         case GSCT_Pin: dprintf(_("waiting for PIN.\n")); break;
2685                         case GSCT_Pin2: dprintf(_("waiting for PIN2.\n")); break;
2686                         case GSCT_Puk: dprintf(_("waiting for PUK.\n")); break;
2687                         case GSCT_Puk2: dprintf(_("waiting for PUK2.\n")); break;
2688                         case GSCT_None: dprintf(_("nothing to enter.\n")); break;
2689                         default: dprintf(_("Unknown!\n")); break;
2690                         }
2691                         CurrentSecurityCodeError = GE_NONE;
2692                         break;
2693
2694                 case 0x0b:
2695                         dprintf(_("Message: Security code accepted.\n"));
2696                         CurrentSecurityCodeError = GE_NONE;
2697                         break;
2698
2699                 default:
2700                         dprintf(_("Message: Security code is wrong. You're not my big owner :-)\n"));
2701                         CurrentSecurityCodeError = GE_INVALIDSECURITYCODE;
2702                         break;
2703                 }
2704
2705                 break;
2706
2707                 /* Network Info */
2708
2709         case 0x0a:
2710
2711                 switch (MessageBuffer[3]) {
2712                 case 0x71:
2713                         /* Make sure we are expecting NetworkInfo frame */
2714                         if (CurrentNetworkInfo && CurrentNetworkInfoError == GE_BUSY) {
2715                                 sprintf(CurrentNetworkInfo->NetworkCode, "%x%x%x %x%x", MessageBuffer[14] & 0x0f, MessageBuffer[14] >>4, MessageBuffer[15] & 0x0f, MessageBuffer[16] & 0x0f, MessageBuffer[16] >> 4);
2716                                 sprintf(CurrentNetworkInfo->CellID, "%02x%02x", MessageBuffer[10], MessageBuffer[11]);
2717                                 sprintf(CurrentNetworkInfo->LAC, "%02x%02x", MessageBuffer[12], MessageBuffer[13]);
2718
2719                                 dprintf(_("Message: Network information:\n"));
2720
2721                                 dprintf(_("   CellID: %s\n"), CurrentNetworkInfo->CellID);
2722                                 dprintf(_("   LAC: %s\n"), CurrentNetworkInfo->LAC);
2723                                 dprintf(_("   Network code: %s\n"), CurrentNetworkInfo->NetworkCode);
2724                                 dprintf(_("   Network name: %s (%s)\n"),
2725                                         GSM_GetNetworkName(CurrentNetworkInfo->NetworkCode),
2726                                         GSM_GetCountryName(CurrentNetworkInfo->NetworkCode));
2727                                 dprintf(_("   Status: "));
2728
2729                                 switch (MessageBuffer[8]) {
2730                                 case 0x01: dprintf(_("home network selected")); break;
2731                                 case 0x02: dprintf(_("roaming network")); break;
2732                                 case 0x03: dprintf(_("requesting network")); break;
2733                                 case 0x04: dprintf(_("not registered in the network")); break;
2734                                 default: dprintf(_("unknown")); break;
2735                                 }
2736
2737                                 dprintf("\n");
2738
2739                                 dprintf(_("   Network selection: %s\n"), MessageBuffer[9] == 1 ? _("manual") : _("automatic"));
2740                         }
2741                         CurrentNetworkInfoError = GE_NONE;
2742                         break;
2743
2744                 default:
2745                         dprintf(_("Message: Unknown message of type 0x0a\n"));
2746                         break;
2747                 }
2748
2749                 break;
2750
2751                 /* Display status. */
2752
2753         case 0x0d:
2754                 switch(MessageBuffer[3]) {
2755                 case 0x50:
2756                         dprintf("%i %i ", MessageBuffer[6], MessageBuffer[5]);
2757                         for (i = 0; i < MessageBuffer[7]; i++)
2758                                 dprintf("%c", MessageBuffer[9+(i*2)]);
2759                         dprintf("\n");
2760                         break;
2761  
2762                 case 0x52:
2763                         for (i = 0; i < MessageBuffer[4]; i++)
2764                                 if (MessageBuffer[2*i+6] == 2)
2765                                         DisplayStatus |= 1 << (MessageBuffer[2*i+5] - 1);
2766                                 else
2767                                         DisplayStatus &= (0xff - (1 << (MessageBuffer[2*i+5] - 1)));
2768                         dprintf(_("Call in progress: %s\n"), DisplayStatus & (1 << DS_Call_In_Progress) ? "on" : "off");
2769                         dprintf(_("Unknown: %s\n"),          DisplayStatus & (1 << DS_Unknown) ? "on" : "off");
2770                         dprintf(_("Unread SMS: %s\n"),       DisplayStatus & (1 << DS_Unread_SMS) ? "on" : "off");
2771                         dprintf(_("Voice call: %s\n"),       DisplayStatus & (1 << DS_Voice_Call) ? "on" : "off");
2772                         dprintf(_("Fax call active: %s\n"),  DisplayStatus & (1 << DS_Fax_Call) ? "on" : "off");
2773                         dprintf(_("Data call active: %s\n"), DisplayStatus & (1 << DS_Data_Call) ? "on" : "off");
2774                         dprintf(_("Keyboard lock: %s\n"),    DisplayStatus & (1 << DS_Keyboard_Lock) ? "on" : "off");
2775                         dprintf(_("SMS storage full: %s\n"), DisplayStatus & (1 << DS_SMS_Storage_Full) ? "on" : "off");
2776                         DisplayStatusError = GE_NONE;
2777                         break;
2778       
2779                 case 0x54:
2780                         if (MessageBuffer[5] == 1) {
2781                                 dprintf(_("Display output successfully disabled/enabled.\n"));
2782                                 CurrentDisplayOutputError = GE_NONE;
2783                         }
2784                         break;
2785       
2786                 default:
2787                         dprintf(_("Unknown message of type 0x0d.\n"));
2788                         break;
2789                 }
2790                 break;
2791
2792                 /* Phone Clock and Alarm */
2793
2794         case 0x11:
2795                 switch (MessageBuffer[3]) {
2796                 case 0x61:
2797                         switch (MessageBuffer[4]) {
2798                         case 0x01:
2799                                 dprintf(_("Message: Date and time set correctly\n"));
2800                                 CurrentSetDateTimeError = GE_NONE;
2801                                 break;
2802       
2803                         default:
2804                                 dprintf(_("Message: Date and time set error\n"));
2805                                 CurrentSetDateTimeError = GE_INVALIDDATETIME;
2806                                 break;
2807                         }
2808                         break;
2809
2810                 case 0x63:
2811                         CurrentDateTime->Year = 256 * MessageBuffer[8] + MessageBuffer[9];
2812                         CurrentDateTime->Month = MessageBuffer[10];
2813                         CurrentDateTime->Day = MessageBuffer[11];
2814
2815                         CurrentDateTime->Hour = MessageBuffer[12];
2816                         CurrentDateTime->Minute = MessageBuffer[13];
2817                         CurrentDateTime->Second = MessageBuffer[14];
2818
2819                         dprintf(_("Message: Date and time\n"));
2820                         dprintf(_("   Time: %02d:%02d:%02d\n"), CurrentDateTime->Hour, CurrentDateTime->Minute, CurrentDateTime->Second);
2821                         dprintf(_("   Date: %4d/%02d/%02d\n"), CurrentDateTime->Year, CurrentDateTime->Month, CurrentDateTime->Day);
2822
2823                         CurrentDateTimeError = GE_NONE;
2824                         break;
2825
2826                 case 0x6c:
2827                         switch (MessageBuffer[4]) {
2828                         case 0x01:
2829                                 dprintf(_("Message: Alarm set correctly\n"));
2830                                 CurrentSetAlarmError = GE_NONE;
2831                                 break;
2832       
2833                         default:
2834                                 dprintf(_("Message: Date and time set error\n"));
2835                                 CurrentSetAlarmError = GE_INVALIDDATETIME;
2836                                 break;
2837                         }
2838                         break;
2839
2840                 case 0x6e:
2841                         dprintf(_("Message: Alarm\n"));
2842                         dprintf(_("   Alarm: %02d:%02d\n"), MessageBuffer[9], MessageBuffer[10]);
2843                         dprintf(_("   Alarm is %s\n"), (MessageBuffer[8] == 2) ? _("on") : _("off"));
2844
2845                         CurrentAlarm->Hour = MessageBuffer[9];
2846                         CurrentAlarm->Minute = MessageBuffer[10];
2847                         CurrentAlarm->Second = 0;
2848                         CurrentAlarm->AlarmEnabled = (MessageBuffer[8] == 2);
2849                         CurrentAlarmError = GE_NONE;
2850                         break;
2851
2852                 default:
2853                         dprintf(_("Message: Unknown message of type 0x11\n"));
2854                         break;
2855                 }
2856                 break;
2857
2858                 /* Calendar notes handling */
2859
2860         case 0x13:
2861                 switch (MessageBuffer[3]) {
2862                 case 0x65:
2863                         switch(MessageBuffer[4]) {
2864                         case 0x01: /* This message is also sent when the user enters the new entry on keypad */
2865                                 dprintf(_("Message: Calendar note write succesfull!\n"));
2866                                 CurrentCalendarNoteError = GE_NONE;
2867                                 break;
2868                         case 0x73:
2869                                 dprintf(_("Message: Calendar note write failed!\n"));
2870                                 CurrentCalendarNoteError = GE_INTERNALERROR;
2871                                 break;
2872                         case 0x7d:
2873                                 dprintf(_("Message: Calendar note write failed!\n"));
2874                                 CurrentCalendarNoteError = GE_INTERNALERROR;
2875                                 break;
2876                         default:
2877                                 dprintf(_("Unknown message of type 0x13 and subtype 0x65\n"));
2878                                 break;
2879                         }
2880     
2881                         break;
2882
2883                 case 0x67:
2884
2885                         switch (MessageBuffer[4]) {
2886
2887                         case 0x01:
2888       
2889                                 CurrentCalendarNote->Type = MessageBuffer[8];
2890
2891                                 CurrentCalendarNote->Time.Year = 256 * MessageBuffer[9] + MessageBuffer[10];
2892                                 CurrentCalendarNote->Time.Month = MessageBuffer[11];
2893                                 CurrentCalendarNote->Time.Day = MessageBuffer[12];
2894
2895                                 CurrentCalendarNote->Time.Hour = MessageBuffer[13];
2896                                 CurrentCalendarNote->Time.Minute = MessageBuffer[14];
2897                                 CurrentCalendarNote->Time.Second = MessageBuffer[15];
2898
2899                                 CurrentCalendarNote->Alarm.Year = 256 * MessageBuffer[16] + MessageBuffer[17];
2900                                 CurrentCalendarNote->Alarm.Month = MessageBuffer[18];
2901                                 CurrentCalendarNote->Alarm.Day = MessageBuffer[19];
2902
2903                                 CurrentCalendarNote->Alarm.Hour = MessageBuffer[20];
2904                                 CurrentCalendarNote->Alarm.Minute = MessageBuffer[21];
2905                                 CurrentCalendarNote->Alarm.Second = MessageBuffer[22];
2906
2907                                 memcpy(CurrentCalendarNote->Text, MessageBuffer + 24, MessageBuffer[23]);
2908                                 CurrentCalendarNote->Text[MessageBuffer[23]] = 0;
2909
2910                                 if (CurrentCalendarNote->Type == GCN_CALL) {
2911                                         memcpy(CurrentCalendarNote->Phone,MessageBuffer + 24 + MessageBuffer[23] + 1,MessageBuffer[24+MessageBuffer[23]]);
2912                                         CurrentCalendarNote->Phone[MessageBuffer[24+MessageBuffer[23]]] = 0;
2913                                 }
2914
2915                                 dprintf(_("Message: Calendar note received.\n"));
2916                                 dprintf(_("   Date: %d-%02d-%02d\n"), CurrentCalendarNote->Time.Year,
2917                                         CurrentCalendarNote->Time.Month,
2918                                         CurrentCalendarNote->Time.Day);
2919                                 dprintf(_("   Time: %02d:%02d:%02d\n"), CurrentCalendarNote->Time.Hour,
2920                                         CurrentCalendarNote->Time.Minute,
2921                                         CurrentCalendarNote->Time.Second);
2922
2923                                 /* Some messages do not have alarm set up */
2924
2925                                 if (CurrentCalendarNote->Alarm.Year != 0) {
2926                                         dprintf(_("   Alarm date: %d-%02d-%02d\n"), CurrentCalendarNote->Alarm.Year,
2927                                                 CurrentCalendarNote->Alarm.Month,
2928                                                 CurrentCalendarNote->Alarm.Day);
2929                                         dprintf(_("   Alarm time: %02d:%02d:%02d\n"), CurrentCalendarNote->Alarm.Hour,
2930                                                 CurrentCalendarNote->Alarm.Minute,
2931                                                 CurrentCalendarNote->Alarm.Second);
2932                                 }
2933
2934                                 dprintf(_("   Type: %d\n"), CurrentCalendarNote->Type);
2935                                 dprintf(_("   Text: %s\n"), CurrentCalendarNote->Text);
2936                                 if (CurrentCalendarNote->Type == GCN_CALL)
2937                                         dprintf(_("   Phone: %s\n"), CurrentCalendarNote->Phone);
2938                                 CurrentCalendarNoteError = GE_NONE;
2939                                 break;
2940
2941                         case 0x93:
2942                                 dprintf(_("Message: Calendar note not available\n"));
2943                                 CurrentCalendarNoteError = GE_INVALIDCALNOTELOCATION;
2944                                 break;
2945
2946                         default:
2947                                 dprintf(_("Message: Calendar note error\n"));
2948                                 CurrentCalendarNoteError = GE_INTERNALERROR;
2949                                 break;
2950                         }
2951                         break;
2952
2953                 case 0x69:
2954                         switch (MessageBuffer[4]) {
2955                                 /* This message is also sent when the user deletes an old entry on
2956                                    keypad or moves an old entry somewhere (there is also `write'
2957                                    message). */
2958                         case 0x01:
2959                                 dprintf(_("Message: Calendar note deleted\n"));
2960                                 CurrentCalendarNoteError = GE_NONE;
2961                                 break;
2962                         case 0x93:
2963                                 dprintf(_("Message: Calendar note can't be deleted\n"));
2964                                 CurrentCalendarNoteError = GE_INVALIDCALNOTELOCATION;
2965                                 break;
2966                         default:
2967                                 dprintf(_("Message: Calendar note deleting error\n"));
2968                                 CurrentCalendarNoteError = GE_INTERNALERROR;
2969                                 break;
2970                         }
2971
2972                         break;
2973
2974                 case 0x6a:
2975                         /* Jano will probably implement something similar to IncomingCall
2976                            notification for easy integration into xgnokii */
2977                         dprintf(_("Message: Calendar Alarm active\n"));
2978                         dprintf(_("   Item number: %d\n"), MessageBuffer[4]);
2979                         break;
2980
2981                 default:
2982                         dprintf(_("Message: Unknown message of type 0x13\n"));
2983                         break;
2984                 }
2985
2986                 break;
2987
2988                 /* SMS Messages frame received */
2989
2990         case 0x14:
2991                 switch (MessageBuffer[3]) {
2992                 case 0x08:
2993                         switch (MessageBuffer[7]) {
2994                         case 0x00:
2995                                 CurrentSMSMessage->Type = GST_MT;
2996                                 offset = 4;
2997                                 break;
2998                         case 0x01:
2999                                 CurrentSMSMessage->Type = GST_DR;
3000                                 offset = 3;
3001                                 break;
3002                         case 0x02:
3003                                 CurrentSMSMessage->Type = GST_MO;
3004                                 offset = 5;
3005                                 break;
3006                         default:
3007                                 CurrentSMSMessage->Type = GST_UN;
3008                                 offset = 4; /* ??? */
3009                                 break;
3010                         }
3011
3012                         /* Field Short Message Status - MessageBuffer[4] seems not to be
3013                            compliant with GSM 07.05 spec.
3014                            Meaning      Nokia protocol          GMS spec
3015                            ----------------------------------------------------
3016                            MO Sent      0x05                    0x07 or 0x01
3017                            MO Not sent  0x07                    0x06 or 0x00
3018                            MT Read      0x01                    0x05 or 0x01
3019                            MT Not read  0x03                    0x04 or 0x00
3020                            ----------------------------------------------------
3021                            See GSM 07.05 section 2.5.2.6 and correct me if I'm wrong.
3022          
3023                            Pawel Kot */
3024
3025                         if (MessageBuffer[4] & 0x02)
3026                                 CurrentSMSMessage->Status = GSS_NOTSENTREAD;
3027                         else
3028                                 CurrentSMSMessage->Status = GSS_SENTREAD;
3029
3030                         off = 0;
3031                         CurrentSMSMessage->UDHPresent=!!(MessageBuffer[20] & 0x40);
3032       
3033                         MessageBuffer[20+offset] = (MessageBuffer[20+offset]+1)/2+1;
3034
3035                         dprintf(_("Number: %d\n"), MessageBuffer[6]);
3036                         switch (CurrentSMSMessage->Type) {
3037                         case GST_MO:
3038                                 dprintf(_("Message: Outbox message (mobile originated)\n"));
3039                                 if (CurrentSMSMessage->Status)
3040                                         dprintf(_("Sent\n"));
3041                                 else
3042                                         dprintf(_("Not sent\n"));
3043                                 break;
3044
3045                         default:
3046                                 dprintf(_("Message: Received SMS (mobile terminated)\n"));
3047                                 if (CurrentSMSMessage->Type == GST_DR)
3048                                         dprintf(_("Delivery Report\n"));
3049                                 if (CurrentSMSMessage->Type == GST_UN)
3050                                         dprintf(_("Unknown type\n"));
3051
3052                                 if (CurrentSMSMessage->Status)
3053                                         dprintf(_("Read\n"));
3054                                 else
3055                                         dprintf(_("Not read\n"));
3056
3057                                 dprintf(_("   Date: %s "), FB61_GetPackedDateTime(MessageBuffer + 32 + offset));
3058
3059                                 if (MessageBuffer[38+offset]) {
3060                                         if (MessageBuffer[38+offset] & 0x08)
3061                                                 dprintf("-");
3062                                         else
3063                                                 dprintf("+");
3064
3065                                         dprintf(_("%02d00"), (10 * (MessageBuffer[38+offset] & 0x07) + (MessageBuffer[38+offset] >> 4)) / 4);
3066                                 }
3067                                 dprintf("\n");
3068
3069                                 if (CurrentSMSMessage->Type == GST_DR) {
3070                                         dprintf(_("   SMSC response date: %s "), FB61_GetPackedDateTime(MessageBuffer + 39 + offset));
3071                                         if (MessageBuffer[45+offset]) {
3072                                                 if (MessageBuffer[45+offset] & 0x08)
3073                                                         dprintf("-");
3074                                                 else
3075                                                         dprintf("+");
3076
3077                                                 dprintf(_("%02d00"),(10 * (MessageBuffer[45+offset] & 0x07) + (MessageBuffer[45+offset] >> 4)) / 4);
3078                                         }
3079                                         dprintf("\n");
3080                                 }
3081                                 dprintf(_("   SMS center number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 8));
3082                                 dprintf(_("   Remote number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 20 + offset));
3083                                 break;
3084                         }
3085
3086                         /* In Outbox messages fields:
3087                            - datetime
3088                            - sender
3089                            - message center
3090                            are not filled in, so we ignore it.
3091                         */
3092                         if (CurrentSMSMessage->Type != GST_MO) {
3093                                 CurrentSMSMessage->Time.Year = 10 * (MessageBuffer[32+offset] & 0x0f) + (MessageBuffer[32+offset] >> 4);
3094                                 CurrentSMSMessage->Time.Month = 10 * (MessageBuffer[33+offset] & 0x0f) + (MessageBuffer[33+offset] >> 4);
3095                                 CurrentSMSMessage->Time.Day = 10 * (MessageBuffer[34+offset] & 0x0f) + (MessageBuffer[34+offset] >> 4);
3096                                 CurrentSMSMessage->Time.Hour = 10 * (MessageBuffer[35+offset] & 0x0f) + (MessageBuffer[35+offset] >> 4);
3097                                 CurrentSMSMessage->Time.Minute = 10 * (MessageBuffer[36+offset] & 0x0f) + (MessageBuffer[36+offset] >> 4);
3098                                 CurrentSMSMessage->Time.Second = 10 * (MessageBuffer[37+offset] & 0x0f) + (MessageBuffer[37+offset] >> 4);
3099                                 CurrentSMSMessage->Time.Timezone = (10 * (MessageBuffer[38+offset] & 0x07) + (MessageBuffer[38+offset] >> 4)) / 4;
3100                                 if (MessageBuffer[38+offset] & 0x08)
3101                                         CurrentSMSMessage->Time.Timezone = -CurrentSMSMessage->Time.Timezone;
3102                                 strcpy(CurrentSMSMessage->Sender, SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 20 + offset));
3103                                 strcpy(CurrentSMSMessage->MessageCenter.Number, SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 8));
3104                         }
3105
3106                         if (CurrentSMSMessage->Type != GST_DR) {
3107                                 /* 8bit SMS */
3108                                 if ((MessageBuffer[18+offset] & 0xf4) == 0xf4) {
3109                                         CurrentSMSMessage->EightBit = true;
3110                                         tmp=MessageBuffer[19+offset];
3111                                         offset += off;
3112                                         memcpy(output, MessageBuffer - 39 - offset - 2, tmp - offset);
3113                                         /* 7bit SMS */
3114                                 } else {
3115                                         CurrentSMSMessage->EightBit = false;
3116                                         tmp=MessageBuffer[19+offset] - (off * 8 + ((7-off)%7)) / 7;
3117                                         offset += off;
3118                                         tmp=UnpackEightBitsToSeven((7-off)%7, MessageLength - 39 - offset - 2, tmp, MessageBuffer + 39 + offset, output);
3119                                 }
3120                                 for (i = 0; i < tmp;i++) {
3121                                         dprintf("%c", GSM_Default_Alphabet[output[i]]);
3122                                         CurrentSMSMessage->MessageText[i] = GSM_Default_Alphabet[output[i]];
3123                                 }
3124                                 CurrentSMSMessage->MessageTextLength = tmp;
3125                         } else { /* CurrentSMSMessage->Type == GST_DR (Delivery Report) */
3126                                 /* SMSC Response time */
3127                                 CurrentSMSMessage->SMSCTime.Year = 10 * (MessageBuffer[39+offset] & 0x0f) + (MessageBuffer[39+offset] >> 4);
3128                                 CurrentSMSMessage->SMSCTime.Month = 10 * (MessageBuffer[40+offset] & 0x0f) + (MessageBuffer[40+offset] >> 4);
3129                                 CurrentSMSMessage->SMSCTime.Day = 10 * (MessageBuffer[41+offset] & 0x0f) + (MessageBuffer[41+offset] >> 4);
3130                                 CurrentSMSMessage->SMSCTime.Hour = 10 * (MessageBuffer[42+offset] & 0x0f) + (MessageBuffer[42+offset] >> 4);
3131                                 CurrentSMSMessage->SMSCTime.Minute = 10 * (MessageBuffer[43+offset] & 0x0f) + (MessageBuffer[43+offset] >> 4);
3132                                 CurrentSMSMessage->SMSCTime.Second = 10 * (MessageBuffer[44+offset] & 0x0f) + (MessageBuffer[44+offset] >> 4);
3133                                 CurrentSMSMessage->SMSCTime.Timezone = (10 * (MessageBuffer[45+offset] & 0x07) + (MessageBuffer[45+offset] >> 4)) / 4;
3134                                 if (MessageBuffer[45+offset] & 0x08) CurrentSMSMessage->SMSCTime.Timezone = -CurrentSMSMessage->SMSCTime.Timezone;
3135                                 if (MessageBuffer[22] < 0x03) {
3136                                         strcpy(CurrentSMSMessage->MessageText, _("Delivered"));
3137                                         switch (MessageBuffer[22]) {
3138                                         case 0x00:
3139                                                 dprintf(_("SM received by the SME"));
3140                                                 break;
3141                                         case 0x01:
3142                                                 dprintf(_("SM forwarded by the SC to the SME but the SC is unable to confirm delivery"));
3143                                                 break;
3144                                         case 0x02:
3145                                                 dprintf(_("SM replaced by the SC"));
3146                                                 break;
3147                                         }
3148                                 } else if (MessageBuffer[22] & 0x40) {
3149
3150                                         strcpy(CurrentSMSMessage->MessageText, _("Failed"));
3151
3152                                         /* more detailed reason only for debug */
3153
3154                                         if (MessageBuffer[22] & 0x20) {
3155                                                 dprintf(_("Temporary error, SC is not making any more transfer attempts\n"));
3156
3157                                                 switch (MessageBuffer[22]) {
3158                                                 case 0x60:
3159                                                         dprintf(_("Congestion"));
3160                                                         break;
3161                                                 case 0x61:
3162                                                         dprintf(_("SME busy"));
3163                                                         break;
3164                                                 case 0x62:
3165                                                         dprintf(_("No response from SME"));
3166                                                         break;
3167                                                 case 0x63:
3168                                                         dprintf(_("Service rejected"));
3169                                                         break;
3170                                                 case 0x64:
3171                                                         dprintf(_("Quality of service not aviable"));
3172                                                         break;
3173                                                 case 0x65:
3174                                                         dprintf(_("Error in SME"));
3175                                                         break;
3176                                                 default:
3177                                                         dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3178                                                         break;
3179                                                 }
3180                                         } else {
3181                                                 dprintf(_("Permanent error, SC is not making any more transfer attempts\n"));
3182                                                 switch (MessageBuffer[22]) {
3183                                                 case 0x40:
3184                                                         dprintf(_("Remote procedure error"));
3185                                                         break;
3186                                                 case 0x41:
3187                                                         dprintf(_("Incompatibile destination"));
3188                                                         break;
3189                                                 case 0x42:
3190                                                         dprintf(_("Connection rejected by SME"));
3191                                                         break;
3192                                                 case 0x43:
3193                                                         dprintf(_("Not obtainable"));
3194                                                         break;
3195                                                 case 0x44:
3196                                                         dprintf(_("Quality of service not aviable"));
3197                                                         break;
3198                                                 case 0x45:
3199                                                         dprintf(_("No internetworking available"));
3200                                                         break;
3201                                                 case 0x46:
3202                                                         dprintf(_("SM Validity Period Expired"));
3203                                                         break;
3204                                                 case 0x47:
3205                                                         dprintf(_("SM deleted by originating SME"));
3206                                                         break;
3207                                                 case 0x48:
3208                                                         dprintf(_("SM Deleted by SC Administration"));
3209                                                         break;
3210                                                 case 0x49:
3211                                                         dprintf(_("SM does not exist"));
3212                                                         break;
3213                                                 default:
3214                                                         dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3215                                                         break;
3216                                                 }
3217                                         }
3218                                 } else if (MessageBuffer[22] & 0x20) {
3219                                         strcpy(CurrentSMSMessage->MessageText, _("Pending"));
3220
3221                                         /* more detailed reason only for debug */
3222                                         dprintf(_("Temporary error, SC still trying to transfer SM\n"));
3223                                         switch (MessageBuffer[22]) {
3224                                         case 0x20:
3225                                                 dprintf(_("Congestion"));
3226                                                 break;
3227                                         case 0x21:
3228                                                 dprintf(_("SME busy"));
3229                                                 break;
3230                                         case 0x22:
3231                                                 dprintf(_("No response from SME"));
3232                                                 break;
3233                                         case 0x23:
3234                                                 dprintf(_("Service rejected"));
3235                                                 break;
3236                                         case 0x24:
3237                                                 dprintf(_("Quality of service not aviable"));
3238                                                 break;
3239                                         case 0x25:
3240                                                 dprintf(_("Error in SME"));
3241                                                 break;
3242                                         default:
3243                                                 dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3244                                                 break;
3245                                         }
3246                                 } else {
3247                                         strcpy(CurrentSMSMessage->MessageText, _("Unknown"));
3248
3249                                         /* more detailed reason only for debug */
3250                                         dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3251                                 }
3252                                 CurrentSMSMessage->MessageTextLength = strlen(CurrentSMSMessage->MessageText);
3253                         }
3254
3255                         CurrentSMSMessage->MessageText[CurrentSMSMessage->MessageTextLength] = 0;
3256
3257                         CurrentSMSMessage->MemoryType = MessageBuffer[5];
3258                         CurrentSMSMessage->MessageNumber = MessageBuffer[6];
3259  
3260                         /* Signal no error to calling code. */
3261
3262                         CurrentSMSMessageError = GE_NONE;
3263                         dprintf("\n");
3264                         break;
3265     
3266                 case 0x05:
3267                         dprintf(_("Message stored at %d\n"), MessageBuffer[5]);
3268                         CurrentSMSMessageError = GE_NONE;
3269                         break;
3270
3271                 case 0x06:
3272                         dprintf(_("SMS saving failed\n"));
3273                         switch (MessageBuffer[4]) {
3274                         case 0x02:
3275                                 dprintf(_("   All locations busy.\n"));
3276                                 CurrentSMSMessageError = GE_MEMORYFULL;
3277                                 break;
3278                         case 0x03:
3279                                 dprintf(_("   Invalid location!\n"));
3280                                 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3281                                 break;
3282                         default:
3283                                 dprintf(_("   Unknown error.\n"));
3284                                 CurrentSMSMessageError = GE_UNKNOWN;
3285                                 break;
3286                         }
3287                         break;
3288
3289                 case 0x09:
3290                         /* We have requested invalid or empty location. */
3291                         dprintf(_("Message: SMS reading failed.\n"));
3292                         switch (MessageBuffer[4]) {
3293                         case 0x02:
3294                                 dprintf(_("   Invalid location!\n"));
3295                                 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3296                                 break;
3297                         case 0x07:
3298                                 dprintf(_("   Empty SMS location.\n"));
3299                                 CurrentSMSMessageError = GE_EMPTYSMSLOCATION;
3300                                 break;
3301                         }
3302                         break;
3303
3304                 case 0x0b:      /* successful delete */
3305                         dprintf(_("Message: SMS deleted successfully.\n"));
3306                         CurrentSMSMessageError = GE_NONE;       
3307                         break;
3308
3309                 case 0x37:
3310                         dprintf(_("Message: SMS Status Received\n"));
3311                         dprintf(_("   The number of messages: %d\n"), MessageBuffer[10]);
3312                         dprintf(_("   Unread messages: %d\n"), MessageBuffer[11]);
3313                         CurrentSMSStatus->UnRead = MessageBuffer[11];
3314                         CurrentSMSStatus->Used   = MessageBuffer[10];
3315                         CurrentSMSStatus->Slots  = CurrentSMSStatus->Used; /* is it correct? */
3316                         CurrentSMSStatusError = GE_NONE;
3317                         break;
3318
3319                 case 0x38:
3320                         dprintf(_("Message: SMS Status error, probably not authorized by PIN\n"));
3321                         CurrentSMSStatusError = GE_INTERNALERROR;
3322                         break;
3323           
3324                 default:
3325                         CurrentSMSStatusError = GE_INTERNALERROR;
3326                         break;
3327       
3328                 }
3329                 break;
3330
3331
3332                 /* Internal phone functions? */
3333
3334         case 0x40:
3335
3336                 switch(MessageBuffer[2]) {
3337
3338                 case 0x7e:
3339
3340                         switch(MessageBuffer[3]) {
3341                         case 0x00:
3342                                 dprintf(_("Message: Netmonitor correctly set.\n"));
3343                                 CurrentNetmonitorError = GE_NONE;
3344                                 break;
3345                         default:
3346                                 dprintf(_("Message: Netmonitor menu %d received:\n"), MessageBuffer[3]);
3347                                 dprintf("%s\n", MessageBuffer + 4);
3348                                 strcpy(CurrentNetmonitor, MessageBuffer + 4);
3349                                 CurrentNetmonitorError = GE_NONE;
3350                                 break;
3351                         }
3352
3353                         break;
3354
3355                 default:
3356                         dprintf(_("Unknown message of type 0x40.\n"));
3357                         break;
3358                 }
3359                 break;
3360         
3361                 /* Mobile phone identification */
3362
3363         case 0x64:
3364 #if defined WIN32 || !defined HAVE_SNPRINTF
3365                 sprintf(IMEI, "%s", MessageBuffer + 9);
3366                 sprintf(Model, "%s", MessageBuffer + 25);
3367                 sprintf(Revision, "SW%s, HW%s", MessageBuffer + 44, MessageBuffer + 39);
3368 #else
3369                 snprintf(IMEI, FB61_MAX_IMEI_LENGTH, "%s", MessageBuffer + 9);
3370                 snprintf(Model, FB61_MAX_MODEL_LENGTH, "%s", MessageBuffer + 25);
3371                 snprintf(Revision, FB61_MAX_REVISION_LENGTH, "SW%s, HW%s", MessageBuffer + 44, MessageBuffer + 39);
3372 #endif
3373
3374                 dprintf(_("Message: Mobile phone identification received:\n"));
3375                 dprintf(_("   IMEI: %s\n"), IMEI);
3376                 dprintf(_("   Model: %s\n"), Model);
3377                 dprintf(_("   Production Code: %s\n"), MessageBuffer + 31);
3378                 dprintf(_("   HW: %s\n"), MessageBuffer + 39);
3379                 dprintf(_("   Firmware: %s\n"), MessageBuffer + 44);
3380
3381                 /* These bytes are probably the source of the "Accessory not connected"
3382                    messages on the phone when trying to emulate NCDS... I hope....
3383                    UPDATE: of course, now we have the authentication algorithm. */
3384
3385                 dprintf(_("   Magic bytes: %02x %02x %02x %02x\n"), MessageBuffer[50], MessageBuffer[51], MessageBuffer[52], MessageBuffer[53]);
3386
3387                 MagicBytes[0] = MessageBuffer[50];
3388                 MagicBytes[1] = MessageBuffer[51];
3389                 MagicBytes[2] = MessageBuffer[52];
3390                 MagicBytes[3] = MessageBuffer[53];
3391                 CurrentMagicError = GE_NONE;
3392                 break;
3393
3394                 /***** Acknowlegment of our frames. *****/
3395         case 0x7f:
3396                 dprintf(_("[Received Ack of type %02x, seq: %2x]\n"), MessageBuffer[0], MessageBuffer[1]);
3397                 AcksReceived++;
3398                 FB61_LinkOK = true;
3399                 break;
3400
3401                 /***** Power on message. *****/
3402         case 0xd0:
3403                 dprintf(_("Message: The phone is powered on - seq 1.\n"));
3404                 break;
3405
3406                 /***** Phone info. *****/
3407         case 0xd2:
3408 #if defined WIN32 || !defined HAVE_SNPRINTF
3409                 sprintf(Model, "%s", MessageBuffer + 21);
3410                 sprintf(Revision, "SW%s", MessageBuffer + 5);
3411 #else
3412                 snprintf(Model, FB61_MAX_MODEL_LENGTH, "%s", MessageBuffer + 21);
3413                 Model[FB61_MAX_MODEL_LENGTH-1] = 0;
3414                 snprintf(Revision, FB61_MAX_SW_LENGTH, "SW%s", MessageBuffer + 5);
3415                 Revision[FB61_MAX_SW_LENGTH-1] = 0;
3416 #endif
3417                 dprintf(_("Phone info:\n%s\n"), MessageBuffer + 4);
3418                 CurrentPhoneInfoError = GE_NONE;
3419                 break;
3420
3421                 /***** RLP frame received. *****/
3422         case 0xf1:
3423                 FB61_RX_HandleRLPMessage();
3424                 break;
3425
3426                 /***** Power on message. *****/
3427         case 0xf4:
3428                 dprintf(_("Message: The phone is powered on - seq 2.\n"));
3429                 break;
3430
3431                 /***** Unknown message *****/
3432                 /* If you think that you know the exact meaning of other messages - please
3433                    let us know. */
3434         default:
3435                 dprintf(_("Message: Unknown message.\n"));
3436                 break;
3437         }
3438         return FB61_RX_Sync;
3439 }
3440
3441 /* RX_State machine for receive handling.  Called once for each character
3442    received from the phone/phone. */
3443
3444 void FB61_RX_StateMachine(char rx_byte)
3445 {
3446         static int checksum[2];
3447 #ifdef WIN32
3448         static struct _timeb time_now, time_last;
3449         static struct timeval time_diff;
3450 #else
3451         static struct timeval time_now, time_last, time_diff;
3452 #endif
3453
3454         /* XOR the byte with the current checksum */
3455         checksum[BufferCount&1] ^= rx_byte;
3456
3457         switch (RX_State) {
3458         
3459                 /* Messages from the phone start with an 0x1e (cable) or 0x1c (IR).
3460                    We use this to "synchronise" with the incoming data stream. However,
3461                    if we see something else, we assume we have lost sync and we require
3462                    a gap of at least 5ms before we start looking again. This is because
3463                    the data part of the frame could contain a byte which looks like the
3464                    sync byte */
3465
3466         case FB61_RX_Discarding:
3467                 gettimeofday(&time_now, NULL);
3468                 timersub(&time_now, &time_last, &time_diff);
3469                 if (time_diff.tv_sec == 0 && time_diff.tv_usec < 5000) {
3470                         time_last = time_now;  /* no gap seen, continue discarding */
3471                         break;
3472                 }
3473                 /* else fall through to... */
3474
3475         case FB61_RX_Sync:
3476
3477                 if ( CurrentConnectionType == GCT_Infrared ) {
3478                         if (rx_byte == FB61_IR_FRAME_ID) {
3479
3480                                 if (RX_Multiple == false) BufferCount = 0;
3481                                 else BufferCount = MessageLength - 2;
3482                                 RX_State = FB61_RX_GetDestination;
3483         
3484                                 /* Initialize checksums. */
3485                                 checksum[0] = FB61_IR_FRAME_ID;
3486                                 checksum[1] = 0;
3487                         } else {
3488                                 /* Lost frame sync */
3489                                 RX_State = FB61_RX_Discarding;
3490                                 gettimeofday(&time_last, NULL);
3491                         }
3492                 } else { /* CurrentConnectionType == GCT_Serial */
3493                         if (rx_byte == FB61_FRAME_ID) {
3494
3495                                 if (RX_Multiple == false) BufferCount = 0;
3496                                 else BufferCount = MessageLength - 2;
3497                                 RX_State = FB61_RX_GetDestination;
3498         
3499                                 /* Initialize checksums. */
3500                                 checksum[0] = FB61_FRAME_ID;
3501                                 checksum[1] = 0;
3502                         } else {
3503                                 /* Lost frame sync */
3504                                 RX_State = FB61_RX_Discarding;
3505                                 gettimeofday(&time_last, NULL);
3506                         }
3507                 }
3508     
3509                 break;
3510
3511         case FB61_RX_GetDestination:
3512
3513                 MessageDestination = rx_byte;
3514                 RX_State = FB61_RX_GetSource;
3515
3516                 /* When there is a checksum error and things get out of sync we have to manage to resync */
3517                 /* If doing a data call at the time, finding a 0x1e etc is really quite likely in the data stream */
3518                 /* Then all sorts of horrible things happen because the packet length etc is wrong... */
3519                 /* Therefore we test here for a destination of 0x0c and return to the top if it is not */
3520     
3521                 if (rx_byte != 0x0c) {
3522                         RX_State = FB61_RX_Sync;
3523                         dprintf("The fbus stream is out of sync - expected 0x0c, got %2x\n",rx_byte);
3524                 }
3525                 break;
3526
3527         case FB61_RX_GetSource:
3528                 MessageSource = rx_byte;
3529                 RX_State = FB61_RX_GetType;
3530
3531                 /* Source should be 0x00 */
3532     
3533                 if (rx_byte != 0x00)  {
3534                         RX_State = FB61_RX_Sync;
3535                         dprintf("The fbus stream is out of sync - expected 0x00, got %2x\n",rx_byte);
3536                 }
3537                 break;
3538
3539         case FB61_RX_GetType:
3540                 if ((RX_Multiple == true) && (MessageType != rx_byte)) {
3541                         dprintf(_("Interrupted MultiFrame-Message - Ignoring it !!!\n"));
3542                         dprintf(_("Please report it ...\n"));
3543                         BufferCount = 0;
3544                         RX_Multiple = false;
3545                 }
3546
3547                 MessageType = rx_byte;
3548                 RX_State = FB61_RX_GetUnknown;
3549                 break;
3550
3551         case FB61_RX_GetUnknown:
3552                 MessageUnknown = rx_byte;
3553                 RX_State = FB61_RX_GetLength;
3554                 break;
3555     
3556         case FB61_RX_GetLength:
3557                 if (RX_Multiple == true)
3558                         MessageLength = MessageLength - 2 + rx_byte;
3559                 else
3560                         MessageLength = rx_byte;
3561                 RX_State = FB61_RX_GetMessage;
3562                 break;
3563     
3564         case FB61_RX_GetMessage:
3565                 MessageBuffer[BufferCount] = rx_byte;
3566                 BufferCount++;
3567                 if (BufferCount > FB61_MAX_RECEIVE_LENGTH*6) {
3568                         dprintf(_("FB61: Message buffer overun - resetting\n"));
3569                         RX_Multiple = false;
3570                         RX_State = FB61_RX_Sync;
3571                         break;
3572                 }
3573
3574                 /* If this is the last byte, it's the checksum. */
3575
3576                 if (BufferCount == MessageLength + (MessageLength % 2) + 2) {
3577                         /* Is the checksum correct? */
3578                         if (checksum[0] == checksum[1]) {
3579                                 /* We do not want to send ACK of ACKs and ACK of RLP frames. */
3580
3581                                 if (MessageType != FB61_FRTYPE_ACK && MessageType != 0xf1) {
3582                                         FB61_TX_SendAck(MessageType, MessageBuffer[MessageLength-1] & 0x0f);
3583                                         if ((MessageLength > 1) && (MessageBuffer[MessageLength-2] != 0x01))
3584                                                 RX_Multiple = true;
3585                                         else
3586                                                 RX_Multiple = false;
3587                                 }
3588
3589                                 FB61_RX_DispatchMessage();
3590
3591                         }
3592                         else {
3593                                 dprintf(_("Bad checksum!\n"));
3594                                 RX_Multiple = false;    /* Just to be sure! */
3595                         }
3596
3597                         RX_State = FB61_RX_Sync;
3598                 }
3599                 break;
3600         }
3601 }
3602
3603 /* This function is used for parsing the RLP frame into fields. */
3604
3605 enum FB61_RX_States FB61_RX_HandleRLPMessage(void)
3606 {
3607         RLP_F96Frame frame;
3608         int count;
3609         int valid = true;
3610
3611         /* We do not need RLP frame parsing to be done when we do not have callback
3612            specified. */
3613     
3614         if (RLP_RXCallback == NULL)
3615                 return (FB61_RX_Sync);
3616
3617         /* Anybody know the official meaning of the first two bytes?
3618            Nokia 6150 sends junk frames starting D9 01, and real frames starting
3619            D9 00. We'd drop the junk frames anyway because the FCS is bad, but
3620            it's tidier to do it here. We still need to call the callback function
3621            to give it a chance to handle timeouts and/or transmit a frame */
3622
3623         if (MessageBuffer[0] == 0xd9 && MessageBuffer[1] == 0x01)
3624                 valid = false;
3625
3626         /* Nokia uses 240 bit frame size of RLP frames as per GSM 04.22
3627            specification, so Header consists of 16 bits (2 bytes). See section 4.1
3628            of the specification. */
3629     
3630         frame.Header[0] = MessageBuffer[2];
3631         frame.Header[1] = MessageBuffer[3];
3632
3633         /* Next 200 bits (25 bytes) contain the Information. We store the
3634            information in the Data array. */
3635
3636         for (count = 0; count < 25; count ++)
3637                 frame.Data[count] = MessageBuffer[4 + count];
3638
3639         /* The last 24 bits (3 bytes) contain FCS. */
3640
3641         frame.FCS[0] = MessageBuffer[29];
3642         frame.FCS[1] = MessageBuffer[30];
3643         frame.FCS[2] = MessageBuffer[31];
3644
3645         /* Here we pass the frame down in the input stream. */
3646     
3647         RLP_RXCallback(valid ? &frame : NULL);
3648
3649         return (FB61_RX_Sync);
3650 }
3651
3652 char *FB61_PrintDevice(int Device)
3653 {
3654
3655         switch (Device) {
3656
3657         case FB61_DEVICE_PHONE:
3658                 return _("Phone");
3659
3660         case FB61_DEVICE_PC:
3661                 return _("PC");
3662
3663         default:
3664                 return _("Unknown");
3665                 break;
3666         }
3667 }
3668
3669 /* FB61_RX_DisplayMessage is called when a message we don't know about is
3670    received so that the user can see what is going back and forth, and perhaps
3671    shed some more light/explain another message type! */
3672         
3673 void FB61_RX_DisplayMessage(void)
3674 {
3675 #ifdef DEBUG
3676
3677         int count;
3678         dprintf(_("Msg Dest: %s\n"), FB61_PrintDevice(MessageDestination));
3679         dprintf(_("Msg Source: %s\n"), FB61_PrintDevice(MessageSource));
3680         dprintf(_("Msg Type: %02x\n"), MessageType);
3681         dprintf(_("Msg Unknown: %02x\n"), MessageUnknown);
3682         dprintf(_("Msg Len: %02x\nPhone: "), MessageLength);
3683
3684         for (count = 0; count < MessageLength + (MessageLength % 2) + 2; count ++)
3685                 if (isprint(MessageBuffer[count]))
3686                         dprintf("[%02x%c]", MessageBuffer[count], MessageBuffer[count]);
3687                 else
3688                         dprintf("[%02x ]", MessageBuffer[count]);
3689
3690         dprintf("\n");
3691 #endif /* DEBUG */
3692 }
3693
3694 /* Prepares the message header and sends it, prepends the message start byte
3695            (0x1e) and other values according the value specified when called.
3696            Calculates checksum and then sends the lot down the pipe... */
3697
3698 int FB61_TX_SendFrame(u8 message_length, u8 message_type, u8 *buffer)
3699 {
3700         u8 out_buffer[FB61_MAX_TRANSMIT_LENGTH + 5];
3701         int count, current = 0;
3702         unsigned char   checksum;
3703
3704         /* FIXME - we should check for the message length ... */
3705
3706         /* Now construct the message header. */
3707
3708         if (CurrentConnectionType == GCT_Infrared)
3709                 out_buffer[current++] = FB61_IR_FRAME_ID; /* Start of the IR frame indicator */
3710         else /* CurrentConnectionType == GCT_Serial */
3711                 out_buffer[current++] = FB61_FRAME_ID;    /* Start of the frame indicator */
3712
3713         out_buffer[current++] = FB61_DEVICE_PHONE; /* Destination */
3714         out_buffer[current++] = FB61_DEVICE_PC;    /* Source */
3715         out_buffer[current++] = message_type; /* Type */
3716         out_buffer[current++] = 0; /* Unknown */
3717         out_buffer[current++] = message_length; /* Length */
3718
3719         /* Copy in data if any. */      
3720         
3721         if (message_length != 0) {
3722                 memcpy(out_buffer + current, buffer, message_length);
3723                 current += message_length;
3724         }
3725
3726         /* If the message length is odd we should add pad byte 0x00 */
3727         if (message_length % 2)
3728                 out_buffer[current++] = 0x00;
3729
3730         /* Now calculate checksums over entire message and append to message. */
3731
3732         /* Odd bytes */
3733
3734         checksum = 0;
3735         for (count = 0; count < current; count += 2)
3736                 checksum ^= out_buffer[count];
3737
3738         out_buffer[current++] = checksum;
3739
3740         /* Even bytes */
3741
3742         checksum = 0;
3743         for (count = 1; count < current; count += 2)
3744                 checksum ^= out_buffer[count];
3745
3746         out_buffer[current++] = checksum;
3747
3748         dprintf(_("PC: "));
3749         for (count = 0; count < current; count++)
3750                 dprintf("%02x:", out_buffer[count]);
3751         dprintf("\n");
3752
3753         /* Send it out... */
3754   
3755         if (WRITEPHONE(PortFD, out_buffer, current) != current)
3756                 return (false);
3757
3758         if(message_type != 0x7f)
3759                 MessagesSent++;
3760
3761         return (true);
3762 }
3763
3764 int FB61_TX_SendMessage(u16 message_length, u8 message_type, u8 *buffer)
3765 {
3766         u8 seqnum, frame_buffer[FB61_MAX_CONTENT_LENGTH + 2];
3767         u8 nom, lml;  /* number of messages, last message len */
3768         int i;
3769
3770         seqnum = 0x40 + RequestSequenceNumber;
3771         RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07;
3772
3773         if (message_length > FB61_MAX_CONTENT_LENGTH) {
3774
3775                 nom = (message_length + FB61_MAX_CONTENT_LENGTH - 1)
3776                         / FB61_MAX_CONTENT_LENGTH;
3777                 lml = message_length - ((nom - 1) * FB61_MAX_CONTENT_LENGTH);
3778
3779                 for (i = 0; i < nom - 1; i++) {
3780
3781                         memcpy(frame_buffer, buffer + (i * FB61_MAX_CONTENT_LENGTH),
3782                                FB61_MAX_CONTENT_LENGTH);
3783                         frame_buffer[FB61_MAX_CONTENT_LENGTH] = nom - i;
3784                         frame_buffer[FB61_MAX_CONTENT_LENGTH + 1] = seqnum;
3785
3786                         FB61_TX_SendFrame(FB61_MAX_CONTENT_LENGTH + 2, message_type,
3787                                           frame_buffer);
3788
3789                         seqnum = RequestSequenceNumber;
3790                         RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07;    
3791                 }
3792
3793                 memcpy(frame_buffer, buffer + ((nom - 1) * FB61_MAX_CONTENT_LENGTH), lml);
3794                 frame_buffer[lml] = 0x01;
3795                 frame_buffer[lml + 1] = seqnum;
3796                 FB61_TX_SendFrame(lml + 2, message_type, frame_buffer);
3797
3798         }
3799         else {
3800                 memcpy(frame_buffer, buffer, message_length);
3801                 frame_buffer[message_length] = 0x01;
3802                 frame_buffer[message_length + 1] = seqnum;
3803                 FB61_TX_SendFrame(message_length + 2, message_type, frame_buffer);
3804         }
3805
3806         return (true);
3807 }
3808
3809 int FB61_TX_SendAck(u8 message_type, u8 message_seq)
3810 {
3811         unsigned char request[2];
3812         request[0] = message_type;
3813         request[1] = message_seq;
3814         dprintf(_("[Sending Ack of type %02x, seq: %x]\n"), message_type, message_seq);
3815         return FB61_TX_SendFrame(2, FB61_FRTYPE_ACK, request);
3816 }
3817
3818