7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 1999, 2000 Hugh Blemings & Pavel JanÃk ml.
11 Released under the terms of the GNU GPL, see file COPYING for more details.
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.
16 The various routines are called FB61 (whatever) as a concatenation of FBUS
20 Revision 1.1.1.2 2002/04/03 00:07:54 short
21 Found in "gnokii-working" directory, some November-patches version
23 Revision 1.136 2001/08/20 23:27:37 pkot
24 Add hardware shakehand to the link layer (Manfred Jonsson)
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)
29 Revision 1.134 2001/06/10 11:24:57 machek
30 Kill "slash star" inside comment.
32 Revision 1.133 2001/03/19 23:43:46 pkot
33 Solaris/ *BSD '#if defined' cleanup
35 Revision 1.132 2001/03/13 01:23:17 pkot
36 Windows updates (Manfred Jonsson)
38 Revision 1.131 2001/03/13 01:21:38 pkot
39 *BSD updates (Bert Driehuis)
41 Revision 1.130 2001/02/28 21:30:52 machek
42 Return data in GBF_Arbitrary if we can't handle units requested.
44 Revision 1.129 2001/02/21 19:56:55 chris
45 More fiddling with the directory layout
47 Revision 1.128 2001/02/17 22:40:48 chris
50 Revision 1.127 2001/02/06 21:15:34 chris
51 Preliminary irda support for 7110 etc. Not well tested!
53 Revision 1.126 2001/02/06 14:35:55 pkot
54 Few more cleanups on authentication
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)
60 Revision 1.124 2001/02/01 15:17:27 pkot
61 Fixed --identify and added Manfred's manufacturer patch
63 Revision 1.123 2001/01/31 12:49:00 pkot
64 Many cleanups in fbus-6110 code.
65 3210/3310 really work now.
67 Revision 1.122 2001/01/23 15:32:35 chris
68 Pavel's 'break' and 'static' corrections.
69 Work on logos for 7110.
71 Revision 1.121 2001/01/15 17:00:45 pkot
72 Initial keypress sequence support. Disable compilation warning
74 Revision 1.120 2001/01/14 22:46:56 chris
75 Preliminary 7110 support (dlr9 only) and the beginnings of a new structure
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.
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
89 Revision 1.117 2000/12/21 15:13:46 pkot
90 Fixed functions converting ascii to and from PDU
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)
97 /* "Turn on" prototypes in fbus-6110.h */
101 /* System header files */
110 #include "win32/winserial.h"
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;
122 #define WRITEPHONE(a, b, c) device_write(b, c)
128 #include <sys/ioctl.h>
129 #include <sys/types.h>
130 #include <sys/time.h>
134 #include "devices/unixserial.h"
138 /* Various header file */
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"
150 /* Global variables used by code in gsm-api.c to expose the functions
151 supported by this model of phone. */
156 /* fd opened in device.c */
157 extern int device_portfd;
162 void FB61_InitializeLink();
166 /* Here we initialise model specific functions. */
168 GSM_Functions FB61_Functions = {
171 FB61_GetMemoryLocation,
172 FB61_WritePhonebookLocation,
175 FB61_GetMemoryStatus,
180 FB61_DeleteSMSMessage,
184 FB61_GetBatteryLevel,
186 FB61_GetDisplayStatus,
187 FB61_EnterSecurityCode,
188 FB61_GetSecurityCodeStatus,
192 PNOK_GetManufacturer,
199 FB61_GetIncomingCallNr,
201 FB61_GetCalendarNote,
202 FB61_WriteCalendarNote,
203 FB61_DeleteCalendarNote,
214 FB61_EnableDisplayOutput,
215 FB61_DisableDisplayOutput,
216 FB61_EnableCellBroadcast,
217 FB61_DisableCellBroadcast,
218 FB61_ReadCellBroadcast,
224 /* Mobile phone information */
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 */
242 const char *FB61_MemoryType_String [] = {
255 /* Local variables */
258 char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH];
260 /* This is the connection type used in gnokii. */
262 GSM_ConnectionType CurrentConnectionType;
266 u8 MessageBuffer[FB61_MAX_RECEIVE_LENGTH * 6];
269 u8 MessageType, MessageDestination, MessageSource, MessageUnknown;
270 u8 MessagesSent=0, AcksReceived=0;
272 /* Magic bytes from the phone. */
274 unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };
275 GSM_Error CurrentMagicError = GE_BUSY;
277 enum FB61_RX_States RX_State;
278 bool RX_Multiple = false;
280 u8 RequestSequenceNumber = 0x00;
281 bool RequestTerminate;
282 bool DisableKeepalive = false;
284 u8 CallSequenceNumber; /* Used to disconnect the call */
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. */
300 static GSM_PhonebookEntry *CurrentPhonebookEntry;
301 static GSM_Error CurrentPhonebookError;
303 static GSM_SpeedDial *CurrentSpeedDialEntry;
304 static GSM_Error CurrentSpeedDialError;
306 static GSM_SMSMessage *CurrentSMSMessage;
307 static GSM_Error CurrentSMSMessageError;
309 static GSM_MemoryStatus *CurrentMemoryStatus;
310 static GSM_Error CurrentMemoryStatusError;
312 static GSM_NetworkInfo *CurrentNetworkInfo = NULL;
313 static GSM_Error CurrentNetworkInfoError;
315 static GSM_SMSStatus *CurrentSMSStatus;
316 static GSM_Error CurrentSMSStatusError;
318 static GSM_MessageCenter *CurrentMessageCenter;
319 static GSM_Error CurrentMessageCenterError;
321 static int *CurrentSecurityCodeStatus;
322 static GSM_Error CurrentSecurityCodeError;
324 static GSM_DateTime *CurrentDateTime;
325 static GSM_Error CurrentDateTimeError;
327 static GSM_DateTime *CurrentAlarm;
328 static GSM_Error CurrentAlarmError;
330 static GSM_CalendarNote *CurrentCalendarNote;
331 static GSM_Error CurrentCalendarNoteError;
333 static GSM_Error CurrentSetDateTimeError;
334 static GSM_Error CurrentSetAlarmError;
336 static int CurrentRFLevel,
340 static int DisplayStatus;
341 static GSM_Error DisplayStatusError;
343 static char *CurrentNetmonitor;
344 static GSM_Error CurrentNetmonitorError;
346 static GSM_Bitmap *GetBitmap=NULL;
347 static GSM_Error GetBitmapError;
349 static GSM_Error SetBitmapError;
351 static GSM_Profile *CurrentProfile;
352 static GSM_Error CurrentProfileError;
354 static GSM_Error CurrentDisplayOutputError;
356 static GSM_CBMessage *CurrentCBMessage;
357 static GSM_Error CurrentCBError;
359 static GSM_Error CurrentPhoneInfoError;
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];
365 static char CurrentIncomingCall[20] = " ";
367 /* Pointer to callback function in user code to be called when RLP frames
370 void (*RLP_RXCallback)(RLP_F96Frame *frame);
372 /* Pointer to a callback function used to return changes to a calls status */
373 /* This saves unreliable polling */
374 void (*CallPassup)(char c);
377 /* called repeatedly from a separate thread */
378 void FB61_KeepAliveProc()
380 if (!DisableKeepalive)
381 FB61_TX_SendStatusRequest();
386 /* Initialise variables and state machine. */
388 GSM_Error FB61_Initialise(char *port_device, char *initlength,
389 GSM_ConnectionType connection,
390 void (*rlp_callback)(RLP_F96Frame *frame))
394 RequestTerminate = false;
396 RLP_RXCallback = rlp_callback;
399 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
401 InitLength = atoi(initlength);
402 if (!strcmp(initlength, "default") || (InitLength == 0)) {
403 InitLength = 250; /* This is the usual value, lower may work. */
406 CurrentConnectionType = connection;
408 /* Create and start main thread. */
411 DisableKeepalive = true;
412 rtn = ! OpenConnection(PortDevice, FB61_RX_StateMachine, FB61_KeepAliveProc);
414 FB61_InitializeLink(); /* makes more sense to do this in 'this' thread */
415 DisableKeepalive = false;
418 rtn = pthread_create(&Thread, NULL, (void *)FB61_ThreadLoop, (void *)NULL);
422 return (GE_INTERNALERROR);
428 /* thread for handling incoming data */
429 void FB61_SelectLoop()
433 struct timeval timeout;
436 FD_SET(device_portfd, &readfds);
437 /* set timeout to 15 seconds */
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");
450 /* This function send the status request to the phone. */
452 GSM_Error FB61_TX_SendStatusRequest(void)
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);
461 /* This function translates GMT_MemoryType to FB61_MEMORY_xx */
463 int FB61_GetMemoryType(GSM_MemoryType memory_type)
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;
481 /* This function is used to get storage status from the phone. It currently
482 supports two different memory areas - internal and SIM. */
485 wait_on(volatile GSM_Error *what, int timeout)
488 while (timeout && (*what == GE_BUSY)) {
496 #define WAIT_ON(x, y) \
498 GSM_Error res = wait_on(x, y); \
499 if (res != GE_NONE) \
503 #define WAIT_ON1(x, y) \
505 GSM_Error res = wait_on(x, y); \
506 if (res != GE_NONE) \
510 static GSM_Error FB61_GetPhoneInfo()
512 unsigned char req[] = { FB61_FRAME_HEADER, 0x03, 0x00 };
513 FB61_TX_SendMessage(5, 0xd1, req);
514 return (wait_on(&CurrentPhoneInfoError, 20));
517 GSM_Error FB61_AnswerCall(char s)
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};
523 dprintf("Answering call %d\n\r",s);
524 FB61_TX_SendMessage(sizeof(req0), 0x01, req0);
526 FB61_TX_SendMessage(sizeof(req), 0x01, req);
527 return (wait_on(&CurrentPhoneInfoError, 20));
530 GSM_Error FB61_GetMemoryStatus(GSM_MemoryStatus *Status)
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);
539 GSM_Error FB61_GetNetworkInfo(GSM_NetworkInfo *NetworkInfo)
541 unsigned char req[] = { FB61_FRAME_HEADER, 0x70 };
542 CurrentNetworkInfo = NetworkInfo;
543 FB61_TX_SendMessage(4, 0x0a, req);
544 return wait_on(&CurrentNetworkInfoError, 20);
547 GSM_Error FB61_EnableDisplayOutput(void)
549 unsigned char req[] = { FB61_FRAME_HEADER, 0x53, 0x01};
550 FB61_TX_SendMessage(5, 0x0d, req);
551 return wait_on(&CurrentDisplayOutputError, 20);
554 GSM_Error FB61_DisableDisplayOutput(void)
556 unsigned char req[] = { FB61_FRAME_HEADER, 0x53, 0x02};
557 FB61_TX_SendMessage(5, 0x0d, req);
558 return wait_on(&CurrentDisplayOutputError, 20);
561 GSM_Error FB61_GetProfile(GSM_Profile *Profile)
564 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
566 unsigned char name_req[] = { FB61_FRAME_HEADER, 0x1a, 0x00};
567 unsigned char feat_req[] = { FB61_FRAME_HEADER, 0x13, 0x01, 0x00, 0x00};
569 CurrentProfile = Profile;
571 name_req[4] = Profile->Number;
572 feat_req[5] = Profile->Number;
573 FB61_TX_SendMessage(5, 0x05, name_req);
575 WAIT_ON(&CurrentProfileError, 20);
577 for (i = 0x00; i <= 0x09; i++) {
578 CurrentProfileError = GE_BUSY;
580 FB61_TX_SendMessage(7, 0x05, feat_req);
581 WAIT_ON(&CurrentProfileError, 20);
584 if (Profile->DefaultName > -1)
586 while (FB61_GetModel(model) != GE_NONE)
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;
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;
614 GSM_Error FB61_SetProfile(GSM_Profile *Profile)
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};
620 name_req[7] = Profile->Number;
621 name_req[8] = strlen(Profile->Name);
622 name_req[6] = name_req[8] + 2;
624 for (i = 0; i < name_req[8]; i++)
625 name_req[9 + i] = Profile->Name[i];
627 FB61_TX_SendMessage(name_req[8] + 9, 0x05, name_req);
628 WAIT_ON(&CurrentProfileError, 30);
630 feat_req[5] = Profile->Number;
631 for (i = 0x00; i <= 0x09; 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;
646 FB61_TX_SendMessage(8, 0x05, feat_req);
647 WAIT_ON(&CurrentProfileError, 20);
653 bool FB61_SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
655 u8 req[60] = { 0x00, 0xd9 };
656 /* Discontinuos transmission (DTX). See section 5.6 of GSM 04.22 version 7.0.1. */
658 if (out_dtx) req[1] = 0x01;
659 memcpy(req + 2, (u8 *) frame, 32);
660 return (FB61_TX_SendFrame(32, 0xf0, req));
664 GSM_Error FB61_GetCalendarNote(GSM_CalendarNote *CalendarNote)
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);
674 GSM_Error FB61_WriteCalendarNote(GSM_CalendarNote *CalendarNote)
676 unsigned char req[200] = { FB61_FRAME_HEADER,
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
685 req[7] = CalendarNote->Type;
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;
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;
705 req[22] = strlen(CalendarNote->Text);
709 for (i=0; i<strlen(CalendarNote->Text); i++)
710 req[current++] = CalendarNote->Text[i];
712 req[current++] = strlen(CalendarNote->Phone);
714 for (i=0; i<strlen(CalendarNote->Phone); i++)
715 req[current++] = CalendarNote->Phone[i];
717 CurrentCalendarNote = CalendarNote;
718 CurrentCalendarNoteError = GE_BUSY;
720 FB61_TX_SendMessage(current, 0x13, req);
721 return wait_on(&CurrentCalendarNoteError, 20);
724 GSM_Error FB61_DeleteCalendarNote(GSM_CalendarNote *CalendarNote)
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);
733 /* Init ir for win32 is made in winserial.c */
736 void FB61_InitIR(void)
739 unsigned char init_char = FB61_SYNC_BYTE;
740 unsigned char end_init_char = FB61_IR_END_INIT_BYTE;
742 for ( i = 0; i < 32; i++ )
743 device_write(&init_char, 1);
745 device_write(&end_init_char, 1);
749 bool FB61_InitIR115200(void)
752 u8 connect_seq[] = {FB61_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
757 struct timeval timeout;
763 /* send the connection sequence to phone */
764 FB61_TX_SendMessage(7, 0x02, connect_seq);
766 /* Wait for 1 sec. */
770 PortFD = device_getfd();
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 ) {
793 dprintf(_("Timeout in IR-mode\n"));
802 /* This function is used to open the IR connection with the phone. */
804 bool FB61_OpenIR(void)
813 struct sigaction sig_io;
815 /* Set up and install handler before enabling async IO on port. */
817 sig_io.sa_handler = FB61_SigHandler;
819 sigaction (SIGIO, &sig_io, NULL);
824 result = device_open(PortDevice, false, true, false, GCT_Infrared);
827 perror(_("Couldn't open FB61 infrared device"));
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;
837 device_changespeed(9600);
839 device_changespeed(115200);
840 ret = FB61_InitIR115200();
842 for ( i = 0; i < 4 ; i++) {
844 device_changespeed(9600);
846 device_changespeed(115200);
847 ret = FB61_InitIR115200();
855 static void FB61_Authentication()
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};
862 unsigned char magic_connect[] = {FB61_FRAME_HEADER,
865 /* The real magic goes here ... These bytes are filled in with the
866 external function FB61_GetNokiaAuth(). */
868 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
871 /* NOKIA&GNOKII Accessory */
873 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x26, 0x4e, 0x4f, 0x4b, 0x49, 0x41, 0x20,
874 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x79,
876 0x00, 0x00, 0x00, 0x00};
878 usleep(100); FB61_GetPhoneInfo(); usleep(100);
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);
886 WAIT_ON1(&CurrentMagicError, 50);
888 FB61_GetNokiaAuth(IMEI, MagicBytes, magic_connect+4);
890 FB61_TX_SendMessage(45, 0x64, magic_connect);
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)
901 unsigned char init_char = 0x55;
902 int count, idle_timer;
904 CurrentPhonebookEntry = NULL;
906 if ( CurrentConnectionType == GCT_Infrared ) {
907 dprintf(_("Starting IR mode...!\n"));
908 if (FB61_OpenIR() != true) {
910 while (!RequestTerminate)
915 } else { /* CurrentConnectionType == GCT_Serial */
917 /* Try to open serial port, if we fail we sit here and don't proceed to the
920 if (FB61_OpenSerial() != true) {
923 /* Fail so sit here till calling code works out there is a problem. */
925 while (!RequestTerminate)
932 /* Initialise link with phone or what have you */
934 /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
937 for (count = 0; count < InitLength; count ++) {
939 WRITEPHONE(PortFD, &init_char, 1);
942 FB61_TX_SendStatusRequest();
944 FB61_Authentication();
946 /* FIXME: we should implement better support for ringtones and the utility
949 // FB61_SendRingtoneRTTTL("/tmp/barbie.txt");
953 /* Now enter main loop */
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();
963 usleep(100000); /* Avoid becoming a "busy" loop. */
969 void FB61_InitializeLink()
974 unsigned char init_char = 0x55;
976 unsigned char end_init_char = 0xc1;
978 /* Daxer Added for infared support */
979 if ( CurrentConnectionType == GCT_Infrared ) {
980 dcb.DCBlength = sizeof(DCB);
982 GetCommState(hPhone, &dcb);
983 dcb.BaudRate = CBR_9600;
984 SetCommState(hPhone, &dcb);
987 /* Send init string to phone, this is a bunch of 0x55 characters. Timing is
990 for (count = 0; count < 32; count ++) {
992 WRITEPHONE(PortFD, &init_char, 1);
995 WRITEPHONE(PortFD, &end_init_char, 1);
997 if ( CurrentConnectionType == GCT_Infrared ) {
998 dcb.BaudRate = CBR_115200;
999 SetCommState(hPhone, &dcb);
1002 FB61_TX_SendStatusRequest();
1004 FB61_Authentication();
1008 /* Applications should call FB61_Terminate to shut down the FB61 thread and
1009 close the serial port. */
1011 void FB61_Terminate(void)
1013 /* Request termination of thread */
1014 RequestTerminate = true;
1017 /* Now wait for thread to terminate. */
1018 pthread_join(Thread, NULL);
1020 /* Close serial port. */
1028 GSM_Error FB61_GetRFLevel(GSM_RFUnits *units, float *level)
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
1033 float csq_map[5] = {0, 8, 16, 24, 31};
1037 CurrentRFLevel = -1;
1039 FB61_TX_SendStatusRequest();
1041 /* Wait for timeout or other error. */
1043 while (timeout && (CurrentRFLevel == -1)) {
1045 return (GE_TIMEOUT);
1049 /* Make copy in case it changes. */
1050 rf_level = CurrentRFLevel;
1055 /* Now convert between the different units we support. */
1057 /* Arbitrary units. */
1058 if (*units == GRF_Arbitrary) {
1064 if (*units == GRF_CSQ) {
1067 *level = csq_map[rf_level];
1069 *level = 99; /* Unknown/undefined */
1074 *units = GRF_Arbitrary;
1079 GSM_Error FB61_GetBatteryLevel(GSM_BatteryUnits *units, float *level)
1084 CurrentBatteryLevel = -1;
1086 FB61_TX_SendStatusRequest();
1088 /* Wait for timeout or other error. */
1089 while (timeout && (CurrentBatteryLevel == -1)) {
1091 return (GE_TIMEOUT);
1095 /* Take copy in case it changes. */
1096 batt_level = CurrentBatteryLevel;
1098 if (batt_level != -1) {
1099 /* Only units we handle at present are GBU_Arbitrary */
1100 *units = GBU_Arbitrary;
1101 *level = batt_level;
1103 } else return (GE_NOLINK);
1106 GSM_Error FB61_GetPowerSource(GSM_PowerSource *source)
1109 CurrentPowerSource=-1;
1111 FB61_TX_SendStatusRequest();
1113 /* Wait for timeout or other error. */
1114 while (timeout && (CurrentPowerSource == -1)) {
1116 return (GE_TIMEOUT);
1120 if (CurrentPowerSource != -1) {
1121 *source = CurrentPowerSource;
1123 } else return (GE_NOLINK);
1126 GSM_Error FB61_GetDisplayStatus(int *Status)
1128 unsigned char req[4]={ FB61_FRAME_HEADER, 0x51 };
1129 FB61_TX_SendMessage(4, 0x0d, req);
1130 WAIT_ON(&DisplayStatusError, 10);
1131 *Status = DisplayStatus;
1135 GSM_Error FB61_DialVoice(char *Number)
1137 unsigned char req[64] = {FB61_FRAME_HEADER, 0x01};
1138 unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01};
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);
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!
1156 GSM_Error FB61_DialData(char *Number, char type, void (* callpassup)(char c))
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 };
1181 CallPassup=callpassup;
1186 size = sizeof(req_end0);
1189 FB61_TX_SendMessage(sizeof(req3), 0x01, req3);
1190 FB61_TX_SendMessage(sizeof(req4), 0x01, req4);
1192 size = sizeof(req_end1);
1194 case -1: /* Just used to set the call passup */
1199 size = sizeof(req_end0);
1203 req[4] = strlen(Number);
1205 for(i = 0; i < strlen(Number) ; i++)
1206 req[5+i] = Number[i];
1208 memcpy(req + 5 + strlen(Number), req_end, size);
1210 FB61_TX_SendMessage(5 + size + strlen(Number), 0x01, req);
1211 if (type != 1) FB61_TX_SendMessage(26, 0x01, req2);
1216 GSM_Error FB61_GetIncomingCallNr(char *Number)
1218 if (*CurrentIncomingCall != ' ') {
1219 strcpy(Number, CurrentIncomingCall);
1221 } else return GE_BUSY;
1224 GSM_Error FB61_CancelCall(void)
1226 unsigned char req[] = { FB61_FRAME_HEADER, 0x08, 0x00, 0x85};
1228 req[4] = CallSequenceNumber;
1229 FB61_TX_SendMessage(6, 0x01, req);
1234 GSM_Error FB61_EnterSecurityCode(GSM_SecurityCode SecurityCode)
1236 unsigned char req[15] = { FB61_FRAME_HEADER, 0x0a /* Enter code request. */, 0x00 /* Type of the entered code. */ };
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);
1247 GSM_Error FB61_GetSecurityCodeStatus(int *Status)
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);
1255 GSM_Error FB61_GetDateTime(GSM_DateTime *date_time)
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);
1263 GSM_Error FB61_GetAlarm(int alarm_number, GSM_DateTime *date_time)
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);
1271 /* This function sends to the mobile phone a request for the SMS Center */
1273 GSM_Error FB61_GetSMSCenter(GSM_MessageCenter *MessageCenter)
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);
1282 /* This function set the SMS Center profile on the phone. */
1284 GSM_Error FB61_SetSMSCenter(GSM_MessageCenter *MessageCenter)
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. */
1296 req[5] = MessageCenter->No;
1297 req[7] = MessageCenter->Format;
1298 req[9] = MessageCenter->Validity;
1300 req[22] = SemiOctetPack(MessageCenter->Number, req+23);
1301 if (req[22] % 2) req[22]++;
1302 req[22] = req[22] / 2 + 1;
1304 sprintf(req+34, "%s", MessageCenter->Name);
1306 CurrentMessageCenter = MessageCenter;
1307 CurrentMessageCenterError = GE_BUSY;
1309 FB61_TX_SendMessage(35+strlen(MessageCenter->Name), 0x02, req);
1310 return wait_on(&CurrentMessageCenterError,20);
1313 GSM_Error FB61_GetSMSStatus(GSM_SMSStatus *Status)
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);
1321 GSM_Error FB61_GetIMEI(char *imei)
1324 strncpy (imei, IMEI, FB61_MAX_IMEI_LENGTH);
1326 } else return (GE_TRYAGAIN);
1329 GSM_Error FB61_GetRevision(char *revision)
1332 strncpy (revision, Revision, FB61_MAX_REVISION_LENGTH);
1334 } else return (GE_TRYAGAIN);
1337 GSM_Error FB61_GetModel(char *model)
1340 strncpy (model, Model, FB61_MAX_MODEL_LENGTH);
1342 } else return (GE_TRYAGAIN);
1345 GSM_Error FB61_SetDateTime(GSM_DateTime *date_time)
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. */
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;
1362 FB61_TX_SendMessage(14, 0x11, req);
1363 return wait_on(&CurrentSetDateTimeError, 20);
1366 /* FIXME: we should also allow to set the alarm off :-) */
1368 GSM_Error FB61_SetAlarm(int alarm_number, GSM_DateTime *date_time)
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. */
1377 req[8] = date_time->Hour;
1378 req[9] = date_time->Minute;
1380 FB61_TX_SendMessage(11, 0x11, req);
1381 return wait_on(&CurrentSetAlarmError, 20);
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
1388 GSM_Error FB61_GetMemoryLocation(GSM_PhonebookEntry *entry)
1390 unsigned char req[] = {FB61_FRAME_HEADER, 0x01, 0x00, 0x00, 0x00};
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);
1399 /* Routine to write phonebook location in phone. Designed to be called by
1400 application code. Will block until location is written or timeout
1403 GSM_Error FB61_WritePhonebookLocation(GSM_PhonebookEntry *entry)
1405 unsigned char req[128] = { FB61_FRAME_HEADER, 0x04, 0x00, 0x00 };
1406 int i = 0, current = 0;
1408 req[4] = FB61_GetMemoryType(entry->MemoryType);
1409 req[5] = entry->Location;
1411 req[6] = strlen(entry->Name);
1415 for (i = 0; i<strlen(entry->Name); i++)
1416 req[current+i] = entry->Name[i];
1418 current += strlen(entry->Name);
1420 req[current++] = strlen(entry->Number);
1422 for (i = 0; i < strlen(entry->Number); i++)
1423 req[current+i] = entry->Number[i];
1425 current += strlen(entry->Number);
1427 /* Jano: This allow to save 14 characters name into SIM memory, when
1428 No Group is selected. */
1430 if (entry->Group == 5)
1431 req[current++] = 0xff;
1433 req[current++] = entry->Group;
1435 FB61_TX_SendMessage(current, 3, req);
1436 return wait_on(&CurrentPhonebookError, 50);
1439 GSM_Error FB61_NetMonitor(unsigned char mode, char *Screen)
1441 unsigned char req1[] = { 0x00, 0x01, 0x64, 0x01 };
1442 unsigned char req2[] = { 0x00, 0x01, 0x7e, 0x00 };
1444 CurrentNetmonitor = Screen;
1445 FB61_TX_SendMessage(4, 0x40, req1);
1447 FB61_TX_SendMessage(4, 0x40, req2);
1448 return wait_on(&CurrentNetmonitorError, 20);
1451 GSM_Error FB61_SendDTMF(char *String)
1453 unsigned char req[64] = { FB61_FRAME_HEADER, 0x50, 0x00 /* Length of DTMF string. */ };
1454 u8 length=strlen(String);
1457 sprintf(req+5, "%s", String);
1458 FB61_TX_SendMessage(5+length, 0x01, req);
1462 GSM_Error FB61_GetSpeedDial(GSM_SpeedDial *entry)
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);
1471 GSM_Error FB61_SetSpeedDial(GSM_SpeedDial *entry)
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);
1481 GSM_Error FB61_GetSMSMessage(GSM_SMSMessage *message)
1483 unsigned char req[10] = { FB61_FRAME_HEADER, 0x07, 0x02 /* Unknown */, 0x00 /* Location */, 0x01, 0x64};
1486 /* State machine code writes data to these variables when it comes in. */
1488 CurrentSMSMessage = message;
1489 CurrentSMSMessageError = GE_BUSY;
1490 req[5] = message->Location;
1491 FB61_TX_SendMessage(8, 0x02, req);
1493 while (timeout && (CurrentSMSMessageError == GE_BUSY || CurrentSMSMessageError == GE_SMSWAITING)) {
1495 return (GE_TIMEOUT);
1498 return (CurrentSMSMessageError);
1501 GSM_Error FB61_DeleteSMSMessage(GSM_SMSMessage *message)
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);
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)
1516 unsigned char req[256] = {
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)
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
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)
1549 SMS->MessageCenter.No = 0;
1551 dprintf(_("Sending SMS to %s via message center %s\n"), SMS->Destination, SMS->MessageCenter.Number);
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);
1561 /* such messages should be sent as concatenated */
1562 if (strlen(SMS->MessageText) > GSM_MAX_SMS_LENGTH)
1563 return(GE_SMSTOOLONG);
1566 /* size is the length of the data in octets including udh */
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
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 */
1579 size += SMS->MessageTextLength;
1582 size += PackSevenBitsToEight((7-offset)%7, SMS->MessageText, req + 42 + offset);
1583 req[22] = (offset*8 +6/*round-up*/)/7 +strlen(SMS->MessageText)*7;
1586 CurrentSMSMessageError=GE_BUSY;
1588 req[6] = SemiOctetPack(SMS->MessageCenter.Number, req+7);
1589 if (req[6] % 2) req[6]++;
1591 req[6] = req[6] / 2 + 1;
1593 /* Mask for request for delivery report from SMSC */
1594 if (SMS->Type == GST_DR) req[18] |= 0x20;
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;
1605 /* Mask for compression */
1606 /* FIXME: support for compression */
1608 /* if (SMS->Compression) req[21] = req[21] | 0x20; */
1610 req[23] = SemiOctetPack(SMS->Destination, req+24);
1612 /* TP-Validity Period handling */
1613 req[35] = SMS_Validity_to_VP(SMS->Validity);
1615 FB61_TX_SendMessage(42+size, 0x02, req);
1616 return wait_on(&CurrentSMSMessageError, 70);
1619 /* FIXME: UDH & EightBit not implemented yet */
1620 GSM_Error FB61_SaveSMSMessage(GSM_SMSMessage *SMS)
1622 unsigned char req[256] = {
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)
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
1650 if (SMS->Status == GSS_NOTSENTREAD)
1654 req[6] = SMS->Location;
1657 /* such messages should be sent as concatenated */
1658 if (strlen(SMS->MessageText) > GSM_MAX_SMS_LENGTH)
1659 return(GE_SMSTOOLONG);
1661 /* size is the length of the data in octets including udh */
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
1667 /* offset now denotes UDH length */
1668 size = PackSevenBitsToEight((7-offset)%7, SMS->MessageText, req + 44 + offset);
1671 req[24] = (offset*8 + ((7-offset)%7)) / 7 + strlen(SMS->MessageText);
1673 FB61_TX_SendMessage(44+size, 0x14, req);
1674 return wait_on(&CurrentSMSMessageError, 70);
1677 /* Enable and disable Cell Broadcasting */
1679 GSM_Error FB61_EnableCellBroadcast(void)
1681 unsigned char req[] = {FB61_FRAME_HEADER, 0x20, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01};
1682 CurrentCBError = GE_BUSY;
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);
1692 GSM_Error FB61_DisableCellBroadcast(void) /* Should work, but not tested fully */
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);
1699 GSM_Error FB61_ReadCellBroadcast(GSM_CBMessage *Message)
1701 if (CurrentCBMessage != NULL) {
1702 if (CurrentCBMessage->New == true) {
1703 Message->Channel = CurrentCBMessage->Channel;
1704 strcpy(Message->Message,CurrentCBMessage->Message);
1705 CurrentCBMessage->New = false;
1709 return (GE_NONEWCBRECEIVED);
1712 /* Send a bitmap or welcome-note */
1714 GSM_Error FB61_SetBitmap(GSM_Bitmap *Bitmap)
1716 unsigned char req[600] = { FB61_FRAME_HEADER };
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);
1729 FB61_TX_SendMessage(count, 0x05, req);
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);
1740 FB61_TX_SendMessage(count, 0x05, req);
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);
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);
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:
1780 0x02 - View Graphics
1781 0x03 - Send Graphics
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);
1796 case GSM_PictureImage:
1797 return (GE_NOTIMPLEMENTED);
1803 return wait_on(&SetBitmapError, 70);
1806 /* Get a bitmap from the phone */
1808 GSM_Error FB61_GetBitmap(GSM_Bitmap *Bitmap)
1810 unsigned char req[10] = { FB61_FRAME_HEADER };
1815 GetBitmapError = GE_BUSY;
1817 /* This is needed to avoid the packet being interrupted */
1818 /* Remove when multipacket code is implemented fully */
1820 DisableKeepalive = true;
1822 while (timeout && (MessagesSent != AcksReceived)) {
1827 /* We'll assume that nothing more will be received after 1 sec */
1829 MessagesSent = AcksReceived;
1831 switch (GetBitmap->type) {
1832 case GSM_StartupLogo:
1833 req[count++] = 0x16;
1834 FB61_TX_SendMessage(count, 0x05, req);
1836 case GSM_WelcomeNoteText:
1837 req[count++] = 0x16;
1838 FB61_TX_SendMessage(count, 0x05, req);
1840 case GSM_DealerNoteText:
1841 req[count++] = 0x16;
1842 FB61_TX_SendMessage(count, 0x05, req);
1844 case GSM_OperatorLogo:
1845 req[count++] = 0x33;
1846 req[count++] = 0x01; /* Location 1 */
1847 FB61_TX_SendMessage(count, 0x05, req);
1849 case GSM_CallerLogo:
1850 req[count++] = 0x10;
1851 req[count++] = Bitmap->number;
1852 FB61_TX_SendMessage(count, 0x03, req);
1858 /* 5secs for the command to complete */
1860 WAIT_ON(&GetBitmapError, 50);
1862 DisableKeepalive = false;
1864 return (GetBitmapError);
1868 GSM_Error FB61_SetRingTone(GSM_Ringtone *ringtone)
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
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);
1888 GSM_Error FB61_Reset(unsigned char type)
1890 unsigned char req[4] = { 0x00,0x01,0x64,0x03 };
1892 FB61_TX_SendMessage(4, 0x40, req);
1898 void FB61_DumpSerial(void)
1901 unsigned int Flags=0;
1903 PortFD = device_getfd();
1904 ioctl(PortFD, TIOCMGET, &Flags);
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"));
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
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.
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.
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
1936 /* FIXME: In this function we use ioctls - can people with different OSes than
1937 my (Linux) tell me if it works for them? */
1939 void FB61_SetFBUS(void)
1943 dprintf(_("Setting FBUS communication...\n"));
1946 /* clearing the RTS bit and setting the DTR bit*/
1947 device_setdtrrts(1, 0);
1954 /* Called by initialisation code to open comm port in asynchronous mode. */
1956 bool FB61_OpenSerial(void)
1963 struct sigaction sig_io;
1965 /* Set up and install handler before enabling async IO on port. */
1967 sig_io.sa_handler = FB61_SigHandler;
1968 sig_io.sa_flags = 0;
1969 sigaction (SIGIO, &sig_io, NULL);
1974 result = device_open(PortDevice, false, true, false, GCT_Serial);
1977 perror(_("Couldn't open FB61 device"));
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;
1987 device_changespeed(115200);
1992 void FB61_SigHandler(int status)
1994 unsigned char buffer[255];
1996 res = device_read(buffer, 255);
1997 for (count = 0; count < res ; count ++)
1998 FB61_RX_StateMachine(buffer[count]);
2002 char *FB61_GetPackedDateTime(u8 *Number)
2004 static char Buffer[20] = "";
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);
2016 enum FB61_RX_States FB61_RX_DispatchMessage(void)
2018 int i, tmp, count, offset, off, length;
2019 unsigned char output[160];
2022 if (RX_Multiple) return FB61_RX_Sync;
2025 /* Do not debug Ack and RLP frames to detail. */
2027 if (MessageType != FB61_FRTYPE_ACK && MessageType != 0xf1)
2028 FB61_RX_DisplayMessage();
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.
2039 The message looks like this:
2047 Phone: [01 ][08 ][00 ] is the header of the frame
2049 [03 ] is the call message subtype
2051 [05 ] is the call sequence number
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 :-(
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"));
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');
2076 /* Remote end has gone away before you answer the call. Probably your
2077 mother-in-law or banker (which is worse?) ... */
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(' ');
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
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]);
2095 dprintf(_(" Name: "));
2096 for (tmp = 0; tmp < MessageBuffer[7+count]; tmp++)
2097 dprintf("%c", MessageBuffer[8+count+tmp]);
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]);
2106 /* Call answered. Probably your girlfriend...*/
2108 dprintf(_("Message: Call answered.\n"));
2109 dprintf(_(" Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2112 /* Call ended. Girlfriend is girlfriend, but time is money :-) */
2114 dprintf(_("Message: Call ended by your phone.\n"));
2115 dprintf(_(" Sequence nr. of the call: %d\n"), MessageBuffer[4]);
2118 /* This message has been seen with the message of subtype 0x09
2119 after I hang the call.
2126 Phone: [01 ][08 ][00 ][0a ][04 ][87 ][01 ][42B][1a ][c2 ]
2128 What is the meaning of 87? Can you spell some magic light into
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"));
2138 CurrentIncomingCall[0] = ' ';
2139 if (CallPassup) CallPassup(' ');
2143 dprintf(_("Message: Unknown message of type 0x01\n"));
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;
2157 case 0x03: /* SMS message send to the network failed */
2158 dprintf(_("Message: Sending SMS Message failed.\n"));
2159 CurrentSMSMessageError = GE_SMSSENDFAILED;
2163 dprintf(_("Message: SMS Message Received\n"));
2164 dprintf(_(" SMS center number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer+7));
2166 MessageBuffer[23] = (MessageBuffer[23]+1)/2+1;
2168 dprintf(_(" Remote number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer+23));
2169 dprintf(_(" Date: %s\n"), FB61_GetPackedDateTime(MessageBuffer+35));
2170 dprintf(_(" SMS: "));
2172 tmp = UnpackEightBitsToSeven(0, MessageLength - 42 - 2, MessageBuffer[22], MessageBuffer + 42, output);
2174 for (i = 0; i < tmp; i++) dprintf("%c", GSM_Default_Alphabet[output[i]]);
2180 dprintf(_("Message: Cell Broadcast enabled/disabled successfully.\n"));
2181 CurrentCBError = GE_NONE;
2185 CurrentCBMessage->Channel = MessageBuffer[7];
2186 CurrentCBMessage->New = true;
2187 tmp=UnpackEightBitsToSeven(0, 82, 82, MessageBuffer+10, output);
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]]);
2195 for (i = 0; i < tmp; i++)
2196 CurrentCBMessage->Message[i] = GSM_Default_Alphabet[output[i]];
2202 dprintf(_("Message: SMS Center correctly set.\n"));
2203 CurrentMessageCenterError = GE_NONE;
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));
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 "));
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;
2229 dprintf(_(" SMS Center message validity is "));
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;
2241 CurrentMessageCenterError = GE_NONE;
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
2248 dprintf(_("Message: SMS Center error received:\n"));
2249 dprintf(_(" The request for SMS Center failed.\n"));
2251 /* FIXME: appropriate error. */
2252 CurrentMessageCenterError = GE_INTERNALERROR;
2256 dprintf(_("Unknown message!\n"));
2262 /* Phonebook handling */
2266 switch (MessageBuffer[3]) {
2270 CurrentPhonebookEntry->Empty = true;
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]);
2279 memcpy(CurrentPhonebookEntry->Name, MessageBuffer + 6, count);
2280 CurrentPhonebookEntry->Name[count] = 0x00;
2281 CurrentPhonebookEntry->Empty = false;
2284 count = MessageBuffer[6+count];
2286 dprintf(_(" Number: "));
2287 for (tmp = 0; tmp < count; tmp++)
2288 dprintf("%c", MessageBuffer[i+tmp]);
2291 memcpy(CurrentPhonebookEntry->Number, MessageBuffer + i, count);
2292 CurrentPhonebookEntry->Number[count] = 0x00;
2293 CurrentPhonebookEntry->Group = MessageBuffer[i+count];
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];
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);
2307 /* Signal no error to calling code. */
2309 CurrentPhonebookError = GE_NONE;
2314 dprintf(_("Message: Phonebook read entry error received:\n"));
2315 switch (MessageBuffer[4]) {
2317 dprintf(_(" Invalid memory type!\n"));
2318 CurrentPhonebookError = GE_INVALIDMEMORYTYPE;
2321 dprintf(_(" Unknown error!\n"));
2322 CurrentPhonebookError = GE_INTERNALERROR;
2328 dprintf(_("Message: Phonebook written correctly.\n"));
2329 CurrentPhonebookError = GE_NONE;
2333 switch (MessageBuffer[4]) {
2335 /* FIXME: other errors? When I send the phonebook with index of 350 it
2336 still report error 0x7d :-( */
2339 dprintf(_("Message: Phonebook not written - name is too long.\n"));
2340 CurrentPhonebookError = GE_PHBOOKNAMETOOLONG;
2344 dprintf(_(" Unknown error!\n"));
2345 CurrentPhonebookError = GE_INTERNALERROR;
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;
2362 switch (MessageBuffer[4]) {
2364 dprintf(_("Message: Memory status error, phone is probably powered off.\n"));
2365 CurrentMemoryStatusError = GE_TIMEOUT;
2369 dprintf(_("Message: Memory status error, memory type not supported by phone model.\n"));
2370 CurrentMemoryStatusError = GE_INTERNALERROR;
2374 dprintf(_("Message: Memory status error, waiting for security code.\n"));
2375 CurrentMemoryStatusError = GE_INVALIDSECURITYCODE;
2379 dprintf(_("Message: Unknown Memory status error, subtype (MessageBuffer[4]) = %02x\n"),MessageBuffer[4]);
2385 case 0x11: /* Get group data */
2387 /* [ID],[name_len],[name].,[ringtone],[graphicon],[lenhi],[lenlo],[bitmap] */
2389 if (GetBitmap != NULL) {
2390 count = MessageBuffer[5];
2391 memcpy(GetBitmap->text, MessageBuffer+6, count);
2392 GetBitmap->text[count] = 0;
2394 dprintf(_("Message: Caller group logo etc.\n"));
2395 dprintf(_("Caller group name: %s\n"), GetBitmap->text);
2398 GetBitmap->ringtone = MessageBuffer[count++];
2400 GetBitmap->size = MessageBuffer[count++]<<8;
2401 GetBitmap->size += MessageBuffer[count++];
2403 GetBitmap->width = MessageBuffer[count++];
2404 GetBitmap->height = MessageBuffer[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;
2412 dprintf(_("Message: Caller group data received but not requested!\n"));
2416 case 0x12: /* Get group data error */
2417 GetBitmapError = GE_UNKNOWN;
2418 dprintf(_("Message: Error attempting to get caller group data.\n"));
2421 case 0x14: /* Set group data OK */
2422 SetBitmapError = GE_NONE;
2423 dprintf(_("Message: Caller group data set correctly.\n"));
2426 case 0x15: /* Set group data error */
2427 SetBitmapError = GE_UNKNOWN;
2428 dprintf(_("Message: Error attempting to set caller group data\n"));
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;
2442 dprintf(_("Message: Speed dial entry error\n"));
2443 CurrentSpeedDialError = GE_INVALIDSPEEDDIALLOCATION;
2447 dprintf(_("Message: Speed dial entry set.\n"));
2448 CurrentSpeedDialError = GE_NONE;
2452 dprintf(_("Message: Speed dial entry setting error.\n"));
2453 CurrentSpeedDialError = GE_INVALIDSPEEDDIALLOCATION;
2457 dprintf(_("Message: Unknown message of type 0x03\n"));
2466 switch (MessageBuffer[3]) {
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
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;
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;
2485 dprintf(_(" Battery Level: %d\n"), MessageBuffer[8]);
2486 dprintf(_(" Signal strength: %d\n"), MessageBuffer[5]);
2488 CurrentRFLevel = MessageBuffer[5];
2489 CurrentBatteryLevel = MessageBuffer[8];
2490 CurrentPowerSource = MessageBuffer[7];
2494 dprintf(_("Message: Unknown message of type 0x04\n"));
2500 /* Startup Logo, Operator Logo and Profiles. */
2503 switch (MessageBuffer[3]) {
2504 case 0x11: /* Profile feature change result */
2505 dprintf(_("Message: Profile feature change result.\n"));
2506 CurrentProfileError = GE_NONE;
2509 case 0x14: /* Profile feature */
2510 switch (MessageBuffer[6]) {
2512 CurrentProfile->KeypadTone = MessageBuffer[8];
2515 CurrentProfile->Lights = MessageBuffer[8];
2518 CurrentProfile->CallAlert = MessageBuffer[8];
2521 CurrentProfile->Ringtone = MessageBuffer[8];
2524 CurrentProfile->Volume = MessageBuffer[8];
2527 CurrentProfile->MessageTone = MessageBuffer[8];
2530 CurrentProfile->Vibration = MessageBuffer[8];
2533 CurrentProfile->WarningTone = MessageBuffer[8];
2536 CurrentProfile->CallerGroups = MessageBuffer[8];
2539 CurrentProfile->AutomaticAnswer = MessageBuffer[8];
2543 CurrentProfileError = GE_NONE;
2546 case 0x17: /* Startup Logo */
2547 dprintf(_("Message: Startup Logo, welcome note and dealer welcome note received.\n"));
2548 if (GetBitmap != NULL) {
2551 for (tmp = 0; tmp < MessageBuffer[4]; tmp++){
2552 switch (MessageBuffer[count++]) {
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);
2561 length = MessageBuffer[count++];
2562 length = length * MessageBuffer[count++] / 8;
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;
2571 length = MessageBuffer[count];
2572 if (GetBitmap->type == GSM_WelcomeNoteText) {
2573 memcpy(GetBitmap->text, MessageBuffer + count + 1, length);
2574 GetBitmap->text[length] = 0;
2576 dprintf(_("Startup Text supported - "));
2578 dprintf(_("currently set to \""));
2579 for (i = 0; i < length; i++) dprintf(_("%c"), MessageBuffer[count+1+i]);
2582 dprintf(_("currently empty\n"));
2584 count += length + 1;
2585 if (GetBitmap->type == GSM_WelcomeNoteText) supported = true;
2588 length = MessageBuffer[count];
2589 if (GetBitmap->type == GSM_DealerNoteText) {
2590 memcpy(GetBitmap->text, MessageBuffer + count + 1, length);
2591 GetBitmap->text[length] = 0;
2593 dprintf(_("Dealer Welcome supported - "));
2595 dprintf(_("currently set to \""));
2596 for (i = 0;i < length; i++) dprintf(_("%c"), MessageBuffer[count+1+i]);
2598 } else dprintf(_("currently empty\n"));
2599 count += length + 1;
2600 if (GetBitmap->type==GSM_DealerNoteText) supported = true;
2604 if (supported) GetBitmapError = GE_NONE;
2605 else GetBitmapError = GE_NOTSUPPORTED;
2606 } else dprintf(_("Message: Startup logo received but not requested!\n"));
2609 case 0x19: /* Set startup OK */
2610 SetBitmapError = GE_NONE;
2611 dprintf(_("Message: Startup logo, welcome note or dealer welcome note correctly set.\n"));
2614 case 0x1b: /* Incoming profile name */
2615 if (MessageBuffer[9] == 0x00)
2616 CurrentProfile->DefaultName = MessageBuffer[8];
2618 CurrentProfile->DefaultName = -1;
2619 sprintf(CurrentProfile->Name, MessageBuffer + 10, MessageBuffer[9]);
2620 CurrentProfile->Name[MessageBuffer[9]] = '\0';
2622 CurrentProfileError = GE_NONE;
2625 case 0x1d: /* Profile name set result */
2626 CurrentProfileError = GE_NONE;
2629 case 0x31: /* Set Operator Logo OK */
2630 dprintf(_("Message: Operator logo correctly set.\n"));
2631 SetBitmapError = GE_NONE;
2634 case 0x32: /* Set Operator Logo Error */
2635 SetBitmapError = GE_UNKNOWN;
2636 dprintf(_("Message: Error setting operator logo!\n"));
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"),
2653 GSM_GetNetworkName(GetBitmap->netcode));
2654 GetBitmap->size = MessageBuffer[count++] << 8;
2655 GetBitmap->size += MessageBuffer[count++];
2657 GetBitmap->width = MessageBuffer[count++];
2658 GetBitmap->height = MessageBuffer[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;
2665 else dprintf(_("Message: Operator logo received but not requested!\n"));
2668 case 0x35: /* Get op logo error */
2669 dprintf(_("Message: Error getting operator logo!\n"));
2670 GetBitmapError = GE_UNKNOWN;
2675 /* Security code requests */
2678 switch(MessageBuffer[3]) {
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;
2691 CurrentSecurityCodeError = GE_NONE;
2695 dprintf(_("Message: Security code accepted.\n"));
2696 CurrentSecurityCodeError = GE_NONE;
2700 dprintf(_("Message: Security code is wrong. You're not my big owner :-)\n"));
2701 CurrentSecurityCodeError = GE_INVALIDSECURITYCODE;
2711 switch (MessageBuffer[3]) {
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]);
2719 dprintf(_("Message: Network information:\n"));
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: "));
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;
2739 dprintf(_(" Network selection: %s\n"), MessageBuffer[9] == 1 ? _("manual") : _("automatic"));
2741 CurrentNetworkInfoError = GE_NONE;
2745 dprintf(_("Message: Unknown message of type 0x0a\n"));
2751 /* Display status. */
2754 switch(MessageBuffer[3]) {
2756 dprintf("%i %i ", MessageBuffer[6], MessageBuffer[5]);
2757 for (i = 0; i < MessageBuffer[7]; i++)
2758 dprintf("%c", MessageBuffer[9+(i*2)]);
2763 for (i = 0; i < MessageBuffer[4]; i++)
2764 if (MessageBuffer[2*i+6] == 2)
2765 DisplayStatus |= 1 << (MessageBuffer[2*i+5] - 1);
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;
2780 if (MessageBuffer[5] == 1) {
2781 dprintf(_("Display output successfully disabled/enabled.\n"));
2782 CurrentDisplayOutputError = GE_NONE;
2787 dprintf(_("Unknown message of type 0x0d.\n"));
2792 /* Phone Clock and Alarm */
2795 switch (MessageBuffer[3]) {
2797 switch (MessageBuffer[4]) {
2799 dprintf(_("Message: Date and time set correctly\n"));
2800 CurrentSetDateTimeError = GE_NONE;
2804 dprintf(_("Message: Date and time set error\n"));
2805 CurrentSetDateTimeError = GE_INVALIDDATETIME;
2811 CurrentDateTime->Year = 256 * MessageBuffer[8] + MessageBuffer[9];
2812 CurrentDateTime->Month = MessageBuffer[10];
2813 CurrentDateTime->Day = MessageBuffer[11];
2815 CurrentDateTime->Hour = MessageBuffer[12];
2816 CurrentDateTime->Minute = MessageBuffer[13];
2817 CurrentDateTime->Second = MessageBuffer[14];
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);
2823 CurrentDateTimeError = GE_NONE;
2827 switch (MessageBuffer[4]) {
2829 dprintf(_("Message: Alarm set correctly\n"));
2830 CurrentSetAlarmError = GE_NONE;
2834 dprintf(_("Message: Date and time set error\n"));
2835 CurrentSetAlarmError = GE_INVALIDDATETIME;
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"));
2845 CurrentAlarm->Hour = MessageBuffer[9];
2846 CurrentAlarm->Minute = MessageBuffer[10];
2847 CurrentAlarm->Second = 0;
2848 CurrentAlarm->AlarmEnabled = (MessageBuffer[8] == 2);
2849 CurrentAlarmError = GE_NONE;
2853 dprintf(_("Message: Unknown message of type 0x11\n"));
2858 /* Calendar notes handling */
2861 switch (MessageBuffer[3]) {
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;
2869 dprintf(_("Message: Calendar note write failed!\n"));
2870 CurrentCalendarNoteError = GE_INTERNALERROR;
2873 dprintf(_("Message: Calendar note write failed!\n"));
2874 CurrentCalendarNoteError = GE_INTERNALERROR;
2877 dprintf(_("Unknown message of type 0x13 and subtype 0x65\n"));
2885 switch (MessageBuffer[4]) {
2889 CurrentCalendarNote->Type = MessageBuffer[8];
2891 CurrentCalendarNote->Time.Year = 256 * MessageBuffer[9] + MessageBuffer[10];
2892 CurrentCalendarNote->Time.Month = MessageBuffer[11];
2893 CurrentCalendarNote->Time.Day = MessageBuffer[12];
2895 CurrentCalendarNote->Time.Hour = MessageBuffer[13];
2896 CurrentCalendarNote->Time.Minute = MessageBuffer[14];
2897 CurrentCalendarNote->Time.Second = MessageBuffer[15];
2899 CurrentCalendarNote->Alarm.Year = 256 * MessageBuffer[16] + MessageBuffer[17];
2900 CurrentCalendarNote->Alarm.Month = MessageBuffer[18];
2901 CurrentCalendarNote->Alarm.Day = MessageBuffer[19];
2903 CurrentCalendarNote->Alarm.Hour = MessageBuffer[20];
2904 CurrentCalendarNote->Alarm.Minute = MessageBuffer[21];
2905 CurrentCalendarNote->Alarm.Second = MessageBuffer[22];
2907 memcpy(CurrentCalendarNote->Text, MessageBuffer + 24, MessageBuffer[23]);
2908 CurrentCalendarNote->Text[MessageBuffer[23]] = 0;
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;
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);
2923 /* Some messages do not have alarm set up */
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);
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;
2942 dprintf(_("Message: Calendar note not available\n"));
2943 CurrentCalendarNoteError = GE_INVALIDCALNOTELOCATION;
2947 dprintf(_("Message: Calendar note error\n"));
2948 CurrentCalendarNoteError = GE_INTERNALERROR;
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'
2959 dprintf(_("Message: Calendar note deleted\n"));
2960 CurrentCalendarNoteError = GE_NONE;
2963 dprintf(_("Message: Calendar note can't be deleted\n"));
2964 CurrentCalendarNoteError = GE_INVALIDCALNOTELOCATION;
2967 dprintf(_("Message: Calendar note deleting error\n"));
2968 CurrentCalendarNoteError = GE_INTERNALERROR;
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]);
2982 dprintf(_("Message: Unknown message of type 0x13\n"));
2988 /* SMS Messages frame received */
2991 switch (MessageBuffer[3]) {
2993 switch (MessageBuffer[7]) {
2995 CurrentSMSMessage->Type = GST_MT;
2999 CurrentSMSMessage->Type = GST_DR;
3003 CurrentSMSMessage->Type = GST_MO;
3007 CurrentSMSMessage->Type = GST_UN;
3008 offset = 4; /* ??? */
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.
3025 if (MessageBuffer[4] & 0x02)
3026 CurrentSMSMessage->Status = GSS_NOTSENTREAD;
3028 CurrentSMSMessage->Status = GSS_SENTREAD;
3031 CurrentSMSMessage->UDHPresent=!!(MessageBuffer[20] & 0x40);
3033 MessageBuffer[20+offset] = (MessageBuffer[20+offset]+1)/2+1;
3035 dprintf(_("Number: %d\n"), MessageBuffer[6]);
3036 switch (CurrentSMSMessage->Type) {
3038 dprintf(_("Message: Outbox message (mobile originated)\n"));
3039 if (CurrentSMSMessage->Status)
3040 dprintf(_("Sent\n"));
3042 dprintf(_("Not sent\n"));
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"));
3052 if (CurrentSMSMessage->Status)
3053 dprintf(_("Read\n"));
3055 dprintf(_("Not read\n"));
3057 dprintf(_(" Date: %s "), FB61_GetPackedDateTime(MessageBuffer + 32 + offset));
3059 if (MessageBuffer[38+offset]) {
3060 if (MessageBuffer[38+offset] & 0x08)
3065 dprintf(_("%02d00"), (10 * (MessageBuffer[38+offset] & 0x07) + (MessageBuffer[38+offset] >> 4)) / 4);
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)
3077 dprintf(_("%02d00"),(10 * (MessageBuffer[45+offset] & 0x07) + (MessageBuffer[45+offset] >> 4)) / 4);
3081 dprintf(_(" SMS center number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 8));
3082 dprintf(_(" Remote number: %s\n"), SEMIOCTETUNPACK_STATIC_BYTES(MessageBuffer + 20 + offset));
3086 /* In Outbox messages fields:
3090 are not filled in, so we ignore it.
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));
3106 if (CurrentSMSMessage->Type != GST_DR) {
3108 if ((MessageBuffer[18+offset] & 0xf4) == 0xf4) {
3109 CurrentSMSMessage->EightBit = true;
3110 tmp=MessageBuffer[19+offset];
3112 memcpy(output, MessageBuffer - 39 - offset - 2, tmp - offset);
3115 CurrentSMSMessage->EightBit = false;
3116 tmp=MessageBuffer[19+offset] - (off * 8 + ((7-off)%7)) / 7;
3118 tmp=UnpackEightBitsToSeven((7-off)%7, MessageLength - 39 - offset - 2, tmp, MessageBuffer + 39 + offset, output);
3120 for (i = 0; i < tmp;i++) {
3121 dprintf("%c", GSM_Default_Alphabet[output[i]]);
3122 CurrentSMSMessage->MessageText[i] = GSM_Default_Alphabet[output[i]];
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]) {
3139 dprintf(_("SM received by the SME"));
3142 dprintf(_("SM forwarded by the SC to the SME but the SC is unable to confirm delivery"));
3145 dprintf(_("SM replaced by the SC"));
3148 } else if (MessageBuffer[22] & 0x40) {
3150 strcpy(CurrentSMSMessage->MessageText, _("Failed"));
3152 /* more detailed reason only for debug */
3154 if (MessageBuffer[22] & 0x20) {
3155 dprintf(_("Temporary error, SC is not making any more transfer attempts\n"));
3157 switch (MessageBuffer[22]) {
3159 dprintf(_("Congestion"));
3162 dprintf(_("SME busy"));
3165 dprintf(_("No response from SME"));
3168 dprintf(_("Service rejected"));
3171 dprintf(_("Quality of service not aviable"));
3174 dprintf(_("Error in SME"));
3177 dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3181 dprintf(_("Permanent error, SC is not making any more transfer attempts\n"));
3182 switch (MessageBuffer[22]) {
3184 dprintf(_("Remote procedure error"));
3187 dprintf(_("Incompatibile destination"));
3190 dprintf(_("Connection rejected by SME"));
3193 dprintf(_("Not obtainable"));
3196 dprintf(_("Quality of service not aviable"));
3199 dprintf(_("No internetworking available"));
3202 dprintf(_("SM Validity Period Expired"));
3205 dprintf(_("SM deleted by originating SME"));
3208 dprintf(_("SM Deleted by SC Administration"));
3211 dprintf(_("SM does not exist"));
3214 dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3218 } else if (MessageBuffer[22] & 0x20) {
3219 strcpy(CurrentSMSMessage->MessageText, _("Pending"));
3221 /* more detailed reason only for debug */
3222 dprintf(_("Temporary error, SC still trying to transfer SM\n"));
3223 switch (MessageBuffer[22]) {
3225 dprintf(_("Congestion"));
3228 dprintf(_("SME busy"));
3231 dprintf(_("No response from SME"));
3234 dprintf(_("Service rejected"));
3237 dprintf(_("Quality of service not aviable"));
3240 dprintf(_("Error in SME"));
3243 dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3247 strcpy(CurrentSMSMessage->MessageText, _("Unknown"));
3249 /* more detailed reason only for debug */
3250 dprintf(_("Reserved/Specific to SC: %x"), MessageBuffer[22]);
3252 CurrentSMSMessage->MessageTextLength = strlen(CurrentSMSMessage->MessageText);
3255 CurrentSMSMessage->MessageText[CurrentSMSMessage->MessageTextLength] = 0;
3257 CurrentSMSMessage->MemoryType = MessageBuffer[5];
3258 CurrentSMSMessage->MessageNumber = MessageBuffer[6];
3260 /* Signal no error to calling code. */
3262 CurrentSMSMessageError = GE_NONE;
3267 dprintf(_("Message stored at %d\n"), MessageBuffer[5]);
3268 CurrentSMSMessageError = GE_NONE;
3272 dprintf(_("SMS saving failed\n"));
3273 switch (MessageBuffer[4]) {
3275 dprintf(_(" All locations busy.\n"));
3276 CurrentSMSMessageError = GE_MEMORYFULL;
3279 dprintf(_(" Invalid location!\n"));
3280 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3283 dprintf(_(" Unknown error.\n"));
3284 CurrentSMSMessageError = GE_UNKNOWN;
3290 /* We have requested invalid or empty location. */
3291 dprintf(_("Message: SMS reading failed.\n"));
3292 switch (MessageBuffer[4]) {
3294 dprintf(_(" Invalid location!\n"));
3295 CurrentSMSMessageError = GE_INVALIDSMSLOCATION;
3298 dprintf(_(" Empty SMS location.\n"));
3299 CurrentSMSMessageError = GE_EMPTYSMSLOCATION;
3304 case 0x0b: /* successful delete */
3305 dprintf(_("Message: SMS deleted successfully.\n"));
3306 CurrentSMSMessageError = GE_NONE;
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;
3320 dprintf(_("Message: SMS Status error, probably not authorized by PIN\n"));
3321 CurrentSMSStatusError = GE_INTERNALERROR;
3325 CurrentSMSStatusError = GE_INTERNALERROR;
3332 /* Internal phone functions? */
3336 switch(MessageBuffer[2]) {
3340 switch(MessageBuffer[3]) {
3342 dprintf(_("Message: Netmonitor correctly set.\n"));
3343 CurrentNetmonitorError = GE_NONE;
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;
3356 dprintf(_("Unknown message of type 0x40.\n"));
3361 /* Mobile phone identification */
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);
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);
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);
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. */
3385 dprintf(_(" Magic bytes: %02x %02x %02x %02x\n"), MessageBuffer[50], MessageBuffer[51], MessageBuffer[52], MessageBuffer[53]);
3387 MagicBytes[0] = MessageBuffer[50];
3388 MagicBytes[1] = MessageBuffer[51];
3389 MagicBytes[2] = MessageBuffer[52];
3390 MagicBytes[3] = MessageBuffer[53];
3391 CurrentMagicError = GE_NONE;
3394 /***** Acknowlegment of our frames. *****/
3396 dprintf(_("[Received Ack of type %02x, seq: %2x]\n"), MessageBuffer[0], MessageBuffer[1]);
3401 /***** Power on message. *****/
3403 dprintf(_("Message: The phone is powered on - seq 1.\n"));
3406 /***** Phone info. *****/
3408 #if defined WIN32 || !defined HAVE_SNPRINTF
3409 sprintf(Model, "%s", MessageBuffer + 21);
3410 sprintf(Revision, "SW%s", MessageBuffer + 5);
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;
3417 dprintf(_("Phone info:\n%s\n"), MessageBuffer + 4);
3418 CurrentPhoneInfoError = GE_NONE;
3421 /***** RLP frame received. *****/
3423 FB61_RX_HandleRLPMessage();
3426 /***** Power on message. *****/
3428 dprintf(_("Message: The phone is powered on - seq 2.\n"));
3431 /***** Unknown message *****/
3432 /* If you think that you know the exact meaning of other messages - please
3435 dprintf(_("Message: Unknown message.\n"));
3438 return FB61_RX_Sync;
3441 /* RX_State machine for receive handling. Called once for each character
3442 received from the phone/phone. */
3444 void FB61_RX_StateMachine(char rx_byte)
3446 static int checksum[2];
3448 static struct _timeb time_now, time_last;
3449 static struct timeval time_diff;
3451 static struct timeval time_now, time_last, time_diff;
3454 /* XOR the byte with the current checksum */
3455 checksum[BufferCount&1] ^= rx_byte;
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
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 */
3473 /* else fall through to... */
3477 if ( CurrentConnectionType == GCT_Infrared ) {
3478 if (rx_byte == FB61_IR_FRAME_ID) {
3480 if (RX_Multiple == false) BufferCount = 0;
3481 else BufferCount = MessageLength - 2;
3482 RX_State = FB61_RX_GetDestination;
3484 /* Initialize checksums. */
3485 checksum[0] = FB61_IR_FRAME_ID;
3488 /* Lost frame sync */
3489 RX_State = FB61_RX_Discarding;
3490 gettimeofday(&time_last, NULL);
3492 } else { /* CurrentConnectionType == GCT_Serial */
3493 if (rx_byte == FB61_FRAME_ID) {
3495 if (RX_Multiple == false) BufferCount = 0;
3496 else BufferCount = MessageLength - 2;
3497 RX_State = FB61_RX_GetDestination;
3499 /* Initialize checksums. */
3500 checksum[0] = FB61_FRAME_ID;
3503 /* Lost frame sync */
3504 RX_State = FB61_RX_Discarding;
3505 gettimeofday(&time_last, NULL);
3511 case FB61_RX_GetDestination:
3513 MessageDestination = rx_byte;
3514 RX_State = FB61_RX_GetSource;
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 */
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);
3527 case FB61_RX_GetSource:
3528 MessageSource = rx_byte;
3529 RX_State = FB61_RX_GetType;
3531 /* Source should be 0x00 */
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);
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"));
3544 RX_Multiple = false;
3547 MessageType = rx_byte;
3548 RX_State = FB61_RX_GetUnknown;
3551 case FB61_RX_GetUnknown:
3552 MessageUnknown = rx_byte;
3553 RX_State = FB61_RX_GetLength;
3556 case FB61_RX_GetLength:
3557 if (RX_Multiple == true)
3558 MessageLength = MessageLength - 2 + rx_byte;
3560 MessageLength = rx_byte;
3561 RX_State = FB61_RX_GetMessage;
3564 case FB61_RX_GetMessage:
3565 MessageBuffer[BufferCount] = rx_byte;
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;
3574 /* If this is the last byte, it's the checksum. */
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. */
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))
3586 RX_Multiple = false;
3589 FB61_RX_DispatchMessage();
3593 dprintf(_("Bad checksum!\n"));
3594 RX_Multiple = false; /* Just to be sure! */
3597 RX_State = FB61_RX_Sync;
3603 /* This function is used for parsing the RLP frame into fields. */
3605 enum FB61_RX_States FB61_RX_HandleRLPMessage(void)
3611 /* We do not need RLP frame parsing to be done when we do not have callback
3614 if (RLP_RXCallback == NULL)
3615 return (FB61_RX_Sync);
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 */
3623 if (MessageBuffer[0] == 0xd9 && MessageBuffer[1] == 0x01)
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. */
3630 frame.Header[0] = MessageBuffer[2];
3631 frame.Header[1] = MessageBuffer[3];
3633 /* Next 200 bits (25 bytes) contain the Information. We store the
3634 information in the Data array. */
3636 for (count = 0; count < 25; count ++)
3637 frame.Data[count] = MessageBuffer[4 + count];
3639 /* The last 24 bits (3 bytes) contain FCS. */
3641 frame.FCS[0] = MessageBuffer[29];
3642 frame.FCS[1] = MessageBuffer[30];
3643 frame.FCS[2] = MessageBuffer[31];
3645 /* Here we pass the frame down in the input stream. */
3647 RLP_RXCallback(valid ? &frame : NULL);
3649 return (FB61_RX_Sync);
3652 char *FB61_PrintDevice(int Device)
3657 case FB61_DEVICE_PHONE:
3660 case FB61_DEVICE_PC:
3664 return _("Unknown");
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! */
3673 void FB61_RX_DisplayMessage(void)
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);
3684 for (count = 0; count < MessageLength + (MessageLength % 2) + 2; count ++)
3685 if (isprint(MessageBuffer[count]))
3686 dprintf("[%02x%c]", MessageBuffer[count], MessageBuffer[count]);
3688 dprintf("[%02x ]", MessageBuffer[count]);
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... */
3698 int FB61_TX_SendFrame(u8 message_length, u8 message_type, u8 *buffer)
3700 u8 out_buffer[FB61_MAX_TRANSMIT_LENGTH + 5];
3701 int count, current = 0;
3702 unsigned char checksum;
3704 /* FIXME - we should check for the message length ... */
3706 /* Now construct the message header. */
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 */
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 */
3719 /* Copy in data if any. */
3721 if (message_length != 0) {
3722 memcpy(out_buffer + current, buffer, message_length);
3723 current += message_length;
3726 /* If the message length is odd we should add pad byte 0x00 */
3727 if (message_length % 2)
3728 out_buffer[current++] = 0x00;
3730 /* Now calculate checksums over entire message and append to message. */
3735 for (count = 0; count < current; count += 2)
3736 checksum ^= out_buffer[count];
3738 out_buffer[current++] = checksum;
3743 for (count = 1; count < current; count += 2)
3744 checksum ^= out_buffer[count];
3746 out_buffer[current++] = checksum;
3749 for (count = 0; count < current; count++)
3750 dprintf("%02x:", out_buffer[count]);
3753 /* Send it out... */
3755 if (WRITEPHONE(PortFD, out_buffer, current) != current)
3758 if(message_type != 0x7f)
3764 int FB61_TX_SendMessage(u16 message_length, u8 message_type, u8 *buffer)
3766 u8 seqnum, frame_buffer[FB61_MAX_CONTENT_LENGTH + 2];
3767 u8 nom, lml; /* number of messages, last message len */
3770 seqnum = 0x40 + RequestSequenceNumber;
3771 RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07;
3773 if (message_length > FB61_MAX_CONTENT_LENGTH) {
3775 nom = (message_length + FB61_MAX_CONTENT_LENGTH - 1)
3776 / FB61_MAX_CONTENT_LENGTH;
3777 lml = message_length - ((nom - 1) * FB61_MAX_CONTENT_LENGTH);
3779 for (i = 0; i < nom - 1; i++) {
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;
3786 FB61_TX_SendFrame(FB61_MAX_CONTENT_LENGTH + 2, message_type,
3789 seqnum = RequestSequenceNumber;
3790 RequestSequenceNumber = (RequestSequenceNumber + 1) & 0x07;
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);
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);
3809 int FB61_TX_SendAck(u8 message_type, u8 message_seq)
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);