7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000 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.2 2002/04/03 00:07:58 short
15 Found in "gnokii-working" directory, some November-patches version
17 Revision 1.39 2001/09/14 12:15:28 pkot
18 Cleanups from 0.3.3 (part1)
20 Revision 1.38 2001/07/03 00:03:36 pkot
21 Small fixes to let gnokii compile and work under solaris (thanks to Artur Kubiak)
23 Revision 1.37 2001/03/05 08:02:16 machek
26 Revision 1.36 2001/02/27 22:16:25 machek
27 Kill unneccessary variable and annoying warning.
29 Revision 1.35 2001/02/25 19:15:33 machek
30 Fixed udelay() to work w.r.t. signals.
32 Revision 1.34 2001/02/21 19:56:58 chris
33 More fiddling with the directory layout
35 Revision 1.33 2001/02/20 21:30:28 machek
36 We really have 150 addressbook places, better
37 getrflevel/getbatterylevel, wait one second on collision.
39 Revision 1.32 2001/02/17 22:40:49 chris
42 Revision 1.31 2001/02/17 14:39:19 machek
43 Make writing/reading phonebook less verbose (as it should be).
45 Revision 1.30 2001/02/01 15:17:30 pkot
46 Fixed --identify and added Manfred's manufacturer patch
48 Revision 1.29 2001/01/31 11:46:50 machek
49 Comment out SendSMSMessage to kill warning.
51 Revision 1.28 2001/01/29 17:14:42 chris
52 dprintf now in misc.h (and fiddling with 7110 code)
54 Revision 1.27 2001/01/23 18:58:51 machek
55 Implement collision protocol slightly better. It is still not
56 completely okay -- we should check if echo is exactly same characters
59 Revision 1.26 2001/01/23 15:32:38 chris
60 Pavel's 'break' and 'static' corrections.
61 Work on logos for 7110.
63 Revision 1.25 2001/01/12 14:09:12 pkot
64 More cleanups. This time mainly in the code.
66 Revision 1.24 2001/01/10 16:32:17 pkot
67 Documentation updates.
68 FreeBSD fix for 3810 code.
69 Added possibility for deleting SMS just after reading it in gnokii.
73 Revision 1.23 2001/01/02 09:09:08 pkot
74 Misc fixes and updates.
76 Revision 1.22 2000/12/20 09:11:19 pkot
77 Fixes to mbus-2110.c to let it compile (by Pavel Machek)
79 Revision 1.21 2000/12/19 16:32:28 pkot
80 Lots of updates in common/mbus-2110.c. (thanks to Pavel Machek)
95 #include <sys/types.h>
97 #include <sys/ioctl.h>
103 # include <sys/file.h>
106 #include "gsm-common.h"
107 #include "mbus-2110.h"
108 #include "phones/nokia.h"
114 #define usleep(x) do { usleep(x); SigHandler(0); } while (0)
117 #define msleep(x) do { usleep(x*1000); } while (0)
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,
130 GSM_Information MB21_Information = {
131 "2110|2140|6080", /* Models */
132 100, /* Max RF Level */
133 0, /* Min RF Level */
134 GRF_Percentage, /* RF level units */
135 100, /* Max Battery Level */
136 0, /* Min Battery Level */
137 GBU_Percentage, /* Battery level units */
138 GDT_None, /* No date/time support */
139 GDT_None, /* No alarm support */
140 0, /* Max alarms = 0 */
141 0, 0, /* Startup logo size */
142 0, 0, /* Op logo size */
143 0, 0 /* Caller logo size */
146 /* Local variables */
148 static pthread_t Thread;
150 static volatile bool RequestTerminate;
152 static struct termios old_termios; /* old termios */
153 static u8 TXPacketNumber = 0x01;
154 #define MAX_MODEL_LENGTH 16
155 static bool ModelValid = false;
156 static volatile unsigned char PacketData[256];
162 static volatile int SMSpos = 0;
163 static volatile unsigned char SMSData[256];
165 static long long LastChar = 0;
172 gettimeofday(&tv, NULL);
173 return (long long) tv.tv_sec * 1000000 + tv.tv_usec;
177 Wait(long long from, int msec)
179 while (GetTime() < from + ((long long) msec)*1000)
183 #define usleep(x) do { Wait(GetTime(), x/1000); } while (0)
185 /* Checksum calculation */
187 GetChecksum( u8 * packet, int len )
192 for( i = 0; i < len; i++ ) checksum ^= packet[i]; /* calculate checksum */
197 SendFrame( u8 *buffer, u8 command, u8 length )
202 pkt[current++] = 0x00; /* Construct the header. */
203 pkt[current++] = MYID;
204 pkt[current++] = length; /* Set data size */
205 pkt[current++] = command;
206 memcpy( pkt + current, buffer, length ); /* Copy in data. */
208 pkt[current++] = TXPacketNumber; /* Set packet number */
209 pkt[current++] = GetChecksum( pkt, current); /* Calculate and set checksum */
214 fprintf( stderr, _("PC : ") );
215 for( i = 0; i < current; i++ ) {
217 fprintf( stderr, "[%02X %c]", b, b > 0x20 ? b : '.' );
219 fprintf( stderr, "\n" );
226 /* I should put my messages at least 2msec apart... */
228 if (write(PortFD, pkt, current) != current) /* BUGGY, we should handle -EINTR and short writes! */ {
229 perror( _("Write error!\n") );
230 return (GE_INTERNALERROR);
233 while( !EchoOK && current-- )
236 fprintf(stderr, "no echo?!");
244 SendCommand( u8 *buffer, u8 command, u8 length )
246 int time, retries = 10;
250 SendFrame(buffer, command, length);
257 fprintf(stderr, "[resend]");
259 fprintf(stderr, "Command not okay after 10 retries!\n");
263 /* Applications should call Terminate to close the serial port. */
267 /* Request termination of thread */
268 RequestTerminate = true;
270 /* Now wait for thread to terminate. */
271 pthread_join(Thread, NULL);
273 /* Close serial port. */
275 tcsetattr(PortFD, TCSANOW, &old_termios);
281 SMS(GSM_SMSMessage *message, int command)
283 u8 pkt[] = { 0x10, 0x02, 0, 0 };
286 memset((void *) &SMSData[0], 0, 160);
289 pkt[2] = 1; /* == LM_SMS_MEM_TYPE_DEFAULT or LM_SMS_MEM_TYPE_SIM or LM_SMS_MEM_TYPE_ME */
290 pkt[3] = message->Location;
291 message->MessageNumber = message->Location;
293 SendCommand(pkt, 0x38 /* LN_SMS_COMMAND */, sizeof(pkt));
298 fprintf(stderr, _("Impossible timeout?\n"));
302 if (PacketData[3] != 0x37 /* LN_SMS_EVENT */) {
303 fprintf(stderr, _("Something is very wrong with GetValue\n"));
304 return GE_BUSY; /* FIXME */
310 GetSMSMessage(GSM_SMSMessage *m)
313 if (SMS(m, 2) != GE_NONE)
314 return GE_BUSY; /* FIXME */
315 dprintf("Have message?\n");
316 if (m->Location > 10)
317 return GE_INVALIDSMSLOCATION;
319 if (SMSData[0] != 0x0b) {
320 dprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
321 return GE_EMPTYSMSLOCATION;
323 dprintf("Status: " );
324 switch (SMSData[3]) {
325 case 7: m->Type = GST_MO; m->Status = GSS_NOTSENTREAD; dprintf("not sent\n"); break;
326 case 5: m->Type = GST_MO; m->Status = GSS_SENTREAD; dprintf("sent\n"); break;
327 case 3: m->Type = GST_MT; m->Status = GSS_NOTSENTREAD; dprintf("not read\n"); break;
328 case 1: m->Type = GST_MT; m->Status = GSS_SENTREAD; dprintf("read\n"); break;
331 /* Date is at SMSData[7]; this code is copied from fbus-6110.c*/
333 int offset = -32 + 7;
334 m->Time.Year=10*(SMSData[32+offset]&0x0f)+(SMSData[32+offset]>>4);
335 m->Time.Month=10*(SMSData[33+offset]&0x0f)+(SMSData[33+offset]>>4);
336 m->Time.Day=10*(SMSData[34+offset]&0x0f)+(SMSData[34+offset]>>4);
337 m->Time.Hour=10*(SMSData[35+offset]&0x0f)+(SMSData[35+offset]>>4);
338 m->Time.Minute=10*(SMSData[36+offset]&0x0f)+(SMSData[36+offset]>>4);
339 m->Time.Second=10*(SMSData[37+offset]&0x0f)+(SMSData[37+offset]>>4);
340 m->Time.Timezone=(10*(SMSData[38+offset]&0x07)+(SMSData[38+offset]>>4))/4;
344 dprintf("%d bytes: ", len );
345 for (i = 0; i<len; i++)
346 dprintf("%c", SMSData[15+i]);
350 fprintf(stderr, "Magic not allowed\n");
351 memset(m->MessageText, 0, 161);
352 strncpy(m->MessageText, (void *) &SMSData[15], len);
354 dprintf("Text is %s\n", m->MessageText);
356 /* Originator address is at 15+i,
357 followed by message center addres (?) */
359 char *s = (char *) &SMSData[15+i]; /* We discard volatile. Make compiler quiet. */
360 strcpy(m->Sender, s);
362 strcpy(m->MessageCenter.Number, s);
363 dprintf("Sender = %s, MessageCenter = %s\n", m->Sender, m->MessageCenter.Name);
366 m->MessageCenter.No = 0;
367 strcpy(m->MessageCenter.Name, "(unknown)");
368 m->UDHType = GSM_NoUDH;
369 usleep(300000); /* If phone lost our ack, it might retransmit data */
375 SendSMSMessage(GSM_SMSMessage *m)
377 if (m->Location > 10)
378 return GE_INVALIDSMSLOCATION;
380 if (SMSData[0] != 0x0b) {
381 dprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos);
382 return GE_EMPTYSMSLOCATION;
384 dprintf("Status: " );
385 switch (SMSData[3]) {
386 case 7: m->Type = GST_MO; m->Status = GSS_NOTSENTREAD; dprintf("not sent\n"); break;
387 case 5: m->Type = GST_MO; m->Status = GSS_SENTREAD; dprintf("sent\n"); break;
388 case 3: m->Type = GST_MT; m->Status = GSS_NOTSENTREAD; dprintf("not read\n"); break;
389 case 1: m->Type = GST_MT; m->Status = GSS_SENTREAD; dprintf("read\n"); break;
395 static GSM_Error DeleteSMSMessage(GSM_SMSMessage *message)
397 dprintf("deleting...");
398 return SMS(message, 3);
404 GetValue(u8 index, u8 type)
406 u8 pkt[] = {0x84, 2, 0}; /* Sending 4 at pkt[0] makes phone crash */
413 dprintf("\nRequesting value(%d)", index);
414 SendCommand(pkt, 0xe5, 3);
419 if ((PacketData[3] != 0xe6) ||
420 (PacketData[4] != index) ||
421 (PacketData[5] != type))
422 fprintf(stderr, "Something is very wrong with GetValue\n");
424 dprintf( "Value = %d\n", val );
429 GetRFLevel(GSM_RFUnits *units, float *level)
431 int val = GetValue(0x84, 2);
433 if (*units == GRF_Arbitrary) {
434 res = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
445 *level = (100* (float) val) / 60.0; /* This should be / 99.0 for some models other than nokia-2110 */
446 *units = GRF_Percentage;
452 GetBatteryLevel(GSM_BatteryUnits *units, float *level)
454 int val = GetValue(0x85, 2);
462 if (*units == GBU_Arbitrary) {
464 /* *level = (100 * (float) val) / 90.0;*/ /* 5..first bar, 10..second bar, 90..third bar */
465 *level = *level * 33;
466 *units = GBU_Percentage;
472 static GSM_Error GetVersionInfo()
474 char *s = VersionInfo;
475 if (GetValue(0x11, 0x03) == -1)
478 strncpy( s, (void *) &PacketData[6], sizeof(VersionInfo) );
480 for( Revision = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
482 for( RevisionDate = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
484 for( Model = s; *s != 0x0A; s++ ) if( !*s ) return (GE_NONE);
486 dprintf("Revision %s, Date %s, Model %s\n", Revision, RevisionDate, Model );
492 GetRevision(char *revision)
494 GSM_Error err = GE_NONE;
496 if(!Revision) err = GetVersionInfo();
497 if(err == GE_NONE) strncpy(revision, Revision, 64);
503 GetModel2110(char *model)
505 GSM_Error err = GE_NONE;
507 if(!Model) err = GetVersionInfo();
508 if(err == GE_NONE) strncpy(model, Model, 64);
513 /* Our "Not implemented" functions */
515 GetMemoryStatus(GSM_MemoryStatus *Status)
517 switch(Status->MemoryType) {
535 return (GE_NOTIMPLEMENTED);
541 SendRLPFrame(RLP_F96Frame *frame, bool out_dtx)
547 Display(u8 b, int shift, char *s)
553 case 1: case 2: printf( "!!!" );
554 case 3: printf("%s ", s);
560 switch(PacketData[3]) {
562 printf("Display text at (%d,%d: %s)\n", PacketData[6], PacketData[7], &PacketData[8]);
565 printf("Display indicators: "); /* Valid for 2110 */
566 Display(PacketData[4], 0, "d");
567 Display(PacketData[4], 2, "b");
568 Display(PacketData[4], 4, "a");
569 Display(PacketData[4], 6, "lights");
571 Display(PacketData[5], 0, "service");
572 Display(PacketData[5], 2, "scroll_up");
573 Display(PacketData[5], 4, "scroll_down");
574 Display(PacketData[5], 6, "ABC");
576 Display(PacketData[6], 0, "2.>");
577 Display(PacketData[6], 2, "1.>");
578 Display(PacketData[6], 4, "roam");
579 Display(PacketData[6], 6, "handset");
581 Display(PacketData[7], 0, "vmail");
582 Display(PacketData[7], 2, "envelope");
583 Display(PacketData[7], 4, "battbar");
584 Display(PacketData[7], 6, "3.>");
586 Display(PacketData[8], 0, "?1");
587 Display(PacketData[8], 2, "?2");
588 Display(PacketData[8], 4, "fieldbar");
589 Display(PacketData[8], 6, "ring");
594 /* copy bytes 5+ to smsbuf */
598 for (i=5; i<PacketData[2]+4; i++) {
599 SMSData[SMSpos++] = PacketData[i];
600 dprintf("%c", PacketData[i]);
604 return ((PacketData[4] & 0xf) != 0);
605 /* Make all but last fragment "secret" */
611 /* Handler called when characters received from serial port.
612 * and process them. */
614 SigHandler(int status)
616 unsigned char buffer[256], ack[5], b;
618 static unsigned int Index = 0, Length = 5;
619 static unsigned char pkt[256];
624 res = read(PortFD, buffer, 256);
625 if( res < 0 ) return;
626 for(i = 0; i < res ; i++) {
628 // fprintf(stderr, "(%x)", b, Index);
629 if (!Index && b != MYID && b != 0xf8 && b != 0x00) /* MYID is code of computer */ {
630 /* something strange goes from phone. Just ignore it */
632 fprintf( stdout, "Get [%02X %c]\n", b, b >= 0x20 ? b : '.' );
639 if (b == 0x7f) Length = 5;
640 if (b == 0x7e) Length = 8;
642 if(Index >= Length) {
643 if((pkt[0] == MYID || pkt[0]==0xf8) && pkt[1] == 0x00) /* packet from phone */ {
645 fprintf( stdout, _("Phone: ") );
646 for( j = 0; j < Length; j++ ) {
648 fprintf( stdout, "[%02X %c]", b, b >= 0x20 ? b : '.' );
650 fprintf( stdout, "\n" );
652 /* ensure that we received valid packet */
653 if(pkt[Length - 1] != GetChecksum(pkt, Length-1)) {
654 fprintf( stderr, "***bad checksum***");
656 if((pkt[2] == 0x7F) || (pkt[2] == 0x7E)) /* acknowledge by phone */ {
657 if (pkt[2] == 0x7F) {
658 fprintf( stderr, "[ack]" );
661 /* Increase TX packet number */
663 fprintf( stderr, "[registration ack]" );
668 /* Copy packet data */
669 fprintf( stderr, "[data]" );
670 memcpy((void *) PacketData,pkt,Length);
671 /* send acknowledge packet to phone */
673 ack[0] = 0x00; /* Construct the header. */
674 ack[1] = pkt[0]; /* Send back id */
675 ack[2] = 0x7F; /* Set special size value */
676 ack[3] = pkt[Length - 2]; /* Send back packet number */
677 ack[4] = GetChecksum( ack, 4); /* Set checksum */
679 fprintf( stdout, _("PC : ") );
680 for( j = 0; j < 5; j++ ) {
682 fprintf( stdout, "[%02X %c]", b, b >= 0x20 ? b : '.' );
684 fprintf( stdout, "\n" );
686 if( write( PortFD, ack, 5 ) != 5 )
687 perror( _("Write error!\n") );
688 /* Set validity flag */
694 fprintf(stderr, "[echo]\n");
697 /* Look for new packet */
705 /* Called by initialisation code to open comm port in asynchronous mode. */
706 bool OpenSerial(void)
708 struct termios new_termios;
709 struct sigaction sig_io;
713 fprintf(stdout, _("Setting MBUS communication with 2110...\n"));
716 PortFD = open(PortDevice, O_RDWR | O_NOCTTY | O_NONBLOCK);
718 fprintf(stderr, "Failed to open %s ...\n", PortDevice);
723 fprintf(stdout, "%s opened...\n", PortDevice);
726 sig_io.sa_handler = SigHandler;
728 sigaction (SIGIO, &sig_io, NULL);
729 /* Allow process/thread to receive SIGIO */
730 fcntl(PortFD, F_SETOWN, getpid());
732 /* Make filedescriptor asynchronous. */
733 fcntl(PortFD, F_SETFL, FASYNC);
735 /* Save old termios */
736 tcgetattr(PortFD, &old_termios);
737 /* set speed , 8bit, odd parity */
738 memset( &new_termios, 0, sizeof(new_termios) );
739 new_termios.c_cflag = B9600 | CS8 | CLOCAL | CREAD | PARODD | PARENB;
740 new_termios.c_iflag = 0;
741 new_termios.c_lflag = 0;
742 new_termios.c_oflag = 0;
743 new_termios.c_cc[VMIN] = 1;
744 new_termios.c_cc[VTIME] = 0;
745 tcflush(PortFD, TCIFLUSH);
746 tcsetattr(PortFD, TCSANOW, &new_termios);
747 /* setting the RTS & DTR bit */
749 ioctl(PortFD, TIOCMBIS, &flags);
751 ioctl(PortFD, TIOCMBIS, &flags);
753 ioctl(PortFD, TIOCMGET, &flags);
754 fprintf(stdout, _("DTR is %s.\n"), flags & TIOCM_DTR ? _("up") : _("down"));
755 fprintf(stdout, _("RTS is %s.\n"), flags & TIOCM_RTS ? _("up") : _("down"));
756 fprintf(stdout, "\n");
762 SetKey(int c, int up)
764 u8 reg[] = { 0x7a /* RPC_UI_KEY_PRESS or RPC_UI_KEY_RELEASE */, 0, 1, 0 /* key code */ };
767 fprintf(stderr, "\n Pressing %d\n", c );
769 SendCommand( reg, 0xe5, 4 );
775 #define XCTRL(a) (a&0x1f)
776 #define POWER XCTRL('o')
777 #define SEND XCTRL('t')
778 #define END XCTRL('s')
779 #define CLR XCTRL('h')
780 #define MENU XCTRL('d')
781 #define ALPHA XCTRL('a')
782 #define PLUS XCTRL('b')
783 #define MINUS XCTRL('e')
784 #define PREV XCTRL('p')
785 #define NEXT XCTRL('n')
786 #define SOFTA XCTRL('x')
787 #define SOFTB XCTRL('q')
791 static void PressKey(char c, int i)
794 #define X( a, b ) case a: SetKey(b, i); break;
796 case '1' ... '9': SetKey(c-'0',i); break;
813 X(STO, 19) /* These are not present on 2110, so I can't test this. Enable once tested. */
817 default: fprintf(stderr, "Unknown key %d\n", c);
824 PressString(char *s, int upcase)
827 static int lastupcase = 1;
829 if (lastchar == *s) {
830 fprintf(stderr, "***collision");
839 if (upcase != lastupcase) {
840 fprintf(stderr, "***size change");
850 * This is able to press keys at 62letters/36seconds, tested on message
851 * "Tohle je testovaci zprava schvalne za jak dlouho ji to napise"
857 #define X(a, b) case a: PressString(b, 0); break;
867 X('$', "1111111111");
868 /* X('$', "11111111111"); libra, not in ascii */
869 X('(', "111111111111");
870 X(')', "1111111111111");
871 X('/', "11111111111111");
872 X('%', "111111111111111");
873 X('@', "1111111111111111");
874 X('_', "11111111111111111");
875 X('=', "111111111111111111");
903 #define X(a, b) case a: PressString(b, 1); break;
931 case ' ': PressKey('#', 0); break;
932 case '+': PressKey(ALPHA, 0); PressKey('*', 0); PressKey('*', 0); PressKey(ALPHA, 0); break;
934 case '0' ... '9': PressKey(ALPHA, 0); PressKey(c, 0); PressKey(ALPHA, 0); break;
935 default: PressKey(c, 0);
940 HandleString(char *s)
946 fprintf(stderr,"***end of input");
947 PressKey(lastkey, 1);
954 u8 reg[] = { 1, 1, 0x0f, 1, 0x0f };
955 SendFrame( reg, 0xe9, 5 );
958 /* Fixme: implement grabdisplay properly */
960 EnableDisplayOutput(void)
962 /* LN_UC_SHARE, LN_UC_SHARE, LN_UC_RELEASE, LN_UC_RELEASE, LN_UC_KEEP */
963 u8 pkt[] = {3, 3, 0, 0, 1};
965 return GE_NOTIMPLEMENTED; /* We can do grab display, but we do not know how to ungrab it and with
966 display grabbed, we can't even initialize connection. */
969 SendCommand(pkt, 0x19, 5);
971 fprintf(stderr, "\nGrabbing display");
974 if ((PacketData[3] != 0xcd) ||
975 (PacketData[2] != 1) ||
976 (PacketData[4] != 1 /* LN_UC_REQUEST_OK */))
977 fprintf(stderr, "Something is very wrong with GrabDisplay\n");
978 fprintf(stderr, "Display grabbed okay\n");
983 /* This is the main loop for the MB21 functions. When MB21_Initialise
984 is called a thread is created to run this loop. This loop is
985 exited when the application calls the MB21_Terminate function. */
989 fprintf(stderr, "Initializing... ");
990 /* Do initialisation stuff */
991 LastChar = GetTime();
992 if (OpenSerial() != true) {
995 while (!RequestTerminate) {
1003 while(!MB21_LinkOK) {
1004 fprintf(stderr, "registration... ");
1011 fprintf(stderr, "okay\n");
1013 while (!RequestTerminate)
1014 msleep(100); /* Avoid becoming a "busy" loop. */
1018 /* Initialise variables and state machine. */
1020 Initialise(char *port_device, char *initlength, GSM_ConnectionType connection,
1021 void (*rlp_callback)(RLP_F96Frame *frame))
1023 RequestTerminate = false;
1024 MB21_LinkOK = false;
1025 memset(VersionInfo,0,sizeof(VersionInfo));
1026 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
1030 rtn = pthread_create(&Thread, NULL, (void *) ThreadLoop, (void *)NULL);
1031 if(rtn == EAGAIN || rtn == EINVAL)
1032 return (GE_INTERNALERROR);
1040 /* Routine to get specifed phone book location. Designed to be called by
1041 application. Will block until location is retrieved or a timeout/error
1045 GetPhonebookLocation(GSM_PhonebookEntry *entry)
1047 u8 pkt[] = {0x1a, 0 /* 1 == phone */, 0};
1050 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1051 pkt[2] = entry->Location;
1054 SendCommand(pkt, /* LN_LOC_COMMAND */ 0x1f, 3);
1057 if ((PacketData[3] != 0xc9) ||
1058 (PacketData[4] != 0x1a)) {
1059 fprintf(stderr, "Something is very wrong with GetPhonebookLocation\n");
1062 dprintf("type= %x\n", PacketData[5]);
1063 dprintf("location= %x\n", PacketData[6]);
1064 dprintf("status= %x\n", PacketData[7]);
1065 for (i=8; PacketData[i]; i++) {
1066 dprintf("%c", PacketData[i]);
1068 strcpy(entry->Name, (void *)&PacketData[8]);
1070 strcpy(entry->Number, (void *)&PacketData[i]);
1071 for (; PacketData[i]; i++) {
1072 dprintf("%c", PacketData[i]);
1075 entry->Empty = false;
1081 /* Routine to write phonebook location in phone. Designed to be called by
1082 application code. Will block until location is written or timeout
1086 WritePhonebookLocation(GSM_PhonebookEntry *entry)
1088 u8 pkt[999] = {0x1b, 0 /* 1 == phone */, 0};
1090 pkt[1] = 3 + (entry->MemoryType != GMT_ME);
1091 pkt[2] = entry->Location;
1092 strcpy(&pkt[3], entry->Name);
1093 strcpy(&pkt[3+strlen(entry->Name)+1], entry->Number);
1096 SendCommand(pkt, /* LN_LOC_COMMAND */ 0x1f, 3+strlen(entry->Number)+strlen(entry->Name)+2);
1101 if ((PacketData[3] != 0xc9) ||
1102 (PacketData[4] != 0x1b)) {
1103 fprintf(stderr, "Something is very wrong with WritePhonebookLocation\n");
1106 printf("type= %x\n", PacketData[5]);
1107 printf("location= %x\n", PacketData[6]);
1108 printf("status= %x\n", PacketData[7]);
1113 GetSMSStatus(GSM_SMSStatus *Status)
1121 GSM_Functions MB21_Functions = {
1124 GetPhonebookLocation,
1125 WritePhonebookLocation,
1145 PNOK_GetManufacturer,
1169 EnableDisplayOutput,