7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000, 2001 Pavel Machek <pavel@ucw.cz>
11 Released under the terms of the GNU GPL, see file COPYING for more details.
14 Revision 1.1.1.1 2001/11/25 21:59:11 short
15 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
17 Revision 1.16 2001/11/23 22:07:44 machek
18 Fix SMS receiving to work, again. Unfortunately, it is not possible to
19 reuse much of gsm-sms.c...
21 Revision 1.15 2001/11/15 12:10:57 pkot
22 Removed a warning from 2110 compilation
24 Revision 1.14 2001/11/09 13:49:12 pkot
25 Pavel! You haven't implemented slave_process() function!
27 Revision 1.13 2001/11/09 13:17:11 pkot
28 Update 2110 to a new libsms api
30 Revision 1.12 2001/10/21 22:23:56 machek
31 Use symbolic constants instead of numbers
33 At least detect when we get other message than we asked for
35 Provide option to passively wait for sms-es
37 Revision 1.11 2001/08/20 23:27:37 pkot
38 Add hardware shakehand to the link layer (Manfred Jonsson)
40 Revision 1.10 2001/07/17 22:46:27 pkot
41 Removed warning when compiling with --enable-debug (Pawel Kot)
43 Revision 1.9 2001/06/17 16:42:59 machek
44 Created another level of error message (ddprintf), fixed code not to
45 exit on error condition. Now it is actualy usable on my Philips Velo.
47 Revision 1.8 2001/06/16 10:00:41 machek
48 Implement timeouts on waiting for SMS.
50 Revision 1.7 2001/06/10 23:49:49 pkot
51 Small fixes to hide compilation warnings and allow gnokii.c to compile
53 Revision 1.6 2001/06/10 11:28:00 machek
54 Convert GetSMS/DeleteSMS to new structure.
56 Revision 1.5 2001/06/06 09:05:56 machek
57 Convert Grab/Release display to new structure.
59 Revision 1.4 2001/05/09 20:18:46 machek
60 Cleaned up code a bit. Made it use device_() interface. Reworked delay
61 system; now it is 4 times faster. 5 times faster if you hold * key on
64 Revision 1.3 2001/05/07 14:13:03 machek
65 nokia-2110 module converted to suit new API better. --identify now works.
67 Revision 1.2 2001/04/27 16:00:01 machek
68 Better error messages.
70 Revision 1.1 2001/04/25 12:54:47 machek
71 Partly converted nokia 2110 to "new" form, and moved it to phone
75 Notice that this code was (partly) converted to "new" structure, but it
76 does not have code for bus separated. I think that separating it would
77 be waste of effort... --pavel
90 #include <sys/types.h>
92 #include <sys/ioctl.h>
99 #include "gsm-common.h"
100 #include "mbus-2110.h"
101 #include "phones/nokia.h"
110 #include "gsm-common.h"
111 #include "phones/generic.h"
112 #include "phones/nk2110.h"
115 #define ddprintf(x...)
116 #define eprintf(x...) fprintf(stderr, x)
119 static GSM_Error P2110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state);
121 /* Global variables used by code in gsm-api.c to expose the
122 functions supported by this model of phone. */
124 static char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH];
125 static char *Revision = NULL,
126 *RevisionDate = NULL,
132 "2110|2140|6080", /* Models */ \
133 100, /* Max RF Level */ \
134 0, /* Min RF Level */ \
135 GRF_Percentage, /* RF level units */ \
136 100, /* Max Battery Level */ \
137 0, /* Min Battery Level */ \
138 GBU_Percentage, /* Battery level units */ \
139 GDT_None, /* No date/time support */ \
140 GDT_None, /* No alarm support */ \
141 0, /* Max alarms = 0 */ \
142 0, 0, /* Startup logo size */ \
143 0, 0, /* Op logo size */ \
144 0, 0 /* Caller logo size */ \
147 GSM_Information N2110_Information = INFO;
149 GSM_Phone phone_nokia_2110 = {
156 /* Local variables */
157 static volatile bool RequestTerminate;
158 static u8 TXPacketNumber = 0x01;
159 #define MAX_MODEL_LENGTH 16
160 static volatile unsigned char PacketData[10240];
165 static volatile int SMSpos = 0;
166 static volatile unsigned char SMSData[10240];
168 static long long LastChar = 0;
175 gettimeofday(&tv, NULL);
176 return (long long) tv.tv_sec * 1000000 + tv.tv_usec;
178 static void SigHandler(int status);
179 #define POLLIT do { SigHandler(0); } while (0)
188 Wait(long long from, int msec)
190 while (GetTime() < from + ((long long) msec)*1000) {
197 Wait2(long long from, int msec)
199 while (GetTime() < from + ((long long) msec)*1000) {
204 #define msleep(x) do { usleep(x*1000); } while (0)
205 #define msleep_poll(x) do { Wait(GetTime(), x); } while (0)
207 #define waitfor(condition, maxtime) \
209 long long limit = GetTime() + maxtime*1000; \
210 if (!maxtime) limit = 0x7fffffffffffffffULL; \
211 while ((!(condition)) && (limit > GetTime())) { \
215 if (!(limit > GetTime())) eprintf("???? TIMEOUT!"); \
218 /* Checksum calculation */
220 GetChecksum( u8 * packet, int len )
225 for( i = 0; i < len; i++ ) checksum ^= packet[i]; /* calculate checksum */
229 /* --------------- */
231 static int xread(unsigned char *d, int len)
235 res = device_read(d, len);
237 if (errno != EAGAIN) {
238 dprintf("I/O error : %m?!\n");
240 } else device_select(NULL);
244 dprintf("(%d)", len);
250 static int xwrite(unsigned char *d, int len)
254 res = device_write(d, len);
256 if (errno != EAGAIN) {
257 dprintf("I/O error : %m?!\n");
263 dprintf("<%d>", len);
269 /* --------------------------- */
272 SendFrame( u8 *buffer, u8 command, u8 length )
274 u8 pkt[10240], pkt2[10240];
277 pkt[current++] = 0x00; /* Construct the header. */
278 pkt[current++] = MYID;
279 pkt[current++] = length; /* Set data size */
280 pkt[current++] = command;
281 memcpy( pkt + current, buffer, length ); /* Copy in data. */
283 pkt[current++] = TXPacketNumber; /* Set packet number */
284 pkt[current++] = GetChecksum( pkt, current); /* Calculate and set checksum */
289 fprintf( stderr, _("PC : ") );
290 for( i = 0; i < current; i++ ) {
292 fprintf( stderr, "[%02X %c]", b, b > 0x20 ? b : '.' );
294 fprintf( stderr, "\n" );
300 /* I should put my messages at least 2msec apart... */
302 dprintf("writing...");
303 LastChar = GetTime();
304 if (xwrite(pkt, current) == -1)
305 return (GE_INTERNALERROR);
306 if (xread(pkt2, current) == -1)
307 return (GE_INTERNALERROR);
309 if (memcmp(pkt, pkt2, current)) {
310 eprintf("Bad echo?!");
318 SendCommand( u8 *buffer, u8 command, u8 length )
320 int time, retries = 10;
324 while ((time = device_read(pkt, 10240)) != -1) {
327 dprintf("Spurious? (%d)", time);
328 dprintf( _("Phone: ") );
329 for( j = 0; j < time; j++ ) {
331 dprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
340 SendFrame(buffer, command, length);
342 while ((GetTime() - now) < time*1000) {
348 time = 50; /* 5 seems to be enough */
351 eprintf("Command not okay after 10 retries!\n");
355 /* Applications should call Terminate to close the serial port. */
359 /* Request termination of thread */
360 RequestTerminate = true;
365 SMS(GSM_SMSMessage *message, int command)
367 u8 pkt[] = { 0x10, 0x02, 0, 0 };
370 memset((void *) &SMSData[0], 0, 255);
373 pkt[2] = 1; /* == LM_SMS_MEM_TYPE_DEFAULT or LM_SMS_MEM_TYPE_SIM or LM_SMS_MEM_TYPE_ME */
374 pkt[3] = message->Number;
376 SendCommand(pkt, LM_SMS_COMMAND, sizeof(pkt));
377 msleep_poll(300); /* We have to keep acknowledning phone's data */
378 waitfor(PacketOK, 1000);
380 eprintf("SMS: No reply came within second!\n");
382 if (PacketData[3] != LM_SMS_EVENT) {
383 eprintf("Something is very wrong with SMS\n");
384 return GE_BUSY; /* FIXME */
386 if ((SMSData[2]) && (SMSData[2] != message->Number)) {
387 eprintf("Wanted message @%d, got message at @%d!\n", message->Number, SMSData[2]);
395 DecodeIncomingSMS(GSM_SMSMessage *m)
401 /* Should be moved to gsm-sms.c */
403 ddprintf("Status: " );
404 switch (SMSData[3]) {
405 case 7: m->Type = SMS_Submit; /* m->Status = GSS_NOTSENTREAD; */ ddprintf("not sent\n"); break;
406 case 5: m->Type = SMS_Submit; /* m->Status = GSS_SENTREAD; */ ddprintf("sent\n"); break;
407 case 3: m->Type = SMS_Deliver; /* m->Status = GSS_NOTSENTREAD; */ ddprintf("not read\n"); break;
408 case 1: m->Type = SMS_Deliver; /* m->Status = GSS_SENTREAD; */ ddprintf("read\n"); break;
411 UnpackDateTime(SMSData+7, &m->Time);
413 m->Length = len = SMSData[14];
414 ddprintf("%d bytes: ", len );
415 for (i = 0; i<len; i++)
416 ddprintf("%c", SMSData[15+i]);
420 eprintf("Magic not allowed\n");
421 memset(m->MessageText, 0, 161);
422 strncpy(m->MessageText, (void *) &SMSData[15], len);
424 ddprintf("Text is %s\n", m->MessageText);
427 Originator address is at 15+i,
428 followed by message center addres (?)
431 char *s = (char *) &SMSData[15+i]; /* We discard volatile. Make compiler quiet. */
432 strcpy(m->RemoteNumber.number, s);
434 strcpy(m->MessageCenter.Number, s);
435 ddprintf("Sender = %s, MessageCenter = %s\n", m->Sender, m->MessageCenter.Name);
438 m->MessageCenter.No = 0;
439 strcpy(m->MessageCenter.Name, "(unknown)");
446 GetSMSMessage(GSM_SMSMessage *m)
449 return GE_INVALIDSMSLOCATION;
451 if (SMS(m, LM_SMS_READ_STORED_DATA) != GE_NONE)
452 return GE_BUSY; /* FIXME */
453 ddprintf("Have message?\n");
455 if (DecodeIncomingSMS(m) != GE_NONE)
458 if (SMSData[0] != LM_SMS_FORWARD_STORED_DATA) {
459 ddprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
460 return GE_EMPTYSMSLOCATION;
462 msleep_poll(1000); /* If phone lost our ack, it might retransmit data */
468 SendSMSMessage(GSM_SMSMessage *m)
471 return GE_INVALIDSMSLOCATION;
473 if (SMSData[0] != 0x0b) {
474 ddprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
475 return GE_EMPTYSMSLOCATION;
477 ddprintf("Status: " );
478 switch (SMSData[3]) {
479 case 7: m->Type = GST_MO; m->Status = GSS_NOTSENTREAD; ddprintf("not sent\n"); break;
480 case 5: m->Type = GST_MO; m->Status = GSS_SENTREAD; ddprintf("sent\n"); break;
481 case 3: m->Type = GST_MT; m->Status = GSS_NOTSENTREAD; ddprintf("not read\n"); break;
482 case 1: m->Type = GST_MT; m->Status = GSS_SENTREAD; ddprintf("read\n"); break;
488 static GSM_Error DeleteSMSMessage(GSM_SMSMessage *message)
490 ddprintf("deleting...");
491 return SMS(message, 3);
497 GetValue(u8 index, u8 type)
499 u8 pkt[] = {0x84, 2, 0}; /* Sending 4 at pkt[0] makes phone crash */
506 ddprintf("\nRequesting value(%d)", index);
507 SendCommand(pkt, 0xe5, 3);
509 waitfor(PacketOK, 0);
510 if ((PacketData[3] != 0xe6) ||
511 (PacketData[4] != index) ||
512 (PacketData[5] != type))
513 dprintf("Something is very wrong with GetValue\n");
515 ddprintf( "Value = %d\n", val );
520 GetRFLevel(GSM_RFUnits *units, float *level)
522 int val = GetValue(0x84, 2);
524 if (*units == GRF_Arbitrary) {
525 res = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
536 *level = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
537 *units = GRF_Percentage;
543 GetBatteryLevel(GSM_BatteryUnits *units, float *level)
545 int val = GetValue(0x85, 2);
553 if (*units == GBU_Arbitrary) {
555 /* *level = (100 * (float) val) / 90.0;*/ /* 5..first bar, 10..second bar, 90..third bar */
556 *level = *level * 33;
557 *units = GBU_Percentage;
563 static GSM_Error GetVersionInfo(void)
565 char *s = VersionInfo;
566 ddprintf("Getting version info...\n");
567 if (GetValue(0x11, 0x03) == -1)
570 strncpy( s, (void *) &PacketData[6], sizeof(VersionInfo) );
572 for( Revision = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
574 for( RevisionDate = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
576 for( Model = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
578 ddprintf("Revision %s, Date %s, Model %s\n", Revision, RevisionDate, Model );
582 /* Our "Not implemented" functions */
584 GetMemoryStatus(GSM_MemoryStatus *Status)
586 switch(Status->MemoryType) {
604 return (GE_NOTIMPLEMENTED);
610 SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
616 Display(u8 b, int shift, char *s, char *buf)
622 case 1: case 2: *buf++ = '!';
623 case 3: strcpy(buf, s); buf += strlen(s); *buf++ = ' ';
628 static GSM_Error (*OutputFn)(char *text, char *ctrl);
633 eprintf("[%x]", PacketData[3]);
634 switch(PacketData[3]) {
635 case 0x12: { /* Text from display */
636 char buf[10240], *s = buf, *t;
637 t = (char *)&PacketData[8];
638 #define COPY(x) strncpy(s, t, x); t+=x; s+=x; *s++ = '\n'
639 COPY(10); COPY(10); COPY(10); COPY(3); COPY(12); *s++ = 0;
641 (*OutputFn)(buf, NULL);
644 case 0x2f: { /* Display lights */
645 char buf[10240], *s = buf;
647 #define COPY(x, y, z) s = Display(PacketData[x], y, z, s)
649 COPY(4, 0, "d"); COPY(4, 2, "b"); COPY(4, 4, "a"); COPY(4, 6, "lights");
650 COPY(5, 0, "service"); COPY(5, 2, "scroll_up"); COPY(5, 4, "scroll_down"); COPY(5, 6, "ABC");
651 COPY(6, 0, "2.>"); COPY(6, 2, "1.>"); COPY(6, 4, "roam"); COPY(6, 6, "handset");
652 COPY(7, 0, "vmail"); COPY(7, 2, "envelope"); COPY(7, 4, "battbar"); COPY(7, 6, "3.>");
653 COPY(8, 0, "?1"); COPY(8, 2, "?2"); COPY(8, 4, "fieldbar"); COPY(8, 6, "ring");
656 (*OutputFn)(NULL, buf);
660 case LM_SMS_EVENT: /* SMS Data */
661 /* copy bytes 5+ to smsbuf */
662 ddprintf("SMSdata:");
665 for (i=5; i<PacketData[2]+4; i++) {
666 SMSData[SMSpos++] = PacketData[i];
667 ddprintf("%c", PacketData[i]);
671 return ((PacketData[4] & 0xf) != 0);
672 /* Make all but last fragment "secret" */
674 default: dprintf("Unknown response %dx\n", PacketData[3]);
679 /* Handler called when characters received from serial port.
680 * and process them. */
682 SigHandler(int status)
684 unsigned char buffer[256], ack[5], b;
686 static unsigned int Index = 0, Length = 5;
687 static unsigned char pkt[256];
690 res = device_read(buffer, 256);
691 if( res < 0 ) return;
692 for(i = 0; i < res ; i++) {
694 // dprintf("(%x)", b, Index);
695 if (!Index && b != MYID && b != 0xf8 && b != 0x00) /* MYID is code of computer */ {
696 /* something strange goes from phone. Just ignore it */
697 ddprintf( "Get [%02X %c]\n", b, b >= 0x20 ? b : '.' );
703 if (b == 0x7f) Length = 5;
704 if (b == 0x7e) Length = 8;
706 if(Index >= Length) {
707 if((pkt[0] == MYID || pkt[0]==0xf8) && pkt[1] == 0x00) /* packet from phone */ {
708 ddprintf( _("Phone: ") );
709 for( j = 0; j < Length; j++ ) {
711 ddprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
714 /* ensure that we received valid packet */
715 if(pkt[Length - 1] != GetChecksum(pkt, Length-1)) {
716 eprintf( "***bad checksum***");
718 if((pkt[2] == 0x7F) || (pkt[2] == 0x7E)) /* acknowledge by phone */ {
719 if (pkt[2] == 0x7F) {
723 /* Increase TX packet number */
725 dprintf( "[registration ack]" );
730 /* Copy packet data */
732 memcpy((void *) PacketData,pkt,Length);
733 /* send acknowledge packet to phone */
735 ack[0] = 0x00; /* Construct the header. */
736 ack[1] = pkt[0]; /* Send back id */
737 ack[2] = 0x7F; /* Set special size value */
738 ack[3] = pkt[Length - 2]; /* Send back packet number */
739 ack[4] = GetChecksum( ack, 4); /* Set checksum */
740 ddprintf( _("PC : ") );
741 for( j = 0; j < 5; j++ ) {
743 ddprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
746 LastChar = GetTime();
747 if( xwrite( ack, 5 ) == -1 )
748 perror( _("Write error!\n") );
749 if( xread( ack, 5 ) == -1 )
750 perror( _("Read ack error!\n") );
752 /* Set validity flag */
758 eprintf("Got my own echo? That should not be possible!\n");
759 /* Look for new packet */
767 /* Called by initialisation code to open comm port in asynchronous mode. */
768 bool OpenSerial(void)
772 ddprintf(_("Setting MBUS communication with 2110...\n"));
774 result = device_open(PortDevice, true, false, false, GCT_Serial);
776 fprintf(stderr, "Failed to open %s ...\n", PortDevice);
780 ddprintf("%s opened...\n", PortDevice);
782 device_changespeed(9600);
783 device_setdtrrts(1, 1);
788 SetKey(int c, int up)
790 u8 reg[] = { 0x7a /* RPC_UI_KEY_PRESS or RPC_UI_KEY_RELEASE */, 0, 1, 0 /* key code */ };
793 dprintf("\n Pressing %d\n", c );
795 SendCommand( reg, 0xe5, 4 );
796 waitfor(PacketOK, 0);
800 #define XCTRL(a) (a&0x1f)
801 #define POWER XCTRL('o')
802 #define SEND XCTRL('t')
803 #define END XCTRL('s')
804 #define CLR XCTRL('h')
805 #define MENU XCTRL('d')
806 #define ALPHA XCTRL('a')
807 #define PLUS XCTRL('b')
808 #define MINUS XCTRL('e')
809 #define PREV XCTRL('p')
810 #define NEXT XCTRL('n')
811 #define SOFTA XCTRL('x')
812 #define SOFTB XCTRL('q')
816 static void PressKey(char c, int i)
819 #define X( a, b ) case a: SetKey(b, i); break;
821 case '1' ... '9': SetKey(c-'0',i); break;
838 X(STO, 19) /* These are not present on 2110, so I can't test this. Enable once tested. */
842 default: fprintf(stderr, "Unknown key %d\n", c);
849 PressString(char *s, int upcase)
852 static int lastupcase = 1;
854 if (lastchar == *s) {
855 fprintf(stderr, "***collision");
864 if (upcase != lastupcase) {
865 fprintf(stderr, "***size change");
875 * This is able to press keys at 62letters/36seconds, tested on message
876 * "Tohle je testovaci zprava schvalne za jak dlouho ji to napise"
877 * Well, it is possible to write that message in 17seconds...
883 #define X(a, b) case a: PressString(b, 0); break;
893 X('$', "1111111111");
894 /* X('$', "11111111111"); libra, not in ascii */
895 X('(', "111111111111");
896 X(')', "1111111111111");
897 X('/', "11111111111111");
898 X('%', "111111111111111");
899 X('@', "1111111111111111");
900 X('_', "11111111111111111");
901 X('=', "111111111111111111");
929 #define X(a, b) case a: PressString(b, 1); break;
957 case ' ': PressKey('#', 0); break;
958 case '+': PressKey(ALPHA, 0); PressKey('*', 0); PressKey('*', 0); PressKey(ALPHA, 0); break;
960 case '0' ... '9': PressKey(ALPHA, 0); PressKey(c, 0); PressKey(ALPHA, 0); break;
961 default: PressKey(c, 0);
966 HandleString(char *s)
972 fprintf(stderr,"***end of input");
973 PressKey(lastkey, 1);
980 u8 reg[] = { 1, 1, 0x0f, 1, 0x0f };
981 SendFrame( reg, 0xe9, 5 );
985 EnableDisplayOutput(GSM_Statemachine *sm)
987 /* LN_UC_SHARE, LN_UC_SHARE, LN_UC_RELEASE, LN_UC_RELEASE, LN_UC_KEEP */
988 u8 pkt[] = {3, 3, 0, 0, 1};
991 fprintf(stderr, "\nShould display output\n");
997 SendCommand(pkt, 0x19, 5);
998 fprintf(stderr, "\nGrabbing display");
999 waitfor(PacketOK, 0);
1000 if ((PacketData[3] != 0xcd) ||
1001 (PacketData[2] != 1) ||
1002 (PacketData[4] != 1 /* LN_UC_REQUEST_OK */))
1003 fprintf(stderr, "Something is very wrong with GrabDisplay\n");
1004 fprintf(stderr, "Display grabbed okay (waiting)\n");
1006 fprintf(stderr, "Okay\n");
1010 static GSM_Error SMS_Reserve(GSM_Statemachine *sm)
1012 u8 pkt[] = { 0x10, LM_SMS_RESERVE_PP, LN_SMS_NORMAL_RESERVE };
1014 SendCommand(pkt, LM_SMS_COMMAND, sizeof(pkt));
1016 waitfor(PacketOK, 100);
1018 eprintf("No reply trying to reserve SMS-es\n");
1019 if (PacketData[3] != LM_SMS_EVENT)
1020 eprintf("Bad reply trying to reserve SMS-es\n");
1021 if (SMSData[0] != LM_SMS_PP_RESERVE_COMPLETE)
1022 eprintf("Not okay trying to reserve SMS-es (%d)\n", SMSData[0]);
1026 static GSM_Error SMS_Slave(GSM_Statemachine *sm)
1029 eprintf("Reserved okay\n");
1033 memset((void *) &SMSData[0], 0, 255);
1034 waitfor(PacketOK, 1000000);
1035 if (PacketData[3] != LM_SMS_EVENT)
1036 eprintf("Wrong packet came!\n");
1037 switch (SMSData[0]) {
1038 case LM_SMS_RECEIVED_PP_DATA:
1039 eprintf("Data came!\n");
1041 case LM_SMS_ALIVE_TEST:
1042 eprintf("Am I alive?\n");
1044 case LM_SMS_NEW_MESSAGE_INDICATION:
1047 eprintf("New message indicated @%d\n", SMSData[2]);
1049 memset(&m, 0, sizeof(m));
1050 m.Number = SMSData[2];
1051 m.MemoryType = GMT_ME;
1052 if (GetSMSMessage(&m) != GE_NONE)
1053 eprintf("Could not find promissed message?\n");
1056 slave_process(&m, SMSData[2]);
1061 eprintf("Unexpected packet came: %x\n", SMSData[0]);
1066 /* This is the main loop for the MB21 functions. When N2110_Initialise
1067 is called a thread is created to run this loop. This loop is
1068 exited when the application calls the N2110_Terminate function. */
1072 fprintf(stderr, "Initializing... ");
1073 /* Do initialisation stuff */
1074 LastChar = GetTime();
1075 if (OpenSerial() != true) {
1076 N2110_LinkOK = false;
1081 while(!N2110_LinkOK) {
1082 fprintf(stderr, "registration... ");
1086 fprintf(stderr, "okay\n");
1089 /* Initialise variables and state machine. */
1091 Initialise(char *port_device, char *initlength,
1092 GSM_ConnectionType connection,
1093 void (*rlp_callback)(RLP_F96Frame *frame))
1095 RequestTerminate = false;
1096 N2110_LinkOK = false;
1097 setvbuf(stdout, NULL, _IONBF, 0);
1098 setvbuf(stderr, NULL, _IONBF, 0);
1099 memset(VersionInfo, 0, sizeof(VersionInfo));
1100 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
1101 switch (connection) {
1106 return GE_NOTSUPPORTED;
1113 /* Routine to get specifed phone book location. Designed to be called by
1114 application. Will block until location is retrieved or a timeout/error
1118 GetPhonebookLocation(GSM_PhonebookEntry *entry)
1120 u8 pkt[] = {0x1a, 0 /* 1 == phone */, 0};
1123 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1124 pkt[2] = entry->Location;
1127 SendCommand(pkt, LN_LOC_COMMAND, 3);
1128 waitfor(PacketOK, 0);
1129 if ((PacketData[3] != 0xc9) ||
1130 (PacketData[4] != 0x1a)) {
1131 fprintf(stderr, "Something is very wrong with GetPhonebookLocation\n");
1134 ddprintf("type= %x\n", PacketData[5]);
1135 ddprintf("location= %x\n", PacketData[6]);
1136 ddprintf("status= %x\n", PacketData[7]);
1137 for (i=8; PacketData[i]; i++) {
1138 ddprintf("%c", PacketData[i]);
1140 strcpy(entry->Name, (void *)&PacketData[8]);
1142 strcpy(entry->Number, (void *)&PacketData[i]);
1143 for (; PacketData[i]; i++) {
1144 ddprintf("%c", PacketData[i]);
1147 entry->Empty = false;
1153 /* Routine to write phonebook location in phone. Designed to be called by
1154 application code. Will block until location is written or timeout
1158 WritePhonebookLocation(GSM_PhonebookEntry *entry)
1160 u8 pkt[999] = {0x1b, 0 /* 1 == phone */, 0};
1162 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1163 pkt[2] = entry->Location;
1164 strcpy(&pkt[3], entry->Name);
1165 strcpy(&pkt[3+strlen(entry->Name)+1], entry->Number);
1168 SendCommand(pkt, LN_LOC_COMMAND, 3+strlen(entry->Number)+strlen(entry->Name)+2);
1169 waitfor(PacketOK, 0);
1171 if ((PacketData[3] != 0xc9) ||
1172 (PacketData[4] != 0x1b)) {
1173 fprintf(stderr, "Something is very wrong with WritePhonebookLocation\n");
1176 printf("type= %x\n", PacketData[5]);
1177 printf("location= %x\n", PacketData[6]);
1178 printf("status= %x\n", PacketData[7]);
1183 GetSMSStatus(GSM_SMSMemoryStatus *Status)
1191 GSM_Functions N2110_Functions = {
1194 GetPhonebookLocation,
1195 WritePhonebookLocation,
1215 PNOK_GetManufacturer,
1238 EnableDisplayOutput,
1250 static GSM_Error link_Loop(struct timeval *tm)
1256 GSM_Error P2110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
1258 GSM_Error err = GE_NONE;
1260 printf("Asked for %d\n", op);
1263 state->Link.Loop = link_Loop;
1267 case GOP_GetRevision:
1268 if (!Model) err = GetVersionInfo();
1270 if (data->Model) strncpy(data->Model, Model, 64);
1271 if (data->Revision) strncpy(data->Revision, Revision, 64);
1273 case GOP_GetBatteryLevel:
1274 err = GetBatteryLevel(data->BatteryUnits, data->BatteryLevel);
1276 case GOP_GetRFLevel:
1277 err = GetRFLevel(data->RFUnits, data->RFLevel);
1280 case GOP_GetMemoryStatus:
1281 err = N2110_GetMemoryStatus(data, state);
1284 case GOP_DisplayOutput:
1285 printf("DisplayOutput(%px)\n", data->OutputFn);
1286 OutputFn = data->OutputFn;
1288 err = EnableDisplayOutput(state);
1292 SMS_Slave(state); /* FIXME!!! */
1295 err = GetSMSMessage(data->SMSMessage);
1298 err = SMS(data->SMSMessage, 3);
1300 case GOP_ReadPhonebook:
1301 err = GetPhonebookLocation(data->PhonebookEntry);
1303 case GOP_WritePhonebook:
1304 err = WritePhonebookLocation(data->PhonebookEntry);
1307 err = SMS_Slave(state); /* Dirty hack, Fallthrough */
1310 err = GE_NOTIMPLEMENTED;