:pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
[gnokii.git] / common / phones / nk3110.c
1 /*
2
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 2000 Hugh Blemings & Pavel Janík ml.
10   Copyright (C) 2001 Pawe³ Kot <pkot@linuxnews.pl>
11
12   Released under the terms of the GNU GPL, see file COPYING for more details.
13
14   This file provides functions specific to the 3110 series. 
15   See README for more details on supported mobile phones.
16
17   $Log$
18   Revision 1.1.1.2  2001/11/27 22:01:20  short
19   :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
20
21   Revision 1.7  2001/11/27 12:19:01  pkot
22   Cleanup, indentation, ANSI complaint preprocesor symbols (Jan Kratochvil, me)
23
24   Revision 1.6  2001/11/20 16:22:22  pkot
25   First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
26
27   Revision 1.5  2001/11/19 13:03:18  pkot
28   nk3110.c cleanup
29
30   Revision 1.4  2001/11/17 16:42:47  pkot
31   Cleanup
32
33   Revision 1.3  2001/11/09 14:25:04  pkot
34   DEBUG cleanups
35
36   Revision 1.2  2001/11/09 13:47:58  pkot
37   Removed pthreads from 3110 support. It may break it.
38
39   Revision 1.1  2001/11/08 16:39:09  pkot
40   3810/3110 support for the new structure (Tamas Bondar)
41
42
43 */
44
45 #include <string.h>
46 #include <stdlib.h>
47 #include <ctype.h>
48
49 #define __phones_nk3110_c
50 #include "misc.h"
51 #include "gsm-common.h"
52 #include "phones/generic.h"
53 #include "phones/nk3110.h"
54 #include "links/fbus-3110.h"
55 #include "phones/nokia.h"
56
57 #ifndef WIN32
58 #  include <unistd.h>
59 #else
60 #  define snprintf _snprintf
61 #  define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
62 #endif
63
64 /* Some globals */
65
66 static GSM_IncomingFunctionType IncomingFunctions[] = {
67         { 0x0a, P3110_IncomingNothing },
68         { 0x0b, P3110_IncomingCall },
69         { 0x0c, P3110_IncomingNothing },
70         { 0x0d, P3110_IncomingCallAnswered },
71         { 0x0e, P3110_IncomingCallEstablished },
72         { 0x0f, P3110_IncomingNothing },
73         { 0x10, P3110_IncomingEndOfOutgoingCall },
74         { 0x11, P3110_IncomingEndOfIncomingCall },
75         { 0x12, P3110_IncomingEndOfOutgoingCall2 },
76         { 0x13, P3110_IncomingRestart },
77         { 0x15, P3110_IncomingInitFrame_0x15 },
78         { 0x16, P3110_IncomingInitFrame_0x16 },
79         { 0x17, P3110_IncomingInitFrame_0x17 },
80         { 0x20, P3110_IncomingNothing },
81         /*{ 0x21, P3110_IncomingDTMFSucess },*/
82         /*{ 0x22, P3110_IncomingDTMFFailure },*/
83         { 0x23, P3110_IncomingNothing },
84         { 0x24, P3110_IncomingNothing },
85         { 0x25, P3110_IncomingNothing },
86         { 0x26, P3110_IncomingNothing },
87         { 0x27, P3110_IncomingSMSUserData },
88         { 0x28, P3110_IncomingSMSSend },
89         { 0x29, P3110_IncomingSMSSendError },
90         /* ... */
91         { 0x2c, P3110_IncomingSMSHeader },
92         { 0x2d, P3110_IncomingSMSError },
93         { 0x2e, P3110_IncomingSMSDelete },
94         { 0x2f, P3110_IncomingSMSDeleteError },
95         /* ... */
96         { 0x32, P3110_IncomingSMSDelivered },
97         { 0x3f, P3110_IncomingNothing },
98         { 0x40, P3110_IncomingNoSMSInfo },
99         { 0x41, P3110_IncomingSMSInfo },
100         { 0x48, P3110_IncomingPINEntered },
101         { 0x4a, P3110_IncomingNothing },
102         { 0x4b, P3110_IncomingStatusInfo },
103         { 0x4c, P3110_IncomingNothing },
104         { 0x4d, P3110_IncomingPhoneInfo },
105         { 0, NULL}
106 };
107
108 GSM_Phone phone_nokia_3110 = {
109         IncomingFunctions,
110         PGEN_IncomingDefault,
111         /* Mobile phone information */
112         {
113                 "3110|3810|8110|8110i", /* Models */
114                 4,                      /* Max RF Level */
115                 0,                      /* Min RF Level */
116                 GRF_Arbitrary,          /* RF level units */
117                 4,                      /* Max Battery Level */
118                 0,                      /* Min Battery Level */
119                 GBU_Arbitrary,          /* Battery level units */
120                 GDT_None,               /* No date/time support */
121                 GDT_None,               /* No alarm support */
122                 0,                      /* Max alarms = 0 */
123                 0, 0,                   /* Startup logo size */
124                 0, 0,                   /* Op logo size */
125                 0, 0                    /* Caller logo size */
126         },
127         Functions
128 };
129
130 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
131 {
132         switch (op) {
133         case GOP_Init:
134                 return P3110_Initialise(state);
135         case GOP_GetModel:
136         case GOP_GetRevision:
137         case GOP_GetImei:
138                 return P3110_GetPhoneInfo(data, state);
139         case GOP_Identify:
140                 return P3110_Identify(data, state);
141         case GOP_GetBatteryLevel:
142         case GOP_GetRFLevel:
143                 return P3110_GetStatusInfo(data, state);
144         case GOP_GetMemoryStatus:
145                 return P3110_GetMemoryStatus(data, state);
146         case GOP_ReadPhonebook:
147         case GOP_WritePhonebook:
148         case GOP_GetPowersource:
149         case GOP_GetAlarm:
150         case GOP_GetSMSStatus:
151         case GOP_GetIncomingCallNr:
152         case GOP_GetNetworkInfo:
153                 return GE_NOTIMPLEMENTED;
154         case GOP_GetSMS:
155                 return P3110_GetSMSMessage(data, state);
156         case GOP_DeleteSMS:
157                 return P3110_DeleteSMSMessage(data, state);
158         case GOP_SendSMS:
159                 return P3110_SendSMSMessage(data, state);
160         case GOP_GetSMSCenter:
161                 return P3110_GetSMSInfo(data, state);
162         case GOP_GetSpeedDial:
163         case GOP_GetDateTime:
164         default:
165                 return GE_NOTIMPLEMENTED;
166         }
167 }
168
169 static bool LinkOK = false;
170 static bool SimAvailable = false;
171
172 /* These are related to keepalive functionality */
173 static bool RequestTerminate;
174 static bool DisableKeepAlive;
175 static int KeepAliveTimer;
176
177 /* Initialise is the only function allowed to 'use' state */
178 static GSM_Error P3110_Initialise(GSM_Statemachine *state)
179 {
180         GSM_Data data;
181         u8 init_sequence[20] = {0x02, 0x01, 0x07, 0xa2, 0x88, 0x81, 0x21, 0x55, 0x63, 0xa8, 0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15, 0x63, 0x80};
182
183         /* Copy in the phone info */
184         memcpy(&(state->Phone), &phone_nokia_3110, sizeof(GSM_Phone));
185
186         /* Only serial connection is supported */
187         if (state->Link.ConnectionType != GCT_Serial) return GE_NOTSUPPORTED;
188
189         /* Initialise FBUS link */
190         if (FB3110_Initialise(&(state->Link), state) != GE_NONE) {
191                 dprintf("Error in link initialisation\n");
192                 return GE_NOTREADY;
193         }
194
195         /* Initialise state machine */
196         SM_Initialise(state);
197
198         /* 0x15 messages are sent by the PC during the initialisation phase.
199            Anyway, the contents of the message are not understood so we 
200            simply send the same sequence observed between the W95 PC and 
201            the phone.  The init sequence may still be a bit flaky and is not 
202            fully understood. */
203         if (SM_SendMessage(state, 20, 0x15, init_sequence) != GE_NONE) return GE_NOTREADY;
204
205         /* Wait for response to 0x15 sequence */
206         GSM_DataClear(&data);
207         if (SM_Block(state, &data, 0x16) != GE_NONE) return GE_NOTREADY;
208
209         /* Most probably link is OK now */
210         LinkOK = true;
211
212         /* Start sending keepalive messages in separate thread */
213         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
214         RequestTerminate = false;
215         DisableKeepAlive = false;
216         return GE_NONE;
217 }
218
219
220 static GSM_Error P3110_GetSMSInfo(GSM_Data *data, GSM_Statemachine *state)
221 {
222         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
223         if (SM_SendMessage(state, 0, 0x3f, NULL) != GE_NONE) return GE_NOTREADY;
224         return SM_Block(state, data, 0x41);
225 }
226
227 static GSM_Error P3110_GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
228 {
229         dprintf("Getting phone info...\n");
230         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
231         if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
232         return SM_Block(state, data, 0x4d);
233 }
234
235 static GSM_Error P3110_GetStatusInfo(GSM_Data *data, GSM_Statemachine *state)
236 {
237         dprintf("Getting phone status...\n");
238         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
239         if (SM_SendMessage(state, 0, 0x4a, NULL) != GE_NONE) return GE_NOTREADY;
240         return SM_Block(state, data, 0x4b);
241 }
242
243 static GSM_Error P3110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
244 {
245         dprintf("Getting memory status...\n");
246
247         /* Check if this type of memory is available */
248         switch (data->MemoryStatus->MemoryType) {
249         case GMT_SM:
250                 if (!SimAvailable) return GE_NOTREADY;
251                 return P3110_GetSMSInfo(data, state);
252         case GMT_ME:
253                 if (P3110_MEMORY_SIZE_ME == 0) return GE_NOTREADY;
254                 return P3110_GetSMSInfo(data, state);
255         default:
256                 break;
257         }
258         return GE_NOTREADY;
259 }
260
261
262 static GSM_Error P3110_Identify(GSM_Data *data, GSM_Statemachine *state)
263 {
264         dprintf("Identifying...\n");
265         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
266         if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
267         SM_Block(state, data, 0x4d);
268         
269         /* Check that we are back at state Initialised */
270         if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
271         return GE_NONE;
272 }
273
274
275 static GSM_Error P3110_GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
276 {
277         int total_length, timeout, c;
278         u8 response = 0, request[2];
279         GSM_Error error = GE_INTERNALERROR;
280
281         dprintf("Getting SMS message...\n");
282
283         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
284
285         switch(data->SMSMessage->MemoryType) {
286         case GMT_ME:
287                 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
288                 break;
289         case GMT_SM:
290                 data->SMSMessage->MemoryType = 2;
291                 break;
292         default:
293                 return (GE_INVALIDMEMORYTYPE);
294         }
295
296         /* Set memory type and location in the request */
297         request[0] = data->SMSMessage->MemoryType;
298         request[1] = data->SMSMessage->Number;
299
300         /* 0x25 messages requests the contents of an SMS message
301            from the phone.  The first byte has only ever been 
302            observed to be 0x02 - could be selecting internal versus
303            external memory.  Specifying memory 0x00 may request the
304            first location?  Phone replies with 0x2c and 0x27 messages
305            for valid locations, 0x2d for empty ones. */
306         if (SM_SendMessage(state, 2, 0x25, request) != GE_NONE) return GE_NOTREADY;
307
308         SM_WaitFor(state, data, 0x2d);
309         SM_WaitFor(state, data, 0x2c);
310
311         timeout = 30; /* ~3secs timeout */
312
313         do {
314                 SM_Loop(state, 1);
315                 timeout--;
316         } while ((timeout > 0) && state->NumReceived == 0);
317
318         /* timeout */ 
319         if (state->NumReceived == 0) return GE_TIMEOUT;
320
321         /* find response in state machine */
322         for (c = 0; c < state->NumWaitingFor; c++) {
323                 if (state->ResponseError[c] != GE_BUSY) {
324                         response = state->WaitingFor[c];
325                         error = state->ResponseError[c];
326                 }
327         }
328
329         /* reset state machine */
330         SM_Reset(state);
331
332         /* process response */
333         switch (response) {
334         case 0x2c:
335                 if (error != GE_NONE) return error;
336
337                 /* Save total length of message */
338                 total_length = data->SMSMessage->Length;
339
340                 /* Block for subsequent content frames... */
341                 do {
342                         SM_Block(state, data, 0x27);
343                 } while (data->SMSMessage->Length < total_length);
344
345                 /* Terminate message text */
346                 data->SMSMessage->MessageText[data->SMSMessage->Length] = 0;
347                 return GE_NONE;
348         case 0x2d:
349                 return error;
350         default:
351                 return GE_INTERNALERROR;
352         }
353 }
354
355
356 static GSM_Error P3110_DeleteSMSMessage(GSM_Data *data, GSM_Statemachine *state)
357 {
358         int timeout, c;
359         u8 response = 0, request[2];
360         GSM_Error error = GE_INTERNALERROR;
361
362         dprintf("Deleting SMS message...\n");
363
364         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
365
366         switch(data->SMSMessage->MemoryType) {
367         case GMT_ME:
368                 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
369                 break;
370         case GMT_SM:
371                 data->SMSMessage->MemoryType = 2;
372                 break;
373         default:
374                 return (GE_INVALIDMEMORYTYPE);
375         }
376
377         /* Set memory type and location in the request */
378         request[0] = data->SMSMessage->MemoryType;
379         request[1] = data->SMSMessage->Number;
380
381         /* 0x26 message deletes an SMS message from the phone. 
382            The first byte has only ever been observed to be 0x02
383            but is assumed to be selecting internal versus
384            external memory.  Phone replies with 0x2e for valid locations,
385            0x2f for invalid ones.  If a location is empty but otherwise
386            valid 0x2e is still returned. */
387         if (SM_SendMessage(state, 2, 0x26, request) != GE_NONE) return GE_NOTREADY;
388
389         SM_WaitFor(state, data, 0x2e);
390         SM_WaitFor(state, data, 0x2f);
391
392         timeout = 30; /* ~3secs timeout */
393
394         do {
395                 SM_Loop(state, 1);
396                 timeout--;
397         } while ((timeout > 0) && state->NumReceived == 0);
398
399         /* timeout */ 
400         if (state->NumReceived == 0) return GE_TIMEOUT;
401
402         /* find response in state machine */
403         for (c = 0; c < state->NumWaitingFor; c++) {
404                 if (state->ResponseError[c] != GE_BUSY) {
405                         response = state->WaitingFor[c];
406                         error = state->ResponseError[c];
407                 }
408         }
409
410         /* reset state machine */
411         SM_Reset(state);
412
413         /* process response */
414         switch (response) {
415         case 0x2e:
416         case 0x2f:
417                 return error;
418         default:
419                 return GE_INTERNALERROR;
420         }
421 }
422
423
424 static GSM_Error P3110_SendSMSMessage(GSM_Data *data, GSM_Statemachine *state)
425 {
426         int timeout, c, retry_count, block_count, block_length;
427         u8 userdata[GSM_MAX_SMS_LENGTH];
428         int userdata_length, userdata_offset, userdata_remaining;
429         u8 response, request[GSM_MAX_SMS_LENGTH];
430         GSM_Error error;
431         SMS_MessageCenter smsc;
432         int i;
433
434         /* Get default SMSC from phone if not set in SMS */
435         if (!data->SMSMessage->MessageCenter.Number[0]) {
436                 data->MessageCenter = &smsc;
437                 error = P3110_GetSMSInfo(data, state);
438                 if (error != GE_NONE) return error;
439                 data->SMSMessage->MessageCenter = smsc;
440         }
441
442         dprintf("Sending SMS to %s via message center %s\n", data->SMSMessage->RemoteNumber.number, data->SMSMessage->MessageCenter.Number);
443
444 /*
445   Moved to gsm-sms.c
446   if (data->SMSMessage->UDH[0].Type) {
447   userdata_offset = 1 + data->SMSMessage->udhlen;
448   memcpy(userdata, data->SMSMessage->MessageText, userdata_offset);
449   fo |= FO_UDHI;
450   } else {
451   userdata_offset = 0;
452   }
453 */
454
455 /*
456   Moved to gsm-sms.c
457   if (data->SMSMessage->EightBit) {
458   memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, data->SMSMessage->Length);
459   userdata_length = data->SMSMessage->Length + userdata_offset;
460   max_userdata_length = GSM_MAX_SMS_8_BIT_LENGTH;
461   dcs = DCS_DATA | DCS_CLASS1;
462   } else {
463   userdata_length = strlen(data->SMSMessage->MessageText);
464   memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, userdata_length);
465   userdata_length += userdata_offset;
466   max_userdata_length = GSM_MAX_SMS_LENGTH;
467   }
468 */
469
470 /*
471   Moved to gsm-sms.c
472   request[0] = fo;
473   request[1] = PID_DEFAULT;
474   request[2] = dcs;
475   request[3] = GSMV_Max_Time;
476   request[4] = 0x00;
477   request[5] = 0x00;
478   request[6] = 0x00;
479   request[7] = 0x00;
480   request[8] = 0x00;
481   request[9] = 0x00;
482   request[10] = userdata_length;
483   request[11] = smsc_length;
484   memcpy(request+12, data->SMSMessage->MessageCenter.Number, smsc_length);
485   request[12+smsc_length] = dest_length;
486   memcpy(request+13+smsc_length, data->SMSMessage->Destination, dest_length);
487 */
488
489         error = EncodePDUSMS(data->SMSMessage, request);
490         if (error) return error;
491
492         /* We have a loop here as if the response from the phone is
493            0x65 0x26 the rule appears to be just to try sending the
494            message again.  We do this a maximum of FB38_SMS_SEND_RETRY_COUNT
495            times before giving up.  This value is empirical only! */
496         retry_count = P3110_SMS_SEND_RETRY_COUNT;
497
498         while (retry_count > 0) {
499
500                 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
501
502                 dprintf("Transferring FBUS SMS header [");
503                 for (i = 0; i < data->SMSMessage->Length; i++) dprintf(" %02hhX", request[i]);
504                 dprintf(" ]\n");
505
506                 if (SM_SendMessage(state, data->SMSMessage->Length, 0x23, request) != GE_NONE) return GE_NOTREADY;
507
508                 error = SM_Block(state, data, 0x23);
509                 if (error != GE_NONE) return error;
510
511                 /* Now send as many blocks of maximum 55 characters as required
512                    to send complete message. */
513                 block_count = 1;
514                 userdata_offset = 0;
515                 userdata_remaining = userdata_length;
516
517                 while (userdata_remaining > 0) {
518                         block_length = userdata_remaining;
519
520                         /* Limit block length */
521                         if (block_length > 55) block_length = 55;
522
523                         /* Create block */
524                         request[0] = block_count;
525                         memcpy(request+1, userdata + userdata_offset, block_length);
526
527                         /* Send block */
528                         if (SM_SendMessage(state, block_length+1, 0x27, request) != GE_NONE) return GE_NOTREADY;
529                         error = SM_Block(state, data, 0x27);
530                         if (error != GE_NONE) return error;
531
532                         /* update remaining and offset values for next block */
533                         userdata_remaining -= block_length;
534                         userdata_offset += block_length;
535                         block_count ++;
536                 }
537
538                 /* Now wait for response from network which will see
539                    CurrentSMSMessageError change from busy. */
540                 SM_WaitFor(state, data, 0x28);
541                 SM_WaitFor(state, data, 0x29);
542
543                 timeout = 1200; /* 120secs timeout */
544
545                 do {
546                         SM_Loop(state, 1);
547                         timeout--;
548                 } while ((timeout > 0) && state->NumReceived == 0);
549
550                 /* timeout */ 
551                 if (state->NumReceived == 0) return GE_TIMEOUT;
552
553                 /* find response in state machine */
554                 for (c = 0; c < state->NumWaitingFor; c++) {
555                         if (state->ResponseError[c] != GE_BUSY) {
556                                 response = state->WaitingFor[c];
557                                 error = state->ResponseError[c];
558                         }
559                 }
560
561                 /* reset state machine */
562                 SM_Reset(state);
563
564                 /* process response */
565                 switch (response) {
566                 case 0x28:
567                         return error;
568                 case 0x29:
569                         /* Got a retry response so try again! */
570                         dprintf("SMS send attempt failed, trying again...\n");
571                         retry_count--;
572                         /* After an empirically determined pause... */
573                         usleep(500000); /* 0.5 seconds. */
574                         break;
575                 default:
576                         return GE_INTERNALERROR;
577                 }
578         }
579         /* Retries must have failed. */
580         return GE_SMSSENDFAILED;
581 }
582
583
584 static GSM_Error P3110_IncomingNothing(int messagetype, unsigned char *message, int length, GSM_Data *data)
585 {
586         return GE_NONE;
587 }
588
589 /* 0x0b messages are sent by phone when an incoming call occurs,
590    this message must be acknowledged. */
591 static GSM_Error P3110_IncomingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
592 {
593         int     count;
594         char    buffer[256];
595
596         /* Get info out of message.  At present, first three bytes are 
597            unknown (though third seems to correspond to length of 
598            number).  Remaining bytes are the phone number, ASCII 
599            encoded. */
600         for (count = 0; count < message[4]; count ++) {
601                 buffer[count] = message[5 + count];
602         }
603         buffer[count] = 0x00;
604
605         /* Now display incoming call message. */
606         dprintf("Incoming call - Type: %s. %02x, Number %s.\n",
607                 (message[2] == 0x05 ? "Voice":"Data?"), message[3], buffer);
608
609         return GE_NONE;
610 }
611
612 static GSM_Error P3110_IncomingCallAnswered(int messagetype, unsigned char *message, int length, GSM_Data *data)
613 {
614         dprintf("Incoming call answered from phone.\n");
615
616         return GE_NONE;
617 }
618
619 /* Fairly self explanatory these two, though the outgoing 
620    call message has three (unexplained) data bytes. */
621 static GSM_Error P3110_IncomingCallEstablished(int messagetype, unsigned char *message, int length, GSM_Data *data)
622 {
623         dprintf("%s call established - status bytes %02x %02x.\n",
624                 (message[2] == 0x05 ? "voice":"data(?)"), message[3], message[4]);
625
626         return GE_NONE;
627 }
628
629 /* 0x10 messages are sent by the phone when an outgoing
630    call terminates. */
631 static GSM_Error P3110_IncomingEndOfOutgoingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
632 {
633         dprintf("Call terminated from phone (0x10 message).\n");
634         /* FIXME: Tell datapump code that the call has terminated. */
635         /*if (CallPassup) {
636                 CallPassup(' ');
637                 }*/
638
639         return GE_NONE;
640 }
641
642 /* 0x11 messages are sent by the phone when an incoming call
643    terminates.  There is some other data in the message, 
644    purpose as yet undertermined. */
645 static GSM_Error P3110_IncomingEndOfIncomingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
646 {
647         dprintf("Call terminated from opposite end of line (or from network).\n");
648
649         /* FIXME: Tell datapump code that the call has terminated. */
650         /*if (CallPassup) {
651                 CallPassup(' ');
652                 }*/
653
654         return GE_NONE;
655 }
656
657 /* 0x12 messages are sent after the 0x10 message at the 
658    end of an outgoing call.  Significance of two messages
659    versus the one at the end of an incoming call  is as 
660    yet undertermined. */
661 static GSM_Error P3110_IncomingEndOfOutgoingCall2(int messagetype, unsigned char *message, int length, GSM_Data *data)
662 {
663         dprintf("Call terminated from phone (0x12 message).\n");
664
665         /* FIXME: Tell datapump code that the call has terminated. */
666         /*if (CallPassup) {
667                 CallPassup(' ');
668                 }*/
669
670         return GE_NONE;
671 }
672
673
674 /* 0x13 messages are sent after the phone restarts. 
675    Re-initialise */
676
677 static GSM_Error P3110_IncomingRestart(int messagetype, unsigned char *message, int length, GSM_Data *data)
678 {
679         /* FIXME: send 0x15 message somehow */
680         return GE_NONE;
681 }
682
683
684 /* 0x15 messages are sent by the phone in response to the
685    init sequence sent so we don't acknowledge them! */
686
687 static GSM_Error P3110_IncomingInitFrame_0x15(int messagetype, unsigned char *message, int length, GSM_Data *data)
688 {
689         return GE_NONE;
690 }
691
692
693 /* 0x16 messages are sent by the phone during initialisation, to response 
694    to the 0x15 message.
695    Sequence bytes have been observed to change with differing software 
696    versions: V06.61 (19/08/97) sends 0x10 0x02, V07.02 (17/03/98) sends 
697    0x30 0x02. The actual data byte is 0x02 when SIM memory is available,
698    and 0x01 when not (e.g. when SIM card isn't inserted to phone or when 
699    it is waiting for PIN) */
700
701 static GSM_Error P3110_IncomingInitFrame_0x16(int messagetype, unsigned char *message, int length, GSM_Data *data)
702 {
703         SimAvailable = (message[2] == 0x02);
704         dprintf("SIM available: %s.\n", (SimAvailable ? "Yes" : "No"));
705         return GE_NONE;
706 }
707
708
709 static GSM_Error P3110_IncomingInitFrame_0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
710 {
711         dprintf("0x17 Registration Response: Failure!\n");
712         return GE_NONE;
713 }
714
715
716 /* 0x27 messages are a little unusual when sent by the phone in that
717    they can either be an acknowledgement of an 0x27 message we sent
718    to the phone with message text in it or they could
719    contain message text for a message we requested. */
720
721 static GSM_Error P3110_IncomingSMSUserData(int messagetype, unsigned char *message, int length, GSM_Data *data)
722 {
723         int count;
724     
725         /* First see if it was an acknowledgement to one of our messages,
726            if so then nothing to do */
727         if (length == 0x02) return GE_NONE;
728
729         /* Copy into current SMS message as long as it's non-NULL */
730         if (!data->SMSMessage) return GE_INTERNALERROR;
731
732         /* If this is the first block, reset accumulated message length. */
733         if (message[2] == 1) data->SMSMessage->Length = 0;
734
735         /* Copy message text */
736         for (count = 0; count < length-3 && data->SMSMessage->Length < GSM_MAX_SMS_LENGTH; count++, data->SMSMessage->Length++)
737                 data->SMSMessage->MessageText[data->SMSMessage->Length] = message[count + 3];
738
739         return GE_NONE;
740 }
741
742
743 /* 0x28 messages are sent by the phone to acknowledge succesfull
744    sending of an SMS message.  The byte returned is a receipt
745    number of some form, not sure if it's from the network, sending
746    sending of an SMS message.  The byte returned is the TP-MR
747    (TP-Message-Reference) from sending phone (Also sent to network).
748    TP-MR is send from phone within 0x32 message. TP-MR is increased
749    by phone after each sent SMS */
750
751 static GSM_Error P3110_IncomingSMSSend(int messagetype, unsigned char *message, int length, GSM_Data *data)
752 {
753         dprintf("SMS send OK (0x%02hhx)\n", message[2]);
754         data->SMSMessage->Number = (int) message[2];
755         return GE_SMSSENDOK;
756 }
757
758
759 /* 0x29 messages are sent by the phone to indicate an error in
760    sending an SMS message.  Observed values are 0x65 0x15 when
761    the phone originated SMS was disabled by the network for
762    the particular phone.  0x65 0x26 was observed too, whereupon
763    the message was retried. */
764
765 static GSM_Error P3110_IncomingSMSSendError(int messagetype, unsigned char *message, int length, GSM_Data *data)
766 {
767         dprintf("SMS send failed (0x%02hhx 0x%02hhx)\n", message[2], message[3]);
768         return GE_SMSSENDFAILED;
769 }
770
771
772 /* 0x2c messages are generated by the phone when we request an SMS 
773    message with an 0x25 message.  Appears to have the same fields 
774    as the 0x30 notification but with one extra.  Immediately after 
775    the 0x2c nessage, the phone sends 0x27 message(s) */
776
777 static GSM_Error P3110_IncomingSMSHeader(int messagetype, unsigned char *message, int length, GSM_Data *data)
778 {
779         /* u8 sender_length, smsc_length, l; */
780
781         if (!data->SMSMessage) return GE_INTERNALERROR;
782
783         /* Extract data from message into SMSMessage */
784
785         DecodePDUSMS(message, data->SMSMessage, length);
786
787         /* All these moved to gsm-sms.c
788         Set memory type
789         switch(message[2]) {
790         case 1:
791                 data->SMSMessage->MemoryType = GMT_ME;
792                 break;
793         case 2:
794                 data->SMSMessage->MemoryType = GMT_SM;
795                 break;
796         default:
797                 data->SMSMessage->MemoryType = GMT_XX;
798                 break;
799         }
800
801         Set location in memory
802         data->SMSMessage->Location = message[3];
803         data->SMSMessage->MessageNumber = message[3];
804
805           3810 series has limited support for different SMS "mailboxes"
806            to the extent that the only know differentiation is between
807            received messages 0x01, 0x04 and written messages 0x07 0x01.
808            No flag has been found (yet) that indicates whether the 
809            message has been sent or not.
810
811         Default to unknown message type
812         data->SMSMessage->Type = GST_UN;
813
814         Consider received messages "Inbox" (Mobile Terminated)
815         if (message[4] == 0x01 && message[5] == 0x04)
816                 data->SMSMessage->Type = GST_MT;
817
818         Consider written messages "Outbox" (Mobile Originated)
819         if (message[4] == 0x07 && message[5] == 0x01)
820                 data->SMSMessage->Type = GST_MO;
821
822         We don't know about read/unread or sent/unsent status.
823            so assume has been sent or read
824         data->SMSMessage->Status = GSS_SENTREAD;
825
826         Based on experiences with a 3110 it seems, that
827            0x03 means a received unread message,
828            0x07 means a stored unsent message
829         if (message[4] == 0x03 || message[4] == 0x07)
830                 data->SMSMessage->Status = GSS_NOTSENTREAD;
831         else
832                 data->SMSMessage->Status = GSS_SENTREAD;
833
834         Check UDHI
835         if (message[5] & FO_UDHI)
836                 data->SMSMessage->UDHType = GSM_RingtoneUDH; FIXME
837         else
838                 data->SMSMessage->UDHType = GSM_NoUDH;
839
840         Check Data Coding Scheme and set text/binary flag
841         if (message[7] == 0xf5)
842                 data->SMSMessage->EightBit = true;
843         else
844                 data->SMSMessage->EightBit = false;
845
846         Extract date and time information which is packed in to 
847            nibbles of each byte in reverse order.  Thus day 28 would be
848            encoded as 0x82
849         P3110_DecodeTime(message+8, &(data->SMSMessage->Time));
850
851         Set message length
852         data->SMSMessage->Length = message[15];
853
854         Now get sender and message center length
855         smsc_length = message[16];
856         sender_length = message[17 + smsc_length];
857
858         Copy SMSC number
859         l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
860         strncpy(data->SMSMessage->MessageCenter.Number, message + 17, l);
861         data->SMSMessage->MessageCenter.Number[l] = 0;
862
863         Copy sender number
864         l = sender_length < GSM_MAX_SENDER_LENGTH ? sender_length : GSM_MAX_SENDER_LENGTH;
865         strncpy(data->SMSMessage->Sender, message + 18 + smsc_length, l);
866         data->SMSMessage->Sender[l] = 0;
867 */
868
869         dprintf("PID:%02x DCS:%02x Timezone:%02x Stat1:%02x Stat2:%02x\n",
870                 message[6], message[7], message[14], message[4], message[5]);
871
872         dprintf("Message Read:\n");
873         dprintf("  Location: %d. Type: %d Status: %d\n", data->SMSMessage->Number, data->SMSMessage->Type, data->SMSMessage->Status);
874         dprintf("  Sender: %s\n", data->SMSMessage->RemoteNumber.number);
875         dprintf("  Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
876         dprintf("  Time: %02d.%02d.%02d %02d:%02d:%02d\n",
877                 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
878
879         return GE_NONE;
880 }
881
882
883 /* 0x2d messages are generated when an SMS message is requested
884    that does not exist or is empty. */
885
886 static GSM_Error P3110_IncomingSMSError(int messagetype, unsigned char *message, int length, GSM_Data *data)
887 {
888         if (message[2] == 0x74)
889                 return GE_INVALIDSMSLOCATION;
890         else
891                 return GE_EMPTYSMSLOCATION;
892 }
893
894
895 /* 0x2e messages are generated when an SMS message is deleted
896    successfully. */
897
898 static GSM_Error P3110_IncomingSMSDelete(int messagetype, unsigned char *message, int length, GSM_Data *data)
899 {
900         return GE_NONE;
901 }
902
903
904 /* 0x2f messages are generated when an SMS message is deleted
905    that does not exist.  Unlike responses to a getsms message
906    no error is returned when the entry is already empty */
907
908 static GSM_Error P3110_IncomingSMSDeleteError(int messagetype, unsigned char *message, int length, GSM_Data *data)
909 {
910         /* Note 0x74 is the only value that has been seen! */
911         if (message[2] == 0x74)
912                 return GE_INVALIDSMSLOCATION;
913         else
914                 return GE_EMPTYSMSLOCATION;
915 }
916
917
918 /* 0x32 messages are generated when delivery notification arrives
919    to phone from network */
920
921 static GSM_Error P3110_IncomingSMSDelivered(int messagetype, unsigned char *message, int length, GSM_Data *data)
922 {
923         static GSM_SMSMessage sms;
924 /*      u8 dest_length, smsc_length, l;*/
925         u8 U0, U1, U2;
926
927         data->SMSMessage = &sms;
928
929         if (!data->SMSMessage) return GE_INTERNALERROR;
930
931         U0 = message[1];
932         U1 = message[2];
933         U2 = message[17];
934
935         DecodePDUSMS(message, data->SMSMessage, length);
936
937         /* All these are moved fo gsm-sms.c
938         P3110_DecodeTime(message+3, &(data->SMSMessage->Time));
939         P3110_DecodeTime(message+10, &(data->SMSMessage->SMSCTime));
940
941
942         Get message id
943         data->SMSMessage->MessageNumber = (int) message[18];
944
945         Get sender and message center length
946         dest_length = message[19];
947         smsc_length = message[20 + dest_length];
948
949         Copy destination number
950         l = dest_length < GSM_MAX_DESTINATION_LENGTH ? dest_length : GSM_MAX_DESTINATION_LENGTH;
951         strncpy(data->SMSMessage->Destination, message + 20, l);
952         data->SMSMessage->Destination[l] = 0;
953
954         Copy SMSC number
955         l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
956         strncpy(data->SMSMessage->MessageCenter.Number, message + 21 + dest_length, l);
957         data->SMSMessage->MessageCenter.Number[l] = 0;
958         */
959
960         dprintf("Message [0x%02x] Delivered!\n", data->SMSMessage->Number);
961         dprintf("   Destination: %s\n", data->SMSMessage->RemoteNumber.number);
962         dprintf("   Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
963         dprintf("   Unknowns: 0x%02x 0x%02x 0x%02x\n", U0, U1, U2);
964         dprintf("   Discharge Time: %02d.%02d.%02d %02d:%02d:%02d\n",
965                 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
966         dprintf("   SMSC Time Stamp:  %02d.%02d.%02d %02d:%02d:%02d\n",
967                 data->SMSMessage->SMSCTime.Day, data->SMSMessage->SMSCTime.Month, data->SMSMessage->SMSCTime.Year, data->SMSMessage->SMSCTime.Hour, data->SMSMessage->SMSCTime.Minute, data->SMSMessage->SMSCTime.Second);
968
969         return GE_NONE;
970 }
971
972
973 /* 0x40 Messages are sent to response to an 0x3f request.
974    e.g. when phone is waiting for PIN */
975
976 static GSM_Error P3110_IncomingNoSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
977 {
978         dprintf("SMS Message Center Data not reachable.\n");
979         return GE_NOTREADY;
980 }
981
982
983 /* Handle 0x41 message which is sent by phone in response to an
984    0x3f request.  Contains data about the Message Center in use */
985
986 static GSM_Error P3110_IncomingSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
987 {
988         u8 center_number_length;
989         u8 option_number_length;
990         int count;
991
992         if (!data) return GE_INTERNALERROR;
993
994         /* We don't know what this option number is, just handle it */
995         option_number_length = message[12];
996
997         /* Get message center length */
998         center_number_length = message[13 + option_number_length];
999
1000         dprintf("SMS Message Center Data:\n");
1001         dprintf("   Selected memory: 0x%02x\n", message[2]);
1002         dprintf("   Messages in Phone: 0x%02x Unread: 0x%02x\n", message[3], message[4]);
1003         dprintf("   Messages in SIM: 0x%02x Unread: 0x%02x\n", message[5], message[6]);
1004         dprintf("   Reply via own centre: 0x%02x (%s)\n", message[10], (message[10] == 0x02 ? "Yes" : "No"));
1005         dprintf("   Delivery reports: 0x%02x (%s)\n", message[11], (message[11] == 0x02 ? "Yes" : "No"));
1006         dprintf("   Messages sent as: 0x%02x\n", message[7]);
1007         dprintf("   Message validity: 0x%02x\n", message[9]);
1008         dprintf("   Unknown: 0x%02x\n", message[8]);
1009
1010         dprintf("   UnknownNumber: ");
1011         for (count = 0; count < option_number_length; count ++)
1012                 dprintf("%c", message[13 + count]);
1013         dprintf("\n");
1014
1015         dprintf("   Message center number: ");
1016         for (count = 0; count < center_number_length; count ++) {
1017                 dprintf("%c", message[14 + option_number_length + count]);
1018         }
1019         dprintf("\n");
1020
1021         /* Get message center related info if upper layer wants to know */
1022         if (data->MessageCenter) {
1023                 data->MessageCenter->Format = message[7];
1024                 data->MessageCenter->Validity = message[9];
1025
1026                 if (center_number_length == 0) {
1027                         data->MessageCenter->Number[0] = 0x00; /* Null terminate */
1028                 } else {
1029                         memcpy(data->MessageCenter->Number,
1030                                message + 14 + option_number_length,
1031                                center_number_length);
1032                         data->MessageCenter->Number[center_number_length] = '\0';
1033                 }
1034
1035                 /* 3810 series doesn't support Name or multiple center numbers
1036                    so put in null data for them . */
1037                 data->MessageCenter->Name[0] = 0x00;
1038                 data->MessageCenter->No = 0;
1039         }
1040
1041         /* Get SMS related info if upper layer wants to know */
1042         if (data->SMSStatus) {
1043                 data->SMSStatus->Unread = message[4] + message[6];
1044                 data->SMSStatus->Number = message[3] + message[5];
1045         }
1046
1047         /* Get memory info if upper layer wants to know */
1048         if (data->MemoryStatus) {
1049                 switch (data->MemoryStatus->MemoryType) {
1050                 case GMT_SM:
1051                         data->MemoryStatus->Used = message[5];
1052                         data->MemoryStatus->Free = P3110_MEMORY_SIZE_SM - message[5];
1053                         break;
1054                 case GMT_ME:
1055                         data->MemoryStatus->Used = message[3];
1056                         data->MemoryStatus->Free = P3110_MEMORY_SIZE_ME - message[3];
1057                         break;
1058                 default:
1059                         break;
1060                 }
1061         }
1062
1063         return GE_NONE;
1064 }
1065
1066
1067 /* 0x48 is sent during power-on of the phone, after the 0x13
1068    message is received and the PIN (if any) has been entered
1069    correctly. */
1070
1071 static GSM_Error P3110_IncomingPINEntered(int messagetype, unsigned char *message, int length, GSM_Data *data)
1072 {
1073         SimAvailable = true;
1074         dprintf("PIN [possibly] entered.\n");
1075         return GE_NONE;
1076 }
1077
1078
1079 /* 0x4b messages are sent by phone in response (it seems) to the keep 
1080    alive packet.  We must acknowledge these it seems by sending a 
1081    response with the "sequence number" byte loaded appropriately. */
1082
1083 static GSM_Error P3110_IncomingStatusInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1084 {
1085         /* Strings for the status byte received from phone. */
1086         char *StatusStr[] = {
1087                 "Unknown",
1088                 "Ready",
1089                 "Interworking",
1090                 "Call in progress",
1091                 "No network access"
1092         };
1093
1094         /* There are three data bytes in the status message, two have been
1095            attributed to signal level, the third is presently unknown. 
1096            Unknown byte has been observed to be 0x01 when connected to normal
1097            network, 0x04 when no network available.   Steps through 0x02, 0x03
1098            when incoming or outgoing calls occur...*/   
1099         /*FB38_LinkOK = true;*/
1100
1101         /* Note: GetRFLevel function in fbus-3810.c does conversion 
1102            into required units. */
1103         if (data->RFLevel) {
1104                 *(data->RFUnits) = GRF_Arbitrary;
1105                 *(data->RFLevel) = message[3];
1106         }
1107
1108         /* Note: GetBatteryLevel function in fbus-3810.c does conversion 
1109            into required units. */
1110         if (data->BatteryLevel) { 
1111                 *(data->BatteryUnits) = GBU_Arbitrary;
1112                 *(data->BatteryLevel) = message[4];
1113         }
1114
1115         /* Only output connection status byte now as the RF and Battery
1116            levels are displayed by the main gnokii code. */
1117         dprintf("Status: %s, Battery level: %d, RF level: %d.\n",
1118                 StatusStr[message[2]], message[4], message[3]);
1119         return GE_NONE;
1120 }
1121
1122 /* 0x4d Message provides IMEI, Revision and Model information. */
1123
1124 static GSM_Error P3110_IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1125 {
1126         size_t imei_length, rev_length, model_length;
1127
1128         imei_length = strlen(message + 2);
1129         rev_length = strlen(message + 3 + imei_length);
1130         model_length = strlen(message + 4 + imei_length + rev_length);
1131
1132         if (data->Imei)
1133                 strcpy(data->Imei, message + 2);
1134
1135         if (data->Revision)
1136                 strcpy(data->Revision, message + 3 + imei_length);
1137
1138         if (data->Model)
1139                 strcpy(data->Model, message + 4 + imei_length + rev_length);
1140
1141         dprintf("Mobile Phone Identification:\n");
1142         dprintf("   IMEI: %s\n", message + 2);
1143         dprintf("   Model: %s\n", message + 4 + imei_length + rev_length);
1144         dprintf("   Revision: %s\n", message + 3 + imei_length);
1145
1146         return GE_NONE;
1147 }
1148
1149
1150 /*
1151  */
1152
1153 void P3110_KeepAliveLoop(GSM_Statemachine *state)
1154 {
1155         GSM_Data data;
1156         GSM_DataClear(&data);
1157
1158         while (!RequestTerminate) {
1159
1160                 if (KeepAliveTimer == 0) {
1161                         KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
1162                         /* Dont send keepalive packets when statemachine
1163                            is doing other transactions. */
1164                         if (state->CurrentState == Initialised) {
1165                                 dprintf("Sending keepalive message.\n");
1166                                 P3110_GetStatusInfo(&data, state);
1167                         }
1168                 } else {
1169                         KeepAliveTimer--;
1170                 }
1171                 usleep(100000); /* Avoid becoming a "busy" loop. */
1172         }
1173 }
1174
1175 void P3110_DecodeTime(unsigned char *b, GSM_DateTime *dt)
1176 {
1177         dt->Year = P3110_bcd2int(b[0]);
1178         dt->Month = P3110_bcd2int(b[1]);
1179         dt->Day = P3110_bcd2int(b[2]);
1180         dt->Hour = P3110_bcd2int(b[3]);
1181         dt->Minute = P3110_bcd2int(b[4]);
1182         dt->Second = P3110_bcd2int(b[5]);
1183         dt->Timezone = P3110_bcd2int(b[6]);
1184         return;
1185 }
1186
1187 int P3110_bcd2int(u8 x)
1188 {
1189         return (int)(10 * ((x & 0x0f)) + (x >> 4));
1190 }