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