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.2 2001/11/27 22:01:20 short
19 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
21 Revision 1.7 2001/11/27 12:19:01 pkot
22 Cleanup, indentation, ANSI complaint preprocesor symbols (Jan Kratochvil, me)
24 Revision 1.6 2001/11/20 16:22:22 pkot
25 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
27 Revision 1.5 2001/11/19 13:03:18 pkot
30 Revision 1.4 2001/11/17 16:42:47 pkot
33 Revision 1.3 2001/11/09 14:25:04 pkot
36 Revision 1.2 2001/11/09 13:47:58 pkot
37 Removed pthreads from 3110 support. It may break it.
39 Revision 1.1 2001/11/08 16:39:09 pkot
40 3810/3110 support for the new structure (Tamas Bondar)
49 #define __phones_nk3110_c
51 #include "gsm-common.h"
52 #include "phones/generic.h"
53 #include "phones/nk3110.h"
54 #include "links/fbus-3110.h"
55 #include "phones/nokia.h"
60 # define snprintf _snprintf
61 # define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
66 static GSM_IncomingFunctionType IncomingFunctions[] = {
67 { 0x0a, P3110_IncomingNothing },
68 { 0x0b, P3110_IncomingCall },
69 { 0x0c, P3110_IncomingNothing },
70 { 0x0d, P3110_IncomingCallAnswered },
71 { 0x0e, P3110_IncomingCallEstablished },
72 { 0x0f, P3110_IncomingNothing },
73 { 0x10, P3110_IncomingEndOfOutgoingCall },
74 { 0x11, P3110_IncomingEndOfIncomingCall },
75 { 0x12, P3110_IncomingEndOfOutgoingCall2 },
76 { 0x13, P3110_IncomingRestart },
77 { 0x15, P3110_IncomingInitFrame_0x15 },
78 { 0x16, P3110_IncomingInitFrame_0x16 },
79 { 0x17, P3110_IncomingInitFrame_0x17 },
80 { 0x20, P3110_IncomingNothing },
81 /*{ 0x21, P3110_IncomingDTMFSucess },*/
82 /*{ 0x22, P3110_IncomingDTMFFailure },*/
83 { 0x23, P3110_IncomingNothing },
84 { 0x24, P3110_IncomingNothing },
85 { 0x25, P3110_IncomingNothing },
86 { 0x26, P3110_IncomingNothing },
87 { 0x27, P3110_IncomingSMSUserData },
88 { 0x28, P3110_IncomingSMSSend },
89 { 0x29, P3110_IncomingSMSSendError },
91 { 0x2c, P3110_IncomingSMSHeader },
92 { 0x2d, P3110_IncomingSMSError },
93 { 0x2e, P3110_IncomingSMSDelete },
94 { 0x2f, P3110_IncomingSMSDeleteError },
96 { 0x32, P3110_IncomingSMSDelivered },
97 { 0x3f, P3110_IncomingNothing },
98 { 0x40, P3110_IncomingNoSMSInfo },
99 { 0x41, P3110_IncomingSMSInfo },
100 { 0x48, P3110_IncomingPINEntered },
101 { 0x4a, P3110_IncomingNothing },
102 { 0x4b, P3110_IncomingStatusInfo },
103 { 0x4c, P3110_IncomingNothing },
104 { 0x4d, P3110_IncomingPhoneInfo },
108 GSM_Phone phone_nokia_3110 = {
110 PGEN_IncomingDefault,
111 /* Mobile phone information */
113 "3110|3810|8110|8110i", /* Models */
114 4, /* Max RF Level */
115 0, /* Min RF Level */
116 GRF_Arbitrary, /* RF level units */
117 4, /* Max Battery Level */
118 0, /* Min Battery Level */
119 GBU_Arbitrary, /* Battery level units */
120 GDT_None, /* No date/time support */
121 GDT_None, /* No alarm support */
122 0, /* Max alarms = 0 */
123 0, 0, /* Startup logo size */
124 0, 0, /* Op logo size */
125 0, 0 /* Caller logo size */
130 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
134 return P3110_Initialise(state);
136 case GOP_GetRevision:
138 return P3110_GetPhoneInfo(data, state);
140 return P3110_Identify(data, state);
141 case GOP_GetBatteryLevel:
143 return P3110_GetStatusInfo(data, state);
144 case GOP_GetMemoryStatus:
145 return P3110_GetMemoryStatus(data, state);
146 case GOP_ReadPhonebook:
147 case GOP_WritePhonebook:
148 case GOP_GetPowersource:
150 case GOP_GetSMSStatus:
151 case GOP_GetIncomingCallNr:
152 case GOP_GetNetworkInfo:
153 return GE_NOTIMPLEMENTED;
155 return P3110_GetSMSMessage(data, state);
157 return P3110_DeleteSMSMessage(data, state);
159 return P3110_SendSMSMessage(data, state);
160 case GOP_GetSMSCenter:
161 return P3110_GetSMSInfo(data, state);
162 case GOP_GetSpeedDial:
163 case GOP_GetDateTime:
165 return GE_NOTIMPLEMENTED;
169 static bool LinkOK = false;
170 static bool SimAvailable = false;
172 /* These are related to keepalive functionality */
173 static bool RequestTerminate;
174 static bool DisableKeepAlive;
175 static int KeepAliveTimer;
177 /* Initialise is the only function allowed to 'use' state */
178 static GSM_Error P3110_Initialise(GSM_Statemachine *state)
181 u8 init_sequence[20] = {0x02, 0x01, 0x07, 0xa2, 0x88, 0x81, 0x21, 0x55, 0x63, 0xa8, 0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15, 0x63, 0x80};
183 /* Copy in the phone info */
184 memcpy(&(state->Phone), &phone_nokia_3110, sizeof(GSM_Phone));
186 /* Only serial connection is supported */
187 if (state->Link.ConnectionType != GCT_Serial) return GE_NOTSUPPORTED;
189 /* Initialise FBUS link */
190 if (FB3110_Initialise(&(state->Link), state) != GE_NONE) {
191 dprintf("Error in link initialisation\n");
195 /* Initialise state machine */
196 SM_Initialise(state);
198 /* 0x15 messages are sent by the PC during the initialisation phase.
199 Anyway, the contents of the message are not understood so we
200 simply send the same sequence observed between the W95 PC and
201 the phone. The init sequence may still be a bit flaky and is not
203 if (SM_SendMessage(state, 20, 0x15, init_sequence) != GE_NONE) return GE_NOTREADY;
205 /* Wait for response to 0x15 sequence */
206 GSM_DataClear(&data);
207 if (SM_Block(state, &data, 0x16) != GE_NONE) return GE_NOTREADY;
209 /* Most probably link is OK now */
212 /* Start sending keepalive messages in separate thread */
213 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
214 RequestTerminate = false;
215 DisableKeepAlive = false;
220 static GSM_Error P3110_GetSMSInfo(GSM_Data *data, GSM_Statemachine *state)
222 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
223 if (SM_SendMessage(state, 0, 0x3f, NULL) != GE_NONE) return GE_NOTREADY;
224 return SM_Block(state, data, 0x41);
227 static GSM_Error P3110_GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
229 dprintf("Getting phone info...\n");
230 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
231 if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
232 return SM_Block(state, data, 0x4d);
235 static GSM_Error P3110_GetStatusInfo(GSM_Data *data, GSM_Statemachine *state)
237 dprintf("Getting phone status...\n");
238 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
239 if (SM_SendMessage(state, 0, 0x4a, NULL) != GE_NONE) return GE_NOTREADY;
240 return SM_Block(state, data, 0x4b);
243 static GSM_Error P3110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
245 dprintf("Getting memory status...\n");
247 /* Check if this type of memory is available */
248 switch (data->MemoryStatus->MemoryType) {
250 if (!SimAvailable) return GE_NOTREADY;
251 return P3110_GetSMSInfo(data, state);
253 if (P3110_MEMORY_SIZE_ME == 0) return GE_NOTREADY;
254 return P3110_GetSMSInfo(data, state);
262 static GSM_Error P3110_Identify(GSM_Data *data, GSM_Statemachine *state)
264 dprintf("Identifying...\n");
265 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
266 if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
267 SM_Block(state, data, 0x4d);
269 /* Check that we are back at state Initialised */
270 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
275 static GSM_Error P3110_GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
277 int total_length, timeout, c;
278 u8 response = 0, request[2];
279 GSM_Error error = GE_INTERNALERROR;
281 dprintf("Getting SMS message...\n");
283 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
285 switch(data->SMSMessage->MemoryType) {
287 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
290 data->SMSMessage->MemoryType = 2;
293 return (GE_INVALIDMEMORYTYPE);
296 /* Set memory type and location in the request */
297 request[0] = data->SMSMessage->MemoryType;
298 request[1] = data->SMSMessage->Number;
300 /* 0x25 messages requests the contents of an SMS message
301 from the phone. The first byte has only ever been
302 observed to be 0x02 - could be selecting internal versus
303 external memory. Specifying memory 0x00 may request the
304 first location? Phone replies with 0x2c and 0x27 messages
305 for valid locations, 0x2d for empty ones. */
306 if (SM_SendMessage(state, 2, 0x25, request) != GE_NONE) return GE_NOTREADY;
308 SM_WaitFor(state, data, 0x2d);
309 SM_WaitFor(state, data, 0x2c);
311 timeout = 30; /* ~3secs timeout */
316 } while ((timeout > 0) && state->NumReceived == 0);
319 if (state->NumReceived == 0) return GE_TIMEOUT;
321 /* find response in state machine */
322 for (c = 0; c < state->NumWaitingFor; c++) {
323 if (state->ResponseError[c] != GE_BUSY) {
324 response = state->WaitingFor[c];
325 error = state->ResponseError[c];
329 /* reset state machine */
332 /* process response */
335 if (error != GE_NONE) return error;
337 /* Save total length of message */
338 total_length = data->SMSMessage->Length;
340 /* Block for subsequent content frames... */
342 SM_Block(state, data, 0x27);
343 } while (data->SMSMessage->Length < total_length);
345 /* Terminate message text */
346 data->SMSMessage->MessageText[data->SMSMessage->Length] = 0;
351 return GE_INTERNALERROR;
356 static GSM_Error P3110_DeleteSMSMessage(GSM_Data *data, GSM_Statemachine *state)
359 u8 response = 0, request[2];
360 GSM_Error error = GE_INTERNALERROR;
362 dprintf("Deleting SMS message...\n");
364 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
366 switch(data->SMSMessage->MemoryType) {
368 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
371 data->SMSMessage->MemoryType = 2;
374 return (GE_INVALIDMEMORYTYPE);
377 /* Set memory type and location in the request */
378 request[0] = data->SMSMessage->MemoryType;
379 request[1] = data->SMSMessage->Number;
381 /* 0x26 message deletes an SMS message from the phone.
382 The first byte has only ever been observed to be 0x02
383 but is assumed to be selecting internal versus
384 external memory. Phone replies with 0x2e for valid locations,
385 0x2f for invalid ones. If a location is empty but otherwise
386 valid 0x2e is still returned. */
387 if (SM_SendMessage(state, 2, 0x26, request) != GE_NONE) return GE_NOTREADY;
389 SM_WaitFor(state, data, 0x2e);
390 SM_WaitFor(state, data, 0x2f);
392 timeout = 30; /* ~3secs timeout */
397 } while ((timeout > 0) && state->NumReceived == 0);
400 if (state->NumReceived == 0) return GE_TIMEOUT;
402 /* find response in state machine */
403 for (c = 0; c < state->NumWaitingFor; c++) {
404 if (state->ResponseError[c] != GE_BUSY) {
405 response = state->WaitingFor[c];
406 error = state->ResponseError[c];
410 /* reset state machine */
413 /* process response */
419 return GE_INTERNALERROR;
424 static GSM_Error P3110_SendSMSMessage(GSM_Data *data, GSM_Statemachine *state)
426 int timeout, c, retry_count, block_count, block_length;
427 u8 userdata[GSM_MAX_SMS_LENGTH];
428 int userdata_length, userdata_offset, userdata_remaining;
429 u8 response, request[GSM_MAX_SMS_LENGTH];
431 SMS_MessageCenter smsc;
434 /* Get default SMSC from phone if not set in SMS */
435 if (!data->SMSMessage->MessageCenter.Number[0]) {
436 data->MessageCenter = &smsc;
437 error = P3110_GetSMSInfo(data, state);
438 if (error != GE_NONE) return error;
439 data->SMSMessage->MessageCenter = smsc;
442 dprintf("Sending SMS to %s via message center %s\n", data->SMSMessage->RemoteNumber.number, data->SMSMessage->MessageCenter.Number);
446 if (data->SMSMessage->UDH[0].Type) {
447 userdata_offset = 1 + data->SMSMessage->udhlen;
448 memcpy(userdata, data->SMSMessage->MessageText, userdata_offset);
457 if (data->SMSMessage->EightBit) {
458 memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, data->SMSMessage->Length);
459 userdata_length = data->SMSMessage->Length + userdata_offset;
460 max_userdata_length = GSM_MAX_SMS_8_BIT_LENGTH;
461 dcs = DCS_DATA | DCS_CLASS1;
463 userdata_length = strlen(data->SMSMessage->MessageText);
464 memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, userdata_length);
465 userdata_length += userdata_offset;
466 max_userdata_length = GSM_MAX_SMS_LENGTH;
473 request[1] = PID_DEFAULT;
475 request[3] = GSMV_Max_Time;
482 request[10] = userdata_length;
483 request[11] = smsc_length;
484 memcpy(request+12, data->SMSMessage->MessageCenter.Number, smsc_length);
485 request[12+smsc_length] = dest_length;
486 memcpy(request+13+smsc_length, data->SMSMessage->Destination, dest_length);
489 error = EncodePDUSMS(data->SMSMessage, request);
490 if (error) return error;
492 /* We have a loop here as if the response from the phone is
493 0x65 0x26 the rule appears to be just to try sending the
494 message again. We do this a maximum of FB38_SMS_SEND_RETRY_COUNT
495 times before giving up. This value is empirical only! */
496 retry_count = P3110_SMS_SEND_RETRY_COUNT;
498 while (retry_count > 0) {
500 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
502 dprintf("Transferring FBUS SMS header [");
503 for (i = 0; i < data->SMSMessage->Length; i++) dprintf(" %02hhX", request[i]);
506 if (SM_SendMessage(state, data->SMSMessage->Length, 0x23, request) != GE_NONE) return GE_NOTREADY;
508 error = SM_Block(state, data, 0x23);
509 if (error != GE_NONE) return error;
511 /* Now send as many blocks of maximum 55 characters as required
512 to send complete message. */
515 userdata_remaining = userdata_length;
517 while (userdata_remaining > 0) {
518 block_length = userdata_remaining;
520 /* Limit block length */
521 if (block_length > 55) block_length = 55;
524 request[0] = block_count;
525 memcpy(request+1, userdata + userdata_offset, block_length);
528 if (SM_SendMessage(state, block_length+1, 0x27, request) != GE_NONE) return GE_NOTREADY;
529 error = SM_Block(state, data, 0x27);
530 if (error != GE_NONE) return error;
532 /* update remaining and offset values for next block */
533 userdata_remaining -= block_length;
534 userdata_offset += block_length;
538 /* Now wait for response from network which will see
539 CurrentSMSMessageError change from busy. */
540 SM_WaitFor(state, data, 0x28);
541 SM_WaitFor(state, data, 0x29);
543 timeout = 1200; /* 120secs timeout */
548 } while ((timeout > 0) && state->NumReceived == 0);
551 if (state->NumReceived == 0) return GE_TIMEOUT;
553 /* find response in state machine */
554 for (c = 0; c < state->NumWaitingFor; c++) {
555 if (state->ResponseError[c] != GE_BUSY) {
556 response = state->WaitingFor[c];
557 error = state->ResponseError[c];
561 /* reset state machine */
564 /* process response */
569 /* Got a retry response so try again! */
570 dprintf("SMS send attempt failed, trying again...\n");
572 /* After an empirically determined pause... */
573 usleep(500000); /* 0.5 seconds. */
576 return GE_INTERNALERROR;
579 /* Retries must have failed. */
580 return GE_SMSSENDFAILED;
584 static GSM_Error P3110_IncomingNothing(int messagetype, unsigned char *message, int length, GSM_Data *data)
589 /* 0x0b messages are sent by phone when an incoming call occurs,
590 this message must be acknowledged. */
591 static GSM_Error P3110_IncomingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
596 /* Get info out of message. At present, first three bytes are
597 unknown (though third seems to correspond to length of
598 number). Remaining bytes are the phone number, ASCII
600 for (count = 0; count < message[4]; count ++) {
601 buffer[count] = message[5 + count];
603 buffer[count] = 0x00;
605 /* Now display incoming call message. */
606 dprintf("Incoming call - Type: %s. %02x, Number %s.\n",
607 (message[2] == 0x05 ? "Voice":"Data?"), message[3], buffer);
612 static GSM_Error P3110_IncomingCallAnswered(int messagetype, unsigned char *message, int length, GSM_Data *data)
614 dprintf("Incoming call answered from phone.\n");
619 /* Fairly self explanatory these two, though the outgoing
620 call message has three (unexplained) data bytes. */
621 static GSM_Error P3110_IncomingCallEstablished(int messagetype, unsigned char *message, int length, GSM_Data *data)
623 dprintf("%s call established - status bytes %02x %02x.\n",
624 (message[2] == 0x05 ? "voice":"data(?)"), message[3], message[4]);
629 /* 0x10 messages are sent by the phone when an outgoing
631 static GSM_Error P3110_IncomingEndOfOutgoingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
633 dprintf("Call terminated from phone (0x10 message).\n");
634 /* FIXME: Tell datapump code that the call has terminated. */
642 /* 0x11 messages are sent by the phone when an incoming call
643 terminates. There is some other data in the message,
644 purpose as yet undertermined. */
645 static GSM_Error P3110_IncomingEndOfIncomingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
647 dprintf("Call terminated from opposite end of line (or from network).\n");
649 /* FIXME: Tell datapump code that the call has terminated. */
657 /* 0x12 messages are sent after the 0x10 message at the
658 end of an outgoing call. Significance of two messages
659 versus the one at the end of an incoming call is as
660 yet undertermined. */
661 static GSM_Error P3110_IncomingEndOfOutgoingCall2(int messagetype, unsigned char *message, int length, GSM_Data *data)
663 dprintf("Call terminated from phone (0x12 message).\n");
665 /* FIXME: Tell datapump code that the call has terminated. */
674 /* 0x13 messages are sent after the phone restarts.
677 static GSM_Error P3110_IncomingRestart(int messagetype, unsigned char *message, int length, GSM_Data *data)
679 /* FIXME: send 0x15 message somehow */
684 /* 0x15 messages are sent by the phone in response to the
685 init sequence sent so we don't acknowledge them! */
687 static GSM_Error P3110_IncomingInitFrame_0x15(int messagetype, unsigned char *message, int length, GSM_Data *data)
693 /* 0x16 messages are sent by the phone during initialisation, to response
695 Sequence bytes have been observed to change with differing software
696 versions: V06.61 (19/08/97) sends 0x10 0x02, V07.02 (17/03/98) sends
697 0x30 0x02. The actual data byte is 0x02 when SIM memory is available,
698 and 0x01 when not (e.g. when SIM card isn't inserted to phone or when
699 it is waiting for PIN) */
701 static GSM_Error P3110_IncomingInitFrame_0x16(int messagetype, unsigned char *message, int length, GSM_Data *data)
703 SimAvailable = (message[2] == 0x02);
704 dprintf("SIM available: %s.\n", (SimAvailable ? "Yes" : "No"));
709 static GSM_Error P3110_IncomingInitFrame_0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
711 dprintf("0x17 Registration Response: Failure!\n");
716 /* 0x27 messages are a little unusual when sent by the phone in that
717 they can either be an acknowledgement of an 0x27 message we sent
718 to the phone with message text in it or they could
719 contain message text for a message we requested. */
721 static GSM_Error P3110_IncomingSMSUserData(int messagetype, unsigned char *message, int length, GSM_Data *data)
725 /* First see if it was an acknowledgement to one of our messages,
726 if so then nothing to do */
727 if (length == 0x02) return GE_NONE;
729 /* Copy into current SMS message as long as it's non-NULL */
730 if (!data->SMSMessage) return GE_INTERNALERROR;
732 /* If this is the first block, reset accumulated message length. */
733 if (message[2] == 1) data->SMSMessage->Length = 0;
735 /* Copy message text */
736 for (count = 0; count < length-3 && data->SMSMessage->Length < GSM_MAX_SMS_LENGTH; count++, data->SMSMessage->Length++)
737 data->SMSMessage->MessageText[data->SMSMessage->Length] = message[count + 3];
743 /* 0x28 messages are sent by the phone to acknowledge succesfull
744 sending of an SMS message. The byte returned is a receipt
745 number of some form, not sure if it's from the network, sending
746 sending of an SMS message. The byte returned is the TP-MR
747 (TP-Message-Reference) from sending phone (Also sent to network).
748 TP-MR is send from phone within 0x32 message. TP-MR is increased
749 by phone after each sent SMS */
751 static GSM_Error P3110_IncomingSMSSend(int messagetype, unsigned char *message, int length, GSM_Data *data)
753 dprintf("SMS send OK (0x%02hhx)\n", message[2]);
754 data->SMSMessage->Number = (int) message[2];
759 /* 0x29 messages are sent by the phone to indicate an error in
760 sending an SMS message. Observed values are 0x65 0x15 when
761 the phone originated SMS was disabled by the network for
762 the particular phone. 0x65 0x26 was observed too, whereupon
763 the message was retried. */
765 static GSM_Error P3110_IncomingSMSSendError(int messagetype, unsigned char *message, int length, GSM_Data *data)
767 dprintf("SMS send failed (0x%02hhx 0x%02hhx)\n", message[2], message[3]);
768 return GE_SMSSENDFAILED;
772 /* 0x2c messages are generated by the phone when we request an SMS
773 message with an 0x25 message. Appears to have the same fields
774 as the 0x30 notification but with one extra. Immediately after
775 the 0x2c nessage, the phone sends 0x27 message(s) */
777 static GSM_Error P3110_IncomingSMSHeader(int messagetype, unsigned char *message, int length, GSM_Data *data)
779 /* u8 sender_length, smsc_length, l; */
781 if (!data->SMSMessage) return GE_INTERNALERROR;
783 /* Extract data from message into SMSMessage */
785 DecodePDUSMS(message, data->SMSMessage, length);
787 /* All these moved to gsm-sms.c
791 data->SMSMessage->MemoryType = GMT_ME;
794 data->SMSMessage->MemoryType = GMT_SM;
797 data->SMSMessage->MemoryType = GMT_XX;
801 Set location in memory
802 data->SMSMessage->Location = message[3];
803 data->SMSMessage->MessageNumber = message[3];
805 3810 series has limited support for different SMS "mailboxes"
806 to the extent that the only know differentiation is between
807 received messages 0x01, 0x04 and written messages 0x07 0x01.
808 No flag has been found (yet) that indicates whether the
809 message has been sent or not.
811 Default to unknown message type
812 data->SMSMessage->Type = GST_UN;
814 Consider received messages "Inbox" (Mobile Terminated)
815 if (message[4] == 0x01 && message[5] == 0x04)
816 data->SMSMessage->Type = GST_MT;
818 Consider written messages "Outbox" (Mobile Originated)
819 if (message[4] == 0x07 && message[5] == 0x01)
820 data->SMSMessage->Type = GST_MO;
822 We don't know about read/unread or sent/unsent status.
823 so assume has been sent or read
824 data->SMSMessage->Status = GSS_SENTREAD;
826 Based on experiences with a 3110 it seems, that
827 0x03 means a received unread message,
828 0x07 means a stored unsent message
829 if (message[4] == 0x03 || message[4] == 0x07)
830 data->SMSMessage->Status = GSS_NOTSENTREAD;
832 data->SMSMessage->Status = GSS_SENTREAD;
835 if (message[5] & FO_UDHI)
836 data->SMSMessage->UDHType = GSM_RingtoneUDH; FIXME
838 data->SMSMessage->UDHType = GSM_NoUDH;
840 Check Data Coding Scheme and set text/binary flag
841 if (message[7] == 0xf5)
842 data->SMSMessage->EightBit = true;
844 data->SMSMessage->EightBit = false;
846 Extract date and time information which is packed in to
847 nibbles of each byte in reverse order. Thus day 28 would be
849 P3110_DecodeTime(message+8, &(data->SMSMessage->Time));
852 data->SMSMessage->Length = message[15];
854 Now get sender and message center length
855 smsc_length = message[16];
856 sender_length = message[17 + smsc_length];
859 l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
860 strncpy(data->SMSMessage->MessageCenter.Number, message + 17, l);
861 data->SMSMessage->MessageCenter.Number[l] = 0;
864 l = sender_length < GSM_MAX_SENDER_LENGTH ? sender_length : GSM_MAX_SENDER_LENGTH;
865 strncpy(data->SMSMessage->Sender, message + 18 + smsc_length, l);
866 data->SMSMessage->Sender[l] = 0;
869 dprintf("PID:%02x DCS:%02x Timezone:%02x Stat1:%02x Stat2:%02x\n",
870 message[6], message[7], message[14], message[4], message[5]);
872 dprintf("Message Read:\n");
873 dprintf(" Location: %d. Type: %d Status: %d\n", data->SMSMessage->Number, data->SMSMessage->Type, data->SMSMessage->Status);
874 dprintf(" Sender: %s\n", data->SMSMessage->RemoteNumber.number);
875 dprintf(" Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
876 dprintf(" Time: %02d.%02d.%02d %02d:%02d:%02d\n",
877 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
883 /* 0x2d messages are generated when an SMS message is requested
884 that does not exist or is empty. */
886 static GSM_Error P3110_IncomingSMSError(int messagetype, unsigned char *message, int length, GSM_Data *data)
888 if (message[2] == 0x74)
889 return GE_INVALIDSMSLOCATION;
891 return GE_EMPTYSMSLOCATION;
895 /* 0x2e messages are generated when an SMS message is deleted
898 static GSM_Error P3110_IncomingSMSDelete(int messagetype, unsigned char *message, int length, GSM_Data *data)
904 /* 0x2f messages are generated when an SMS message is deleted
905 that does not exist. Unlike responses to a getsms message
906 no error is returned when the entry is already empty */
908 static GSM_Error P3110_IncomingSMSDeleteError(int messagetype, unsigned char *message, int length, GSM_Data *data)
910 /* Note 0x74 is the only value that has been seen! */
911 if (message[2] == 0x74)
912 return GE_INVALIDSMSLOCATION;
914 return GE_EMPTYSMSLOCATION;
918 /* 0x32 messages are generated when delivery notification arrives
919 to phone from network */
921 static GSM_Error P3110_IncomingSMSDelivered(int messagetype, unsigned char *message, int length, GSM_Data *data)
923 static GSM_SMSMessage sms;
924 /* u8 dest_length, smsc_length, l;*/
927 data->SMSMessage = &sms;
929 if (!data->SMSMessage) return GE_INTERNALERROR;
935 DecodePDUSMS(message, data->SMSMessage, length);
937 /* All these are moved fo gsm-sms.c
938 P3110_DecodeTime(message+3, &(data->SMSMessage->Time));
939 P3110_DecodeTime(message+10, &(data->SMSMessage->SMSCTime));
943 data->SMSMessage->MessageNumber = (int) message[18];
945 Get sender and message center length
946 dest_length = message[19];
947 smsc_length = message[20 + dest_length];
949 Copy destination number
950 l = dest_length < GSM_MAX_DESTINATION_LENGTH ? dest_length : GSM_MAX_DESTINATION_LENGTH;
951 strncpy(data->SMSMessage->Destination, message + 20, l);
952 data->SMSMessage->Destination[l] = 0;
955 l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
956 strncpy(data->SMSMessage->MessageCenter.Number, message + 21 + dest_length, l);
957 data->SMSMessage->MessageCenter.Number[l] = 0;
960 dprintf("Message [0x%02x] Delivered!\n", data->SMSMessage->Number);
961 dprintf(" Destination: %s\n", data->SMSMessage->RemoteNumber.number);
962 dprintf(" Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
963 dprintf(" Unknowns: 0x%02x 0x%02x 0x%02x\n", U0, U1, U2);
964 dprintf(" Discharge Time: %02d.%02d.%02d %02d:%02d:%02d\n",
965 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
966 dprintf(" SMSC Time Stamp: %02d.%02d.%02d %02d:%02d:%02d\n",
967 data->SMSMessage->SMSCTime.Day, data->SMSMessage->SMSCTime.Month, data->SMSMessage->SMSCTime.Year, data->SMSMessage->SMSCTime.Hour, data->SMSMessage->SMSCTime.Minute, data->SMSMessage->SMSCTime.Second);
973 /* 0x40 Messages are sent to response to an 0x3f request.
974 e.g. when phone is waiting for PIN */
976 static GSM_Error P3110_IncomingNoSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
978 dprintf("SMS Message Center Data not reachable.\n");
983 /* Handle 0x41 message which is sent by phone in response to an
984 0x3f request. Contains data about the Message Center in use */
986 static GSM_Error P3110_IncomingSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
988 u8 center_number_length;
989 u8 option_number_length;
992 if (!data) return GE_INTERNALERROR;
994 /* We don't know what this option number is, just handle it */
995 option_number_length = message[12];
997 /* Get message center length */
998 center_number_length = message[13 + option_number_length];
1000 dprintf("SMS Message Center Data:\n");
1001 dprintf(" Selected memory: 0x%02x\n", message[2]);
1002 dprintf(" Messages in Phone: 0x%02x Unread: 0x%02x\n", message[3], message[4]);
1003 dprintf(" Messages in SIM: 0x%02x Unread: 0x%02x\n", message[5], message[6]);
1004 dprintf(" Reply via own centre: 0x%02x (%s)\n", message[10], (message[10] == 0x02 ? "Yes" : "No"));
1005 dprintf(" Delivery reports: 0x%02x (%s)\n", message[11], (message[11] == 0x02 ? "Yes" : "No"));
1006 dprintf(" Messages sent as: 0x%02x\n", message[7]);
1007 dprintf(" Message validity: 0x%02x\n", message[9]);
1008 dprintf(" Unknown: 0x%02x\n", message[8]);
1010 dprintf(" UnknownNumber: ");
1011 for (count = 0; count < option_number_length; count ++)
1012 dprintf("%c", message[13 + count]);
1015 dprintf(" Message center number: ");
1016 for (count = 0; count < center_number_length; count ++) {
1017 dprintf("%c", message[14 + option_number_length + count]);
1021 /* Get message center related info if upper layer wants to know */
1022 if (data->MessageCenter) {
1023 data->MessageCenter->Format = message[7];
1024 data->MessageCenter->Validity = message[9];
1026 if (center_number_length == 0) {
1027 data->MessageCenter->Number[0] = 0x00; /* Null terminate */
1029 memcpy(data->MessageCenter->Number,
1030 message + 14 + option_number_length,
1031 center_number_length);
1032 data->MessageCenter->Number[center_number_length] = '\0';
1035 /* 3810 series doesn't support Name or multiple center numbers
1036 so put in null data for them . */
1037 data->MessageCenter->Name[0] = 0x00;
1038 data->MessageCenter->No = 0;
1041 /* Get SMS related info if upper layer wants to know */
1042 if (data->SMSStatus) {
1043 data->SMSStatus->Unread = message[4] + message[6];
1044 data->SMSStatus->Number = message[3] + message[5];
1047 /* Get memory info if upper layer wants to know */
1048 if (data->MemoryStatus) {
1049 switch (data->MemoryStatus->MemoryType) {
1051 data->MemoryStatus->Used = message[5];
1052 data->MemoryStatus->Free = P3110_MEMORY_SIZE_SM - message[5];
1055 data->MemoryStatus->Used = message[3];
1056 data->MemoryStatus->Free = P3110_MEMORY_SIZE_ME - message[3];
1067 /* 0x48 is sent during power-on of the phone, after the 0x13
1068 message is received and the PIN (if any) has been entered
1071 static GSM_Error P3110_IncomingPINEntered(int messagetype, unsigned char *message, int length, GSM_Data *data)
1073 SimAvailable = true;
1074 dprintf("PIN [possibly] entered.\n");
1079 /* 0x4b messages are sent by phone in response (it seems) to the keep
1080 alive packet. We must acknowledge these it seems by sending a
1081 response with the "sequence number" byte loaded appropriately. */
1083 static GSM_Error P3110_IncomingStatusInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1085 /* Strings for the status byte received from phone. */
1086 char *StatusStr[] = {
1094 /* There are three data bytes in the status message, two have been
1095 attributed to signal level, the third is presently unknown.
1096 Unknown byte has been observed to be 0x01 when connected to normal
1097 network, 0x04 when no network available. Steps through 0x02, 0x03
1098 when incoming or outgoing calls occur...*/
1099 /*FB38_LinkOK = true;*/
1101 /* Note: GetRFLevel function in fbus-3810.c does conversion
1102 into required units. */
1103 if (data->RFLevel) {
1104 *(data->RFUnits) = GRF_Arbitrary;
1105 *(data->RFLevel) = message[3];
1108 /* Note: GetBatteryLevel function in fbus-3810.c does conversion
1109 into required units. */
1110 if (data->BatteryLevel) {
1111 *(data->BatteryUnits) = GBU_Arbitrary;
1112 *(data->BatteryLevel) = message[4];
1115 /* Only output connection status byte now as the RF and Battery
1116 levels are displayed by the main gnokii code. */
1117 dprintf("Status: %s, Battery level: %d, RF level: %d.\n",
1118 StatusStr[message[2]], message[4], message[3]);
1122 /* 0x4d Message provides IMEI, Revision and Model information. */
1124 static GSM_Error P3110_IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1126 size_t imei_length, rev_length, model_length;
1128 imei_length = strlen(message + 2);
1129 rev_length = strlen(message + 3 + imei_length);
1130 model_length = strlen(message + 4 + imei_length + rev_length);
1133 strcpy(data->Imei, message + 2);
1136 strcpy(data->Revision, message + 3 + imei_length);
1139 strcpy(data->Model, message + 4 + imei_length + rev_length);
1141 dprintf("Mobile Phone Identification:\n");
1142 dprintf(" IMEI: %s\n", message + 2);
1143 dprintf(" Model: %s\n", message + 4 + imei_length + rev_length);
1144 dprintf(" Revision: %s\n", message + 3 + imei_length);
1153 void P3110_KeepAliveLoop(GSM_Statemachine *state)
1156 GSM_DataClear(&data);
1158 while (!RequestTerminate) {
1160 if (KeepAliveTimer == 0) {
1161 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
1162 /* Dont send keepalive packets when statemachine
1163 is doing other transactions. */
1164 if (state->CurrentState == Initialised) {
1165 dprintf("Sending keepalive message.\n");
1166 P3110_GetStatusInfo(&data, state);
1171 usleep(100000); /* Avoid becoming a "busy" loop. */
1175 void P3110_DecodeTime(unsigned char *b, GSM_DateTime *dt)
1177 dt->Year = P3110_bcd2int(b[0]);
1178 dt->Month = P3110_bcd2int(b[1]);
1179 dt->Day = P3110_bcd2int(b[2]);
1180 dt->Hour = P3110_bcd2int(b[3]);
1181 dt->Minute = P3110_bcd2int(b[4]);
1182 dt->Second = P3110_bcd2int(b[5]);
1183 dt->Timezone = P3110_bcd2int(b[6]);
1187 int P3110_bcd2int(u8 x)
1189 return (int)(10 * ((x & 0x0f)) + (x >> 4));