7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000 Hugh Blemings & Pavel Janík ml.
10 Copyright (C) 2001 Pawe³ Kot <pkot@linuxnews.pl>
12 Released under the terms of the GNU GPL, see file COPYING for more details.
14 This file provides functions specific to the 3110 series.
15 See README for more details on supported mobile phones.
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
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
24 Revision 1.7 2001/11/27 12:19:01 pkot
25 Cleanup, indentation, ANSI complaint preprocesor symbols (Jan Kratochvil, me)
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)
30 Revision 1.5 2001/11/19 13:03:18 pkot
33 Revision 1.4 2001/11/17 16:42:47 pkot
36 Revision 1.3 2001/11/09 14:25:04 pkot
39 Revision 1.2 2001/11/09 13:47:58 pkot
40 Removed pthreads from 3110 support. It may break it.
42 Revision 1.1 2001/11/08 16:39:09 pkot
43 3810/3110 support for the new structure (Tamas Bondar)
52 #define __phones_nk3110_c
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"
63 # define snprintf _snprintf
64 # define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
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 },
94 { 0x2c, P3110_IncomingSMSHeader },
95 { 0x2d, P3110_IncomingSMSError },
96 { 0x2e, P3110_IncomingSMSDelete },
97 { 0x2f, P3110_IncomingSMSDeleteError },
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 },
111 GSM_Phone phone_nokia_3110 = {
113 PGEN_IncomingDefault,
114 /* Mobile phone information */
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 */
133 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
137 return P3110_Initialise(state);
139 case GOP_GetRevision:
141 return P3110_GetPhoneInfo(data, state);
143 return P3110_Identify(data, state);
144 case GOP_GetBatteryLevel:
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:
153 case GOP_GetSMSStatus:
154 case GOP_GetIncomingCallNr:
155 case GOP_GetNetworkInfo:
156 return GE_NOTIMPLEMENTED;
158 return P3110_GetSMSMessage(data, state);
160 return P3110_DeleteSMSMessage(data, state);
162 return P3110_SendSMSMessage(data, state);
163 case GOP_GetSMSCenter:
164 return P3110_GetSMSInfo(data, state);
165 case GOP_GetSpeedDial:
166 case GOP_GetDateTime:
168 return GE_NOTIMPLEMENTED;
172 static bool LinkOK = false;
173 static bool SimAvailable = false;
175 /* These are related to keepalive functionality */
176 static bool RequestTerminate;
177 static bool DisableKeepAlive;
178 static int KeepAliveTimer;
180 /* Initialise is the only function allowed to 'use' state */
181 static GSM_Error P3110_Initialise(GSM_Statemachine *state)
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};
186 /* Copy in the phone info */
187 memcpy(&(state->Phone), &phone_nokia_3110, sizeof(GSM_Phone));
189 /* Only serial connection is supported */
190 if (state->Link.ConnectionType != GCT_Serial) return GE_NOTSUPPORTED;
192 /* Initialise FBUS link */
193 if (FB3110_Initialise(&(state->Link), state) != GE_NONE) {
194 dprintf("Error in link initialisation\n");
198 /* Initialise state machine */
199 SM_Initialise(state);
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
206 if (SM_SendMessage(state, 20, 0x15, init_sequence) != GE_NONE) return GE_NOTREADY;
208 /* Wait for response to 0x15 sequence */
209 GSM_DataClear(&data);
210 if (SM_Block(state, &data, 0x16) != GE_NONE) return GE_NOTREADY;
212 /* Most probably link is OK now */
215 /* Start sending keepalive messages in separate thread */
216 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
217 RequestTerminate = false;
218 DisableKeepAlive = false;
223 static GSM_Error P3110_GetSMSInfo(GSM_Data *data, GSM_Statemachine *state)
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);
230 static GSM_Error P3110_GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
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);
238 static GSM_Error P3110_GetStatusInfo(GSM_Data *data, GSM_Statemachine *state)
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);
246 static GSM_Error P3110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
248 dprintf("Getting memory status...\n");
250 /* Check if this type of memory is available */
251 switch (data->MemoryStatus->MemoryType) {
253 if (!SimAvailable) return GE_NOTREADY;
254 return P3110_GetSMSInfo(data, state);
256 if (P3110_MEMORY_SIZE_ME == 0) return GE_NOTREADY;
257 return P3110_GetSMSInfo(data, state);
265 static GSM_Error P3110_Identify(GSM_Data *data, GSM_Statemachine *state)
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);
272 /* Check that we are back at state Initialised */
273 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
278 static GSM_Error P3110_GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
280 int total_length, timeout, c;
281 u8 response = 0, request[2];
282 GSM_Error error = GE_INTERNALERROR;
284 dprintf("Getting SMS message...\n");
286 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
288 switch(data->SMSMessage->MemoryType) {
290 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
293 data->SMSMessage->MemoryType = 2;
296 return (GE_INVALIDMEMORYTYPE);
299 /* Set memory type and location in the request */
300 request[0] = data->SMSMessage->MemoryType;
301 request[1] = data->SMSMessage->Number;
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;
311 SM_WaitFor(state, data, 0x2d);
312 SM_WaitFor(state, data, 0x2c);
314 timeout = 30; /* ~3secs timeout */
319 } while ((timeout > 0) && state->NumReceived == 0);
322 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
332 /* reset state machine */
335 /* process response */
338 if (error != GE_NONE) return error;
340 /* Save total length of message */
341 total_length = data->SMSMessage->Length;
343 /* Block for subsequent content frames... */
345 SM_Block(state, data, 0x27);
346 } while (data->SMSMessage->Length < total_length);
348 /* Terminate message text */
349 data->SMSMessage->MessageText[data->SMSMessage->Length] = 0;
354 return GE_INTERNALERROR;
359 static GSM_Error P3110_DeleteSMSMessage(GSM_Data *data, GSM_Statemachine *state)
362 u8 response = 0, request[2];
363 GSM_Error error = GE_INTERNALERROR;
365 dprintf("Deleting SMS message...\n");
367 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
369 switch(data->SMSMessage->MemoryType) {
371 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
374 data->SMSMessage->MemoryType = 2;
377 return (GE_INVALIDMEMORYTYPE);
380 /* Set memory type and location in the request */
381 request[0] = data->SMSMessage->MemoryType;
382 request[1] = data->SMSMessage->Number;
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;
392 SM_WaitFor(state, data, 0x2e);
393 SM_WaitFor(state, data, 0x2f);
395 timeout = 30; /* ~3secs timeout */
400 } while ((timeout > 0) && state->NumReceived == 0);
403 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
413 /* reset state machine */
416 /* process response */
422 return GE_INTERNALERROR;
427 static GSM_Error P3110_SendSMSMessage(GSM_Data *data, GSM_Statemachine *state)
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];
434 SMS_MessageCenter smsc;
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;
445 dprintf("Sending SMS to %s via message center %s\n", data->SMSMessage->RemoteNumber.number, data->SMSMessage->MessageCenter.Number);
449 if (data->SMSMessage->UDH[0].Type) {
450 userdata_offset = 1 + data->SMSMessage->udhlen;
451 memcpy(userdata, data->SMSMessage->MessageText, userdata_offset);
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;
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;
476 request[1] = PID_DEFAULT;
478 request[3] = GSMV_Max_Time;
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);
492 error = EncodePDUSMS(data->SMSMessage, request);
493 if (error) return error;
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;
501 while (retry_count > 0) {
503 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
505 dprintf("Transferring FBUS SMS header [");
506 for (i = 0; i < data->SMSMessage->Length; i++) dprintf(" %02hhX", request[i]);
509 if (SM_SendMessage(state, data->SMSMessage->Length, 0x23, request) != GE_NONE) return GE_NOTREADY;
511 error = SM_Block(state, data, 0x23);
512 if (error != GE_NONE) return error;
514 /* Now send as many blocks of maximum 55 characters as required
515 to send complete message. */
518 userdata_remaining = userdata_length;
520 while (userdata_remaining > 0) {
521 block_length = userdata_remaining;
523 /* Limit block length */
524 if (block_length > 55) block_length = 55;
527 request[0] = block_count;
528 memcpy(request+1, userdata + userdata_offset, block_length);
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;
535 /* update remaining and offset values for next block */
536 userdata_remaining -= block_length;
537 userdata_offset += block_length;
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);
546 timeout = 1200; /* 120secs timeout */
551 } while ((timeout > 0) && state->NumReceived == 0);
554 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
564 /* reset state machine */
567 /* process response */
572 /* Got a retry response so try again! */
573 dprintf("SMS send attempt failed, trying again...\n");
575 /* After an empirically determined pause... */
576 usleep(500000); /* 0.5 seconds. */
579 return GE_INTERNALERROR;
582 /* Retries must have failed. */
583 return GE_SMSSENDFAILED;
587 static GSM_Error P3110_IncomingNothing(int messagetype, unsigned char *message, int length, GSM_Data *data)
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)
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
603 for (count = 0; count < message[4]; count ++) {
604 buffer[count] = message[5 + count];
606 buffer[count] = 0x00;
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);
615 static GSM_Error P3110_IncomingCallAnswered(int messagetype, unsigned char *message, int length, GSM_Data *data)
617 dprintf("Incoming call answered from phone.\n");
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)
626 dprintf("%s call established - status bytes %02x %02x.\n",
627 (message[2] == 0x05 ? "voice":"data(?)"), message[3], message[4]);
632 /* 0x10 messages are sent by the phone when an outgoing
634 static GSM_Error P3110_IncomingEndOfOutgoingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
636 dprintf("Call terminated from phone (0x10 message).\n");
637 /* FIXME: Tell datapump code that the call has terminated. */
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)
650 dprintf("Call terminated from opposite end of line (or from network).\n");
652 /* FIXME: Tell datapump code that the call has terminated. */
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)
666 dprintf("Call terminated from phone (0x12 message).\n");
668 /* FIXME: Tell datapump code that the call has terminated. */
677 /* 0x13 messages are sent after the phone restarts.
680 static GSM_Error P3110_IncomingRestart(int messagetype, unsigned char *message, int length, GSM_Data *data)
682 /* FIXME: send 0x15 message somehow */
687 /* 0x15 messages are sent by the phone in response to the
688 init sequence sent so we don't acknowledge them! */
690 static GSM_Error P3110_IncomingInitFrame_0x15(int messagetype, unsigned char *message, int length, GSM_Data *data)
696 /* 0x16 messages are sent by the phone during initialisation, to response
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) */
704 static GSM_Error P3110_IncomingInitFrame_0x16(int messagetype, unsigned char *message, int length, GSM_Data *data)
706 SimAvailable = (message[2] == 0x02);
707 dprintf("SIM available: %s.\n", (SimAvailable ? "Yes" : "No"));
712 static GSM_Error P3110_IncomingInitFrame_0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
714 dprintf("0x17 Registration Response: Failure!\n");
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. */
724 static GSM_Error P3110_IncomingSMSUserData(int messagetype, unsigned char *message, int length, GSM_Data *data)
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;
732 /* Copy into current SMS message as long as it's non-NULL */
733 if (!data->SMSMessage) return GE_INTERNALERROR;
735 /* If this is the first block, reset accumulated message length. */
736 if (message[2] == 1) data->SMSMessage->Length = 0;
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];
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 */
754 static GSM_Error P3110_IncomingSMSSend(int messagetype, unsigned char *message, int length, GSM_Data *data)
756 dprintf("SMS send OK (0x%02hhx)\n", message[2]);
757 data->SMSMessage->Number = (int) message[2];
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. */
768 static GSM_Error P3110_IncomingSMSSendError(int messagetype, unsigned char *message, int length, GSM_Data *data)
770 dprintf("SMS send failed (0x%02hhx 0x%02hhx)\n", message[2], message[3]);
771 return GE_SMSSENDFAILED;
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) */
780 static GSM_Error P3110_IncomingSMSHeader(int messagetype, unsigned char *message, int length, GSM_Data *data)
782 /* u8 sender_length, smsc_length, l; */
784 if (!data->SMSMessage) return GE_INTERNALERROR;
786 /* Extract data from message into SMSMessage */
788 DecodePDUSMS(message, data->SMSMessage, length);
790 /* All these moved to gsm-sms.c
794 data->SMSMessage->MemoryType = GMT_ME;
797 data->SMSMessage->MemoryType = GMT_SM;
800 data->SMSMessage->MemoryType = GMT_XX;
804 Set location in memory
805 data->SMSMessage->Location = message[3];
806 data->SMSMessage->MessageNumber = message[3];
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.
814 Default to unknown message type
815 data->SMSMessage->Type = GST_UN;
817 Consider received messages "Inbox" (Mobile Terminated)
818 if (message[4] == 0x01 && message[5] == 0x04)
819 data->SMSMessage->Type = GST_MT;
821 Consider written messages "Outbox" (Mobile Originated)
822 if (message[4] == 0x07 && message[5] == 0x01)
823 data->SMSMessage->Type = GST_MO;
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;
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;
835 data->SMSMessage->Status = GSS_SENTREAD;
838 if (message[5] & FO_UDHI)
839 data->SMSMessage->UDHType = GSM_RingtoneUDH; FIXME
841 data->SMSMessage->UDHType = GSM_NoUDH;
843 Check Data Coding Scheme and set text/binary flag
844 if (message[7] == 0xf5)
845 data->SMSMessage->EightBit = true;
847 data->SMSMessage->EightBit = false;
849 Extract date and time information which is packed in to
850 nibbles of each byte in reverse order. Thus day 28 would be
852 P3110_DecodeTime(message+8, &(data->SMSMessage->Time));
855 data->SMSMessage->Length = message[15];
857 Now get sender and message center length
858 smsc_length = message[16];
859 sender_length = message[17 + smsc_length];
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;
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;
872 dprintf("PID:%02x DCS:%02x Timezone:%02x Stat1:%02x Stat2:%02x\n",
873 message[6], message[7], message[14], message[4], message[5]);
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);
886 /* 0x2d messages are generated when an SMS message is requested
887 that does not exist or is empty. */
889 static GSM_Error P3110_IncomingSMSError(int messagetype, unsigned char *message, int length, GSM_Data *data)
891 if (message[2] == 0x74)
892 return GE_INVALIDSMSLOCATION;
894 return GE_EMPTYSMSLOCATION;
898 /* 0x2e messages are generated when an SMS message is deleted
901 static GSM_Error P3110_IncomingSMSDelete(int messagetype, unsigned char *message, int length, GSM_Data *data)
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 */
911 static GSM_Error P3110_IncomingSMSDeleteError(int messagetype, unsigned char *message, int length, GSM_Data *data)
913 /* Note 0x74 is the only value that has been seen! */
914 if (message[2] == 0x74)
915 return GE_INVALIDSMSLOCATION;
917 return GE_EMPTYSMSLOCATION;
921 /* 0x32 messages are generated when delivery notification arrives
922 to phone from network */
924 static GSM_Error P3110_IncomingSMSDelivered(int messagetype, unsigned char *message, int length, GSM_Data *data)
926 static GSM_SMSMessage sms;
927 /* u8 dest_length, smsc_length, l;*/
930 data->SMSMessage = &sms;
932 if (!data->SMSMessage) return GE_INTERNALERROR;
938 DecodePDUSMS(message, data->SMSMessage, length);
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));
946 data->SMSMessage->MessageNumber = (int) message[18];
948 Get sender and message center length
949 dest_length = message[19];
950 smsc_length = message[20 + dest_length];
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;
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;
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);
976 /* 0x40 Messages are sent to response to an 0x3f request.
977 e.g. when phone is waiting for PIN */
979 static GSM_Error P3110_IncomingNoSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
981 dprintf("SMS Message Center Data not reachable.\n");
986 /* Handle 0x41 message which is sent by phone in response to an
987 0x3f request. Contains data about the Message Center in use */
989 static GSM_Error P3110_IncomingSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
991 u8 center_number_length;
992 u8 option_number_length;
995 if (!data) return GE_INTERNALERROR;
997 /* We don't know what this option number is, just handle it */
998 option_number_length = message[12];
1000 /* Get message center length */
1001 center_number_length = message[13 + option_number_length];
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]);
1013 dprintf(" UnknownNumber: ");
1014 for (count = 0; count < option_number_length; count ++)
1015 dprintf("%c", message[13 + count]);
1018 dprintf(" Message center number: ");
1019 for (count = 0; count < center_number_length; count ++) {
1020 dprintf("%c", message[14 + option_number_length + count]);
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];
1029 if (center_number_length == 0) {
1030 data->MessageCenter->Number[0] = 0x00; /* Null terminate */
1032 memcpy(data->MessageCenter->Number,
1033 message + 14 + option_number_length,
1034 center_number_length);
1035 data->MessageCenter->Number[center_number_length] = '\0';
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;
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];
1050 /* Get memory info if upper layer wants to know */
1051 if (data->MemoryStatus) {
1052 switch (data->MemoryStatus->MemoryType) {
1054 data->MemoryStatus->Used = message[5];
1055 data->MemoryStatus->Free = P3110_MEMORY_SIZE_SM - message[5];
1058 data->MemoryStatus->Used = message[3];
1059 data->MemoryStatus->Free = P3110_MEMORY_SIZE_ME - message[3];
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
1074 static GSM_Error P3110_IncomingPINEntered(int messagetype, unsigned char *message, int length, GSM_Data *data)
1076 SimAvailable = true;
1077 dprintf("PIN [possibly] entered.\n");
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. */
1086 static GSM_Error P3110_IncomingStatusInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1088 /* Strings for the status byte received from phone. */
1089 char *StatusStr[] = {
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;*/
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];
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];
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]);
1125 /* 0x4d Message provides IMEI, Revision and Model information. */
1127 static GSM_Error P3110_IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1129 size_t imei_length, rev_length, model_length;
1131 imei_length = strlen(message + 2);
1132 rev_length = strlen(message + 3 + imei_length);
1133 model_length = strlen(message + 4 + imei_length + rev_length);
1136 strcpy(data->Imei, message + 2);
1139 strcpy(data->Revision, message + 3 + imei_length);
1142 strcpy(data->Model, message + 4 + imei_length + rev_length);
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);
1156 void P3110_KeepAliveLoop(GSM_Statemachine *state)
1159 GSM_DataClear(&data);
1161 while (!RequestTerminate) {
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);
1174 usleep(100000); /* Avoid becoming a "busy" loop. */
1178 void P3110_DecodeTime(unsigned char *b, GSM_DateTime *dt)
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]);
1190 int P3110_bcd2int(u8 x)
1192 return (int)(10 * ((x & 0x0f)) + (x >> 4));