summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/protocol/nokia/fbus2.c
Unidiff
Diffstat (limited to 'gammu/emb/common/protocol/nokia/fbus2.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/protocol/nokia/fbus2.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/gammu/emb/common/protocol/nokia/fbus2.c b/gammu/emb/common/protocol/nokia/fbus2.c
new file mode 100644
index 0000000..8b3e024
--- a/dev/null
+++ b/gammu/emb/common/protocol/nokia/fbus2.c
@@ -0,0 +1,444 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2/* based on some work from Gnokii and MyGnokii */
3
4#include "../../gsmstate.h"
5
6#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303)
7
8#include <stdio.h>
9#include <string.h>
10
11#include "../../gsmcomon.h"
12#include "fbus2.h"
13
14 static GSM_Error FBUS2_WriteFrame(GSM_StateMachine *s,
15 unsigned char *MsgBuffer,
16 int MsgLength,
17 unsigned char MsgType)
18{
19 unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 10];
20 unsigned char checksum=0;
21 int i, len, sent;
22
23 buffer2[0] = FBUS2_FRAME_ID;
24 if (s->ConnectionType==GCT_FBUS2IRDA) buffer2[0] = FBUS2_IRDA_FRAME_ID;
25
26 buffer2[1] = FBUS2_DEVICE_PHONE; //destination
27 buffer2[2] = FBUS2_DEVICE_PC; //source
28 buffer2[3]= MsgType;
29 buffer2[4]= MsgLength / 256;
30 buffer2[5]= MsgLength % 256;
31
32 memcpy(buffer2 + 6, MsgBuffer, MsgLength);
33 len = MsgLength + 6;
34
35 /* Odd messages require additional 0x00 byte */
36 if (MsgLength % 2) buffer2[len++] = 0x00;
37
38 checksum = 0;
39 for (i = 0; i < len; i+=2) checksum ^= buffer2[i];
40 buffer2[len++] = checksum;
41
42 checksum = 0;
43 for (i = 1; i < len; i+=2) checksum ^= buffer2[i];
44 buffer2[len++] = checksum;
45
46 /* Sending to phone */
47 sent=s->Device.Functions->WriteDevice(s,buffer2,len);
48 if (sent!=len) return ERR_DEVICEWRITEERROR;
49
50 return ERR_NONE;
51}
52
53 static GSM_Error FBUS2_WriteMessage (GSM_StateMachine *s,
54 unsigned char *MsgBuffer,
55 int MsgLength,
56 unsigned char MsgType)
57{
58 int i, nom, togo, thislength; /* number of messages, ... */
59 unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 2], seqnum;
60 GSM_Protocol_FBUS2Data*d = &s->Protocol.Data.FBUS2;
61 GSM_Error error;
62
63 GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType);
64
65 nom = (MsgLength + FBUS2_MAX_TRANSMIT_LENGTH - 1) / FBUS2_MAX_TRANSMIT_LENGTH;
66 togo = MsgLength;
67
68 for (i = 0; i < nom; i++) {
69 seqnum = d->MsgSequenceNumber;
70 if (i==0) seqnum = seqnum + 0x40;
71 d->MsgSequenceNumber = (d->MsgSequenceNumber + 1) & 0x07;
72
73 thislength = togo;
74 if (togo > FBUS2_MAX_TRANSMIT_LENGTH) thislength = FBUS2_MAX_TRANSMIT_LENGTH;
75 memcpy(buffer2, MsgBuffer + (MsgLength - togo), thislength);
76 buffer2[thislength]= nom - i;
77 buffer2[thislength + 1]= seqnum;
78 togo = togo - thislength;
79
80 GSM_DumpMessageLevel2(s, buffer2, thislength, MsgType);
81
82 error=FBUS2_WriteFrame(s, buffer2, thislength + 2, MsgType);
83 if (error!=ERR_NONE) return error;
84 }
85
86 return ERR_NONE;
87}
88
89 static GSM_Error FBUS2_SendAck(GSM_StateMachine *s,
90 unsigned char MsgType,
91 unsigned char MsgSequence)
92{
93 unsigned char buffer2[2];
94
95 buffer2[0] = MsgType;
96 buffer2[1] = MsgSequence;
97
98 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
99 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
100 smprintf(s,"[Sending Ack of type %02x, seq %x]\n",buffer2[0],buffer2[1]);
101 }
102
103 /* Sending to phone */
104 return FBUS2_WriteFrame(s, buffer2, 2, FBUS2_ACK_BYTE);
105}
106
107static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
108{
109 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
110 unsigned char frm_num, seq_num;
111 bool correct = false;
112
113 /* XOR the byte with the earlier checksum */
114 d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char;
115
116 if (d->MsgRXState == RX_GetMessage) {
117 d->Msg.Buffer[d->Msg.Count] = rx_char;
118 d->Msg.Count++;
119
120 /* This is not last byte in frame */
121 if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE;
122
123 /* Checksum is incorrect */
124 if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) {
125 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
126 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
127 smprintf(s,"[ERROR: checksum]\n");
128 }
129 free(d->Msg.Buffer);
130 d->Msg.Length = 0;
131 d->Msg.Buffer = NULL;
132
133 d->MsgRXState = RX_Sync;
134 return ERR_NONE;
135 }
136
137 seq_num = d->Msg.Buffer[d->Msg.Length-1];
138
139 if (d->Msg.Type == FBUS2_ACK_BYTE) {
140 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
141 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
142 smprintf(s, "[Received Ack of type %02x, seq %02x]\n",d->Msg.Buffer[0],seq_num);
143 }
144
145 d->MsgRXState = RX_Sync;
146 return ERR_NONE;
147 }
148
149 frm_num = d->Msg.Buffer[d->Msg.Length-2];
150
151 if ((seq_num & 0x40) == 0x40) {
152 d->FramesToGo = frm_num;
153 d->MultiMsg.Length= 0;
154 d->MultiMsg.Type= d->Msg.Type;
155 d->MultiMsg.Destination= d->Msg.Destination;
156 d->MultiMsg.Source= d->Msg.Source;
157 }
158
159 if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) {
160 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
161 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
162 smprintf(s, "[ERROR: Missed part of multiframe msg]\n");
163 }
164
165 free(d->Msg.Buffer);
166 d->Msg.Length = 0;
167 d->Msg.Buffer = NULL;
168
169 d->MsgRXState = RX_Sync;
170 return ERR_NONE;
171 }
172
173 if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) {
174 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
175 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
176 smprintf(s, "[ERROR: Multiframe msg in multiframe msg]\n");
177 }
178
179 free(d->Msg.Buffer);
180 d->Msg.Length = 0;
181 d->Msg.Buffer = NULL;
182
183 d->MsgRXState = RX_Sync;
184 return ERR_NONE;
185 }
186
187 if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) {
188 d->MultiMsg.BufferUsed = d->MultiMsg.Length+d->Msg.Length-2;
189 d->MultiMsg.Buffer = (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed);
190 }
191 memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2);
192 d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2;
193
194 free(d->Msg.Buffer);
195 d->Msg.Length = 0;
196 d->Msg.Buffer = NULL;
197
198 d->FramesToGo--;
199
200 /* do not ack debug trace, as this could generate a
201 * (feedback loop) flood of which even Noah would be scared.
202 */
203 if (d->Msg.Type != 0) {
204 FBUS2_SendAck(s,d->Msg.Type,((unsigned char)(seq_num & 0x0f)));
205 }
206
207 if (d->FramesToGo == 0) {
208 s->Phone.Data.RequestMsg= &d->MultiMsg;
209 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
210 }
211 d->MsgRXState = RX_Sync;
212 return ERR_NONE;
213 }
214 if (d->MsgRXState == RX_GetLength2) {
215 d->Msg.Length = d->Msg.Length + rx_char;
216 d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length+3);
217 d->MsgRXState = RX_GetMessage;
218 return ERR_NONE;
219 }
220 if (d->MsgRXState == RX_GetLength1) {
221 d->Msg.Length = rx_char * 256;
222 d->MsgRXState = RX_GetLength2;
223 return ERR_NONE;
224 }
225 if (d->MsgRXState == RX_GetType) {
226 d->Msg.Type = rx_char;
227 d->MsgRXState = RX_GetLength1;
228 return ERR_NONE;
229 }
230 if (d->MsgRXState == RX_GetSource) {
231 if (rx_char != FBUS2_DEVICE_PHONE) {
232 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
233 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
234 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PHONE);
235 }
236
237 d->MsgRXState = RX_Sync;
238 return ERR_NONE;
239 }
240 d->Msg.Source = rx_char;
241
242 d->MsgRXState = RX_GetType;
243 return ERR_NONE;
244 }
245 if (d->MsgRXState == RX_GetDestination) {
246 if (rx_char != FBUS2_DEVICE_PC) {
247 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
248 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
249 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PC);
250 }
251
252 d->MsgRXState = RX_Sync;
253 return ERR_NONE;
254 }
255 d->Msg.Destination = rx_char;
256
257 d->MsgRXState = RX_GetSource;
258 return ERR_NONE;
259 }
260 if (d->MsgRXState == RX_Sync) {
261 switch (s->ConnectionType) {
262 case GCT_FBUS2:
263 case GCT_FBUS2DLR3:
264 case GCT_FBUS2DKU5:
265 case GCT_FBUS2PL2303:
266 case GCT_FBUS2BLUE:
267 case GCT_BLUEFBUS2:
268 if (rx_char == FBUS2_FRAME_ID) correct = true;
269 break;
270 case GCT_FBUS2IRDA:
271 if (rx_char == FBUS2_IRDA_FRAME_ID) correct = true;
272 break;
273 default:
274 break;
275 }
276 if (!correct) {
277 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR ||
278 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) {
279 if (s->ConnectionType==GCT_FBUS2IRDA) {
280 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_IRDA_FRAME_ID);
281 } else {
282 smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_FRAME_ID);
283 }
284 }
285 return ERR_NONE;
286 }
287
288 d->Msg.CheckSum[0] = rx_char;
289 d->Msg.CheckSum[1] = 0;
290 d->Msg.Count = 0;
291
292 d->MsgRXState = RX_GetDestination;
293 return ERR_NONE;
294 }
295 return ERR_NONE;
296}
297
298#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2PL2303)
299static void FBUS2_WriteDLR3(GSM_StateMachine *s, char *command, int length, int timeout)
300{
301 unsigned char buff[300];
302 int w = 0;
303 bool wassomething = false;
304
305 s->Device.Functions->WriteDevice(s,command,length);
306
307 for (w=0;w<timeout;w++) {
308 if (wassomething) {
309 if (s->Device.Functions->ReadDevice(s, buff, 255)==0) return;
310 } else {
311 if (s->Device.Functions->ReadDevice(s, buff, 255)>0) wassomething = true;
312 }
313 my_sleep(50);
314 }
315}
316#endif
317
318static GSM_Error FBUS2_Initialise(GSM_StateMachine *s)
319{
320 unsigned char init_char= 0x55;
321#ifdef GSM_ENABLE_FBUS2IRDA
322 unsigned char end_init_char= 0xc1;
323#endif
324
325 GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2;
326 GSM_Device_Functions *Device = s->Device.Functions;
327 GSM_Error error;
328 int count;
329
330 d->Msg.Length = 0;
331 d->Msg.Buffer = NULL;
332 d->MultiMsg.BufferUsed= 0;
333 d->MultiMsg.Length= 0;
334 d->MultiMsg.Buffer= NULL;
335
336 d->MsgSequenceNumber= 0;
337 d->FramesToGo = 0;
338 d->MsgRXState = RX_Sync;
339
340 error=Device->DeviceSetParity(s,false);
341 if (error!=ERR_NONE) return error;
342
343 switch (s->ConnectionType) {
344#if defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2BLUE)
345 case GCT_FBUS2BLUE:
346 case GCT_BLUEFBUS2:
347 FBUS2_WriteDLR3(s,"AT\r\n", 4,10);
348 FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10);
349 FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n",14,10);
350 break;
351#endif
352#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303)
353 case GCT_FBUS2DKU5:
354 case GCT_FBUS2PL2303:
355 case GCT_FBUS2DLR3:
356 error=Device->DeviceSetDtrRts(s,false,false);
357 if (error!=ERR_NONE) return error;
358 my_sleep(1000);
359
360 error=Device->DeviceSetDtrRts(s,true,true);
361 if (error!=ERR_NONE) return error;
362 error=Device->DeviceSetSpeed(s,19200);
363 if (error!=ERR_NONE) return error;
364
365 FBUS2_WriteDLR3(s,"AT\r\n", 4,10);
366 FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10);
367 FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n",14,10);
368
369 error=Device->CloseDevice(s);
370 if (error!=ERR_NONE) return error;
371 my_sleep(1000);
372
373 error=Device->OpenDevice(s);
374 if (error!=ERR_NONE) return error;
375 error=Device->DeviceSetParity(s,false);
376 if (error!=ERR_NONE) return error;
377 error=Device->DeviceSetSpeed(s,115200);
378 if (error!=ERR_NONE) return error;
379 error=Device->DeviceSetDtrRts(s,false,false);
380 if (error!=ERR_NONE) return error;
381
382 for (count = 0; count < 55; count ++) {
383 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
384 }
385 break;
386#endif
387 case GCT_FBUS2:
388 error=Device->DeviceSetSpeed(s,115200);
389 if (error!=ERR_NONE) return error;
390
391 error=Device->DeviceSetDtrRts(s,true,false); /*DTR high,RTS low*/
392 if (error!=ERR_NONE) return error;
393
394 for (count = 0; count < 55; count ++) {
395 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
396 my_sleep(10);
397 }
398 break;
399#ifdef GSM_ENABLE_FBUS2IRDA
400 case GCT_FBUS2IRDA:
401 error=Device->DeviceSetSpeed(s,9600);
402 if (error!=ERR_NONE) return error;
403
404 for (count = 0; count < 55; count ++) {
405 if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR;
406 my_sleep(10);
407 }
408
409 if (Device->WriteDevice(s,&end_init_char,1)!=1) return ERR_DEVICEWRITEERROR;
410 my_sleep(20);
411
412 error=Device->DeviceSetSpeed(s,115200);
413 if (error!=ERR_NONE) return error;
414
415 break;
416#endif
417 default:
418 break;
419 }
420
421 return ERR_NONE;
422}
423
424static GSM_Error FBUS2_Terminate(GSM_StateMachine *s)
425{
426 free(s->Protocol.Data.FBUS2.Msg.Buffer);
427 free(s->Protocol.Data.FBUS2.MultiMsg.Buffer);
428
429 my_sleep(200);
430 return ERR_NONE;
431}
432
433GSM_Protocol_Functions FBUS2Protocol = {
434 FBUS2_WriteMessage,
435 FBUS2_StateMachine,
436 FBUS2_Initialise,
437 FBUS2_Terminate
438};
439
440#endif
441
442/* How should editor hadle tabs in this file? Add editor commands here.
443 * vim: noexpandtab sw=8 ts=8 sts=8:
444 */