1 /* (c) 2001-2003 by Marcin Wiacek */
2 /* based on some work from MyGnokii (www.mwiacek.com) */
3 
4 #include "../../gsmstate.h"
5 
6 #ifdef GSM_ENABLE_MBUS2
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 
12 #include "../../gsmcomon.h"
13 #include "mbus2.h"
14 
MBUS2_WriteMessage(GSM_StateMachine * s,unsigned const char * MsgBuffer,size_t MsgLength,int MsgType)15 static GSM_Error MBUS2_WriteMessage (GSM_StateMachine 	*s,
16 				     unsigned const char 	*MsgBuffer,
17 				     size_t	MsgLength,
18 				     int 	MsgType)
19 {
20 	unsigned char 			*buffer=NULL, checksum = 0;
21 	GSM_Protocol_MBUS2Data 		*d = &s->Protocol.Data.MBUS2;
22 	int 				i=0, sent=0, length=0;
23 
24 	GSM_DumpMessageBinary(s, MsgBuffer, MsgLength, MsgType);
25 
26 	buffer = (unsigned char *)malloc(MsgLength + 8);
27 
28 	buffer[0] = MBUS2_FRAME_ID;
29 	buffer[1] = MBUS2_DEVICE_PHONE;		/*  destination */
30 	buffer[2] = MBUS2_DEVICE_PC;    		/*  source */
31 	buffer[3] = MsgType;
32 	buffer[4] = MsgLength / 256;
33 	buffer[5] = MsgLength % 256;
34 
35 	memcpy(buffer + 6, MsgBuffer, MsgLength);
36 	length = 6 + MsgLength;
37 
38 	/* According to http://www.flosys.com/tdma/n5160.html some phones
39          * can have problems with checksum equal 0x1F. Phones can recognize
40          * received frame, but won't send ACK for it. When checksum is 0x1F,
41          * we increment the sequence number
42          */
43 	do {
44 		d->MsgSequenceNumber++;
45 
46 		buffer[length] = d->MsgSequenceNumber;
47 
48 		/* Calculating checksum */
49 		checksum = 0;
50 
51 		for (i = 0; i < length + 1; i++) {
52 			checksum ^= buffer[i];
53 		}
54 	} while (checksum == 0x1f);
55 
56 	buffer[length++] = d->MsgSequenceNumber;
57 	buffer[length++] = checksum;
58 
59 	GSM_DumpMessageText(s, buffer+6, MsgLength, MsgType);
60 
61 	/* Sending to phone */
62 	sent=s->Device.Functions->WriteDevice(s,buffer,length);
63 	free(buffer);
64 	buffer=NULL;
65 
66 	if (sent!=length) {
67 		return ERR_DEVICEWRITEERROR;
68 	}
69 	return ERR_NONE;
70 }
71 
MBUS2_SendAck(GSM_StateMachine * s,unsigned char type,unsigned char sequence)72 static GSM_Error MBUS2_SendAck(GSM_StateMachine 	*s,
73 			       unsigned char 		type,
74 			       unsigned char 		sequence)
75 {
76 	GSM_Device_Functions 	*Device		= s->Device.Functions;
77 	unsigned char 		buffer[6]={0};
78 	int 			i=0,length=0,write_data=0;
79 
80 	buffer[0] = MBUS2_FRAME_ID;
81 	buffer[1] = MBUS2_DEVICE_PHONE;	/* destination */
82 	buffer[2] = MBUS2_DEVICE_PC;		/* source */
83 	buffer[3] = MBUS2_ACK_BYTE;
84 	buffer[4] = sequence;
85 	buffer[5] = '\0';
86 	length=strlen(buffer);
87 
88 	/* Calculating checksum */
89 	for (i = 0; i < length; i++) {
90 		buffer[5] ^= buffer[i];
91 	}
92 	smprintf_level(s, D_TEXT, "[Sending Ack of type %02x, seq: %x]\n",type,sequence);
93 
94 	/* Sending to phone */
95 	write_data=Device->WriteDevice(s,buffer,length);
96 
97 	if (write_data!=length) {
98 		return ERR_DEVICEWRITEERROR;
99 	}
100 	return ERR_NONE;
101 }
102 
MBUS2_StateMachine(GSM_StateMachine * s,unsigned char rx_char)103 static GSM_Error MBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
104 {
105 	GSM_Phone_Functions 	*Phone	= s->Phone.Functions;
106 	GSM_Protocol_MBUS2Data 	*d	= &s->Protocol.Data.MBUS2;
107 
108 	d->Msg.CheckSum[0] = d->Msg.CheckSum[1];
109 	d->Msg.CheckSum[1] ^= rx_char;
110 
111 	if (d->MsgRXState == RX_GetMessage) {
112 		d->Msg.Buffer[d->Msg.Count] = rx_char;
113 		d->Msg.Count++;
114 
115 		/* This is not last byte in frame */
116 		if (d->Msg.Count != d->Msg.Length+2) return ERR_NONE;
117 
118 		/* Checksum is incorrect */
119 		if (d->Msg.CheckSum[0] != rx_char) {
120 			smprintf_level(s, D_ERROR, "[ERROR: checksum]\n");
121 
122 			d->MsgRXState = RX_Sync;
123 			return ERR_NONE;
124 		}
125 
126 		if (d->Msg.Destination != MBUS2_DEVICE_PHONE) {
127 			MBUS2_SendAck(s, d->Msg.Type, d->Msg.Buffer[d->Msg.Count-2]);
128 			s->Phone.Data.RequestMsg	= &d->Msg;
129 			s->Phone.Data.DispatchError	= Phone->DispatchMessage(s);
130 		}
131 
132 		d->MsgRXState = RX_Sync;
133 		return ERR_NONE;
134 	}
135 	if (d->MsgRXState == RX_GetLength2) {
136 		if (d->Msg.Type == MBUS2_ACK_BYTE) {
137 			smprintf_level(s, D_TEXT, "[Received Ack]\n");
138 
139 			d->MsgRXState = RX_Sync;
140 			return ERR_NONE;
141 		}
142 
143 		d->Msg.Length = d->Msg.Length + rx_char;
144 		if (d->Msg.BufferUsed < d->Msg.Length+2) {
145 			d->Msg.BufferUsed 	= d->Msg.Length+2;
146 			d->Msg.Buffer 		= (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
147 		}
148 
149 		d->MsgRXState = RX_GetMessage;
150 		return ERR_NONE;
151 	}
152 	if (d->MsgRXState == RX_GetLength1) {
153 		d->Msg.Length = rx_char * 256;
154 
155 		d->MsgRXState = RX_GetLength2;
156 		return ERR_NONE;
157 	}
158 	if (d->MsgRXState == RX_GetType) {
159 		d->Msg.Type   = rx_char;
160 
161 		d->MsgRXState = RX_GetLength1;
162 		return ERR_NONE;
163 	}
164 	if (d->MsgRXState == RX_GetSource) {
165 		if (rx_char != MBUS2_DEVICE_PHONE && rx_char != MBUS2_DEVICE_PC) {
166 			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x and %02x]\n",
167 					rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
168 			d->MsgRXState = RX_Sync;
169 			return ERR_NONE;
170 		}
171 		d->Msg.Source = rx_char;
172 
173 		d->MsgRXState = RX_GetType;
174 		return ERR_NONE;
175 	}
176 	if (d->MsgRXState == RX_GetDestination) {
177 		if (rx_char != MBUS2_DEVICE_PC && rx_char != MBUS2_DEVICE_PHONE) {
178 			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x and %02x]\n",
179 					rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
180 			d->MsgRXState = RX_Sync;
181 			return ERR_NONE;
182 		}
183 		d->Msg.Destination 	= rx_char;
184 
185 		d->MsgRXState 		= RX_GetSource;
186 		return ERR_NONE;
187 	}
188 	if (d->MsgRXState == RX_Sync) {
189 		if (rx_char != MBUS2_FRAME_ID) {
190 			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
191 					rx_char, MBUS2_FRAME_ID);
192 			return ERR_NONE;
193 		}
194 		d->Msg.CheckSum[1] 	= MBUS2_FRAME_ID;
195 		d->Msg.Count 		= 0;
196 
197 		d->MsgRXState 		= RX_GetDestination;
198 		return ERR_NONE;
199 	}
200 	return ERR_NONE;
201 }
202 
MBUS2_Initialise(GSM_StateMachine * s)203 static GSM_Error MBUS2_Initialise(GSM_StateMachine *s)
204 {
205 	GSM_Device_Functions 	*Device	= s->Device.Functions;
206 	GSM_Protocol_MBUS2Data 	*d	= &s->Protocol.Data.MBUS2;
207 	GSM_Error 		error;
208 
209 	d->Msg.Length		= 0;
210 	d->Msg.BufferUsed	= 0;
211 	d->Msg.Buffer		= NULL;
212 
213 	d->MsgSequenceNumber	= 0;
214 	d->MsgRXState		= RX_Sync;
215 
216 	error=Device->DeviceSetSpeed(s,9600);
217 	if (error!=ERR_NONE) return error;
218 
219 	error=Device->DeviceSetParity(s,TRUE);
220 	if (error!=ERR_NONE) return error;
221 
222 	error=Device->DeviceSetDtrRts(s,FALSE,TRUE); /*DTR low,RTS high*/
223 	if (error!=ERR_NONE) return error;
224         usleep(200000);
225 
226 	return ERR_NONE;
227 }
228 
MBUS2_Terminate(GSM_StateMachine * s)229 static GSM_Error MBUS2_Terminate(GSM_StateMachine *s)
230 {
231 	free(s->Protocol.Data.MBUS2.Msg.Buffer);
232 	s->Protocol.Data.MBUS2.Msg.Buffer=NULL;
233 	return ERR_NONE;
234 }
235 
236 GSM_Protocol_Functions MBUS2Protocol = {
237 	MBUS2_WriteMessage,
238 	MBUS2_StateMachine,
239 	MBUS2_Initialise,
240 	MBUS2_Terminate
241 };
242 
243 #endif
244 
245 /* How should editor hadle tabs in this file? Add editor commands here.
246  * vim: noexpandtab sw=8 ts=8 sts=8:
247  */
248