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