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 2001/11/25 21:59:10 short
20 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
22 Revision 1.2 2001/11/09 14:25:04 pkot
25 Revision 1.1 2001/11/09 12:55:07 pkot
26 Forgot about fbus support for 3110. FIXME: is it really needed?
31 /* System header files */
37 /* Various header file */
41 #include "gsm-common.h"
42 #include "gsm-ringtones.h"
43 #include "gsm-networks.h"
44 #include "gsm-statemachine.h"
45 #include "links/utils.h"
50 #include "win32/winserial.h"
51 #define device_write(a, b) WriteCommBlock(a, b)
52 #define device_read(a, b) ReadCommBlock(a, b)
53 #define sleep(x) Sleep((x) * 1000)
54 #define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
57 #define __links_fbus_3110_c
58 #include "links/fbus-3110.h"
60 /* FIXME - pass device_* the link stuff?? */
61 /* FIXME - win32 stuff! */
66 static GSM_Link *glink;
67 static GSM_Statemachine *statemachine;
68 static FB3110_Link flink; /* FBUS specific stuff, internal to this file */
71 /*--------------------------------------------*/
73 bool FB3110_OpenSerial(void)
77 if (OpenConnection(glink->PortDevice, FB3110_RX_StateMachine, NULL)) {
79 if (!device_open(glink->PortDevice, false, false, false, GCT_Serial)) {
81 perror(_("Couldn't open FBUS device"));
84 device_changespeed(115200);
90 /* RX_State machine for receive handling. Called once for each character
91 received from the phone. */
93 void FB3110_RX_StateMachine(unsigned char rx_byte)
95 FB3110_IncomingFrame *i = &flink.i;
100 /* Phone is currently off. Wait for 0x55 before
102 case FB3110_RX_Discarding:
106 /* Seen 0x55, restart at 0x04 */
107 i->State = FB3110_RX_Sync;
109 dprintf("restarting.\n");
113 /* Messages from the phone start with an 0x04 during
114 "normal" operation, 0x03 when in data/fax mode. We
115 use this to "synchronise" with the incoming data
118 if (rx_byte == 0x04 || rx_byte == 0x03) {
119 i->FrameType = rx_byte;
120 i->Checksum = rx_byte;
121 i->State = FB3110_RX_GetLength;
125 /* Next byte is the length of the message including
126 the message type byte but not including the checksum. */
127 case FB3110_RX_GetLength:
128 i->FrameLength = rx_byte;
130 i->Checksum ^= rx_byte;
131 i->State = FB3110_RX_GetMessage;
134 /* Get each byte of the message. We deliberately
135 get one too many bytes so we get the checksum
137 case FB3110_RX_GetMessage:
138 i->Buffer[i->BufferCount] = rx_byte;
141 if (i->BufferCount > FB3110_MAX_FRAME_LENGTH) {
142 dprintf("FBUS: Message buffer overun - resetting\n");
143 i->State = FB3110_RX_Sync;
147 /* If this is the last byte, it's the checksum. */
148 if (i->BufferCount > i->FrameLength) {
150 /* Is the checksum correct? */
151 if (rx_byte == i->Checksum) {
153 if (i->FrameType == 0x03) {
154 /* FIXME: modify Buffer[0] to code FAX frame types */
157 dprintf("--> %02x:%02x:", i->FrameType, i->FrameLength);
158 for (count = 0; count < i->BufferCount; count++)
159 dprintf("%02hhx:", i->Buffer[count]);
161 /* Transfer message to state machine */
162 SM_IncomingFunction(statemachine, i->Buffer[0], i->Buffer, i->FrameLength);
165 FB3110_TX_SendAck(i->Buffer, i->FrameLength);
168 /* Checksum didn't match so ignore. */
169 dprintf("Bad checksum!\n");
171 i->State = FB3110_RX_Sync;
173 i->Checksum ^= rx_byte;
179 /* This is the main loop function which must be called regularly */
180 /* timeout can be used to make it 'busy' or not */
182 GSM_Error FB3110_Loop(struct timeval *timeout)
185 unsigned char buffer[255];
188 res = device_select(timeout);
190 res = device_read(buffer, 255);
191 for (count = 0; count < res; count++)
192 FB3110_RX_StateMachine(buffer[count]);
196 /* This traps errors from device_read */
200 return GE_INTERNALERROR;
208 /* Prepares the message header and sends it, prepends the
209 message start byte (0x01) and other values according
210 the value specified when called. Calculates checksum
211 and then sends the lot down the pipe... */
213 GSM_Error FB3110_TX_SendFrame(u8 message_length, u8 message_type, u8 sequence_byte, u8 * buffer)
216 u8 out_buffer[FB3110_MAX_TRANSMIT_LENGTH];
217 int count, current = 0;
218 unsigned char checksum;
220 /* Check message isn't too long, once the necessary
221 header and trailer bytes are included. */
222 if ((message_length + 5) > FB3110_MAX_TRANSMIT_LENGTH) {
223 fprintf(stderr, _("FB3110_TX_SendFrame - message too long!\n"));
224 return (GE_INTERNALERROR);
227 /* Now construct the message header. */
228 out_buffer[current++] = FB3110_FRAME_ID; /* Start of frame */
229 out_buffer[current++] = message_length + 2; /* Length */
230 out_buffer[current++] = message_type; /* Type */
231 out_buffer[current++] = sequence_byte; /* Sequence number */
233 /* Copy in data if any. */
234 if (message_length != 0) {
235 memcpy(out_buffer + current, buffer, message_length);
236 current += message_length;
239 /* Now calculate checksum over entire message
240 and append to message. */
242 for (count = 0; count < current; count++)
243 checksum ^= out_buffer[count];
244 out_buffer[current++] = checksum;
247 for (count = 0; count < current; count++)
248 dprintf("%02hhx:", out_buffer[count]);
252 if (device_write(out_buffer, current) != current)
253 return (GE_INTERNALERROR);
259 /* Main function to send an fbus message */
261 GSM_Error FB3110_SendMessage(u16 messagesize, u8 messagetype, void *message)
265 FB3110_UpdateSequenceNumber();
266 seqnum = flink.RequestSequenceNumber;
268 return FB3110_TX_SendFrame(messagesize, messagetype, seqnum, message);
272 /* Sends the "standard" acknowledge message back to the phone in
273 response to a message it sent automatically or in response to
274 a command sent to it. The ack. algorithm isn't 100% understood
277 void FB3110_TX_SendAck(u8 *message, int length)
283 /* We send 0x0a messages to make a call so don't ack. */
285 /* We send 0x0c message to answer to incoming call
288 /* We send 0x0f message to hang up so don't ack */
290 /* 0x15 messages are sent by the phone in response to the
291 init sequence sent so we don't acknowledge them! */
293 /* We send 0x20 message to phone to send DTFM, so don't ack */
295 /* We send 0x23 messages to phone as a header for outgoing SMS
296 messages. So we don't acknowledge it. */
298 /* We send 0x24 messages to phone as a header for storing SMS
299 messages in memory. So we don't acknowledge it. :) */
301 /* We send 0x25 messages to phone to request an SMS message
302 be dumped. Thus we don't acknowledge it. */
304 /* We send 0x26 messages to phone to delete an SMS message
305 so it's not acknowledged. */
307 /* We send an 0x3f message to the phone to request a different
308 type of status dump - this one seemingly concerned with
309 SMS message center details. Phone responds with an ack to
310 our 0x3f request then sends an 0x41 message that has the
311 actual data in it. */
313 /* 0x4a message is a response to our 0x4a request, assumed to
314 be a keepalive message of sorts. No response required. */
316 /* We send 0x4c to request IMEI, Revision and Model info. */
319 /* 0x27 messages are a little different in that both ends of
320 the link send them. So, first we have to check if this
321 is an acknowledgement or a message to be acknowledged */
322 if (length == 0x02) break;
324 /* Standard acknowledge seems to be to return an empty message
325 with the sequence number set to equal the sequence number
327 if (FB3110_TX_SendFrame(0, t, (message[1] & 0x1f) - 0x08, NULL) != GE_NONE)
328 dprintf("Failed to acknowledge message type %02x.\n", t);
330 dprintf("Acknowledged message type %02x.\n", t);
335 /* Initialise variables and start the link */
336 /* newlink is actually part of state - but the link code should not anything about state */
337 /* state is only passed around to allow for muliple state machines (one day...) */
339 GSM_Error FB3110_Initialise(GSM_Link *newlink, GSM_Statemachine *state)
341 unsigned char init_char = 0x55;
346 if (try > 2) return GE_DEVICEOPENFAILED;
347 /* 'Copy in' the global structures */
349 statemachine = state;
351 /* Fill in the link functions */
352 glink->Loop = &FB3110_Loop;
353 glink->SendMessage = &FB3110_SendMessage;
355 /* Check for a valid init length */
356 if (glink->InitLength == 0)
357 glink->InitLength = 100;
359 /* Start up the link */
361 flink.RequestSequenceNumber = 0x10;
363 if (!FB3110_OpenSerial()) return GE_DEVICEOPENFAILED;
365 /* Send init string to phone, this is a bunch of 0x55 characters.
366 Timing is empirical. I believe that we need/can do this for any
367 phone to get the UART synced */
368 for (count = 0; count < glink->InitLength; count++) {
370 device_write(&init_char, 1);
374 flink.i.State = FB3110_RX_Sync;
380 /* Any command we originate must have a unique SequenceNumber.
381 Observation to date suggests that these values startx at 0x10
382 and cycle up to 0x17 before repeating again. Perhaps more
383 accurately, the numbers cycle 0,1,2,3..7 with bit 4 of the byte
386 void FB3110_UpdateSequenceNumber(void)
388 flink.RequestSequenceNumber++;
390 if (flink.RequestSequenceNumber > 0x17 || flink.RequestSequenceNumber < 0x10) {
391 flink.RequestSequenceNumber = 0x10;