summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/protocol/alcatel/alcabus.c
Side-by-side diff
Diffstat (limited to 'gammu/emb/common/protocol/alcatel/alcabus.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/protocol/alcatel/alcabus.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/gammu/emb/common/protocol/alcatel/alcabus.c b/gammu/emb/common/protocol/alcatel/alcabus.c
new file mode 100644
index 0000000..b5b5a30
--- a/dev/null
+++ b/gammu/emb/common/protocol/alcatel/alcabus.c
@@ -0,0 +1,255 @@
+/* (c) 2002-2003 by Michal Cihar
+ *
+ * Low level functions for communication with Alcatel One Touch phones.
+ *
+ * This code implements the protocol used for synchronisation with PC.
+ */
+#include "../../gsmstate.h"
+
+#if defined(GSM_ENABLE_ALCABUS)
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../gsmcomon.h"
+#include "alcabus.h"
+
+static GSM_Error ALCABUS_WriteMessage (GSM_StateMachine *s, unsigned char *data, int len, unsigned char type)
+{
+ GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
+ unsigned char buffer[1024];
+ int size = 0;
+ int sent = 0;
+ int i = 0, checksum = 0;
+
+ if ((type == 0) && (len == 0)) return ERR_NONE;
+
+ buffer[0] = ALCATEL_HEADER;
+ buffer[1] = type;
+ switch (type) {
+ case ALCATEL_CONNECT:
+ buffer[2] = 0x0A;
+ buffer[3] = 0x04;
+ buffer[4] = 0x00;
+ size = 5;
+ d->next_frame = ALCATEL_CONNECT_ACK;
+ d->busy = true;
+ break;
+ case ALCATEL_DISCONNECT:
+ size = 2;
+ d->next_frame = ALCATEL_DISCONNECT_ACK;
+ d->busy = true;
+ break;
+ case ALCATEL_DATA:
+ buffer[2] = d->out_counter;
+
+ /* Increase outgoing packet counter */
+ if (d->out_counter == ALCATEL_MAX_COUNTER) d->out_counter = 0;
+ else d->out_counter++;
+
+ buffer[3] = '\0';
+ buffer[4] = len;
+ memcpy(buffer+5, data, len);
+ size = 5 + len;
+ d->next_frame = ALCATEL_ACK;
+ d->busy = true;
+ break;
+ case ALCATEL_ACK:
+ buffer[2] = d->in_counter;
+ if (d->in_counter == 0) d->in_counter = 1;
+ size = 3;
+ d->next_frame = ALCATEL_DATA;
+ break;
+ default:
+ /* In fact, other types probably can came just from mobile... */
+ smprintf(s,"WARNING: Wanted to send some unknown packet (%02X)\n", type);
+ return ERR_NOTIMPLEMENTED;
+ }
+
+ /* Calculate packet checksum */
+ for (i=0; i<size; i++) checksum ^= buffer[i];
+
+ buffer[size] = checksum;
+ size ++;
+
+ GSM_DumpMessageLevel2(s, buffer, size, type);
+ GSM_DumpMessageLevel3(s, buffer, size, type);
+ while (sent != size ) {
+ if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, size - sent)) == 0) {
+ return ERR_DEVICEWRITEERROR;
+ }
+ sent += i;
+ }
+
+ if (type == ALCATEL_CONNECT || type == ALCATEL_DISCONNECT) {
+ /* For connect and disconnect we need a bit larger delay */
+// my_sleep(10);
+ while (d->busy) {
+ GSM_ReadDevice(s,true);
+ my_sleep(1);
+ i++;
+ if (i == 10) return ERR_TIMEOUT;
+ }
+ }
+ return ERR_NONE;
+}
+
+static GSM_Error ALCABUS_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
+{
+ GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
+ int i;
+ int checksum = 0;
+
+ if (d->Msg.BufferUsed < d->Msg.Length + 1) {
+ d->Msg.BufferUsed = d->Msg.Length + 1;
+ d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
+ }
+
+ /* Check for header */
+ if ((d->Msg.Length == 0) && (rx_char != ALCATEL_HEADER)) {
+ smprintf(s,"WARNING: Expecting alcatel header (%02X) but got (%02X)\n", ALCATEL_HEADER, rx_char);
+ return ERR_UNKNOWNRESPONSE;
+ /* Check for packet type */
+ } else if (d->Msg.Length == 1){
+ d->Msg.Type = rx_char;
+ /* Was it unexpected packet? */
+ if ((rx_char != d->next_frame) && (rx_char != ALCATEL_CONTROL)) {
+ smprintf(s,"WARNING: Expecting alcatel packet type (%02X) but got (%02X)\n", d->next_frame, rx_char);
+ }
+ /* Determine packet size */
+ switch (rx_char) {
+ case ALCATEL_ACK:
+ d->expected_size = 4;
+ break;
+ case ALCATEL_DATA:
+ /* Packet length is in it's header */
+ d->expected_size = -1;
+ break;
+ case ALCATEL_CONTROL:
+ d->expected_size = 4;
+ break;
+ case ALCATEL_CONNECT_ACK:
+ d->expected_size = 6;
+ break;
+ case ALCATEL_DISCONNECT_ACK:
+ d->expected_size = 3;
+ break;
+ default:
+ smprintf(s,"WARNING: Something went wrong, unknown packet received (%02X)\n", rx_char);
+ return ERR_UNKNOWNRESPONSE;
+ }
+ /* Check counter, we can probably ignore error here ;-) */
+ } else if ((d->Msg.Length == 2) && (d->Msg.Type == ALCATEL_DATA)) {
+ if (rx_char != d->in_counter) {
+ smprintf(s,"WARNING: Unexpected packet number, ignoring (expected %02X, received %02X)\n", d->in_counter, rx_char);
+ d->in_counter = rx_char;
+ }
+ /* Increase incoming packet counter */
+ if (d->in_counter == ALCATEL_MAX_COUNTER) d->in_counter = 0;
+ else d->in_counter++;
+ /* Read size for data packet */
+ } else if ((d->Msg.Length == 4) && (d->Msg.Type == ALCATEL_DATA)) {
+ /* Header till now + checksum */
+ d->expected_size = (int)rx_char + 6;
+ }
+
+ /* Write received byte into buffer */
+ d->Msg.Buffer[d->Msg.Length++] = rx_char;
+
+ /* Did we received whole packet? */
+ if (d->expected_size == d->Msg.Length) {
+ /* Check checksum */
+ for (i=0; i< (d->Msg.Length - 1); i++) checksum ^= d->Msg.Buffer[i];
+ if (checksum != d->Msg.Buffer[d->Msg.Length - 1]) {
+ /* We can only warn, as we don't know what should happend now... */
+ smprintf(s,"WARNING: Ignoring incorrect packet checksum!\n");
+ }
+
+ /* Was it data? */
+ if (d->Msg.Type == ALCATEL_DATA) {
+ /* Dispatch message */
+ s->Phone.Data.RequestMsg = &d->Msg;
+ s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
+ /* Send ack */
+ ALCABUS_WriteMessage (s, 0, 0, ALCATEL_ACK);
+ /* Reset message length */
+ d->Msg.Length = 0;
+ /* Was it ack? */
+ } else if ((d->Msg.Type == ALCATEL_ACK) ||
+ (d->Msg.Type == ALCATEL_CONTROL) ||
+ (d->Msg.Type == ALCATEL_CONNECT_ACK) ||
+ (d->Msg.Type == ALCATEL_DISCONNECT_ACK)) {
+ /* TODO: check counter of ack? */
+ if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL ||
+ s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) {
+ smprintf(s, "Received %s ack ",
+ (d->Msg.Type == ALCATEL_ACK) ? "normal" :
+ (d->Msg.Type == ALCATEL_CONTROL) ? "control" :
+ (d->Msg.Type == ALCATEL_CONNECT_ACK) ? "connect" :
+ (d->Msg.Type == ALCATEL_DISCONNECT_ACK) ? "disconnect" :
+ "BUG");
+ smprintf(s, "0x%02x / 0x%04x", d->Msg.Type, d->Msg.Length);
+ DumpMessage(s->di.df, s->di.dl, d->Msg.Buffer, d->Msg.Length);
+ fflush(s->di.df);
+ }
+ if (s->di.dl==DL_BINARY) {
+ smprintf(s,"%c",0x02); /* Receiving */
+ smprintf(s,"%c",d->Msg.Type);
+ smprintf(s,"%c",d->Msg.Length/256);
+ smprintf(s,"%c",d->Msg.Length%256);
+ for (i=0;i<d->Msg.Length;i++) smprintf(s,"%c",d->Msg.Buffer[i]);
+ }
+ if (d->Msg.Type != ALCATEL_CONTROL) {
+ d->next_frame = ALCATEL_DATA;
+ d->busy = false;
+ }
+ /* Reset message length */
+ d->Msg.Length = 0;
+ }
+
+ /* Was it unexpected type? */
+ if ((d->Msg.Type != d->next_frame) && (d->Msg.Type != ALCATEL_CONTROL)) {
+ return ERR_FRAMENOTREQUESTED;
+ }
+ } /* Last byte of packet */
+
+ return ERR_NONE;
+}
+
+static GSM_Error ALCABUS_Initialise(GSM_StateMachine *s)
+{
+ GSM_Protocol_ALCABUSData *d = &s->Protocol.Data.ALCABUS;
+
+ /* Initialise some variables */
+ d->Msg.BufferUsed = 0;
+ d->Msg.Buffer = NULL;
+ d->Msg.Length = 0;
+ d->Msg.Type = 0;
+ d->in_counter = 1;
+ d->out_counter = 0;
+ d->busy = false;
+
+ /* Initialise protocol */
+ dbgprintf ("Initializing binary mode\n");
+ return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_CONNECT);
+}
+
+static GSM_Error ALCABUS_Terminate(GSM_StateMachine *s)
+{
+ /* Terminate protocol */
+ dbgprintf ("Closing binary mode\n");
+ return ALCABUS_WriteMessage (s, 0, 0, ALCATEL_DISCONNECT);
+}
+
+GSM_Protocol_Functions ALCABUSProtocol = {
+ ALCABUS_WriteMessage,
+ ALCABUS_StateMachine,
+ ALCABUS_Initialise,
+ ALCABUS_Terminate
+};
+
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */