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