Gammu internals  1.38.0
alcabus.c
Go to the documentation of this file.
1 /* (c) 2002-2003 by Michal Cihar
2  *
3  * Low level functions for communication with Alcatel One Touch phones.
4  *
5  * This code implements the protocol used for synchronisation with PC.
6  */
7 #include "../../gsmstate.h"
8 
9 #if defined(GSM_ENABLE_ALCABUS)
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 
15 #include "../../gsmcomon.h"
16 #include "alcabus.h"
17 
18 static GSM_Error ALCABUS_WriteMessage (GSM_StateMachine *s, unsigned const char *data, int len, int type)
19 {
20  GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
21  unsigned char buffer[1024];
22  int size = 0;
23  int sent = 0;
24  int i = 0, checksum = 0;
25 
26  if ((type == 0) && (len == 0)) return ERR_NONE;
27 
28  buffer[0] = ALCATEL_HEADER;
29  buffer[1] = type;
30  switch (type) {
31  case ALCATEL_CONNECT:
32  buffer[2] = 0x0A;
33  buffer[3] = 0x04;
34  buffer[4] = 0x00;
35  size = 5;
37  d->busy = TRUE;
38  break;
39  case ALCATEL_DISCONNECT:
40  size = 2;
42  d->busy = TRUE;
43  break;
44  case ALCATEL_DATA:
45  buffer[2] = d->out_counter;
46 
47  /* Increase outgoing packet counter */
49  else d->out_counter++;
50 
51  buffer[3] = '\0';
52  buffer[4] = len;
53  memcpy(buffer+5, data, len);
54  size = 5 + len;
56  d->busy = TRUE;
57  break;
58  case ALCATEL_ACK:
59  buffer[2] = d->in_counter;
60  if (d->in_counter == 0) d->in_counter = 1;
61  size = 3;
63  break;
64  default:
65  /* In fact, other types probably can came just from mobile... */
66  smprintf(s,"WARNING: Wanted to send some unknown packet (%02X)\n", type);
67  return ERR_NOTIMPLEMENTED;
68  }
69 
70  /* Calculate packet checksum */
71  for (i=0; i<size; i++) checksum ^= buffer[i];
72 
73  buffer[size] = checksum;
74  size ++;
75 
76  GSM_DumpMessageText(s, buffer, size, type);
77  GSM_DumpMessageBinary(s, buffer, size, type);
78 
79  while (sent != size ) {
80  i = s->Device.Functions->WriteDevice(s,buffer + sent, size - sent);
81 
82  if (!i) {
83  return ERR_DEVICEWRITEERROR;
84  }
85  sent += i;
86  }
87 
88  if (type == ALCATEL_CONNECT || type == ALCATEL_DISCONNECT) {
89  /* For connect and disconnect we need a bit larger delay */
90  while (d->busy) {
92  usleep(1000);
93 
94  if (++i == 10) {
95  return ERR_TIMEOUT;
96  }
97  }
98  }
99  return ERR_NONE;
100 }
101 
102 static GSM_Error ALCABUS_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
103 {
104  GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
105  size_t i;
106  int checksum = 0;
107 
108  if (d->Msg.BufferUsed < d->Msg.Length + 1) {
109  d->Msg.BufferUsed = d->Msg.Length + 1;
110  d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
111  }
112 
113  /* Check for header */
114  if ((d->Msg.Length == 0) && (rx_char != ALCATEL_HEADER)) {
115  smprintf(s,"WARNING: Expecting alcatel header (%02X) but got (%02X)\n", ALCATEL_HEADER, rx_char);
116  return ERR_UNKNOWNRESPONSE;
117  /* Check for packet type */
118  } else if (d->Msg.Length == 1){
119  d->Msg.Type = rx_char;
120  /* Was it unexpected packet? */
121  if ((rx_char != d->next_frame) && (rx_char != ALCATEL_CONTROL)) {
122  smprintf(s,"WARNING: Expecting alcatel packet type (%02X) but got (%02X)\n", d->next_frame, rx_char);
123  }
124  /* Determine packet size */
125  switch (rx_char) {
126  case ALCATEL_ACK:
127  d->expected_size = 4;
128  break;
129  case ALCATEL_DATA:
130  /* Packet length is in it's header */
131  d->expected_size = -1;
132  break;
133  case ALCATEL_CONTROL:
134  d->expected_size = 4;
135  break;
136  case ALCATEL_CONNECT_ACK:
137  d->expected_size = 6;
138  break;
140  d->expected_size = 3;
141  break;
142  default:
143  smprintf(s,"WARNING: Something went wrong, unknown packet received (%02X)\n", rx_char);
144  return ERR_UNKNOWNRESPONSE;
145  }
146  /* Check counter, we can probably ignore error here ;-) */
147  } else if ((d->Msg.Length == 2) && (d->Msg.Type == ALCATEL_DATA)) {
148  if (rx_char != d->in_counter) {
149  smprintf(s,"WARNING: Unexpected packet number, ignoring (expected %02X, received %02X)\n", d->in_counter, rx_char);
150  d->in_counter = rx_char;
151  }
152  /* Increase incoming packet counter */
153  if (d->in_counter == ALCATEL_MAX_COUNTER) d->in_counter = 0;
154  else d->in_counter++;
155  /* Read size for data packet */
156  } else if ((d->Msg.Length == 4) && (d->Msg.Type == ALCATEL_DATA)) {
157  /* Header till now + checksum */
158  d->expected_size = (int)rx_char + 6;
159  }
160 
161  /* Write received byte into buffer */
162  d->Msg.Buffer[d->Msg.Length++] = rx_char;
163 
164  /* Did we received whole packet? */
165  if (d->expected_size == d->Msg.Length) {
166  /* Check checksum */
167  for (i=0; i< (d->Msg.Length - 1); i++) checksum ^= d->Msg.Buffer[i];
168  if (checksum != d->Msg.Buffer[d->Msg.Length - 1]) {
169  /* We can only warn, as we don't know what should happend now... */
170  smprintf(s,"WARNING: Ignoring incorrect packet checksum!\n");
171  }
172 
173  /* Was it data? */
174  if (d->Msg.Type == ALCATEL_DATA) {
175  /* Dispatch message */
176  s->Phone.Data.RequestMsg = &d->Msg;
178  /* Send ack */
179  ALCABUS_WriteMessage (s, 0, 0, ALCATEL_ACK);
180  /* Reset message length */
181  d->Msg.Length = 0;
182  /* Was it ack? */
183  } else if ((d->Msg.Type == ALCATEL_ACK) ||
184  (d->Msg.Type == ALCATEL_CONTROL) ||
185  (d->Msg.Type == ALCATEL_CONNECT_ACK) ||
186  (d->Msg.Type == ALCATEL_DISCONNECT_ACK)) {
187  /* TODO: check counter of ack? */
188  if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
189  s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
190  smprintf(s, "Received %s ack ",
191  (d->Msg.Type == ALCATEL_ACK) ? "normal" :
192  (d->Msg.Type == ALCATEL_CONTROL) ? "control" :
193  (d->Msg.Type == ALCATEL_CONNECT_ACK) ? "connect" :
194  (d->Msg.Type == ALCATEL_DISCONNECT_ACK) ? "disconnect" :
195  "BUG");
196  smprintf(s, "0x%02x / 0x%04lX", d->Msg.Type, (long)d->Msg.Length);
197  DumpMessage(&s->di, d->Msg.Buffer, d->Msg.Length);
198  }
199  if (s->di.dl==DL_BINARY) {
200  smprintf(s,"%c",0x02); /* Receiving */
201  smprintf(s,"%c",d->Msg.Type);
202  smprintf(s,"%c",(int)d->Msg.Length/256);
203  smprintf(s,"%c",(int)d->Msg.Length%256);
204  for (i=0;i<d->Msg.Length;i++) smprintf(s,"%c",d->Msg.Buffer[i]);
205  }
206  if (d->Msg.Type != ALCATEL_CONTROL) {
208  d->busy = FALSE;
209  }
210  /* Reset message length */
211  d->Msg.Length = 0;
212  }
213 
214  /* Was it unexpected type? */
215  if ((d->Msg.Type != d->next_frame) && (d->Msg.Type != ALCATEL_CONTROL)) {
216  return ERR_FRAMENOTREQUESTED;
217  }
218  } /* Last byte of packet */
219 
220  return ERR_NONE;
221 }
222 
223 static GSM_Error ALCABUS_Initialise(GSM_StateMachine *s)
224 {
225  GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
226 
227  /* Initialise some variables */
228  d->Msg.BufferUsed = 0;
229  d->Msg.Buffer = NULL;
230  d->Msg.Length = 0;
231  d->Msg.Type = 0;
232  d->in_counter = 1;
233  d->out_counter = 0;
234  d->busy = FALSE;
235 
236  /* Initialise protocol */
237  smprintf(s, "Initializing binary mode\n");
238  return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_CONNECT);
239 }
240 
241 static GSM_Error ALCABUS_Terminate(GSM_StateMachine *s)
242 {
243  /* Terminate protocol */
244  smprintf(s, "Closing binary mode\n");
245  return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_DISCONNECT);
246 }
247 
248 GSM_Protocol_Functions ALCABUSProtocol = {
249  ALCABUS_WriteMessage,
250  ALCABUS_StateMachine,
251  ALCABUS_Initialise,
252  ALCABUS_Terminate
253 };
254 
255 #endif
256 
257 /* How should editor hadle tabs in this file? Add editor commands here.
258  * vim: noexpandtab sw=8 ts=8 sts=8:
259  */
void GSM_DumpMessageBinary(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
Definition: gsmstate.c:1583
void DumpMessage(GSM_Debug_Info *d, const unsigned char *message, const size_t messagesize)
Definition: debug.c:314
GSM_Protocol_Message Msg
Definition: alcabus.h:39
struct GSM_Protocol::@1 Data
#define ALCATEL_DISCONNECT_ACK
Definition: alcabus.h:25
#define ALCATEL_CONNECT
Definition: alcabus.h:19
Definition: debug.h:26
GSM_Error
Definition: gammu-error.h:23
GSM_Error DispatchError
Definition: gsmstate.h:689
GSM_Debug_Info di
Definition: gsmstate.h:1412
int GSM_ReadDevice(GSM_StateMachine *s, gboolean waitforreply)
Definition: gsmstate.c:919
#define ALCATEL_DATA
Definition: alcabus.h:31
int(* WriteDevice)(GSM_StateMachine *s, const void *buf, size_t nbytes)
Definition: gsmstate.h:256
GSM_Phone Phone
Definition: gsmstate.h:1431
#define FALSE
Definition: gammu-types.h:25
#define ALCATEL_DISCONNECT
Definition: alcabus.h:23
GSM_Device_Functions * Functions
Definition: gsmstate.h:335
GSM_Protocol Protocol
Definition: gsmstate.h:1430
GSM_Phone_Data Data
Definition: gsmstate.h:1369
unsigned char next_frame
Definition: alcabus.h:47
GSM_Phone_Functions * Functions
Definition: gsmstate.h:1373
#define ALCATEL_CONTROL
Definition: alcabus.h:29
GSM_Error(* DispatchMessage)(GSM_StateMachine *s)
Definition: gsmstate.h:765
#define ALCATEL_MAX_COUNTER
Definition: alcabus.h:36
#define TRUE
Definition: gammu-types.h:28
unsigned char * Buffer
Definition: protocol.h:22
Debug_Level dl
Definition: debug.h:35
GSM_Protocol_Message * RequestMsg
Definition: gsmstate.h:676
#define ALCATEL_CONNECT_ACK
Definition: alcabus.h:21
void GSM_DumpMessageText(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
Definition: gsmstate.c:1555
GSM_Device Device
Definition: gsmstate.h:1429
#define ALCATEL_ACK
Definition: alcabus.h:33
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261
#define ALCATEL_HEADER
Definition: alcabus.h:13