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.3 2002/04/03 00:08:11 short
19 Found in "gnokii-working" directory, some November-patches version
21 Revision 1.1 2001/11/08 16:39:09 pkot
22 3810/3110 support for the new structure (Tamas Bondar)
31 #define __phones_nk3110_c
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"
43 #define snprintf _snprintf
44 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
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 },
74 { 0x2c, P3110_IncomingSMSHeader },
75 { 0x2d, P3110_IncomingSMSError },
76 { 0x2e, P3110_IncomingSMSDelete },
77 { 0x2f, P3110_IncomingSMSDeleteError },
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 },
91 GSM_Phone phone_nokia_3110 = {
94 /* Mobile phone information */
96 "3110|3810|8110|8110i", /* Models */
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 */
113 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
117 return P3110_Initialise(state);
119 case GOP_GetRevision:
121 return P3110_GetPhoneInfo(data, state);
123 return P3110_Identify(data, state);
124 case GOP_GetBatteryLevel:
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:
133 case GOP_GetSMSStatus:
134 case GOP_GetIncomingCallNr:
135 case GOP_GetNetworkInfo:
136 return GE_NOTIMPLEMENTED;
138 return P3110_GetSMSMessage(data, state);
140 return P3110_DeleteSMSMessage(data, state);
142 return P3110_SendSMSMessage(data, state);
143 case GOP_GetSMSCenter:
144 return P3110_GetSMSInfo(data, state);
145 case GOP_GetSpeedDial:
146 case GOP_GetDateTime:
148 return GE_NOTIMPLEMENTED;
152 static bool LinkOK = false;
153 static bool SimAvailable = false;
155 /* These are related to keepalive functionality */
156 static bool RequestTerminate;
157 static bool DisableKeepAlive;
158 static int KeepAliveTimer;
163 /* Initialise is the only function allowed to 'use' state */
164 static GSM_Error P3110_Initialise(GSM_Statemachine *state)
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};
169 /* Copy in the phone info */
170 memcpy(&(state->Phone), &phone_nokia_3110, sizeof(GSM_Phone));
172 /* Only serial connection is supported */
173 if (state->Link.ConnectionType != GCT_Serial) return GE_NOTSUPPORTED;
175 /* Initialise FBUS link */
176 if (FB3110_Initialise(&(state->Link), state) != GE_NONE) {
177 dprintf("Error in link initialisation\n");
181 /* Initialise state machine */
182 SM_Initialise(state);
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
189 if (SM_SendMessage(state, 20, 0x15, init_sequence) != GE_NONE) return GE_NOTREADY;
191 /* Wait for response to 0x15 sequence */
192 GSM_DataClear(&data);
193 if (SM_Block(state, &data, 0x16) != GE_NONE) return GE_NOTREADY;
195 /* Most probably link is OK now */
198 /* Start sending keepalive messages in separate thread */
199 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
200 RequestTerminate = false;
201 DisableKeepAlive = false;
203 if (pthread_create(&Thread, NULL, (void *) P3110_KeepAliveLoop, state) != 0)
204 return (GE_INTERNALERROR);
210 static GSM_Error P3110_GetSMSInfo(GSM_Data *data, GSM_Statemachine *state)
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);
217 static GSM_Error P3110_GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
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);
225 static GSM_Error P3110_GetStatusInfo(GSM_Data *data, GSM_Statemachine *state)
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);
233 static GSM_Error P3110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
235 dprintf("Getting memory status...\n");
237 /* Check if this type of memory is available */
238 switch (data->MemoryStatus->MemoryType) {
240 if (!SimAvailable) return GE_NOTREADY;
241 return P3110_GetSMSInfo(data, state);
243 if (P3110_MEMORY_SIZE_ME == 0) return GE_NOTREADY;
244 return P3110_GetSMSInfo(data, state);
251 static GSM_Error P3110_Identify(GSM_Data *data, GSM_Statemachine *state)
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);
258 /* Check that we are back at state Initialised */
259 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
264 static GSM_Error P3110_GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
266 int total_length, timeout, c;
267 u8 response = 0, request[2];
268 GSM_Error error = GE_INTERNALERROR;
270 dprintf("Getting SMS message...\n");
272 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
274 switch(data->SMSMessage->MemoryType) {
276 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
279 data->SMSMessage->MemoryType = 2;
282 return (GE_INVALIDMEMORYTYPE);
285 /* Set memory type and location in the request */
286 request[0] = data->SMSMessage->MemoryType;
287 request[1] = data->SMSMessage->Number;
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;
297 SM_WaitFor(state, data, 0x2d);
298 SM_WaitFor(state, data, 0x2c);
300 timeout = 30; /* ~3secs timeout */
305 } while ((timeout > 0) && state->NumReceived == 0);
308 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
318 /* reset state machine */
321 /* process response */
324 if (error != GE_NONE) return error;
326 /* Save total length of message */
327 total_length = data->SMSMessage->Length;
329 /* Block for subsequent content frames... */
331 SM_Block(state, data, 0x27);
332 } while (data->SMSMessage->Length < total_length);
334 /* Terminate message text */
335 data->SMSMessage->MessageText[data->SMSMessage->Length] = 0;
340 return GE_INTERNALERROR;
345 static GSM_Error P3110_DeleteSMSMessage(GSM_Data *data, GSM_Statemachine *state)
348 u8 response = 0, request[2];
349 GSM_Error error = GE_INTERNALERROR;
351 dprintf("Deleting SMS message...\n");
353 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
355 switch(data->SMSMessage->MemoryType) {
357 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
360 data->SMSMessage->MemoryType = 2;
363 return (GE_INVALIDMEMORYTYPE);
366 /* Set memory type and location in the request */
367 request[0] = data->SMSMessage->MemoryType;
368 request[1] = data->SMSMessage->Number;
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;
378 SM_WaitFor(state, data, 0x2e);
379 SM_WaitFor(state, data, 0x2f);
381 timeout = 30; /* ~3secs timeout */
386 } while ((timeout > 0) && state->NumReceived == 0);
389 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
399 /* reset state machine */
402 /* process response */
408 return GE_INTERNALERROR;
413 static GSM_Error P3110_SendSMSMessage(GSM_Data *data, GSM_Statemachine *state)
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];
420 SMS_MessageCenter smsc;
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;
431 dprintf("Sending SMS to %s via message center %s\n", data->SMSMessage->RemoteNumber.number, data->SMSMessage->MessageCenter.Number);
435 if (data->SMSMessage->UDH[0].Type) {
436 userdata_offset = 1 + data->SMSMessage->udhlen;
437 memcpy(userdata, data->SMSMessage->MessageText, userdata_offset);
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;
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;
462 request[1] = PID_DEFAULT;
464 request[3] = GSMV_Max_Time;
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);
478 error = EncodePDUSMS(data->SMSMessage, request);
479 if (error) return error;
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;
487 while (retry_count > 0) {
489 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
491 dprintf("Transferring FBUS SMS header [");
492 for (i = 0; i < data->SMSMessage->Length; i++) dprintf(" %02hhX", request[i]);
495 if (SM_SendMessage(state, data->SMSMessage->Length, 0x23, request) != GE_NONE) return GE_NOTREADY;
497 error = SM_Block(state, data, 0x23);
498 if (error != GE_NONE) return error;
500 /* Now send as many blocks of maximum 55 characters as required
501 to send complete message. */
504 userdata_remaining = userdata_length;
506 while (userdata_remaining > 0) {
507 block_length = userdata_remaining;
509 /* Limit block length */
510 if (block_length > 55) block_length = 55;
513 request[0] = block_count;
514 memcpy(request+1, userdata + userdata_offset, block_length);
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;
521 /* update remaining and offset values for next block */
522 userdata_remaining -= block_length;
523 userdata_offset += block_length;
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);
532 timeout = 1200; /* 120secs timeout */
537 } while ((timeout > 0) && state->NumReceived == 0);
540 if (state->NumReceived == 0) return GE_TIMEOUT;
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];
550 /* reset state machine */
553 /* process response */
558 /* Got a retry response so try again! */
559 dprintf("SMS send attempt failed, trying again...\n");
561 /* After an empirically determined pause... */
562 usleep(500000); /* 0.5 seconds. */
565 return GE_INTERNALERROR;
568 /* Retries must have failed. */
569 return GE_SMSSENDFAILED;
573 static GSM_Error P3110_IncomingNothing(int messagetype, unsigned char *message, int length, GSM_Data *data)
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)
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
589 for (count = 0; count < message[4]; count ++) {
590 buffer[count] = message[5 + count];
592 buffer[count] = 0x00;
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);
603 static GSM_Error P3110_IncomingCallAnswered(int messagetype, unsigned char *message, int length, GSM_Data *data)
606 dprintf("Incoming call answered from phone.\n");
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)
617 dprintf("%s call established - status bytes %02x %02x.\n",
618 (message[2] == 0x05 ? "voice":"data(?)"), message[3], message[4]);
624 /* 0x10 messages are sent by the phone when an outgoing
626 static GSM_Error P3110_IncomingEndOfOutgoingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
629 dprintf("Call terminated from phone (0x10 message).\n");
631 /* FIXME: Tell datapump code that the call has terminated. */
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)
645 dprintf("Call terminated from opposite end of line (or from network).\n");
648 /* FIXME: Tell datapump code that the call has terminated. */
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)
663 dprintf("Call terminated from phone (0x12 message).\n");
666 /* FIXME: Tell datapump code that the call has terminated. */
675 /* 0x13 messages are sent after the phone restarts.
678 static GSM_Error P3110_IncomingRestart(int messagetype, unsigned char *message, int length, GSM_Data *data)
680 /* FIXME: send 0x15 message somehow */
685 /* 0x15 messages are sent by the phone in response to the
686 init sequence sent so we don't acknowledge them! */
688 static GSM_Error P3110_IncomingInitFrame_0x15(int messagetype, unsigned char *message, int length, GSM_Data *data)
694 /* 0x16 messages are sent by the phone during initialisation, to response
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) */
702 static GSM_Error P3110_IncomingInitFrame_0x16(int messagetype, unsigned char *message, int length, GSM_Data *data)
704 SimAvailable = (message[2] == 0x02);
706 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;
803 Set location in memory
804 data->SMSMessage->Location = message[3];
805 data->SMSMessage->MessageNumber = message[3];
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.
813 Default to unknown message type
814 data->SMSMessage->Type = GST_UN;
816 Consider received messages "Inbox" (Mobile Terminated)
817 if (message[4] == 0x01 && message[5] == 0x04)
818 data->SMSMessage->Type = GST_MT;
820 Consider written messages "Outbox" (Mobile Originated)
821 if (message[4] == 0x07 && message[5] == 0x01)
822 data->SMSMessage->Type = GST_MO;
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;
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;
834 data->SMSMessage->Status = GSS_SENTREAD;
837 if (message[5] & FO_UDHI)
838 data->SMSMessage->UDHType = GSM_RingtoneUDH; FIXME
840 data->SMSMessage->UDHType = GSM_NoUDH;
842 Check Data Coding Scheme and set text/binary flag
843 if (message[7] == 0xf5)
844 data->SMSMessage->EightBit = true;
846 data->SMSMessage->EightBit = false;
848 Extract date and time information which is packed in to
849 nibbles of each byte in reverse order. Thus day 28 would be
851 P3110_DecodeTime(message+8, &(data->SMSMessage->Time));
854 data->SMSMessage->Length = message[15];
856 Now get sender and message center length
857 smsc_length = message[16];
858 sender_length = message[17 + smsc_length];
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;
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;
871 dprintf("PID:%02x DCS:%02x Timezone:%02x Stat1:%02x Stat2:%02x\n",
872 message[6], message[7], message[14], message[4], message[5]);
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);
885 /* 0x2d messages are generated when an SMS message is requested
886 that does not exist or is empty. */
888 static GSM_Error P3110_IncomingSMSError(int messagetype, unsigned char *message, int length, GSM_Data *data)
890 if (message[2] == 0x74)
891 return GE_INVALIDSMSLOCATION;
893 return GE_EMPTYSMSLOCATION;
897 /* 0x2e messages are generated when an SMS message is deleted
900 static GSM_Error P3110_IncomingSMSDelete(int messagetype, unsigned char *message, int length, GSM_Data *data)
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 */
910 static GSM_Error P3110_IncomingSMSDeleteError(int messagetype, unsigned char *message, int length, GSM_Data *data)
912 /* Note 0x74 is the only value that has been seen! */
913 if (message[2] == 0x74)
914 return GE_INVALIDSMSLOCATION;
916 return GE_EMPTYSMSLOCATION;
920 /* 0x32 messages are generated when delivery notification arrives
921 to phone from network */
923 static GSM_Error P3110_IncomingSMSDelivered(int messagetype, unsigned char *message, int length, GSM_Data *data)
925 static GSM_SMSMessage sms;
926 u8 dest_length, smsc_length, l;
929 data->SMSMessage = &sms;
931 if (!data->SMSMessage) return GE_INTERNALERROR;
937 DecodePDUSMS(message, data->SMSMessage, length);
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));
945 data->SMSMessage->MessageNumber = (int) message[18];
947 Get sender and message center length
948 dest_length = message[19];
949 smsc_length = message[20 + dest_length];
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;
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;
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);
975 /* 0x40 Messages are sent to response to an 0x3f request.
976 e.g. when phone is waiting for PIN */
978 static GSM_Error P3110_IncomingNoSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
981 dprintf("SMS Message Center Data not reachable.\n");
987 /* Handle 0x41 message which is sent by phone in response to an
988 0x3f request. Contains data about the Message Center in use */
990 static GSM_Error P3110_IncomingSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
992 u8 center_number_length;
993 u8 option_number_length;
998 if (!data) return GE_INTERNALERROR;
1000 /* We don't know what this option number is, just handle it */
1001 option_number_length = message[12];
1003 /* Get message center length */
1004 center_number_length = message[13 + option_number_length];
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]);
1018 dprintf(" UnknownNumber: ");
1019 for (count = 0; count < option_number_length; count ++)
1020 dprintf("%c", message[13 + count]);
1023 dprintf(" Message center number: ");
1024 for (count = 0; count < center_number_length; count ++) {
1025 dprintf("%c", message[14 + option_number_length + count]);
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];
1035 if (center_number_length == 0) {
1036 data->MessageCenter->Number[0] = 0x00; /* Null terminate */
1038 memcpy(data->MessageCenter->Number,
1039 message + 14 + option_number_length,
1040 center_number_length);
1041 data->MessageCenter->Number[center_number_length] = '\0';
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;
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];
1056 /* Get memory info if upper layer wants to know */
1057 if (data->MemoryStatus) {
1058 switch (data->MemoryStatus->MemoryType) {
1060 data->MemoryStatus->Used = message[5];
1061 data->MemoryStatus->Free = P3110_MEMORY_SIZE_SM - message[5];
1064 data->MemoryStatus->Used = message[3];
1065 data->MemoryStatus->Free = P3110_MEMORY_SIZE_ME - message[3];
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
1079 static GSM_Error P3110_IncomingPINEntered(int messagetype, unsigned char *message, int length, GSM_Data *data)
1081 SimAvailable = true;
1083 dprintf("PIN [possibly] entered.\n");
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. */
1093 static GSM_Error P3110_IncomingStatusInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1095 /* Strings for the status byte received from phone. */
1097 char *StatusStr[] = {
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;*/
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];
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];
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]);
1136 /* 0x4d Message provides IMEI, Revision and Model information. */
1138 static GSM_Error P3110_IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1140 size_t imei_length, rev_length, model_length;
1142 imei_length = strlen(message + 2);
1143 rev_length = strlen(message + 3 + imei_length);
1144 model_length = strlen(message + 4 + imei_length + rev_length);
1147 strcpy(data->Imei, message + 2);
1150 strcpy(data->Revision, message + 3 + imei_length);
1153 strcpy(data->Model, message + 4 + imei_length + rev_length);
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);
1169 void P3110_KeepAliveLoop(GSM_Statemachine *state)
1172 GSM_DataClear(&data);
1174 while (!RequestTerminate) {
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);
1187 usleep(100000); /* Avoid becoming a "busy" loop. */
1191 void P3110_DecodeTime(unsigned char *b, GSM_DateTime *dt)
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]);
1203 int P3110_bcd2int(u8 x)
1205 return (int)(10 * ((x & 0x0f)) + (x >> 4));