7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 2000 Hugh Blemings & Pavel JanÃk ml.
11 Released under the terms of the GNU GPL, see file COPYING for more details.
13 This file provides an API for accessing functions via fbus.
14 See README for more details on supported mobile phones.
16 The various routines are called FBUS_(whatever).
19 Revision 1.1.1.1.8.1 2001/11/27 23:06:09 short
20 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
22 Revision 1.1.1.1.2.1 2001/11/27 22:48:37 short
23 Update: orig2001_11_27_05_17 -> orig2001_11_27_22_58
25 Revision 1.1.1.2 2001/11/27 22:01:16 short
26 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Tue Nov 27 22:58 CET 2001
28 Revision 1.3 2001/11/27 12:19:01 pkot
29 Cleanup, indentation, ANSI complaint preprocesor symbols (Jan Kratochvil, me)
31 Revision 1.2 2001/11/09 14:25:04 pkot
34 Revision 1.1 2001/11/09 12:55:07 pkot
35 Forgot about fbus support for 3110. FIXME: is it really needed?
40 /* System header files */
46 /* Various header file */
50 #include "gsm-common.h"
51 #include "gsm-ringtones.h"
52 #include "gsm-networks.h"
53 #include "gsm-statemachine.h"
54 #include "links/utils.h"
59 # include "win32/winserial.h"
60 # define device_write(a, b) WriteCommBlock(a, b)
61 # define device_read(a, b) ReadCommBlock(a, b)
62 # define sleep(x) Sleep((x) * 1000)
63 # define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
66 #define __links_fbus_3110_c
67 #include "links/fbus-3110.h"
69 /* FIXME - pass device_* the link stuff?? */
70 /* FIXME - win32 stuff! */
75 static GSM_Link *glink;
76 static GSM_Statemachine *statemachine;
77 static FB3110_Link flink; /* FBUS specific stuff, internal to this file */
80 /*--------------------------------------------*/
82 bool FB3110_OpenSerial(void)
86 if (OpenConnection(glink->PortDevice, FB3110_RX_StateMachine, NULL)) {
88 if (!device_open(glink->PortDevice, false, false, false, GCT_Serial)) {
90 perror(_("Couldn't open FBUS device"));
93 device_changespeed(115200);
99 /* RX_State machine for receive handling. Called once for each character
100 received from the phone. */
102 void FB3110_RX_StateMachine(unsigned char rx_byte)
104 FB3110_IncomingFrame *i = &flink.i;
109 /* Phone is currently off. Wait for 0x55 before
111 case FB3110_RX_Discarding:
115 /* Seen 0x55, restart at 0x04 */
116 i->State = FB3110_RX_Sync;
118 dprintf("restarting.\n");
122 /* Messages from the phone start with an 0x04 during
123 "normal" operation, 0x03 when in data/fax mode. We
124 use this to "synchronise" with the incoming data
127 if (rx_byte == 0x04 || rx_byte == 0x03) {
128 i->FrameType = rx_byte;
129 i->Checksum = rx_byte;
130 i->State = FB3110_RX_GetLength;
134 /* Next byte is the length of the message including
135 the message type byte but not including the checksum. */
136 case FB3110_RX_GetLength:
137 i->FrameLength = rx_byte;
139 i->Checksum ^= rx_byte;
140 i->State = FB3110_RX_GetMessage;
143 /* Get each byte of the message. We deliberately
144 get one too many bytes so we get the checksum
146 case FB3110_RX_GetMessage:
147 i->Buffer[i->BufferCount] = rx_byte;
150 if (i->BufferCount > FB3110_MAX_FRAME_LENGTH) {
151 dprintf("FBUS: Message buffer overun - resetting\n");
152 i->State = FB3110_RX_Sync;
156 /* If this is the last byte, it's the checksum. */
157 if (i->BufferCount > i->FrameLength) {
159 /* Is the checksum correct? */
160 if (rx_byte == i->Checksum) {
162 if (i->FrameType == 0x03) {
163 /* FIXME: modify Buffer[0] to code FAX frame types */
166 dprintf("--> %02x:%02x:", i->FrameType, i->FrameLength);
167 for (count = 0; count < i->BufferCount; count++)
168 dprintf("%02hhx:", i->Buffer[count]);
170 /* Transfer message to state machine */
171 SM_IncomingFunction(statemachine, i->Buffer[0], i->Buffer, i->FrameLength);
174 FB3110_TX_SendAck(i->Buffer, i->FrameLength);
177 /* Checksum didn't match so ignore. */
178 dprintf("Bad checksum!\n");
180 i->State = FB3110_RX_Sync;
182 i->Checksum ^= rx_byte;
188 /* This is the main loop function which must be called regularly */
189 /* timeout can be used to make it 'busy' or not */
191 GSM_Error FB3110_Loop(struct timeval *timeout)
194 unsigned char buffer[255];
197 res = device_select(timeout);
199 res = device_read(buffer, 255);
200 for (count = 0; count < res; count++)
201 FB3110_RX_StateMachine(buffer[count]);
205 /* This traps errors from device_read */
209 return GE_INTERNALERROR;
217 /* Prepares the message header and sends it, prepends the
218 message start byte (0x01) and other values according
219 the value specified when called. Calculates checksum
220 and then sends the lot down the pipe... */
222 GSM_Error FB3110_TX_SendFrame(u8 message_length, u8 message_type, u8 sequence_byte, u8 * buffer)
225 u8 out_buffer[FB3110_MAX_TRANSMIT_LENGTH];
226 int count, current = 0;
227 unsigned char checksum;
229 /* Check message isn't too long, once the necessary
230 header and trailer bytes are included. */
231 if ((message_length + 5) > FB3110_MAX_TRANSMIT_LENGTH) {
232 fprintf(stderr, _("FB3110_TX_SendFrame - message too long!\n"));
233 return (GE_INTERNALERROR);
236 /* Now construct the message header. */
237 out_buffer[current++] = FB3110_FRAME_ID; /* Start of frame */
238 out_buffer[current++] = message_length + 2; /* Length */
239 out_buffer[current++] = message_type; /* Type */
240 out_buffer[current++] = sequence_byte; /* Sequence number */
242 /* Copy in data if any. */
243 if (message_length != 0) {
244 memcpy(out_buffer + current, buffer, message_length);
245 current += message_length;
248 /* Now calculate checksum over entire message
249 and append to message. */
251 for (count = 0; count < current; count++)
252 checksum ^= out_buffer[count];
253 out_buffer[current++] = checksum;
256 for (count = 0; count < current; count++)
257 dprintf("%02hhx:", out_buffer[count]);
261 if (device_write(out_buffer, current) != current)
262 return (GE_INTERNALERROR);
268 /* Main function to send an fbus message */
270 GSM_Error FB3110_SendMessage(u16 messagesize, u8 messagetype, void *message)
274 FB3110_UpdateSequenceNumber();
275 seqnum = flink.RequestSequenceNumber;
277 return FB3110_TX_SendFrame(messagesize, messagetype, seqnum, message);
281 /* Sends the "standard" acknowledge message back to the phone in
282 response to a message it sent automatically or in response to
283 a command sent to it. The ack. algorithm isn't 100% understood
286 void FB3110_TX_SendAck(u8 *message, int length)
292 /* We send 0x0a messages to make a call so don't ack. */
294 /* We send 0x0c message to answer to incoming call
297 /* We send 0x0f message to hang up so don't ack */
299 /* 0x15 messages are sent by the phone in response to the
300 init sequence sent so we don't acknowledge them! */
302 /* We send 0x20 message to phone to send DTFM, so don't ack */
304 /* We send 0x23 messages to phone as a header for outgoing SMS
305 messages. So we don't acknowledge it. */
307 /* We send 0x24 messages to phone as a header for storing SMS
308 messages in memory. So we don't acknowledge it. :) */
310 /* We send 0x25 messages to phone to request an SMS message
311 be dumped. Thus we don't acknowledge it. */
313 /* We send 0x26 messages to phone to delete an SMS message
314 so it's not acknowledged. */
316 /* We send an 0x3f message to the phone to request a different
317 type of status dump - this one seemingly concerned with
318 SMS message center details. Phone responds with an ack to
319 our 0x3f request then sends an 0x41 message that has the
320 actual data in it. */
322 /* 0x4a message is a response to our 0x4a request, assumed to
323 be a keepalive message of sorts. No response required. */
325 /* We send 0x4c to request IMEI, Revision and Model info. */
328 /* 0x27 messages are a little different in that both ends of
329 the link send them. So, first we have to check if this
330 is an acknowledgement or a message to be acknowledged */
331 if (length == 0x02) break;
333 /* Standard acknowledge seems to be to return an empty message
334 with the sequence number set to equal the sequence number
336 if (FB3110_TX_SendFrame(0, t, (message[1] & 0x1f) - 0x08, NULL) != GE_NONE)
337 dprintf("Failed to acknowledge message type %02x.\n", t);
339 dprintf("Acknowledged message type %02x.\n", t);
344 /* Initialise variables and start the link */
345 /* newlink is actually part of state - but the link code should not anything about state */
346 /* state is only passed around to allow for muliple state machines (one day...) */
348 GSM_Error FB3110_Initialise(GSM_Link *newlink, GSM_Statemachine *state)
350 unsigned char init_char = 0x55;
355 if (try > 2) return GE_DEVICEOPENFAILED;
356 /* 'Copy in' the global structures */
358 statemachine = state;
360 /* Fill in the link functions */
361 glink->Loop = &FB3110_Loop;
362 glink->SendMessage = &FB3110_SendMessage;
364 /* Check for a valid init length */
365 if (glink->InitLength == 0)
366 glink->InitLength = 100;
368 /* Start up the link */
370 flink.RequestSequenceNumber = 0x10;
372 if (!FB3110_OpenSerial()) return GE_DEVICEOPENFAILED;
374 /* Send init string to phone, this is a bunch of 0x55 characters.
375 Timing is empirical. I believe that we need/can do this for any
376 phone to get the UART synced */
377 for (count = 0; count < glink->InitLength; count++) {
379 device_write(&init_char, 1);
383 flink.i.State = FB3110_RX_Sync;
389 /* Any command we originate must have a unique SequenceNumber.
390 Observation to date suggests that these values startx at 0x10
391 and cycle up to 0x17 before repeating again. Perhaps more
392 accurately, the numbers cycle 0,1,2,3..7 with bit 4 of the byte
395 void FB3110_UpdateSequenceNumber(void)
397 flink.RequestSequenceNumber++;
399 if (flink.RequestSequenceNumber > 0x17 || flink.RequestSequenceNumber < 0x10) {
400 flink.RequestSequenceNumber = 0x10;