1 /* (c) 2002-2003 by Marcin Wiacek */
2 /* based on some work from MyGnokii (www.mwiacek.com) */
3 /* Based on some work from Gnokii (www.gnokii.org)
4 * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
5 * GNU GPL version 2 or later
6 */
7 /* Due to a problem in the source code management, the names of some of
8 * the authors have unfortunately been lost. We do not mean to belittle
9 * their efforts and hope they will contact us to see their names
10 * properly added to the Copyright notice above.
11 * Having published their contributions under the terms of the GNU
12 * General Public License (GPL) [version 2], the Copyright of these
13 * authors will remain respected by adhering to the license they chose
14 * to publish their code under.
15 */
16
17 #include "../../gsmstate.h"
18
19 #if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_DKU5FBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "../../gsmcomon.h"
26 #include "fbus2.h"
27
28 static GSM_Error FBUS2_Initialise(GSM_StateMachine *s);
29
FBUS2_WriteFrame(GSM_StateMachine * s,unsigned const char * MsgBuffer,int MsgLength,unsigned char MsgType)30 static GSM_Error FBUS2_WriteFrame(GSM_StateMachine *s,
31 unsigned const char *MsgBuffer,
32 int MsgLength,
33 unsigned char MsgType)
34 {
35 unsigned char buffer[FBUS2_MAX_TRANSMIT_LENGTH + 10]={0};
36 unsigned char checksum=0;
37 int i=0, length=0, sent=0;
38
39 buffer[0] = FBUS2_FRAME_ID;
40
41 if (s->ConnectionType==GCT_FBUS2IRDA) {
42 buffer[0] = FBUS2_IRDA_FRAME_ID;
43 }
44 buffer[1] = FBUS2_DEVICE_PHONE; /* destination */
45 buffer[2] = FBUS2_DEVICE_PC; /* source */
46 buffer[3] = MsgType;
47 buffer[4] = MsgLength / 256;
48 buffer[5] = MsgLength % 256;
49 memcpy(buffer + 6, MsgBuffer, MsgLength);
50 length = MsgLength + 6;
51
52 /* Odd messages require additional 0x00 byte */
53 if (MsgLength % 2) {
54 buffer[length++] = 0x00;
55 }
56 checksum = 0;
57
58 for (i = 0; i < length; i+=2) {
59 checksum ^= buffer[i];
60 }
61 buffer[length++] = checksum;
62 checksum = 0;
63
64 for (i = 1; i < length; i+=2) {
65 checksum ^= buffer[i];
66 }
67 buffer[length++] = checksum;
68
69 /* Sending to phone */
70 sent = s->Device.Functions->WriteDevice(s, buffer, length);
71
72 if (sent != length) {
73 return ERR_DEVICEWRITEERROR;
74 }
75 return ERR_NONE;
76 }
77
FBUS2_WriteMessage(GSM_StateMachine * s,unsigned const char * MsgBuffer,size_t MsgLength,int MsgType)78 static GSM_Error FBUS2_WriteMessage (GSM_StateMachine *s,
79 unsigned const char *MsgBuffer,
80 size_t MsgLength,
81 int MsgType)
82 {
83 int i=0, nom=0, togo=0, thislength=0; /* number of messages, ... */
84 unsigned char buffer[FBUS2_MAX_TRANSMIT_LENGTH + 2]={0}, seqnum=0;
85 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
86 GSM_Error error;
87
88 GSM_DumpMessageBinary(s, MsgBuffer, MsgLength, MsgType);
89
90 nom = (MsgLength + FBUS2_MAX_TRANSMIT_LENGTH - 1) / FBUS2_MAX_TRANSMIT_LENGTH;
91 togo = MsgLength;
92
93 for (i = 0; i < nom; i++) {
94 seqnum = d->MsgSequenceNumber;
95
96 if (i==0) {
97 seqnum = seqnum + 0x40;
98 }
99 d->MsgSequenceNumber = (d->MsgSequenceNumber + 1) & 0x07;
100
101 thislength = togo;
102
103 if (togo > FBUS2_MAX_TRANSMIT_LENGTH) {
104 thislength = FBUS2_MAX_TRANSMIT_LENGTH;
105 }
106 memcpy(buffer, MsgBuffer + (MsgLength - togo), thislength);
107 buffer[thislength] = nom - i;
108 buffer[thislength + 1] = seqnum;
109 togo = togo - thislength;
110
111 GSM_DumpMessageText(s, buffer, thislength, MsgType);
112
113 error = FBUS2_WriteFrame(s, buffer, thislength + 2, MsgType);
114
115 if (error != ERR_NONE) {
116 return error;
117 }
118 }
119 return ERR_NONE;
120 }
121
FBUS2_SendAck(GSM_StateMachine * s,unsigned char MsgType,unsigned char MsgSequence)122 static GSM_Error FBUS2_SendAck(GSM_StateMachine *s,
123 unsigned char MsgType,
124 unsigned char MsgSequence)
125 {
126 unsigned char buffer[2]={0};
127
128 buffer[0] = MsgType;
129 buffer[1] = MsgSequence;
130
131 smprintf_level(s, D_TEXT, "[Sending Ack of type %02x, seq %x]\n",
132 buffer[0],
133 buffer[1]);
134
135 /* Sending to phone */
136 return FBUS2_WriteFrame(s, buffer, 2, FBUS2_ACK_BYTE);
137 }
138
FBUS2_StateMachine(GSM_StateMachine * s,unsigned char rx_char)139 static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
140 {
141 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
142 unsigned char frm_num, seq_num;
143 gboolean correct = FALSE;
144
145 /* XOR the byte with the earlier checksum */
146 d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char;
147
148 if (d->MsgRXState == RX_GetMessage) {
149 d->Msg.Buffer[d->Msg.Count] = rx_char;
150 d->Msg.Count++;
151
152 /* This is not last byte in frame */
153 if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE;
154
155 /* Checksum is incorrect */
156 if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) {
157 smprintf_level(s, D_ERROR, "[ERROR: checksum]\n");
158 free(d->Msg.Buffer);
159 d->Msg.Buffer = NULL;
160 d->Msg.Length = 0;
161 d->MsgRXState = RX_Sync;
162 return ERR_NONE;
163 }
164
165 seq_num = d->Msg.Buffer[d->Msg.Length-1];
166
167 if (d->Msg.Type == FBUS2_ACK_BYTE) {
168 smprintf_level(s, D_TEXT, "[Received Ack of type %02x, seq %02x]\n",
169 d->Msg.Buffer[0], seq_num);
170 free(d->Msg.Buffer);
171 d->Msg.Buffer = NULL;
172 d->Msg.Length = 0;
173 d->MsgRXState = RX_Sync;
174 return ERR_NONE;
175 }
176
177 frm_num = d->Msg.Buffer[d->Msg.Length-2];
178
179 if ((seq_num & 0x40) == 0x40) {
180 d->FramesToGo = frm_num;
181 d->MultiMsg.Length = 0;
182 d->MultiMsg.Type = d->Msg.Type;
183 d->MultiMsg.Destination = d->Msg.Destination;
184 d->MultiMsg.Source = d->Msg.Source;
185 }
186
187 if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) {
188 smprintf_level(s, D_ERROR, "[ERROR: Missed part of multiframe msg]\n");
189 free(d->Msg.Buffer);
190 d->Msg.Buffer = NULL;
191 d->Msg.Length = 0;
192 d->MsgRXState = RX_Sync;
193 return ERR_NONE;
194 }
195
196 if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) {
197 smprintf_level(s, D_ERROR, "[ERROR: Multiframe msg in multiframe msg]\n");
198 free(d->Msg.Buffer);
199 d->Msg.Buffer = NULL;
200 d->Msg.Length = 0;
201 d->MsgRXState = RX_Sync;
202 return ERR_NONE;
203 }
204
205 if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) {
206 d->MultiMsg.BufferUsed = d->MultiMsg.Length+d->Msg.Length-2;
207 d->MultiMsg.Buffer = (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed);
208 }
209 memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2);
210 d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2;
211
212 free(d->Msg.Buffer);
213 d->Msg.Buffer = NULL;
214 d->Msg.Length = 0;
215 d->FramesToGo--;
216
217 /* do not ack debug trace, as this could generate a
218 * (feedback loop) flood of which even Noah would be scared.
219 */
220 if (d->Msg.Type != 0) {
221 FBUS2_SendAck(s,d->Msg.Type,((unsigned char)(seq_num & 0x0f)));
222 }
223
224 if (d->FramesToGo == 0) {
225 s->Phone.Data.RequestMsg = &d->MultiMsg;
226 s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
227 }
228 d->MsgRXState = RX_Sync;
229 return ERR_NONE;
230 }
231 if (d->MsgRXState == RX_GetLength2) {
232 d->Msg.Length = d->Msg.Length + rx_char;
233 d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length+3);
234 if (d->Msg.Buffer == NULL) {
235 return ERR_MOREMEMORY;
236 }
237 d->MsgRXState = RX_GetMessage;
238 return ERR_NONE;
239 }
240 if (d->MsgRXState == RX_GetLength1) {
241 d->Msg.Length = rx_char * 256;
242 d->MsgRXState = RX_GetLength2;
243 return ERR_NONE;
244 }
245 if (d->MsgRXState == RX_GetType) {
246 d->Msg.Type = rx_char;
247 d->MsgRXState = RX_GetLength1;
248 return ERR_NONE;
249 }
250 if (d->MsgRXState == RX_GetSource) {
251 if (rx_char != FBUS2_DEVICE_PHONE) {
252 smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
253 rx_char, FBUS2_DEVICE_PHONE);
254
255 d->MsgRXState = RX_Sync;
256 return ERR_NONE;
257 }
258 d->Msg.Source = rx_char;
259
260 d->MsgRXState = RX_GetType;
261 return ERR_NONE;
262 }
263 if (d->MsgRXState == RX_GetDestination) {
264 if (rx_char != FBUS2_DEVICE_PC) {
265 smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
266 rx_char, FBUS2_DEVICE_PC);
267
268 d->MsgRXState = RX_Sync;
269 return ERR_NONE;
270 }
271 d->Msg.Destination = rx_char;
272
273 d->MsgRXState = RX_GetSource;
274 return ERR_NONE;
275 }
276 if (d->MsgRXState == RX_Sync) {
277 switch (s->ConnectionType) {
278 case GCT_FBUS2:
279 case GCT_FBUS2DLR3:
280 case GCT_DKU5FBUS2:
281 case GCT_FBUS2PL2303:
282 case GCT_FBUS2BLUE:
283 case GCT_BLUEFBUS2:
284 if (rx_char == FBUS2_FRAME_ID) correct = TRUE;
285 break;
286 case GCT_FBUS2IRDA:
287 if (rx_char == FBUS2_IRDA_FRAME_ID) correct = TRUE;
288 break;
289 default:
290 break;
291 }
292 if (!correct) {
293 smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
294 rx_char,
295 (s->ConnectionType == GCT_FBUS2IRDA) ? FBUS2_IRDA_FRAME_ID : FBUS2_FRAME_ID);
296 if (rx_char == 0x20) {
297 smprintf(s, "0x20 reply detected...\n");
298 smprintf(s, "Trying to reinit connection...\n");
299 FBUS2_Initialise(s);
300 }
301 return ERR_NONE;
302 }
303
304 d->Msg.CheckSum[0] = rx_char;
305 d->Msg.CheckSum[1] = 0;
306 d->Msg.Count = 0;
307
308 d->MsgRXState = RX_GetDestination;
309 return ERR_NONE;
310 }
311 return ERR_NONE;
312 }
313
314 #if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_DKU5FBUS2) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
315 /**
316 * Writes (AT) command to device and reads reply.
317 *
318 * \todo This makes no reply parsing or error detection.
319 */
FBUS2_WriteDLR3(GSM_StateMachine * s,const char * command,int length,int timeout)320 static void FBUS2_WriteDLR3(GSM_StateMachine *s, const char *command, int length, int timeout)
321 {
322 unsigned char buff[300]={0};
323 int w = 0,recvlen=0;
324 gboolean wassomething = FALSE;
325
326 GSM_DumpMessageText(s, command, length, 0xff);
327 s->Device.Functions->WriteDevice(s, command, length);
328
329 for (w = 0; w < timeout; w++) {
330 recvlen = s->Device.Functions->ReadDevice(s, buff, sizeof(buff));
331
332 if (wassomething && recvlen == 0) {
333 return;
334 } else if (recvlen > 0) {
335 GSM_DumpMessageTextRecv(s, buff, recvlen, 0xff);
336 wassomething = TRUE;
337 }
338 usleep(50000);
339 }
340 }
341
342 /**
343 * Performs switch to FBUS2 protocol using AT commands.
344 *
345 * \todo We should check return codes here.
346 */
FBUS2_ATSwitch(GSM_StateMachine * s)347 static GSM_Error FBUS2_ATSwitch(GSM_StateMachine *s)
348 {
349 static const char init_1[] = "AT\r\n";
350 static const char init_2[] = "AT&F\r\n";
351 static const char init_3[] = "AT*NOKIAFBUS\r\n";
352
353 smprintf(s, "Switching to FBUS using AT commands\n");
354
355 FBUS2_WriteDLR3(s, init_1, strlen(init_1), 100);
356 FBUS2_WriteDLR3(s, init_2, strlen(init_2), 100);
357 FBUS2_WriteDLR3(s, init_3, strlen(init_3), 100);
358
359 return ERR_NONE;
360 }
361 #endif
362
363 /**
364 * Performs initial synchronisation of FBUS2.
365 */
FBUS2_InitSequence(GSM_StateMachine * s,const int repeats,const int delays,const gboolean terminate)366 static GSM_Error FBUS2_InitSequence(GSM_StateMachine *s, const int repeats, const int delays, const gboolean terminate)
367 {
368 int count=0,write_data=0;
369 static const unsigned char init_char = 0x55;
370 static const unsigned char end_init_char = 0xc1;
371
372 for (count = 0; count < repeats; count ++) {
373 write_data=s->Device.Functions->WriteDevice(s, &init_char, 1);
374
375 if (write_data != 1) {
376 return ERR_DEVICEWRITEERROR;
377 }
378
379 if (delays > 0) {
380 usleep(delays);
381 }
382 }
383
384 if (terminate) {
385 write_data=s->Device.Functions->WriteDevice(s, &end_init_char, 1);
386
387 if (write_data != 1) {
388 return ERR_DEVICEWRITEERROR;
389 }
390 }
391 sleep(1);
392 return ERR_NONE;
393 }
394
FBUS2_Initialise(GSM_StateMachine * s)395 static GSM_Error FBUS2_Initialise(GSM_StateMachine *s)
396 {
397 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
398 GSM_Device_Functions *Device = s->Device.Functions;
399 GSM_Error error;
400 unsigned char buff[300]={0};
401
402 d->Msg.Length = 0;
403 d->Msg.Buffer = NULL;
404 d->MultiMsg.BufferUsed = 0;
405 d->MultiMsg.Length = 0;
406 d->MultiMsg.Buffer = NULL;
407
408 d->MsgSequenceNumber = 0;
409 d->FramesToGo = 0;
410 d->MsgRXState = RX_Sync;
411
412 error = Device->DeviceSetParity(s, FALSE);
413 if (error != ERR_NONE) return error;
414
415 switch (s->ConnectionType) {
416 #if defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2BLUE)
417 case GCT_FBUS2BLUE:
418 case GCT_BLUEFBUS2:
419 error = FBUS2_ATSwitch(s);
420 if (error != ERR_NONE) return error;
421 break;
422 #endif
423 #if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_DKU5FBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
424 case GCT_DKU5FBUS2:
425 case GCT_FBUS2PL2303:
426 case GCT_FBUS2DLR3:
427 error = Device->DeviceSetDtrRts(s,FALSE,FALSE);
428 if (error != ERR_NONE) return error;
429 sleep(1);
430
431 if (! s->NoPowerCable) {
432 error = Device->DeviceSetDtrRts(s,TRUE,TRUE);
433 if (error != ERR_NONE) return error;
434 sleep(1);
435 }
436
437 error = Device->DeviceSetSpeed(s,19200);
438 if (error != ERR_NONE) return error;
439
440 error = FBUS2_ATSwitch(s);
441 if (error != ERR_NONE) return error;
442
443 error = Device->DeviceSetSpeed(s,115200);
444 if (error != ERR_NONE) return error;
445
446 error = FBUS2_InitSequence(s, 32, 0, TRUE);
447 if (error != ERR_NONE) return error;
448
449 break;
450 #endif
451 case GCT_FBUS2:
452 error = Device->DeviceSetSpeed(s,115200);
453 if (error != ERR_NONE) return error;
454
455 /* Set DTR as power supply if needed, RTS is always low */
456 error = Device->DeviceSetDtrRts(s, !(s->NoPowerCable), FALSE);
457 if (error != ERR_NONE) return error;
458
459 error = FBUS2_InitSequence(s, 32, 0, TRUE);
460 if (error != ERR_NONE) return error;
461
462 break;
463 #ifdef GSM_ENABLE_FBUS2IRDA
464 case GCT_FBUS2IRDA:
465 error = Device->DeviceSetSpeed(s,9600);
466 if (error != ERR_NONE) return error;
467
468 error = FBUS2_InitSequence(s, 32, 0, TRUE);
469 if (error != ERR_NONE) return error;
470
471 error = Device->DeviceSetSpeed(s,115200);
472 if (error != ERR_NONE) return error;
473
474 break;
475 #endif
476 default:
477 break;
478 }
479
480 /* A bit more of synchronisation could be needed here */
481 if (s->ConnectionType != GCT_FBUS2BLUE && s->ConnectionType != GCT_BLUEFBUS2) {
482 error = FBUS2_InitSequence(s, 250, 100, FALSE);
483 if (error != ERR_NONE) return error;
484 }
485
486 /* Read any possible junk on the line */
487 while (s->Device.Functions->ReadDevice(s, buff, sizeof(buff)) > 0) {
488 usleep(1000);
489 }
490
491 return ERR_NONE;
492 }
493
FBUS2_Terminate(GSM_StateMachine * s)494 static GSM_Error FBUS2_Terminate(GSM_StateMachine *s)
495 {
496 free(s->Protocol.Data.FBUS2.Msg.Buffer);
497 s->Protocol.Data.FBUS2.Msg.Buffer = NULL;
498 free(s->Protocol.Data.FBUS2.MultiMsg.Buffer);
499 s->Protocol.Data.FBUS2.MultiMsg.Buffer = NULL;
500 sleep(2);
501 return ERR_NONE;
502 }
503
504 GSM_Protocol_Functions FBUS2Protocol = {
505 FBUS2_WriteMessage,
506 FBUS2_StateMachine,
507 FBUS2_Initialise,
508 FBUS2_Terminate
509 };
510
511 #endif
512
513 /* How should editor hadle tabs in this file? Add editor commands here.
514 * vim: noexpandtab sw=8 ts=8 sts=8:
515 */
516