Imported gammu 0.90.7
[gammu.git] / common / protocol / alcatel / alcabus.c
blob1a41c7a9f4ea53a0ce6d793ff05b3c0a87a7435a
1 /*
2 * Low level functions for communication with Alcatel One Touch phones.
4 * This code implements the protocol used for synchronisation with PC.
5 */
6 #include "../../gsmstate.h"
8 #if defined(GSM_ENABLE_ALCABUS)
10 #include <stdio.h>
11 #include <string.h>
13 #include "../../gsmcomon.h"
14 #include "alcabus.h"
16 static GSM_Error ALCABUS_WriteMessage (GSM_StateMachine *s, unsigned char *data, int len, unsigned char type)
18 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
19 unsigned char buffer[1024];
20 int size = 0;
21 int sent = 0;
22 int i = 0, checksum = 0;
24 if ((type == 0) && (len == 0)) return GE_NONE;
26 buffer[0] = ALCATEL_HEADER;
27 buffer[1] = type;
28 switch (type) {
29 case ALCATEL_CONNECT:
30 buffer[2] = 0x0A;
31 buffer[3] = 0x04;
32 buffer[4] = 0x00;
33 size = 5;
34 d->next_frame = ALCATEL_CONNECT_ACK;
35 d->busy = true;
36 break;
37 case ALCATEL_DISCONNECT:
38 size = 2;
39 d->next_frame = ALCATEL_DISCONNECT_ACK;
40 d->busy = true;
41 break;
42 case ALCATEL_DATA:
43 buffer[2] = d->out_counter;
45 /* Increase outgoing packet counter */
46 if (d->out_counter == ALCATEL_MAX_COUNTER) d->out_counter = 0;
47 else d->out_counter++;
49 buffer[3] = '\0';
50 buffer[4] = len;
51 memcpy(buffer+5, data, len);
52 size = 5 + len;
53 d->next_frame = ALCATEL_ACK;
54 d->busy = true;
55 break;
56 case ALCATEL_ACK:
57 buffer[2] = d->in_counter;
58 if (d->in_counter == 0) d->in_counter = 1;
59 size = 3;
60 d->next_frame = ALCATEL_DATA;
61 break;
62 default:
63 /* In fact, other types probably can came just from mobile... */
64 smprintf(s,"WARNING: Wanted to send some unknown packet (%02X)\n", type);
65 return GE_NOTIMPLEMENTED;
68 /* Calculate packet checksum */
69 for (i=0; i<size; i++) checksum ^= buffer[i];
71 buffer[size] = checksum;
72 size ++;
74 GSM_DumpMessageLevel2(s, buffer, size, type);
75 GSM_DumpMessageLevel3(s, buffer, size, type);
76 while (sent != size ) {
77 if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, size - sent)) == 0) {
78 return GE_DEVICEWRITEERROR;
80 sent += i;
83 if (type == ALCATEL_CONNECT || type == ALCATEL_DISCONNECT) {
84 /* For connect and disconnect we need a bit larger delay */
85 // my_sleep(10);
86 while (d->busy) {
87 GSM_ReadDevice(s,true);
88 my_sleep(1);
89 i++;
90 if (i == 10) return GE_TIMEOUT;
93 return GE_NONE;
96 static GSM_Error ALCABUS_StateMachine(GSM_StateMachine *s, unsigned char rx_byte)
98 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
99 int i;
100 int checksum = 0;
102 if (d->Msg.BufferUsed < d->Msg.Length + 1) {
103 d->Msg.BufferUsed = d->Msg.Length + 1;
104 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
107 /* Check for header */
108 if ((d->Msg.Length == 0) && (rx_byte != ALCATEL_HEADER)) {
109 smprintf(s,"WARNING: Expecting alcatel header (%02X) but got (%02X)\n", ALCATEL_HEADER, rx_byte);
110 return GE_UNKNOWNRESPONSE;
111 /* Check for packet type */
112 } else if (d->Msg.Length == 1){
113 d->Msg.Type = rx_byte;
114 /* Was it unexpected packet? */
115 if ((rx_byte != d->next_frame) && (rx_byte != ALCATEL_CONTROL)) {
116 smprintf(s,"WARNING: Expecting alcatel packet type (%02X) but got (%02X)\n", d->next_frame, rx_byte);
118 /* Determine packet size */
119 switch (rx_byte) {
120 case ALCATEL_ACK:
121 d->expected_size = 4;
122 break;
123 case ALCATEL_DATA:
124 /* Packet length is in it's header */
125 d->expected_size = -1;
126 break;
127 case ALCATEL_CONTROL:
128 d->expected_size = 4;
129 break;
130 case ALCATEL_CONNECT_ACK:
131 d->expected_size = 6;
132 break;
133 case ALCATEL_DISCONNECT_ACK:
134 d->expected_size = 3;
135 break;
136 default:
137 smprintf(s,"WARNING: Something went wrong, unknown packet received (%02X)\n", rx_byte);
138 return GE_UNKNOWNRESPONSE;
140 /* Check counter, we can probably ignore error here ;-) */
141 } else if ((d->Msg.Length == 2) && (d->Msg.Type == ALCATEL_DATA)) {
142 if (rx_byte != d->in_counter) {
143 smprintf(s,"WARNING: Unexpected packet number, ignoring (expected %02X, received %02X)\n", d->in_counter, rx_byte);
144 d->in_counter = rx_byte;
146 /* Increase incoming packet counter */
147 if (d->in_counter == ALCATEL_MAX_COUNTER) d->in_counter = 0;
148 else d->in_counter++;
149 /* Read size for data packet */
150 } else if ((d->Msg.Length == 4) && (d->Msg.Type == ALCATEL_DATA)) {
151 /* Header till now + checksum */
152 d->expected_size = (int)rx_byte + 6;
155 /* Write received byte into buffer */
156 d->Msg.Buffer[d->Msg.Length++] = rx_byte;
158 /* Did we received whole packet? */
159 if (d->expected_size == d->Msg.Length) {
160 /* Check checksum */
161 for (i=0; i< (d->Msg.Length - 1); i++) checksum ^= d->Msg.Buffer[i];
162 if (checksum != d->Msg.Buffer[d->Msg.Length - 1]) {
163 /* We can only warn, as we don't know what should happend now... */
164 smprintf(s,"WARNING: Ignoring incorrect packet checksum!\n");
167 /* Was it data? */
168 if (d->Msg.Type == ALCATEL_DATA) {
169 /* Dispatch message */
170 s->Phone.Data.RequestMsg = &d->Msg;
171 s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
172 /* Send ack */
173 ALCABUS_WriteMessage (s, 0, 0, ALCATEL_ACK);
174 /* Reset message length */
175 d->Msg.Length = 0;
176 /* Was it ack? */
177 } else if ((d->Msg.Type == ALCATEL_ACK) ||
178 (d->Msg.Type == ALCATEL_CONTROL) ||
179 (d->Msg.Type == ALCATEL_CONNECT_ACK) ||
180 (d->Msg.Type == ALCATEL_DISCONNECT_ACK)) {
181 /* TODO: check counter of ack? */
182 if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
183 s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
184 smprintf(s, "Received %s ack ",
185 (d->Msg.Type == ALCATEL_ACK) ? "normal" :
186 (d->Msg.Type == ALCATEL_CONTROL) ? "control" :
187 (d->Msg.Type == ALCATEL_CONNECT_ACK) ? "connect" :
188 (d->Msg.Type == ALCATEL_DISCONNECT_ACK) ? "disconnect" :
189 "BUG");
190 smprintf(s, "0x%02x / 0x%04x", d->Msg.Type, d->Msg.Length);
191 DumpMessage(s->di.df, d->Msg.Buffer, d->Msg.Length);
192 fflush(s->di.df);
194 if (s->di.dl==DL_BINARY) {
195 smprintf(s,"%c",0x02); /* Receiving */
196 smprintf(s,"%c",d->Msg.Type);
197 smprintf(s,"%c",d->Msg.Length/256);
198 smprintf(s,"%c",d->Msg.Length%256);
199 for (i=0;i<d->Msg.Length;i++) smprintf(s,"%c",d->Msg.Buffer[i]);
201 if (d->Msg.Type != ALCATEL_CONTROL) {
202 d->next_frame = ALCATEL_DATA;
203 d->busy = false;
205 /* Reset message length */
206 d->Msg.Length = 0;
209 /* Was it unexpected type? */
210 if ((d->Msg.Type != d->next_frame) && (d->Msg.Type != ALCATEL_CONTROL)) {
211 return GE_FRAMENOTREQUESTED;
213 } /* Last byte of packet */
215 return GE_NONE;
218 static GSM_Error ALCABUS_Initialise(GSM_StateMachine *s)
220 GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
222 /* Initialise some variables */
223 d->Msg.BufferUsed = 0;
224 d->Msg.Buffer = NULL;
225 d->Msg.Length = 0;
226 d->Msg.Type = 0;
227 d->in_counter = 1;
228 d->out_counter = 0;
229 d->busy = false;
231 /* Initialise protocol */
232 dbgprintf ("Initializing binary mode\n");
233 return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_CONNECT);
236 static GSM_Error ALCABUS_Terminate(GSM_StateMachine *s)
238 /* Terminate protocol */
239 dbgprintf ("Closing binary mode\n");
240 return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_DISCONNECT);
243 GSM_Protocol_Functions ALCABUSProtocol = {
244 ALCABUS_WriteMessage,
245 ALCABUS_StateMachine,
246 ALCABUS_Initialise,
247 ALCABUS_Terminate
250 #endif
252 /* How should editor hadle tabs in this file? Add editor commands here.
253 * vim: noexpandtab sw=8 ts=8 sts=8: