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.3 2002/04/03 00:08:09 short
15 Found in "gnokii-working" directory, some November-patches version
17 Revision 1.12 2001/10/21 22:23:56 machek
18 Use symbolic constants instead of numbers
20 At least detect when we get other message than we asked for
22 Provide option to passively wait for sms-es
24 Revision 1.11 2001/08/20 23:27:37 pkot
25 Add hardware shakehand to the link layer (Manfred Jonsson)
27 Revision 1.10 2001/07/17 22:46:27 pkot
28 Removed warning when compiling with --enable-debug (Pawel Kot)
30 Revision 1.9 2001/06/17 16:42:59 machek
31 Created another level of error message (ddprintf), fixed code not to
32 exit on error condition. Now it is actualy usable on my Philips Velo.
34 Revision 1.8 2001/06/16 10:00:41 machek
35 Implement timeouts on waiting for SMS.
37 Revision 1.7 2001/06/10 23:49:49 pkot
38 Small fixes to hide compilation warnings and allow gnokii.c to compile
40 Revision 1.6 2001/06/10 11:28:00 machek
41 Convert GetSMS/DeleteSMS to new structure.
43 Revision 1.5 2001/06/06 09:05:56 machek
44 Convert Grab/Release display to new structure.
46 Revision 1.4 2001/05/09 20:18:46 machek
47 Cleaned up code a bit. Made it use device_() interface. Reworked delay
48 system; now it is 4 times faster. 5 times faster if you hold * key on
51 Revision 1.3 2001/05/07 14:13:03 machek
52 nokia-2110 module converted to suit new API better. --identify now works.
54 Revision 1.2 2001/04/27 16:00:01 machek
55 Better error messages.
57 Revision 1.1 2001/04/25 12:54:47 machek
58 Partly converted nokia 2110 to "new" form, and moved it to phone
62 Notice that this code was (partly) converted to "new" structure, but it
63 does not have code for bus separated. I think that separating it would
64 be waste of effort... --pavel
77 #include <sys/types.h>
79 #include <sys/ioctl.h>
86 #include "gsm-common.h"
87 #include "mbus-2110.h"
88 #include "phones/nokia.h"
96 #include "gsm-common.h"
97 #include "phones/generic.h"
98 #include "phones/nk2110.h"
101 #define ddprintf(x...)
102 #define eprintf(x...) fprintf(stderr, x)
105 static GSM_Error P2110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state);
107 /* Global variables used by code in gsm-api.c to expose the
108 functions supported by this model of phone. */
110 static char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH];
111 static char *Revision = NULL,
112 *RevisionDate = NULL,
118 "2110|2140|6080", /* Models */ \
119 100, /* Max RF Level */ \
120 0, /* Min RF Level */ \
121 GRF_Percentage, /* RF level units */ \
122 100, /* Max Battery Level */ \
123 0, /* Min Battery Level */ \
124 GBU_Percentage, /* Battery level units */ \
125 GDT_None, /* No date/time support */ \
126 GDT_None, /* No alarm support */ \
127 0, /* Max alarms = 0 */ \
128 0, 0, /* Startup logo size */ \
129 0, 0, /* Op logo size */ \
130 0, 0 /* Caller logo size */ \
133 GSM_Information N2110_Information = INFO;
135 GSM_Phone phone_nokia_2110 = {
142 /* Local variables */
143 static volatile bool RequestTerminate;
144 static u8 TXPacketNumber = 0x01;
145 #define MAX_MODEL_LENGTH 16
146 static volatile unsigned char PacketData[10240];
151 static volatile int SMSpos = 0;
152 static volatile unsigned char SMSData[10240];
154 static long long LastChar = 0;
161 gettimeofday(&tv, NULL);
162 return (long long) tv.tv_sec * 1000000 + tv.tv_usec;
164 static void SigHandler(int status);
165 #define POLLIT do { SigHandler(0); } while (0)
174 Wait(long long from, int msec)
176 while (GetTime() < from + ((long long) msec)*1000) {
183 Wait2(long long from, int msec)
185 while (GetTime() < from + ((long long) msec)*1000) {
190 #define msleep(x) do { usleep(x*1000); } while (0)
191 #define msleep_poll(x) do { Wait(GetTime(), x); } while (0)
193 #define waitfor(condition, maxtime) \
195 long long limit = GetTime() + maxtime*1000; \
196 if (!maxtime) limit = 0x7fffffffffffffffULL; \
197 while ((!(condition)) && (limit > GetTime())) { \
201 if (!(limit > GetTime())) eprintf("???? TIMEOUT!"); \
204 /* Checksum calculation */
206 GetChecksum( u8 * packet, int len )
211 for( i = 0; i < len; i++ ) checksum ^= packet[i]; /* calculate checksum */
215 /* --------------- */
217 static int xread(unsigned char *d, int len)
221 res = device_read(d, len);
223 if (errno != EAGAIN) {
224 dprintf("I/O error : %m?!\n");
226 } else device_select(NULL);
230 dprintf("(%d)", len);
236 static int xwrite(unsigned char *d, int len)
240 res = device_write(d, len);
242 if (errno != EAGAIN) {
243 dprintf("I/O error : %m?!\n");
249 dprintf("<%d>", len);
255 /* --------------------------- */
258 SendFrame( u8 *buffer, u8 command, u8 length )
260 u8 pkt[10240], pkt2[10240];
263 pkt[current++] = 0x00; /* Construct the header. */
264 pkt[current++] = MYID;
265 pkt[current++] = length; /* Set data size */
266 pkt[current++] = command;
267 memcpy( pkt + current, buffer, length ); /* Copy in data. */
269 pkt[current++] = TXPacketNumber; /* Set packet number */
270 pkt[current++] = GetChecksum( pkt, current); /* Calculate and set checksum */
275 fprintf( stderr, _("PC : ") );
276 for( i = 0; i < current; i++ ) {
278 fprintf( stderr, "[%02X %c]", b, b > 0x20 ? b : '.' );
280 fprintf( stderr, "\n" );
286 /* I should put my messages at least 2msec apart... */
288 dprintf("writing...");
289 LastChar = GetTime();
290 if (xwrite(pkt, current) == -1)
291 return (GE_INTERNALERROR);
292 if (xread(pkt2, current) == -1)
293 return (GE_INTERNALERROR);
295 if (memcmp(pkt, pkt2, current)) {
296 eprintf("Bad echo?!");
304 SendCommand( u8 *buffer, u8 command, u8 length )
306 int time, retries = 10;
310 while ((time = device_read(pkt, 10240)) != -1) {
313 dprintf("Spurious? (%d)", time);
314 dprintf( _("Phone: ") );
315 for( j = 0; j < time; j++ ) {
317 dprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
326 SendFrame(buffer, command, length);
328 while ((GetTime() - now) < time*1000) {
334 time = 50; /* 5 seems to be enough */
337 eprintf("Command not okay after 10 retries!\n");
341 /* Applications should call Terminate to close the serial port. */
345 /* Request termination of thread */
346 RequestTerminate = true;
351 SMS(GSM_SMSMessage *message, int command)
353 u8 pkt[] = { 0x10, 0x02, 0, 0 };
356 memset((void *) &SMSData[0], 0, 255);
359 pkt[2] = 1; /* == LM_SMS_MEM_TYPE_DEFAULT or LM_SMS_MEM_TYPE_SIM or LM_SMS_MEM_TYPE_ME */
360 pkt[3] = message->Location;
361 message->MessageNumber = message->Location;
363 SendCommand(pkt, LM_SMS_COMMAND, sizeof(pkt));
364 msleep_poll(300); /* We have to keep acknowledning phone's data */
365 waitfor(PacketOK, 1000);
367 eprintf("SMS: No reply came within second!\n");
369 if (PacketData[3] != LM_SMS_EVENT) {
370 eprintf("Something is very wrong with SMS\n");
371 return GE_BUSY; /* FIXME */
373 if ((SMSData[2]) && (SMSData[2] != message->Location)) {
374 eprintf("Wanted message @%d, got message at @%d!\n", message->Location, SMSData[2]);
382 DecodeIncomingSMS(GSM_SMSMessage *m)
385 ddprintf("Status: " );
386 switch (SMSData[3]) {
387 case 7: m->Type = GST_MO; m->Status = GSS_NOTSENTREAD; ddprintf("not sent\n"); break;
388 case 5: m->Type = GST_MO; m->Status = GSS_SENTREAD; ddprintf("sent\n"); break;
389 case 3: m->Type = GST_MT; m->Status = GSS_NOTSENTREAD; ddprintf("not read\n"); break;
390 case 1: m->Type = GST_MT; m->Status = GSS_SENTREAD; ddprintf("read\n"); break;
393 /* Date is at SMSData[7]; this code is copied from fbus-6110.c*/
395 int offset = -32 + 7;
396 m->Time.Year=10*(SMSData[32+offset]&0x0f)+(SMSData[32+offset]>>4);
397 m->Time.Month=10*(SMSData[33+offset]&0x0f)+(SMSData[33+offset]>>4);
398 m->Time.Day=10*(SMSData[34+offset]&0x0f)+(SMSData[34+offset]>>4);
399 m->Time.Hour=10*(SMSData[35+offset]&0x0f)+(SMSData[35+offset]>>4);
400 m->Time.Minute=10*(SMSData[36+offset]&0x0f)+(SMSData[36+offset]>>4);
401 m->Time.Second=10*(SMSData[37+offset]&0x0f)+(SMSData[37+offset]>>4);
402 m->Time.Timezone=(10*(SMSData[38+offset]&0x07)+(SMSData[38+offset]>>4))/4;
406 ddprintf("%d bytes: ", len );
407 for (i = 0; i<len; i++)
408 ddprintf("%c", SMSData[15+i]);
412 eprintf("Magic not allowed\n");
413 memset(m->MessageText, 0, sizeof(m->MessageText));
414 strncpy(m->MessageText, (void *) &SMSData[15], len);
415 m->MessageTextLength = len; /* we currently do not support UDH & 8-bit so it is simple */
417 ddprintf("Text is %s\n", m->MessageText);
419 /* Originator address is at 15+i,
420 followed by message center addres (?) */
422 char *s = (char *) &SMSData[15+i]; /* We discard volatile. Make compiler quiet. */
423 strcpy(m->Sender, s);
425 strcpy(m->MessageCenter.Number, s);
426 ddprintf("Sender = %s, MessageCenter = %s\n", m->Sender, m->MessageCenter.Name);
429 m->MessageCenter.No = 0;
430 strcpy(m->MessageCenter.Name, "(unknown)");
431 m->UDHPresent = false;
436 GetSMSMessage(GSM_SMSMessage *m)
438 if (m->Location > 10)
439 return GE_INVALIDSMSLOCATION;
441 if (SMS(m, LM_SMS_READ_STORED_DATA) != GE_NONE)
442 return GE_BUSY; /* FIXME */
443 ddprintf("Have message?\n");
445 if (DecodeIncomingSMS(m) != GE_NONE)
448 if (SMSData[0] != LM_SMS_FORWARD_STORED_DATA) {
449 ddprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
450 return GE_EMPTYSMSLOCATION;
452 msleep_poll(1000); /* If phone lost our ack, it might retransmit data */
458 SendSMSMessage(GSM_SMSMessage *m)
460 if (m->Location > 10)
461 return GE_INVALIDSMSLOCATION;
463 if (SMSData[0] != 0x0b) {
464 ddprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
465 return GE_EMPTYSMSLOCATION;
467 ddprintf("Status: " );
468 switch (SMSData[3]) {
469 case 7: m->Type = GST_MO; m->Status = GSS_NOTSENTREAD; ddprintf("not sent\n"); break;
470 case 5: m->Type = GST_MO; m->Status = GSS_SENTREAD; ddprintf("sent\n"); break;
471 case 3: m->Type = GST_MT; m->Status = GSS_NOTSENTREAD; ddprintf("not read\n"); break;
472 case 1: m->Type = GST_MT; m->Status = GSS_SENTREAD; ddprintf("read\n"); break;
478 static GSM_Error DeleteSMSMessage(GSM_SMSMessage *message)
480 ddprintf("deleting...");
481 return SMS(message, 3);
487 GetValue(u8 index, u8 type)
489 u8 pkt[] = {0x84, 2, 0}; /* Sending 4 at pkt[0] makes phone crash */
496 ddprintf("\nRequesting value(%d)", index);
497 SendCommand(pkt, 0xe5, 3);
499 waitfor(PacketOK, 0);
500 if ((PacketData[3] != 0xe6) ||
501 (PacketData[4] != index) ||
502 (PacketData[5] != type))
503 dprintf("Something is very wrong with GetValue\n");
505 ddprintf( "Value = %d\n", val );
510 GetRFLevel(GSM_RFUnits *units, float *level)
512 int val = GetValue(0x84, 2);
514 if (*units == GRF_Arbitrary) {
515 res = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
526 *level = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
527 *units = GRF_Percentage;
533 GetBatteryLevel(GSM_BatteryUnits *units, float *level)
535 int val = GetValue(0x85, 2);
543 if (*units == GBU_Arbitrary) {
545 /* *level = (100 * (float) val) / 90.0;*/ /* 5..first bar, 10..second bar, 90..third bar */
546 *level = *level * 33;
547 *units = GBU_Percentage;
553 static GSM_Error GetVersionInfo(void)
555 char *s = VersionInfo;
556 ddprintf("Getting version info...\n");
557 if (GetValue(0x11, 0x03) == -1)
560 strncpy( s, (void *) &PacketData[6], sizeof(VersionInfo) );
562 for( Revision = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
564 for( RevisionDate = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
566 for( Model = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
568 ddprintf("Revision %s, Date %s, Model %s\n", Revision, RevisionDate, Model );
572 /* Our "Not implemented" functions */
574 GetMemoryStatus(GSM_MemoryStatus *Status)
576 switch(Status->MemoryType) {
594 return (GE_NOTIMPLEMENTED);
600 SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
606 Display(u8 b, int shift, char *s, char *buf)
612 case 1: case 2: *buf++ = '!';
613 case 3: strcpy(buf, s); buf += strlen(s); *buf++ = ' ';
618 static GSM_Error (*OutputFn)(char *text, char *ctrl);
623 eprintf("[%x]", PacketData[3]);
624 switch(PacketData[3]) {
625 case 0x12: { /* Text from display */
626 char buf[10240], *s = buf, *t;
627 t = (char *)&PacketData[8];
628 #define COPY(x) strncpy(s, t, x); t+=x; s+=x; *s++ = '\n'
629 COPY(10); COPY(10); COPY(10); COPY(3); COPY(12); *s++ = 0;
631 (*OutputFn)(buf, NULL);
634 case 0x2f: { /* Display lights */
635 char buf[10240], *s = buf;
637 #define COPY(x, y, z) s = Display(PacketData[x], y, z, s)
639 COPY(4, 0, "d"); COPY(4, 2, "b"); COPY(4, 4, "a"); COPY(4, 6, "lights");
640 COPY(5, 0, "service"); COPY(5, 2, "scroll_up"); COPY(5, 4, "scroll_down"); COPY(5, 6, "ABC");
641 COPY(6, 0, "2.>"); COPY(6, 2, "1.>"); COPY(6, 4, "roam"); COPY(6, 6, "handset");
642 COPY(7, 0, "vmail"); COPY(7, 2, "envelope"); COPY(7, 4, "battbar"); COPY(7, 6, "3.>");
643 COPY(8, 0, "?1"); COPY(8, 2, "?2"); COPY(8, 4, "fieldbar"); COPY(8, 6, "ring");
646 (*OutputFn)(NULL, buf);
650 case LM_SMS_EVENT: /* SMS Data */
651 /* copy bytes 5+ to smsbuf */
652 ddprintf("SMSdata:");
655 for (i=5; i<PacketData[2]+4; i++) {
656 SMSData[SMSpos++] = PacketData[i];
657 ddprintf("%c", PacketData[i]);
661 return ((PacketData[4] & 0xf) != 0);
662 /* Make all but last fragment "secret" */
664 default: dprintf("Unknown response %x\n", (unsigned int)PacketData[3]);
669 /* Handler called when characters received from serial port.
670 * and process them. */
672 SigHandler(int status)
674 unsigned char buffer[256], ack[5], b;
676 static unsigned int Index = 0, Length = 5;
677 static unsigned char pkt[256];
680 res = device_read(buffer, 256);
681 if( res < 0 ) return;
682 for(i = 0; i < res ; i++) {
684 // dprintf("(%x)", b, Index);
685 if (!Index && b != MYID && b != 0xf8 && b != 0x00) /* MYID is code of computer */ {
686 /* something strange goes from phone. Just ignore it */
687 ddprintf( "Get [%02X %c]\n", b, b >= 0x20 ? b : '.' );
693 if (b == 0x7f) Length = 5;
694 if (b == 0x7e) Length = 8;
696 if(Index >= Length) {
697 if((pkt[0] == MYID || pkt[0]==0xf8) && pkt[1] == 0x00) /* packet from phone */ {
698 ddprintf( _("Phone: ") );
699 for( j = 0; j < Length; j++ ) {
701 ddprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
704 /* ensure that we received valid packet */
705 if(pkt[Length - 1] != GetChecksum(pkt, Length-1)) {
706 eprintf( "***bad checksum***");
708 if((pkt[2] == 0x7F) || (pkt[2] == 0x7E)) /* acknowledge by phone */ {
709 if (pkt[2] == 0x7F) {
713 /* Increase TX packet number */
715 dprintf( "[registration ack]" );
720 /* Copy packet data */
722 memcpy((void *) PacketData,pkt,Length);
723 /* send acknowledge packet to phone */
725 ack[0] = 0x00; /* Construct the header. */
726 ack[1] = pkt[0]; /* Send back id */
727 ack[2] = 0x7F; /* Set special size value */
728 ack[3] = pkt[Length - 2]; /* Send back packet number */
729 ack[4] = GetChecksum( ack, 4); /* Set checksum */
730 ddprintf( _("PC : ") );
731 for( j = 0; j < 5; j++ ) {
733 ddprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' );
736 LastChar = GetTime();
737 if( xwrite( ack, 5 ) == -1 )
738 perror( _("Write error!\n") );
739 if( xread( ack, 5 ) == -1 )
740 perror( _("Read ack error!\n") );
742 /* Set validity flag */
748 eprintf("Got my own echo? That should not be possible!\n");
749 /* Look for new packet */
757 /* Called by initialisation code to open comm port in asynchronous mode. */
758 bool OpenSerial(void)
762 ddprintf(_("Setting MBUS communication with 2110...\n"));
764 result = device_open(PortDevice, true, false, false, GCT_Serial);
766 fprintf(stderr, "Failed to open %s ...\n", PortDevice);
770 ddprintf("%s opened...\n", PortDevice);
772 device_changespeed(9600);
773 device_setdtrrts(1, 1);
778 SetKey(int c, int up)
780 u8 reg[] = { 0x7a /* RPC_UI_KEY_PRESS or RPC_UI_KEY_RELEASE */, 0, 1, 0 /* key code */ };
783 dprintf("\n Pressing %d\n", c );
785 SendCommand( reg, 0xe5, 4 );
786 waitfor(PacketOK, 0);
790 #define XCTRL(a) (a&0x1f)
791 #define POWER XCTRL('o')
792 #define SEND XCTRL('t')
793 #define END XCTRL('s')
794 #define CLR XCTRL('h')
795 #define MENU XCTRL('d')
796 #define ALPHA XCTRL('a')
797 #define PLUS XCTRL('b')
798 #define MINUS XCTRL('e')
799 #define PREV XCTRL('p')
800 #define NEXT XCTRL('n')
801 #define SOFTA XCTRL('x')
802 #define SOFTB XCTRL('q')
806 static void PressKey(char c, int i)
809 #define X( a, b ) case a: SetKey(b, i); break;
811 case '1' ... '9': SetKey(c-'0',i); break;
828 X(STO, 19) /* These are not present on 2110, so I can't test this. Enable once tested. */
832 default: fprintf(stderr, "Unknown key %d\n", c);
839 PressString(char *s, int upcase)
842 static int lastupcase = 1;
844 if (lastchar == *s) {
845 fprintf(stderr, "***collision");
854 if (upcase != lastupcase) {
855 fprintf(stderr, "***size change");
865 * This is able to press keys at 62letters/36seconds, tested on message
866 * "Tohle je testovaci zprava schvalne za jak dlouho ji to napise"
867 * Well, it is possible to write that message in 17seconds...
873 #define X(a, b) case a: PressString(b, 0); break;
883 X('$', "1111111111");
884 /* X('$', "11111111111"); libra, not in ascii */
885 X('(', "111111111111");
886 X(')', "1111111111111");
887 X('/', "11111111111111");
888 X('%', "111111111111111");
889 X('@', "1111111111111111");
890 X('_', "11111111111111111");
891 X('=', "111111111111111111");
919 #define X(a, b) case a: PressString(b, 1); break;
947 case ' ': PressKey('#', 0); break;
948 case '+': PressKey(ALPHA, 0); PressKey('*', 0); PressKey('*', 0); PressKey(ALPHA, 0); break;
950 case '0' ... '9': PressKey(ALPHA, 0); PressKey(c, 0); PressKey(ALPHA, 0); break;
951 default: PressKey(c, 0);
956 HandleString(char *s)
962 fprintf(stderr,"***end of input");
963 PressKey(lastkey, 1);
970 u8 reg[] = { 1, 1, 0x0f, 1, 0x0f };
971 SendFrame( reg, 0xe9, 5 );
975 EnableDisplayOutput(GSM_Statemachine *sm)
977 /* LN_UC_SHARE, LN_UC_SHARE, LN_UC_RELEASE, LN_UC_RELEASE, LN_UC_KEEP */
978 u8 pkt[] = {3, 3, 0, 0, 1};
981 fprintf(stderr, "\nShould display output\n");
987 SendCommand(pkt, 0x19, 5);
988 fprintf(stderr, "\nGrabbing display");
989 waitfor(PacketOK, 0);
990 if ((PacketData[3] != 0xcd) ||
991 (PacketData[2] != 1) ||
992 (PacketData[4] != 1 /* LN_UC_REQUEST_OK */))
993 fprintf(stderr, "Something is very wrong with GrabDisplay\n");
994 fprintf(stderr, "Display grabbed okay (waiting)\n");
996 fprintf(stderr, "Okay\n");
1000 static GSM_Error SMS_Reserve(GSM_Statemachine *sm)
1002 u8 pkt[] = { 0x10, LM_SMS_RESERVE_PP, LN_SMS_NORMAL_RESERVE };
1004 SendCommand(pkt, LM_SMS_COMMAND, sizeof(pkt));
1006 waitfor(PacketOK, 100);
1008 eprintf("No reply trying to reserve SMS-es\n");
1009 if (PacketData[3] != LM_SMS_EVENT)
1010 eprintf("Bad reply trying to reserve SMS-es\n");
1011 if (SMSData[0] != LM_SMS_PP_RESERVE_COMPLETE)
1012 eprintf("Not okay trying to reserve SMS-es (%d)\n", SMSData[0]);
1016 static GSM_Error SMS_Slave(GSM_Statemachine *sm)
1019 eprintf("Reserved okay\n");
1023 memset((void *) &SMSData[0], 0, 255);
1024 waitfor(PacketOK, 1000000);
1025 if (PacketData[3] != LM_SMS_EVENT)
1026 eprintf("Wrong packet came!\n");
1027 switch (SMSData[0]) {
1028 case LM_SMS_RECEIVED_PP_DATA:
1029 eprintf("Data came!\n");
1031 case LM_SMS_ALIVE_TEST:
1032 eprintf("Am I alive?\n");
1034 case LM_SMS_NEW_MESSAGE_INDICATION:
1037 eprintf("New message indicated @%d\n", SMSData[2]);
1039 memset(&m, 0, sizeof(m));
1040 m.Location = SMSData[2];
1041 m.MemoryType = GMT_ME;
1042 if (GetSMSMessage(&m) != GE_NONE)
1043 eprintf("Could not find promissed message?\n");
1045 /*slave_process(&m, SMSData[2])*/;
1049 eprintf("Unexpected packet came: %x\n", SMSData[0]);
1054 /* This is the main loop for the MB21 functions. When N2110_Initialise
1055 is called a thread is created to run this loop. This loop is
1056 exited when the application calls the N2110_Terminate function. */
1060 fprintf(stderr, "Initializing... ");
1061 /* Do initialisation stuff */
1062 LastChar = GetTime();
1063 if (OpenSerial() != true) {
1064 N2110_LinkOK = false;
1069 while(!N2110_LinkOK) {
1070 fprintf(stderr, "registration... ");
1074 fprintf(stderr, "okay\n");
1077 /* Initialise variables and state machine. */
1079 Initialise(char *port_device, char *initlength,
1080 GSM_ConnectionType connection,
1081 void (*rlp_callback)(RLP_F96Frame *frame))
1083 RequestTerminate = false;
1084 N2110_LinkOK = false;
1085 setvbuf(stdout, NULL, _IONBF, 0);
1086 setvbuf(stderr, NULL, _IONBF, 0);
1087 memset(VersionInfo, 0, sizeof(VersionInfo));
1088 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
1089 switch (connection) {
1094 return GE_NOTSUPPORTED;
1101 /* Routine to get specifed phone book location. Designed to be called by
1102 application. Will block until location is retrieved or a timeout/error
1106 GetPhonebookLocation(GSM_PhonebookEntry *entry)
1108 u8 pkt[] = {0x1a, 0 /* 1 == phone */, 0};
1111 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1112 pkt[2] = entry->Location;
1115 SendCommand(pkt, LN_LOC_COMMAND, 3);
1116 waitfor(PacketOK, 0);
1117 if ((PacketData[3] != 0xc9) ||
1118 (PacketData[4] != 0x1a)) {
1119 fprintf(stderr, "Something is very wrong with GetPhonebookLocation\n");
1122 ddprintf("type= %x\n", PacketData[5]);
1123 ddprintf("location= %x\n", PacketData[6]);
1124 ddprintf("status= %x\n", PacketData[7]);
1125 for (i=8; PacketData[i]; i++) {
1126 ddprintf("%c", PacketData[i]);
1128 strcpy(entry->Name, (void *)&PacketData[8]);
1130 strcpy(entry->Number, (void *)&PacketData[i]);
1131 for (; PacketData[i]; i++) {
1132 ddprintf("%c", PacketData[i]);
1135 entry->Empty = false;
1141 /* Routine to write phonebook location in phone. Designed to be called by
1142 application code. Will block until location is written or timeout
1146 WritePhonebookLocation(GSM_PhonebookEntry *entry)
1148 u8 pkt[999] = {0x1b, 0 /* 1 == phone */, 0};
1150 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1151 pkt[2] = entry->Location;
1152 strcpy(&pkt[3], entry->Name);
1153 strcpy(&pkt[3+strlen(entry->Name)+1], entry->Number);
1156 SendCommand(pkt, LN_LOC_COMMAND, 3+strlen(entry->Number)+strlen(entry->Name)+2);
1157 waitfor(PacketOK, 0);
1159 if ((PacketData[3] != 0xc9) ||
1160 (PacketData[4] != 0x1b)) {
1161 fprintf(stderr, "Something is very wrong with WritePhonebookLocation\n");
1164 printf("type= %x\n", PacketData[5]);
1165 printf("location= %x\n", PacketData[6]);
1166 printf("status= %x\n", PacketData[7]);
1171 GetSMSStatus(GSM_SMSStatus *Status)
1180 GSM_Functions N2110_Functions = {
1183 GetPhonebookLocation,
1184 WritePhonebookLocation,
1204 PNOK_GetManufacturer,
1226 EnableDisplayOutput,
1238 static GSM_Error link_Loop(struct timeval *tm)
1244 GSM_Error P2110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
1246 GSM_Error err = GE_NONE;
1248 printf("Asked for %d\n", op);
1251 state->Link.Loop = link_Loop;
1255 case GOP_GetRevision:
1256 if (!Model) err = GetVersionInfo();
1258 if (data->Model) strncpy(data->Model, Model, 64);
1259 if (data->Revision) strncpy(data->Revision, Revision, 64);
1261 case GOP_GetBatteryLevel:
1262 err = GetBatteryLevel(data->BatteryUnits, data->BatteryLevel);
1264 case GOP_GetRFLevel:
1265 err = GetRFLevel(data->RFUnits, data->RFLevel);
1268 case GOP_GetMemoryStatus:
1269 err = N2110_GetMemoryStatus(data, state);
1272 case GOP_DisplayOutput:
1273 printf("DisplayOutput(%px)\n", data->OutputFn);
1274 OutputFn = data->OutputFn;
1276 err = EnableDisplayOutput(state);
1280 SMS_Slave(state); /* FIXME!!! */
1283 err = GetSMSMessage(data->SMSMessage);
1286 err = SMS(data->SMSMessage, 3);
1288 case GOP_ReadPhonebook:
1289 err = GetPhonebookLocation(data->PhonebookEntry);
1291 case GOP_WritePhonebook:
1292 err = WritePhonebookLocation(data->PhonebookEntry);
1295 err = SMS_Slave(state); /* Dirty hack, Fallthrough */
1298 err = GE_NOTIMPLEMENTED;