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 2001/11/25 21:59:13 short
19 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
21 Revision 1.6 2001/11/20 16:22:22 pkot
22 First attempt to read Picture Messages. They should appear when you enable DEBUG. Nokia seems to break own standards. :/ (Markus Plail)
24 Revision 1.5 2001/11/19 13:03:18 pkot
27 Revision 1.4 2001/11/17 16:42:47 pkot
30 Revision 1.3 2001/11/09 14:25:04 pkot
33 Revision 1.2 2001/11/09 13:47:58 pkot
34 Removed pthreads from 3110 support. It may break it.
36 Revision 1.1 2001/11/08 16:39:09 pkot
37 3810/3110 support for the new structure (Tamas Bondar)
46 #define __phones_nk3110_c
48 #include "gsm-common.h"
49 #include "phones/generic.h"
50 #include "phones/nk3110.h"
51 #include "links/fbus-3110.h"
52 #include "phones/nokia.h"
57 #define snprintf _snprintf
58 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
63 static GSM_IncomingFunctionType IncomingFunctions[] = {
64 { 0x0a, P3110_IncomingNothing },
65 { 0x0b, P3110_IncomingCall },
66 { 0x0c, P3110_IncomingNothing },
67 { 0x0d, P3110_IncomingCallAnswered },
68 { 0x0e, P3110_IncomingCallEstablished },
69 { 0x0f, P3110_IncomingNothing },
70 { 0x10, P3110_IncomingEndOfOutgoingCall },
71 { 0x11, P3110_IncomingEndOfIncomingCall },
72 { 0x12, P3110_IncomingEndOfOutgoingCall2 },
73 { 0x13, P3110_IncomingRestart },
74 { 0x15, P3110_IncomingInitFrame_0x15 },
75 { 0x16, P3110_IncomingInitFrame_0x16 },
76 { 0x17, P3110_IncomingInitFrame_0x17 },
77 { 0x20, P3110_IncomingNothing },
78 /*{ 0x21, P3110_IncomingDTMFSucess },*/
79 /*{ 0x22, P3110_IncomingDTMFFailure },*/
80 { 0x23, P3110_IncomingNothing },
81 { 0x24, P3110_IncomingNothing },
82 { 0x25, P3110_IncomingNothing },
83 { 0x26, P3110_IncomingNothing },
84 { 0x27, P3110_IncomingSMSUserData },
85 { 0x28, P3110_IncomingSMSSend },
86 { 0x29, P3110_IncomingSMSSendError },
88 { 0x2c, P3110_IncomingSMSHeader },
89 { 0x2d, P3110_IncomingSMSError },
90 { 0x2e, P3110_IncomingSMSDelete },
91 { 0x2f, P3110_IncomingSMSDeleteError },
93 { 0x32, P3110_IncomingSMSDelivered },
94 { 0x3f, P3110_IncomingNothing },
95 { 0x40, P3110_IncomingNoSMSInfo },
96 { 0x41, P3110_IncomingSMSInfo },
97 { 0x48, P3110_IncomingPINEntered },
98 { 0x4a, P3110_IncomingNothing },
99 { 0x4b, P3110_IncomingStatusInfo },
100 { 0x4c, P3110_IncomingNothing },
101 { 0x4d, P3110_IncomingPhoneInfo },
105 GSM_Phone phone_nokia_3110 = {
107 PGEN_IncomingDefault,
108 /* Mobile phone information */
110 "3110|3810|8110|8110i", /* Models */
111 4, /* Max RF Level */
112 0, /* Min RF Level */
113 GRF_Arbitrary, /* RF level units */
114 4, /* Max Battery Level */
115 0, /* Min Battery Level */
116 GBU_Arbitrary, /* Battery level units */
117 GDT_None, /* No date/time support */
118 GDT_None, /* No alarm support */
119 0, /* Max alarms = 0 */
120 0, 0, /* Startup logo size */
121 0, 0, /* Op logo size */
122 0, 0 /* Caller logo size */
127 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
131 return P3110_Initialise(state);
133 case GOP_GetRevision:
135 return P3110_GetPhoneInfo(data, state);
137 return P3110_Identify(data, state);
138 case GOP_GetBatteryLevel:
140 return P3110_GetStatusInfo(data, state);
141 case GOP_GetMemoryStatus:
142 return P3110_GetMemoryStatus(data, state);
143 case GOP_ReadPhonebook:
144 case GOP_WritePhonebook:
145 case GOP_GetPowersource:
147 case GOP_GetSMSStatus:
148 case GOP_GetIncomingCallNr:
149 case GOP_GetNetworkInfo:
150 return GE_NOTIMPLEMENTED;
152 return P3110_GetSMSMessage(data, state);
154 return P3110_DeleteSMSMessage(data, state);
156 return P3110_SendSMSMessage(data, state);
157 case GOP_GetSMSCenter:
158 return P3110_GetSMSInfo(data, state);
159 case GOP_GetSpeedDial:
160 case GOP_GetDateTime:
162 return GE_NOTIMPLEMENTED;
166 static bool LinkOK = false;
167 static bool SimAvailable = false;
169 /* These are related to keepalive functionality */
170 static bool RequestTerminate;
171 static bool DisableKeepAlive;
172 static int KeepAliveTimer;
174 /* Initialise is the only function allowed to 'use' state */
175 static GSM_Error P3110_Initialise(GSM_Statemachine *state)
178 u8 init_sequence[20] = {0x02, 0x01, 0x07, 0xa2, 0x88, 0x81, 0x21, 0x55, 0x63, 0xa8, 0x00, 0x00, 0x07, 0xa3, 0xb8, 0x81, 0x20, 0x15, 0x63, 0x80};
180 /* Copy in the phone info */
181 memcpy(&(state->Phone), &phone_nokia_3110, sizeof(GSM_Phone));
183 /* Only serial connection is supported */
184 if (state->Link.ConnectionType != GCT_Serial) return GE_NOTSUPPORTED;
186 /* Initialise FBUS link */
187 if (FB3110_Initialise(&(state->Link), state) != GE_NONE) {
188 dprintf("Error in link initialisation\n");
192 /* Initialise state machine */
193 SM_Initialise(state);
195 /* 0x15 messages are sent by the PC during the initialisation phase.
196 Anyway, the contents of the message are not understood so we
197 simply send the same sequence observed between the W95 PC and
198 the phone. The init sequence may still be a bit flaky and is not
200 if (SM_SendMessage(state, 20, 0x15, init_sequence) != GE_NONE) return GE_NOTREADY;
202 /* Wait for response to 0x15 sequence */
203 GSM_DataClear(&data);
204 if (SM_Block(state, &data, 0x16) != GE_NONE) return GE_NOTREADY;
206 /* Most probably link is OK now */
209 /* Start sending keepalive messages in separate thread */
210 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
211 RequestTerminate = false;
212 DisableKeepAlive = false;
217 static GSM_Error P3110_GetSMSInfo(GSM_Data *data, GSM_Statemachine *state)
219 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
220 if (SM_SendMessage(state, 0, 0x3f, NULL) != GE_NONE) return GE_NOTREADY;
221 return SM_Block(state, data, 0x41);
224 static GSM_Error P3110_GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
226 dprintf("Getting phone info...\n");
227 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
228 if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
229 return SM_Block(state, data, 0x4d);
232 static GSM_Error P3110_GetStatusInfo(GSM_Data *data, GSM_Statemachine *state)
234 dprintf("Getting phone status...\n");
235 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
236 if (SM_SendMessage(state, 0, 0x4a, NULL) != GE_NONE) return GE_NOTREADY;
237 return SM_Block(state, data, 0x4b);
240 static GSM_Error P3110_GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
242 dprintf("Getting memory status...\n");
244 /* Check if this type of memory is available */
245 switch (data->MemoryStatus->MemoryType) {
247 if (!SimAvailable) return GE_NOTREADY;
248 return P3110_GetSMSInfo(data, state);
250 if (P3110_MEMORY_SIZE_ME == 0) return GE_NOTREADY;
251 return P3110_GetSMSInfo(data, state);
259 static GSM_Error P3110_Identify(GSM_Data *data, GSM_Statemachine *state)
261 dprintf("Identifying...\n");
262 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
263 if (SM_SendMessage(state, 0, 0x4c, NULL) != GE_NONE) return GE_NOTREADY;
264 SM_Block(state, data, 0x4d);
266 /* Check that we are back at state Initialised */
267 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
272 static GSM_Error P3110_GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
274 int total_length, timeout, c;
275 u8 response = 0, request[2];
276 GSM_Error error = GE_INTERNALERROR;
278 dprintf("Getting SMS message...\n");
280 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
282 switch(data->SMSMessage->MemoryType) {
284 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
287 data->SMSMessage->MemoryType = 2;
290 return (GE_INVALIDMEMORYTYPE);
293 /* Set memory type and location in the request */
294 request[0] = data->SMSMessage->MemoryType;
295 request[1] = data->SMSMessage->Number;
297 /* 0x25 messages requests the contents of an SMS message
298 from the phone. The first byte has only ever been
299 observed to be 0x02 - could be selecting internal versus
300 external memory. Specifying memory 0x00 may request the
301 first location? Phone replies with 0x2c and 0x27 messages
302 for valid locations, 0x2d for empty ones. */
303 if (SM_SendMessage(state, 2, 0x25, request) != GE_NONE) return GE_NOTREADY;
305 SM_WaitFor(state, data, 0x2d);
306 SM_WaitFor(state, data, 0x2c);
308 timeout = 30; /* ~3secs timeout */
313 } while ((timeout > 0) && state->NumReceived == 0);
316 if (state->NumReceived == 0) return GE_TIMEOUT;
318 /* find response in state machine */
319 for (c = 0; c < state->NumWaitingFor; c++) {
320 if (state->ResponseError[c] != GE_BUSY) {
321 response = state->WaitingFor[c];
322 error = state->ResponseError[c];
326 /* reset state machine */
329 /* process response */
332 if (error != GE_NONE) return error;
334 /* Save total length of message */
335 total_length = data->SMSMessage->Length;
337 /* Block for subsequent content frames... */
339 SM_Block(state, data, 0x27);
340 } while (data->SMSMessage->Length < total_length);
342 /* Terminate message text */
343 data->SMSMessage->MessageText[data->SMSMessage->Length] = 0;
348 return GE_INTERNALERROR;
353 static GSM_Error P3110_DeleteSMSMessage(GSM_Data *data, GSM_Statemachine *state)
356 u8 response = 0, request[2];
357 GSM_Error error = GE_INTERNALERROR;
359 dprintf("Deleting SMS message...\n");
361 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
363 switch(data->SMSMessage->MemoryType) {
365 data->SMSMessage->MemoryType = 1; /* 3 in 8110, 1 is GMT_CB */
368 data->SMSMessage->MemoryType = 2;
371 return (GE_INVALIDMEMORYTYPE);
374 /* Set memory type and location in the request */
375 request[0] = data->SMSMessage->MemoryType;
376 request[1] = data->SMSMessage->Number;
378 /* 0x26 message deletes an SMS message from the phone.
379 The first byte has only ever been observed to be 0x02
380 but is assumed to be selecting internal versus
381 external memory. Phone replies with 0x2e for valid locations,
382 0x2f for invalid ones. If a location is empty but otherwise
383 valid 0x2e is still returned. */
384 if (SM_SendMessage(state, 2, 0x26, request) != GE_NONE) return GE_NOTREADY;
386 SM_WaitFor(state, data, 0x2e);
387 SM_WaitFor(state, data, 0x2f);
389 timeout = 30; /* ~3secs timeout */
394 } while ((timeout > 0) && state->NumReceived == 0);
397 if (state->NumReceived == 0) return GE_TIMEOUT;
399 /* find response in state machine */
400 for (c = 0; c < state->NumWaitingFor; c++) {
401 if (state->ResponseError[c] != GE_BUSY) {
402 response = state->WaitingFor[c];
403 error = state->ResponseError[c];
407 /* reset state machine */
410 /* process response */
416 return GE_INTERNALERROR;
421 static GSM_Error P3110_SendSMSMessage(GSM_Data *data, GSM_Statemachine *state)
423 int timeout, c, retry_count, block_count, block_length;
424 u8 userdata[GSM_MAX_SMS_LENGTH];
425 int userdata_length, userdata_offset, userdata_remaining;
426 u8 response, request[GSM_MAX_SMS_LENGTH];
428 SMS_MessageCenter smsc;
431 /* Get default SMSC from phone if not set in SMS */
432 if (!data->SMSMessage->MessageCenter.Number[0]) {
433 data->MessageCenter = &smsc;
434 error = P3110_GetSMSInfo(data, state);
435 if (error != GE_NONE) return error;
436 data->SMSMessage->MessageCenter = smsc;
439 dprintf("Sending SMS to %s via message center %s\n", data->SMSMessage->RemoteNumber.number, data->SMSMessage->MessageCenter.Number);
443 if (data->SMSMessage->UDH[0].Type) {
444 userdata_offset = 1 + data->SMSMessage->udhlen;
445 memcpy(userdata, data->SMSMessage->MessageText, userdata_offset);
454 if (data->SMSMessage->EightBit) {
455 memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, data->SMSMessage->Length);
456 userdata_length = data->SMSMessage->Length + userdata_offset;
457 max_userdata_length = GSM_MAX_SMS_8_BIT_LENGTH;
458 dcs = DCS_DATA | DCS_CLASS1;
460 userdata_length = strlen(data->SMSMessage->MessageText);
461 memcpy(userdata + userdata_offset, data->SMSMessage->MessageText, userdata_length);
462 userdata_length += userdata_offset;
463 max_userdata_length = GSM_MAX_SMS_LENGTH;
470 request[1] = PID_DEFAULT;
472 request[3] = GSMV_Max_Time;
479 request[10] = userdata_length;
480 request[11] = smsc_length;
481 memcpy(request+12, data->SMSMessage->MessageCenter.Number, smsc_length);
482 request[12+smsc_length] = dest_length;
483 memcpy(request+13+smsc_length, data->SMSMessage->Destination, dest_length);
486 error = EncodePDUSMS(data->SMSMessage, request);
487 if (error) return error;
489 /* We have a loop here as if the response from the phone is
490 0x65 0x26 the rule appears to be just to try sending the
491 message again. We do this a maximum of FB38_SMS_SEND_RETRY_COUNT
492 times before giving up. This value is empirical only! */
493 retry_count = P3110_SMS_SEND_RETRY_COUNT;
495 while (retry_count > 0) {
497 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
499 dprintf("Transferring FBUS SMS header [");
500 for (i = 0; i < data->SMSMessage->Length; i++) dprintf(" %02hhX", request[i]);
503 if (SM_SendMessage(state, data->SMSMessage->Length, 0x23, request) != GE_NONE) return GE_NOTREADY;
505 error = SM_Block(state, data, 0x23);
506 if (error != GE_NONE) return error;
508 /* Now send as many blocks of maximum 55 characters as required
509 to send complete message. */
512 userdata_remaining = userdata_length;
514 while (userdata_remaining > 0) {
515 block_length = userdata_remaining;
517 /* Limit block length */
518 if (block_length > 55) block_length = 55;
521 request[0] = block_count;
522 memcpy(request+1, userdata + userdata_offset, block_length);
525 if (SM_SendMessage(state, block_length+1, 0x27, request) != GE_NONE) return GE_NOTREADY;
526 error = SM_Block(state, data, 0x27);
527 if (error != GE_NONE) return error;
529 /* update remaining and offset values for next block */
530 userdata_remaining -= block_length;
531 userdata_offset += block_length;
535 /* Now wait for response from network which will see
536 CurrentSMSMessageError change from busy. */
537 SM_WaitFor(state, data, 0x28);
538 SM_WaitFor(state, data, 0x29);
540 timeout = 1200; /* 120secs timeout */
545 } while ((timeout > 0) && state->NumReceived == 0);
548 if (state->NumReceived == 0) return GE_TIMEOUT;
550 /* find response in state machine */
551 for (c = 0; c < state->NumWaitingFor; c++) {
552 if (state->ResponseError[c] != GE_BUSY) {
553 response = state->WaitingFor[c];
554 error = state->ResponseError[c];
558 /* reset state machine */
561 /* process response */
566 /* Got a retry response so try again! */
567 dprintf("SMS send attempt failed, trying again...\n");
569 /* After an empirically determined pause... */
570 usleep(500000); /* 0.5 seconds. */
573 return GE_INTERNALERROR;
576 /* Retries must have failed. */
577 return GE_SMSSENDFAILED;
581 static GSM_Error P3110_IncomingNothing(int messagetype, unsigned char *message, int length, GSM_Data *data)
586 /* 0x0b messages are sent by phone when an incoming call occurs,
587 this message must be acknowledged. */
588 static GSM_Error P3110_IncomingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
593 /* Get info out of message. At present, first three bytes are
594 unknown (though third seems to correspond to length of
595 number). Remaining bytes are the phone number, ASCII
597 for (count = 0; count < message[4]; count ++) {
598 buffer[count] = message[5 + count];
600 buffer[count] = 0x00;
602 /* Now display incoming call message. */
603 dprintf("Incoming call - Type: %s. %02x, Number %s.\n",
604 (message[2] == 0x05 ? "Voice":"Data?"), message[3], buffer);
609 static GSM_Error P3110_IncomingCallAnswered(int messagetype, unsigned char *message, int length, GSM_Data *data)
611 dprintf("Incoming call answered from phone.\n");
616 /* Fairly self explanatory these two, though the outgoing
617 call message has three (unexplained) data bytes. */
618 static GSM_Error P3110_IncomingCallEstablished(int messagetype, unsigned char *message, int length, GSM_Data *data)
620 dprintf("%s call established - status bytes %02x %02x.\n",
621 (message[2] == 0x05 ? "voice":"data(?)"), message[3], message[4]);
626 /* 0x10 messages are sent by the phone when an outgoing
628 static GSM_Error P3110_IncomingEndOfOutgoingCall(int messagetype, unsigned char *message, int length, GSM_Data *data)
630 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)
644 dprintf("Call terminated from opposite end of line (or from network).\n");
646 /* FIXME: Tell datapump code that the call has terminated. */
654 /* 0x12 messages are sent after the 0x10 message at the
655 end of an outgoing call. Significance of two messages
656 versus the one at the end of an incoming call is as
657 yet undertermined. */
658 static GSM_Error P3110_IncomingEndOfOutgoingCall2(int messagetype, unsigned char *message, int length, GSM_Data *data)
660 dprintf("Call terminated from phone (0x12 message).\n");
662 /* FIXME: Tell datapump code that the call has terminated. */
671 /* 0x13 messages are sent after the phone restarts.
674 static GSM_Error P3110_IncomingRestart(int messagetype, unsigned char *message, int length, GSM_Data *data)
676 /* FIXME: send 0x15 message somehow */
681 /* 0x15 messages are sent by the phone in response to the
682 init sequence sent so we don't acknowledge them! */
684 static GSM_Error P3110_IncomingInitFrame_0x15(int messagetype, unsigned char *message, int length, GSM_Data *data)
690 /* 0x16 messages are sent by the phone during initialisation, to response
692 Sequence bytes have been observed to change with differing software
693 versions: V06.61 (19/08/97) sends 0x10 0x02, V07.02 (17/03/98) sends
694 0x30 0x02. The actual data byte is 0x02 when SIM memory is available,
695 and 0x01 when not (e.g. when SIM card isn't inserted to phone or when
696 it is waiting for PIN) */
698 static GSM_Error P3110_IncomingInitFrame_0x16(int messagetype, unsigned char *message, int length, GSM_Data *data)
700 SimAvailable = (message[2] == 0x02);
701 dprintf("SIM available: %s.\n", (SimAvailable ? "Yes" : "No"));
706 static GSM_Error P3110_IncomingInitFrame_0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
708 dprintf("0x17 Registration Response: Failure!\n");
713 /* 0x27 messages are a little unusual when sent by the phone in that
714 they can either be an acknowledgement of an 0x27 message we sent
715 to the phone with message text in it or they could
716 contain message text for a message we requested. */
718 static GSM_Error P3110_IncomingSMSUserData(int messagetype, unsigned char *message, int length, GSM_Data *data)
722 /* First see if it was an acknowledgement to one of our messages,
723 if so then nothing to do */
724 if (length == 0x02) return GE_NONE;
726 /* Copy into current SMS message as long as it's non-NULL */
727 if (!data->SMSMessage) return GE_INTERNALERROR;
729 /* If this is the first block, reset accumulated message length. */
730 if (message[2] == 1) data->SMSMessage->Length = 0;
732 /* Copy message text */
733 for (count = 0; count < length-3 && data->SMSMessage->Length < GSM_MAX_SMS_LENGTH; count++, data->SMSMessage->Length++)
734 data->SMSMessage->MessageText[data->SMSMessage->Length] = message[count + 3];
740 /* 0x28 messages are sent by the phone to acknowledge succesfull
741 sending of an SMS message. The byte returned is a receipt
742 number of some form, not sure if it's from the network, sending
743 sending of an SMS message. The byte returned is the TP-MR
744 (TP-Message-Reference) from sending phone (Also sent to network).
745 TP-MR is send from phone within 0x32 message. TP-MR is increased
746 by phone after each sent SMS */
748 static GSM_Error P3110_IncomingSMSSend(int messagetype, unsigned char *message, int length, GSM_Data *data)
750 dprintf("SMS send OK (0x%02hhx)\n", message[2]);
751 data->SMSMessage->Number = (int) message[2];
756 /* 0x29 messages are sent by the phone to indicate an error in
757 sending an SMS message. Observed values are 0x65 0x15 when
758 the phone originated SMS was disabled by the network for
759 the particular phone. 0x65 0x26 was observed too, whereupon
760 the message was retried. */
762 static GSM_Error P3110_IncomingSMSSendError(int messagetype, unsigned char *message, int length, GSM_Data *data)
764 dprintf("SMS send failed (0x%02hhx 0x%02hhx)\n", message[2], message[3]);
765 return GE_SMSSENDFAILED;
769 /* 0x2c messages are generated by the phone when we request an SMS
770 message with an 0x25 message. Appears to have the same fields
771 as the 0x30 notification but with one extra. Immediately after
772 the 0x2c nessage, the phone sends 0x27 message(s) */
774 static GSM_Error P3110_IncomingSMSHeader(int messagetype, unsigned char *message, int length, GSM_Data *data)
776 /* u8 sender_length, smsc_length, l; */
778 if (!data->SMSMessage) return GE_INTERNALERROR;
780 /* Extract data from message into SMSMessage */
782 DecodePDUSMS(message, data->SMSMessage, length);
784 /* All these moved to gsm-sms.c
788 data->SMSMessage->MemoryType = GMT_ME;
791 data->SMSMessage->MemoryType = GMT_SM;
794 data->SMSMessage->MemoryType = GMT_XX;
798 Set location in memory
799 data->SMSMessage->Location = message[3];
800 data->SMSMessage->MessageNumber = message[3];
802 3810 series has limited support for different SMS "mailboxes"
803 to the extent that the only know differentiation is between
804 received messages 0x01, 0x04 and written messages 0x07 0x01.
805 No flag has been found (yet) that indicates whether the
806 message has been sent or not.
808 Default to unknown message type
809 data->SMSMessage->Type = GST_UN;
811 Consider received messages "Inbox" (Mobile Terminated)
812 if (message[4] == 0x01 && message[5] == 0x04)
813 data->SMSMessage->Type = GST_MT;
815 Consider written messages "Outbox" (Mobile Originated)
816 if (message[4] == 0x07 && message[5] == 0x01)
817 data->SMSMessage->Type = GST_MO;
819 We don't know about read/unread or sent/unsent status.
820 so assume has been sent or read
821 data->SMSMessage->Status = GSS_SENTREAD;
823 Based on experiences with a 3110 it seems, that
824 0x03 means a received unread message,
825 0x07 means a stored unsent message
826 if (message[4] == 0x03 || message[4] == 0x07)
827 data->SMSMessage->Status = GSS_NOTSENTREAD;
829 data->SMSMessage->Status = GSS_SENTREAD;
832 if (message[5] & FO_UDHI)
833 data->SMSMessage->UDHType = GSM_RingtoneUDH; FIXME
835 data->SMSMessage->UDHType = GSM_NoUDH;
837 Check Data Coding Scheme and set text/binary flag
838 if (message[7] == 0xf5)
839 data->SMSMessage->EightBit = true;
841 data->SMSMessage->EightBit = false;
843 Extract date and time information which is packed in to
844 nibbles of each byte in reverse order. Thus day 28 would be
846 P3110_DecodeTime(message+8, &(data->SMSMessage->Time));
849 data->SMSMessage->Length = message[15];
851 Now get sender and message center length
852 smsc_length = message[16];
853 sender_length = message[17 + smsc_length];
856 l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
857 strncpy(data->SMSMessage->MessageCenter.Number, message + 17, l);
858 data->SMSMessage->MessageCenter.Number[l] = 0;
861 l = sender_length < GSM_MAX_SENDER_LENGTH ? sender_length : GSM_MAX_SENDER_LENGTH;
862 strncpy(data->SMSMessage->Sender, message + 18 + smsc_length, l);
863 data->SMSMessage->Sender[l] = 0;
866 dprintf("PID:%02x DCS:%02x Timezone:%02x Stat1:%02x Stat2:%02x\n",
867 message[6], message[7], message[14], message[4], message[5]);
869 dprintf("Message Read:\n");
870 dprintf(" Location: %d. Type: %d Status: %d\n", data->SMSMessage->Number, data->SMSMessage->Type, data->SMSMessage->Status);
871 dprintf(" Sender: %s\n", data->SMSMessage->RemoteNumber.number);
872 dprintf(" Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
873 dprintf(" Time: %02d.%02d.%02d %02d:%02d:%02d\n",
874 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
880 /* 0x2d messages are generated when an SMS message is requested
881 that does not exist or is empty. */
883 static GSM_Error P3110_IncomingSMSError(int messagetype, unsigned char *message, int length, GSM_Data *data)
885 if (message[2] == 0x74)
886 return GE_INVALIDSMSLOCATION;
888 return GE_EMPTYSMSLOCATION;
892 /* 0x2e messages are generated when an SMS message is deleted
895 static GSM_Error P3110_IncomingSMSDelete(int messagetype, unsigned char *message, int length, GSM_Data *data)
901 /* 0x2f messages are generated when an SMS message is deleted
902 that does not exist. Unlike responses to a getsms message
903 no error is returned when the entry is already empty */
905 static GSM_Error P3110_IncomingSMSDeleteError(int messagetype, unsigned char *message, int length, GSM_Data *data)
907 /* Note 0x74 is the only value that has been seen! */
908 if (message[2] == 0x74)
909 return GE_INVALIDSMSLOCATION;
911 return GE_EMPTYSMSLOCATION;
915 /* 0x32 messages are generated when delivery notification arrives
916 to phone from network */
918 static GSM_Error P3110_IncomingSMSDelivered(int messagetype, unsigned char *message, int length, GSM_Data *data)
920 static GSM_SMSMessage sms;
921 /* u8 dest_length, smsc_length, l;*/
924 data->SMSMessage = &sms;
926 if (!data->SMSMessage) return GE_INTERNALERROR;
932 DecodePDUSMS(message, data->SMSMessage, length);
934 /* All these are moved fo gsm-sms.c
935 P3110_DecodeTime(message+3, &(data->SMSMessage->Time));
936 P3110_DecodeTime(message+10, &(data->SMSMessage->SMSCTime));
940 data->SMSMessage->MessageNumber = (int) message[18];
942 Get sender and message center length
943 dest_length = message[19];
944 smsc_length = message[20 + dest_length];
946 Copy destination number
947 l = dest_length < GSM_MAX_DESTINATION_LENGTH ? dest_length : GSM_MAX_DESTINATION_LENGTH;
948 strncpy(data->SMSMessage->Destination, message + 20, l);
949 data->SMSMessage->Destination[l] = 0;
952 l = smsc_length < GSM_MAX_SMS_CENTER_LENGTH ? smsc_length : GSM_MAX_SMS_CENTER_LENGTH;
953 strncpy(data->SMSMessage->MessageCenter.Number, message + 21 + dest_length, l);
954 data->SMSMessage->MessageCenter.Number[l] = 0;
957 dprintf("Message [0x%02x] Delivered!\n", data->SMSMessage->Number);
958 dprintf(" Destination: %s\n", data->SMSMessage->RemoteNumber.number);
959 dprintf(" Message Center: %s\n", data->SMSMessage->MessageCenter.Number);
960 dprintf(" Unknowns: 0x%02x 0x%02x 0x%02x\n", U0, U1, U2);
961 dprintf(" Discharge Time: %02d.%02d.%02d %02d:%02d:%02d\n",
962 data->SMSMessage->Time.Day, data->SMSMessage->Time.Month, data->SMSMessage->Time.Year, data->SMSMessage->Time.Hour, data->SMSMessage->Time.Minute, data->SMSMessage->Time.Second);
963 dprintf(" SMSC Time Stamp: %02d.%02d.%02d %02d:%02d:%02d\n",
964 data->SMSMessage->SMSCTime.Day, data->SMSMessage->SMSCTime.Month, data->SMSMessage->SMSCTime.Year, data->SMSMessage->SMSCTime.Hour, data->SMSMessage->SMSCTime.Minute, data->SMSMessage->SMSCTime.Second);
970 /* 0x40 Messages are sent to response to an 0x3f request.
971 e.g. when phone is waiting for PIN */
973 static GSM_Error P3110_IncomingNoSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
975 dprintf("SMS Message Center Data not reachable.\n");
980 /* Handle 0x41 message which is sent by phone in response to an
981 0x3f request. Contains data about the Message Center in use */
983 static GSM_Error P3110_IncomingSMSInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
985 u8 center_number_length;
986 u8 option_number_length;
989 if (!data) return GE_INTERNALERROR;
991 /* We don't know what this option number is, just handle it */
992 option_number_length = message[12];
994 /* Get message center length */
995 center_number_length = message[13 + option_number_length];
997 dprintf("SMS Message Center Data:\n");
998 dprintf(" Selected memory: 0x%02x\n", message[2]);
999 dprintf(" Messages in Phone: 0x%02x Unread: 0x%02x\n", message[3], message[4]);
1000 dprintf(" Messages in SIM: 0x%02x Unread: 0x%02x\n", message[5], message[6]);
1001 dprintf(" Reply via own centre: 0x%02x (%s)\n", message[10], (message[10] == 0x02 ? "Yes" : "No"));
1002 dprintf(" Delivery reports: 0x%02x (%s)\n", message[11], (message[11] == 0x02 ? "Yes" : "No"));
1003 dprintf(" Messages sent as: 0x%02x\n", message[7]);
1004 dprintf(" Message validity: 0x%02x\n", message[9]);
1005 dprintf(" Unknown: 0x%02x\n", message[8]);
1007 dprintf(" UnknownNumber: ");
1008 for (count = 0; count < option_number_length; count ++)
1009 dprintf("%c", message[13 + count]);
1012 dprintf(" Message center number: ");
1013 for (count = 0; count < center_number_length; count ++) {
1014 dprintf("%c", message[14 + option_number_length + count]);
1018 /* Get message center related info if upper layer wants to know */
1019 if (data->MessageCenter) {
1020 data->MessageCenter->Format = message[7];
1021 data->MessageCenter->Validity = message[9];
1023 if (center_number_length == 0) {
1024 data->MessageCenter->Number[0] = 0x00; /* Null terminate */
1026 memcpy(data->MessageCenter->Number,
1027 message + 14 + option_number_length,
1028 center_number_length);
1029 data->MessageCenter->Number[center_number_length] = '\0';
1032 /* 3810 series doesn't support Name or multiple center numbers
1033 so put in null data for them . */
1034 data->MessageCenter->Name[0] = 0x00;
1035 data->MessageCenter->No = 0;
1038 /* Get SMS related info if upper layer wants to know */
1039 if (data->SMSStatus) {
1040 data->SMSStatus->Unread = message[4] + message[6];
1041 data->SMSStatus->Number = message[3] + message[5];
1044 /* Get memory info if upper layer wants to know */
1045 if (data->MemoryStatus) {
1046 switch (data->MemoryStatus->MemoryType) {
1048 data->MemoryStatus->Used = message[5];
1049 data->MemoryStatus->Free = P3110_MEMORY_SIZE_SM - message[5];
1052 data->MemoryStatus->Used = message[3];
1053 data->MemoryStatus->Free = P3110_MEMORY_SIZE_ME - message[3];
1064 /* 0x48 is sent during power-on of the phone, after the 0x13
1065 message is received and the PIN (if any) has been entered
1068 static GSM_Error P3110_IncomingPINEntered(int messagetype, unsigned char *message, int length, GSM_Data *data)
1070 SimAvailable = true;
1071 dprintf("PIN [possibly] entered.\n");
1076 /* 0x4b messages are sent by phone in response (it seems) to the keep
1077 alive packet. We must acknowledge these it seems by sending a
1078 response with the "sequence number" byte loaded appropriately. */
1080 static GSM_Error P3110_IncomingStatusInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1082 /* Strings for the status byte received from phone. */
1083 char *StatusStr[] = {
1091 /* There are three data bytes in the status message, two have been
1092 attributed to signal level, the third is presently unknown.
1093 Unknown byte has been observed to be 0x01 when connected to normal
1094 network, 0x04 when no network available. Steps through 0x02, 0x03
1095 when incoming or outgoing calls occur...*/
1096 /*FB38_LinkOK = true;*/
1098 /* Note: GetRFLevel function in fbus-3810.c does conversion
1099 into required units. */
1100 if (data->RFLevel) {
1101 *(data->RFUnits) = GRF_Arbitrary;
1102 *(data->RFLevel) = message[3];
1105 /* Note: GetBatteryLevel function in fbus-3810.c does conversion
1106 into required units. */
1107 if (data->BatteryLevel) {
1108 *(data->BatteryUnits) = GBU_Arbitrary;
1109 *(data->BatteryLevel) = message[4];
1112 /* Only output connection status byte now as the RF and Battery
1113 levels are displayed by the main gnokii code. */
1114 dprintf("Status: %s, Battery level: %d, RF level: %d.\n",
1115 StatusStr[message[2]], message[4], message[3]);
1119 /* 0x4d Message provides IMEI, Revision and Model information. */
1121 static GSM_Error P3110_IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
1123 size_t imei_length, rev_length, model_length;
1125 imei_length = strlen(message + 2);
1126 rev_length = strlen(message + 3 + imei_length);
1127 model_length = strlen(message + 4 + imei_length + rev_length);
1130 strcpy(data->Imei, message + 2);
1133 strcpy(data->Revision, message + 3 + imei_length);
1136 strcpy(data->Model, message + 4 + imei_length + rev_length);
1138 dprintf("Mobile Phone Identification:\n");
1139 dprintf(" IMEI: %s\n", message + 2);
1140 dprintf(" Model: %s\n", message + 4 + imei_length + rev_length);
1141 dprintf(" Revision: %s\n", message + 3 + imei_length);
1150 void P3110_KeepAliveLoop(GSM_Statemachine *state)
1153 GSM_DataClear(&data);
1155 while (!RequestTerminate) {
1157 if (KeepAliveTimer == 0) {
1158 KeepAliveTimer = P3110_KEEPALIVE_TIMEOUT;
1159 /* Dont send keepalive packets when statemachine
1160 is doing other transactions. */
1161 if (state->CurrentState == Initialised) {
1162 dprintf("Sending keepalive message.\n");
1163 P3110_GetStatusInfo(&data, state);
1168 usleep(100000); /* Avoid becoming a "busy" loop. */
1172 void P3110_DecodeTime(unsigned char *b, GSM_DateTime *dt)
1174 dt->Year = P3110_bcd2int(b[0]);
1175 dt->Month = P3110_bcd2int(b[1]);
1176 dt->Day = P3110_bcd2int(b[2]);
1177 dt->Hour = P3110_bcd2int(b[3]);
1178 dt->Minute = P3110_bcd2int(b[4]);
1179 dt->Second = P3110_bcd2int(b[5]);
1180 dt->Timezone = P3110_bcd2int(b[6]);
1184 int P3110_bcd2int(u8 x)
1186 return (int)(10 * ((x & 0x0f)) + (x >> 4));