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