From 88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 07 Aug 2004 17:24:40 +0000 Subject: Initial revision --- (limited to 'gammu/emb/common/protocol') 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 +#include + +#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; iDevice.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;iMsg.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: + */ diff --git a/gammu/emb/common/protocol/alcatel/alcabus.h b/gammu/emb/common/protocol/alcatel/alcabus.h new file mode 100644 index 0000000..3b9b44e --- a/dev/null +++ b/gammu/emb/common/protocol/alcatel/alcabus.h @@ -0,0 +1,61 @@ +/* (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. + */ + +#ifndef alcabus_h +#define alcabus_h + +#include "../protocol.h" + +#define ALCATEL_HEADER 0x7E + +/* packet types: */ +/* used for starting binary connection (must be preceeded by + * AT+CPROT=16,"V1.0",16 and phone should response to it by CONNECT_ACK) + */ +#define ALCATEL_CONNECT 0x0A +/* received when connect suceeded */ +#define ALCATEL_CONNECT_ACK 0x0C +/* used for stopping binary connection */ +#define ALCATEL_DISCONNECT 0x0D +/* received when binnary connection ends */ +#define ALCATEL_DISCONNECT_ACK 0x0E +/* some control ack, I really don't know what should it do, so currently it + * is just ignored. It comes time to time, and communication continues OK also + * if no reply was made. */ +#define ALCATEL_CONTROL 0x0F +/* sending/recieving data */ +#define ALCATEL_DATA 0x02 +/* acknowledge to data */ +#define ALCATEL_ACK 0x06 + +/* Maximal value for packet counter */ +#define ALCATEL_MAX_COUNTER 0x3D + +typedef struct { + GSM_Protocol_Message Msg; + /* Incoming packets ID counter */ + int in_counter; + /* Outgoing packets ID counter */ + int out_counter; + /* Expected size of incoming packet */ + int expected_size; + /* What is type of frame we expect next */ + unsigned char next_frame; + /* State of mobile, if we expect something (generally some ack) we set + * this to true and no other action can be performed until it is false. */ + bool busy; +} GSM_Protocol_ALCABUSData; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/at/at.c b/gammu/emb/common/protocol/at/at.c new file mode 100644 index 0000000..f4a75b7 --- a/dev/null +++ b/gammu/emb/common/protocol/at/at.c @@ -0,0 +1,229 @@ +/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */ + +#include "../../gsmstate.h" + +#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT) + +#include +#include + +#include "../../gsmcomon.h" +#include "at.h" + +static GSM_Error AT_WriteMessage (GSM_StateMachine *s, unsigned char *buffer, + int length, unsigned char type) +{ + int i,sent = 0; + + GSM_DumpMessageLevel2(s, buffer, length, type); + GSM_DumpMessageLevel3(s, buffer, length, type); + if (s->Protocol.Data.AT.FastWrite) { + while (sent != length) { + if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, length - sent)) == 0) { + return ERR_DEVICEWRITEERROR; + } + sent += i; + } + } else { + for (i=0;iDevice.Functions->WriteDevice(s,buffer+i,1)!=1) return ERR_DEVICEWRITEERROR; + /* For some phones like Siemens M20 we need to wait a little + * after writing each char. Possible reason: these phones + * can't receive so fast chars or there is bug here in Gammu */ + my_sleep(1); + } + my_sleep(400); + } + + return ERR_NONE; +} + +typedef struct { + char *text; + int lines; +} SpecialAnswersStruct; + +static GSM_Error AT_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Protocol_Message Msg2; + GSM_Protocol_ATData *d = &s->Protocol.Data.AT; + int i; + + /* These are lines with end of "normal" answers */ + static char *StartStrings[] = { + "OK" , "ERROR" , + "+CME ERROR:" , "+CMS ERROR:" , + + "+CPIN: " , /*A2D issue*/ + + NULL}; + + /* Some info from phone can be inside "normal" answers + * It starts with strings written here + */ + static SpecialAnswersStruct SpecialAnswers[] = { + {"_OSIGQ:" ,1}, {"_OBS:" ,1}, + {"^SCN:" ,1}, {"+CGREG:" ,1}, + {"+CBM:" ,1}, {"+CMT:" ,2}, + {"+CMTI:" ,1}, {"+CDS:" ,2}, + {"+CREG:" ,1}, + + {"RING" ,1}, {"NO CARRIER" ,1}, + {"NO ANSWER" ,1}, {"+COLP" ,1}, + {"+CLIP" ,1}, + + {NULL ,1}}; + + /* Ignore leading CR, LF and ESC */ + if (d->Msg.Length == 0) { + if (rx_char == 10 || rx_char == 13 || rx_char == 27) return ERR_NONE; + d->LineStart = d->Msg.Length; + } + + if (d->Msg.BufferUsed < d->Msg.Length + 2) { + d->Msg.BufferUsed = d->Msg.Length + 2; + d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed); + } + d->Msg.Buffer[d->Msg.Length++] = rx_char; + d->Msg.Buffer[d->Msg.Length ] = 0; + + switch (rx_char) { + case 0: + break; + case 10: + case 13: + if (!d->wascrlf) d->LineEnd = d->Msg.Length-1; + d->wascrlf = true; + if (d->Msg.Length > 0 && rx_char == 10 && d->Msg.Buffer[d->Msg.Length-2]==13) { + i = 0; + while (StartStrings[i] != NULL) { + if (strncmp(StartStrings[i],d->Msg.Buffer+d->LineStart,strlen(StartStrings[i])) == 0) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + d->Msg.Length = 0; + break; + } + i++; + } + if (d->Msg.Length == 0) break; + + i = 0; + while (SpecialAnswers[i].text != NULL) { + if (strncmp(SpecialAnswers[i].text,d->Msg.Buffer+d->LineStart,strlen(SpecialAnswers[i].text)) == 0) { + /* We need something better here */ + if (s->Phone.Data.RequestID == ID_GetNetworkInfo && strncmp(SpecialAnswers[i].text,"+CREG:",6) == 0) { + i++; + continue; + } + d->SpecialAnswerStart = d->LineStart; + d->SpecialAnswerLines = SpecialAnswers[i].lines; + } + i++; + } + + + if (d->SpecialAnswerLines == 1) { + /* This is end of special answer. We copy it and send to phone module */ + Msg2.Buffer = malloc(d->LineEnd - d->SpecialAnswerStart + 3); + memcpy(Msg2.Buffer,d->Msg.Buffer+d->SpecialAnswerStart,d->LineEnd - d->SpecialAnswerStart + 2); + Msg2.Length = d->LineEnd - d->SpecialAnswerStart + 2; + Msg2.Buffer[Msg2.Length] = 0; + + s->Phone.Data.RequestMsg = &Msg2; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + free(Msg2.Buffer); + + /* We cut special answer from main buffer */ + d->Msg.Length = d->SpecialAnswerStart; + if (d->Msg.Length != 0) d->Msg.Length = d->Msg.Length - 2; + + /* We need to find earlier values of all variables */ + d->wascrlf = false; + d->LineStart = 0; + for (i=0;iMsg.Length;i++) { + switch(d->Msg.Buffer[i]) { + case 0: + break; + case 10: + case 13: + if (!d->wascrlf) d->LineEnd = d->Msg.Length-1; + d->wascrlf = true; + break; + default: + if (d->wascrlf) { + d->LineStart = d->Msg.Length-1; + d->wascrlf = false; + } + } + } + d->Msg.Buffer[d->Msg.Length] = 0; + } + if (d->SpecialAnswerLines > 0) d->SpecialAnswerLines--; + } + break; + case 'T': + /* When CONNECT string received, we know there will not follow + * anything AT related, after CONNECT can follow ppp data, alcabus + * data and also other things. + */ + if (strncmp(d->Msg.Buffer+d->LineStart, "CONNECT", 7) == 0) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + d->LineStart = -1; + d->Msg.Length = 0; + break; + } + default: + if (d->wascrlf) { + d->LineStart = d->Msg.Length-1; + d->wascrlf = false; + } + if (d->EditMode) { + if (strlen(d->Msg.Buffer+d->LineStart) == 2 && strncmp(d->Msg.Buffer+d->LineStart,"> ",2)==0) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + } + } + } + return ERR_NONE; +} + +static GSM_Error AT_Initialise(GSM_StateMachine *s) +{ + GSM_Protocol_ATData *d = &s->Protocol.Data.AT; + + d->Msg.Buffer = NULL; + d->Msg.BufferUsed = 0; + d->Msg.Length = 0; + d->Msg.Type = 0; + + d->SpecialAnswerLines = 0; + d->LineStart = -1; + d->LineEnd = -1; + d->wascrlf = false; + d->EditMode = false; + d->FastWrite = false; + + s->Device.Functions->DeviceSetDtrRts(s,true,true); + + return s->Device.Functions->DeviceSetSpeed(s,s->Speed); +} + +static GSM_Error AT_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.AT.Msg.Buffer); + return ERR_NONE; +} + +GSM_Protocol_Functions ATProtocol = { + AT_WriteMessage, + AT_StateMachine, + AT_Initialise, + AT_Terminate +}; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/at/at.h b/gammu/emb/common/protocol/at/at.h new file mode 100644 index 0000000..e200646 --- a/dev/null +++ b/gammu/emb/common/protocol/at/at.h @@ -0,0 +1,36 @@ +/* (c) 2002-2003 by Marcin Wiacek and Michal Cihar */ + +#ifndef at_h +#define at_h + +#include "../protocol.h" + +typedef struct { + GSM_Protocol_Message Msg; + bool wascrlf; + int LineStart,LineEnd; + int SpecialAnswerLines,SpecialAnswerStart; + + bool EditMode; /* wait for modem answer or not */ + bool FastWrite; +} GSM_Protocol_ATData; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif +#if defined(GSM_ENABLE_BLUEAT) +# ifndef GSM_USED_BLUETOOTHDEVICE +# define GSM_USED_BLUETOOTHDEVICE +# endif +#endif +#if defined(GSM_ENABLE_IRDAAT) +# ifndef GSM_USED_IRDADEVICE +# define GSM_USED_IRDADEVICE +# endif +#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/fbus2.c b/gammu/emb/common/protocol/nokia/fbus2.c new file mode 100644 index 0000000..8b3e024 --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/fbus2.c @@ -0,0 +1,444 @@ +/* (c) 2002-2003 by Marcin Wiacek */ +/* based on some work from Gnokii and MyGnokii */ + +#include "../../gsmstate.h" + +#if defined(GSM_ENABLE_FBUS2) || defined(GSM_ENABLE_FBUS2IRDA) || defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303) + +#include +#include + +#include "../../gsmcomon.h" +#include "fbus2.h" + +static GSM_Error FBUS2_WriteFrame(GSM_StateMachine *s, + unsigned char *MsgBuffer, + int MsgLength, + unsigned char MsgType) +{ + unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 10]; + unsigned char checksum=0; + int i, len, sent; + + buffer2[0] = FBUS2_FRAME_ID; + if (s->ConnectionType==GCT_FBUS2IRDA) buffer2[0] = FBUS2_IRDA_FRAME_ID; + + buffer2[1] = FBUS2_DEVICE_PHONE; //destination + buffer2[2] = FBUS2_DEVICE_PC; //source + buffer2[3] = MsgType; + buffer2[4] = MsgLength / 256; + buffer2[5] = MsgLength % 256; + + memcpy(buffer2 + 6, MsgBuffer, MsgLength); + len = MsgLength + 6; + + /* Odd messages require additional 0x00 byte */ + if (MsgLength % 2) buffer2[len++] = 0x00; + + checksum = 0; + for (i = 0; i < len; i+=2) checksum ^= buffer2[i]; + buffer2[len++] = checksum; + + checksum = 0; + for (i = 1; i < len; i+=2) checksum ^= buffer2[i]; + buffer2[len++] = checksum; + + /* Sending to phone */ + sent=s->Device.Functions->WriteDevice(s,buffer2,len); + if (sent!=len) return ERR_DEVICEWRITEERROR; + + return ERR_NONE; +} + +static GSM_Error FBUS2_WriteMessage (GSM_StateMachine *s, + unsigned char *MsgBuffer, + int MsgLength, + unsigned char MsgType) +{ + int i, nom, togo, thislength; /* number of messages, ... */ + unsigned char buffer2[FBUS2_MAX_TRANSMIT_LENGTH + 2], seqnum; + GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2; + GSM_Error error; + + GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType); + + nom = (MsgLength + FBUS2_MAX_TRANSMIT_LENGTH - 1) / FBUS2_MAX_TRANSMIT_LENGTH; + togo = MsgLength; + + for (i = 0; i < nom; i++) { + seqnum = d->MsgSequenceNumber; + if (i==0) seqnum = seqnum + 0x40; + d->MsgSequenceNumber = (d->MsgSequenceNumber + 1) & 0x07; + + thislength = togo; + if (togo > FBUS2_MAX_TRANSMIT_LENGTH) thislength = FBUS2_MAX_TRANSMIT_LENGTH; + memcpy(buffer2, MsgBuffer + (MsgLength - togo), thislength); + buffer2[thislength] = nom - i; + buffer2[thislength + 1] = seqnum; + togo = togo - thislength; + + GSM_DumpMessageLevel2(s, buffer2, thislength, MsgType); + + error=FBUS2_WriteFrame(s, buffer2, thislength + 2, MsgType); + if (error!=ERR_NONE) return error; + } + + return ERR_NONE; +} + +static GSM_Error FBUS2_SendAck(GSM_StateMachine *s, + unsigned char MsgType, + unsigned char MsgSequence) +{ + unsigned char buffer2[2]; + + buffer2[0] = MsgType; + buffer2[1] = MsgSequence; + + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) { + smprintf(s,"[Sending Ack of type %02x, seq %x]\n",buffer2[0],buffer2[1]); + } + + /* Sending to phone */ + return FBUS2_WriteFrame(s, buffer2, 2, FBUS2_ACK_BYTE); +} + +static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2; + unsigned char frm_num, seq_num; + bool correct = false; + + /* XOR the byte with the earlier checksum */ + d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char; + + if (d->MsgRXState == RX_GetMessage) { + d->Msg.Buffer[d->Msg.Count] = rx_char; + d->Msg.Count++; + + /* This is not last byte in frame */ + if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE; + + /* Checksum is incorrect */ + if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: checksum]\n"); + } + free(d->Msg.Buffer); + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + seq_num = d->Msg.Buffer[d->Msg.Length-1]; + + if (d->Msg.Type == FBUS2_ACK_BYTE) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) { + smprintf(s, "[Received Ack of type %02x, seq %02x]\n",d->Msg.Buffer[0],seq_num); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + frm_num = d->Msg.Buffer[d->Msg.Length-2]; + + if ((seq_num & 0x40) == 0x40) { + d->FramesToGo = frm_num; + d->MultiMsg.Length = 0; + d->MultiMsg.Type = d->Msg.Type; + d->MultiMsg.Destination = d->Msg.Destination; + d->MultiMsg.Source = d->Msg.Source; + } + + if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s, "[ERROR: Missed part of multiframe msg]\n"); + } + + free(d->Msg.Buffer); + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s, "[ERROR: Multiframe msg in multiframe msg]\n"); + } + + free(d->Msg.Buffer); + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) { + d->MultiMsg.BufferUsed = d->MultiMsg.Length+d->Msg.Length-2; + d->MultiMsg.Buffer = (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed); + } + memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2); + d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2; + + free(d->Msg.Buffer); + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + + d->FramesToGo--; + + /* do not ack debug trace, as this could generate a + * (feedback loop) flood of which even Noah would be scared. + */ + if (d->Msg.Type != 0) { + FBUS2_SendAck(s,d->Msg.Type,((unsigned char)(seq_num & 0x0f))); + } + + if (d->FramesToGo == 0) { + s->Phone.Data.RequestMsg = &d->MultiMsg; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + } + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetLength2) { + d->Msg.Length = d->Msg.Length + rx_char; + d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length+3); + d->MsgRXState = RX_GetMessage; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetLength1) { + d->Msg.Length = rx_char * 256; + d->MsgRXState = RX_GetLength2; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetType) { + d->Msg.Type = rx_char; + d->MsgRXState = RX_GetLength1; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetSource) { + if (rx_char != FBUS2_DEVICE_PHONE) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PHONE); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Source = rx_char; + + d->MsgRXState = RX_GetType; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetDestination) { + if (rx_char != FBUS2_DEVICE_PC) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_DEVICE_PC); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Destination = rx_char; + + d->MsgRXState = RX_GetSource; + return ERR_NONE; + } + if (d->MsgRXState == RX_Sync) { + switch (s->ConnectionType) { + case GCT_FBUS2: + case GCT_FBUS2DLR3: + case GCT_FBUS2DKU5: + case GCT_FBUS2PL2303: + case GCT_FBUS2BLUE: + case GCT_BLUEFBUS2: + if (rx_char == FBUS2_FRAME_ID) correct = true; + break; + case GCT_FBUS2IRDA: + if (rx_char == FBUS2_IRDA_FRAME_ID) correct = true; + break; + default: + break; + } + if (!correct) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + if (s->ConnectionType==GCT_FBUS2IRDA) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_IRDA_FRAME_ID); + } else { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, FBUS2_FRAME_ID); + } + } + return ERR_NONE; + } + + d->Msg.CheckSum[0] = rx_char; + d->Msg.CheckSum[1] = 0; + d->Msg.Count = 0; + + d->MsgRXState = RX_GetDestination; + return ERR_NONE; + } + return ERR_NONE; +} + +#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2BLUE) || defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2PL2303) +static void FBUS2_WriteDLR3(GSM_StateMachine *s, char *command, int length, int timeout) +{ + unsigned char buff[300]; + int w = 0; + bool wassomething = false; + + s->Device.Functions->WriteDevice(s,command,length); + + for (w=0;wDevice.Functions->ReadDevice(s, buff, 255)==0) return; + } else { + if (s->Device.Functions->ReadDevice(s, buff, 255)>0) wassomething = true; + } + my_sleep(50); + } +} +#endif + +static GSM_Error FBUS2_Initialise(GSM_StateMachine *s) +{ + unsigned char init_char = 0x55; +#ifdef GSM_ENABLE_FBUS2IRDA + unsigned char end_init_char = 0xc1; +#endif + + GSM_Protocol_FBUS2Data *d = &s->Protocol.Data.FBUS2; + GSM_Device_Functions *Device = s->Device.Functions; + GSM_Error error; + int count; + + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + d->MultiMsg.BufferUsed = 0; + d->MultiMsg.Length = 0; + d->MultiMsg.Buffer = NULL; + + d->MsgSequenceNumber = 0; + d->FramesToGo = 0; + d->MsgRXState = RX_Sync; + + error=Device->DeviceSetParity(s,false); + if (error!=ERR_NONE) return error; + + switch (s->ConnectionType) { +#if defined(GSM_ENABLE_BLUEFBUS2) || defined(GSM_ENABLE_FBUS2BLUE) + case GCT_FBUS2BLUE: + case GCT_BLUEFBUS2: + FBUS2_WriteDLR3(s,"AT\r\n", 4,10); + FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10); + FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n", 14,10); + break; +#endif +#if defined(GSM_ENABLE_FBUS2DLR3) || defined(GSM_ENABLE_FBUS2DKU5) || defined(GSM_ENABLE_FBUS2PL2303) + case GCT_FBUS2DKU5: + case GCT_FBUS2PL2303: + case GCT_FBUS2DLR3: + error=Device->DeviceSetDtrRts(s,false,false); + if (error!=ERR_NONE) return error; + my_sleep(1000); + + error=Device->DeviceSetDtrRts(s,true,true); + if (error!=ERR_NONE) return error; + error=Device->DeviceSetSpeed(s,19200); + if (error!=ERR_NONE) return error; + + FBUS2_WriteDLR3(s,"AT\r\n", 4,10); + FBUS2_WriteDLR3(s,"AT&F\r\n", 6,10); + FBUS2_WriteDLR3(s,"AT*NOKIAFBUS\r\n", 14,10); + + error=Device->CloseDevice(s); + if (error!=ERR_NONE) return error; + my_sleep(1000); + + error=Device->OpenDevice(s); + if (error!=ERR_NONE) return error; + error=Device->DeviceSetParity(s,false); + if (error!=ERR_NONE) return error; + error=Device->DeviceSetSpeed(s,115200); + if (error!=ERR_NONE) return error; + error=Device->DeviceSetDtrRts(s,false,false); + if (error!=ERR_NONE) return error; + + for (count = 0; count < 55; count ++) { + if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR; + } + break; +#endif + case GCT_FBUS2: + error=Device->DeviceSetSpeed(s,115200); + if (error!=ERR_NONE) return error; + + error=Device->DeviceSetDtrRts(s,true,false); /*DTR high,RTS low*/ + if (error!=ERR_NONE) return error; + + for (count = 0; count < 55; count ++) { + if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR; + my_sleep(10); + } + break; +#ifdef GSM_ENABLE_FBUS2IRDA + case GCT_FBUS2IRDA: + error=Device->DeviceSetSpeed(s,9600); + if (error!=ERR_NONE) return error; + + for (count = 0; count < 55; count ++) { + if (Device->WriteDevice(s,&init_char,1)!=1) return ERR_DEVICEWRITEERROR; + my_sleep(10); + } + + if (Device->WriteDevice(s,&end_init_char,1)!=1) return ERR_DEVICEWRITEERROR; + my_sleep(20); + + error=Device->DeviceSetSpeed(s,115200); + if (error!=ERR_NONE) return error; + + break; +#endif + default: + break; + } + + return ERR_NONE; +} + +static GSM_Error FBUS2_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.FBUS2.Msg.Buffer); + free(s->Protocol.Data.FBUS2.MultiMsg.Buffer); + + my_sleep(200); + return ERR_NONE; +} + +GSM_Protocol_Functions FBUS2Protocol = { + FBUS2_WriteMessage, + FBUS2_StateMachine, + FBUS2_Initialise, + FBUS2_Terminate +}; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/fbus2.h b/gammu/emb/common/protocol/nokia/fbus2.h new file mode 100644 index 0000000..5dd45d7 --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/fbus2.h @@ -0,0 +1,38 @@ +/* (c) 2002-2003 by Marcin Wiacek */ +/* based on some work from Gnokii and MyGnokii */ + +#ifndef fbus2_h +#define fbus2_h + +#include "../protocol.h" + +#define FBUS2_FRAME_ID 0x1e +#define FBUS2_IRDA_FRAME_ID 0x1c +#define FBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */ +#define FBUS2_DEVICE_PC 0x0c /* Our PC */ +#define FBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */ + +#define FBUS2_MAX_TRANSMIT_LENGTH 120 + +typedef struct { + int MsgSequenceNumber; + int MsgRXState; + int FramesToGo; + GSM_Protocol_Message MultiMsg; + GSM_Protocol_Message Msg; +} GSM_Protocol_FBUS2Data; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif +#if defined(GSM_ENABLE_BLUEFBUS2) +# ifndef GSM_USED_BLUETOOTHDEVICE +# define GSM_USED_BLUETOOTHDEVICE +# endif +#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/mbus2.c b/gammu/emb/common/protocol/nokia/mbus2.c new file mode 100644 index 0000000..f07d6c5 --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/mbus2.c @@ -0,0 +1,252 @@ +/* (c) 2001-2003 by Marcin Wiacek */ +/* based on some work from MyGnokii */ + +#include "../../gsmstate.h" + +#ifdef GSM_ENABLE_MBUS2 + +#include +#include + +#include "../../gsmcomon.h" +#include "mbus2.h" + +static GSM_Error MBUS2_WriteMessage (GSM_StateMachine *s, + unsigned char *MsgBuffer, + int MsgLength, + unsigned char MsgType) +{ + unsigned char *buffer2, checksum = 0; + GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2; + int i, sent, len; + + GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType); + + buffer2 = (unsigned char *)malloc(MsgLength + 8); + + buffer2[0] = MBUS2_FRAME_ID; + buffer2[1] = MBUS2_DEVICE_PHONE; // destination + buffer2[2] = MBUS2_DEVICE_PC; // source + buffer2[3] = MsgType; + buffer2[4] = MsgLength / 256; + buffer2[5] = MsgLength % 256; + + memcpy(buffer2 + 6, MsgBuffer, MsgLength); + len = 6 + MsgLength; + + /* According to http://www.flosys.com/tdma/n5160.html some phones + * can have problems with checksum equal 0x1F. Phones can recognize + * received frame, but won't send ACK for it. When checksum is 0x1F, + * we increment the sequence number + */ + do { + d->MsgSequenceNumber++; + + buffer2[len] = d->MsgSequenceNumber; + + /* Calculating checksum */ + checksum = 0; + for (i = 0; i < len + 1; i++) checksum ^= buffer2[i]; + } while (checksum == 0x1f); + + buffer2[len++] = d->MsgSequenceNumber; + buffer2[len++] = checksum; + + GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType); + + /* Sending to phone */ + my_sleep(10); + sent=s->Device.Functions->WriteDevice(s,buffer2,len); + + free(buffer2); + + if (sent!=len) return ERR_DEVICEWRITEERROR; + return ERR_NONE; +} + +static GSM_Error MBUS2_SendAck(GSM_StateMachine *s, + unsigned char type, + unsigned char sequence) +{ + GSM_Device_Functions *Device = s->Device.Functions; + unsigned char buffer2[6]; + int i; + + buffer2[0] = MBUS2_FRAME_ID; + buffer2[1] = MBUS2_DEVICE_PHONE; //destination + buffer2[2] = MBUS2_DEVICE_PC; //source + buffer2[3] = MBUS2_ACK_BYTE; + buffer2[4] = sequence; + buffer2[5] = 0; + + /* Calculating checksum */ + for (i = 0; i < 5; i++) buffer2[5] ^= buffer2[i]; + + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) { + smprintf(s,"[Sending Ack of type %02x, seq: %x]\n",type,sequence); + } + + /* Sending to phone */ + my_sleep(10); + if (Device->WriteDevice(s,buffer2,6)!=6) return ERR_DEVICEWRITEERROR; + + return ERR_NONE; +} + +static GSM_Error MBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Phone_Functions *Phone = s->Phone.Functions; + GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2; + + d->Msg.CheckSum[0] = d->Msg.CheckSum[1]; + d->Msg.CheckSum[1] ^= rx_char; + + if (d->MsgRXState == RX_GetMessage) { + d->Msg.Buffer[d->Msg.Count] = rx_char; + d->Msg.Count++; + + /* This is not last byte in frame */ + if (d->Msg.Count != d->Msg.Length+2) return ERR_NONE; + + /* Checksum is incorrect */ + if (d->Msg.CheckSum[0] != rx_char) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: checksum]\n"); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + if (d->Msg.Destination != MBUS2_DEVICE_PHONE) { + MBUS2_SendAck(s, d->Msg.Type, d->Msg.Buffer[d->Msg.Count-2]); + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = Phone->DispatchMessage(s); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetLength2) { + if (d->Msg.Type == MBUS2_ACK_BYTE) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE) { + smprintf(s,"[Received Ack]\n"); + } + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + + d->Msg.Length = d->Msg.Length + rx_char; + if (d->Msg.BufferUsed < d->Msg.Length+2) { + d->Msg.BufferUsed = d->Msg.Length+2; + d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed); + } + + d->MsgRXState = RX_GetMessage; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetLength1) { + d->Msg.Length = rx_char * 256; + + d->MsgRXState = RX_GetLength2; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetType) { + d->Msg.Type = rx_char; + + d->MsgRXState = RX_GetLength1; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetSource) { + if (rx_char != MBUS2_DEVICE_PHONE && rx_char != MBUS2_DEVICE_PC) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC); + } + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Source = rx_char; + + d->MsgRXState = RX_GetType; + return ERR_NONE; + } + if (d->MsgRXState == RX_GetDestination) { + if (rx_char != MBUS2_DEVICE_PC && rx_char != MBUS2_DEVICE_PHONE) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x and %02x]\n", rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC); + } + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Destination = rx_char; + + d->MsgRXState = RX_GetSource; + return ERR_NONE; + } + if (d->MsgRXState == RX_Sync) { + if (rx_char != MBUS2_FRAME_ID) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, MBUS2_FRAME_ID); + } + return ERR_NONE; + } + d->Msg.CheckSum[1] = MBUS2_FRAME_ID; + d->Msg.Count = 0; + + d->MsgRXState = RX_GetDestination; + return ERR_NONE; + } + return ERR_NONE; +} + +static GSM_Error MBUS2_Initialise(GSM_StateMachine *s) +{ + GSM_Device_Functions *Device = s->Device.Functions; + GSM_Protocol_MBUS2Data *d = &s->Protocol.Data.MBUS2; + GSM_Error error; + + d->Msg.Length = 0; + d->Msg.BufferUsed = 0; + d->Msg.Buffer = NULL; + + d->MsgSequenceNumber = 0; + d->MsgRXState = RX_Sync; + + error=Device->DeviceSetSpeed(s,9600); + if (error!=ERR_NONE) return error; + + error=Device->DeviceSetParity(s,true); + if (error!=ERR_NONE) return error; + + error=Device->DeviceSetDtrRts(s,false,true); /*DTR low,RTS high*/ + if (error!=ERR_NONE) return error; + my_sleep(200); + + return ERR_NONE; +} + +static GSM_Error MBUS2_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.MBUS2.Msg.Buffer); + return ERR_NONE; +} + +GSM_Protocol_Functions MBUS2Protocol = { + MBUS2_WriteMessage, + MBUS2_StateMachine, + MBUS2_Initialise, + MBUS2_Terminate +}; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/mbus2.h b/gammu/emb/common/protocol/nokia/mbus2.h new file mode 100644 index 0000000..86fcab6 --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/mbus2.h @@ -0,0 +1,28 @@ +/* (c) 2001-2003 by Marcin Wiacek */ +/* based on some work from MyGnokii */ + +#ifndef mbus2_h +#define mbus2_h + +#include "../protocol.h" + +#define MBUS2_FRAME_ID 0x1f +#define MBUS2_DEVICE_PHONE 0x00 /* Nokia mobile phone */ +#define MBUS2_DEVICE_PC 0x10 /* Our PC (MBUS) */ +#define MBUS2_ACK_BYTE 0x7f /* Acknowledge of the received frame */ + +typedef struct { + int MsgSequenceNumber; + int MsgRXState; + GSM_Protocol_Message Msg; +} GSM_Protocol_MBUS2Data; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/phonet.c b/gammu/emb/common/protocol/nokia/phonet.c new file mode 100644 index 0000000..bc5717d --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/phonet.c @@ -0,0 +1,217 @@ +/* (c) 2002-2003 by Marcin Wiacek */ +/* based on some work from Gnokii */ + +#include "../../gsmstate.h" + +#if defined(GSM_ENABLE_IRDA) || defined(GSM_ENABLE_PHONETBLUE) || defined(GSM_ENABLE_BLUEPHONET) + +#include +#include + +#include "../../gsmcomon.h" +#include "phonet.h" + +static GSM_Error PHONET_WriteMessage (GSM_StateMachine *s, + unsigned char *MsgBuffer, + int MsgLength, + unsigned char MsgType) +{ + unsigned char *buffer2; + int sent; + + GSM_DumpMessageLevel3(s, MsgBuffer, MsgLength, MsgType); + + buffer2 = (unsigned char *)malloc(MsgLength + 6); + + buffer2[0] = PHONET_FRAME_ID, + buffer2[1] = PHONET_DEVICE_PHONE; //destination + buffer2[2] = PHONET_DEVICE_PC; //source + + if (s->ConnectionType==GCT_PHONETBLUE || s->ConnectionType==GCT_BLUEPHONET) { + buffer2[0] = PHONET_BLUE_FRAME_ID; + buffer2[1] = PHONET_DEVICE_PHONE; //destination + buffer2[2] = PHONET_BLUE_DEVICE_PC; //source + } + + buffer2[3] = MsgType; + buffer2[4] = MsgLength / 256; + buffer2[5] = MsgLength % 256; + + memcpy(buffer2 + 6, MsgBuffer, MsgLength); + + GSM_DumpMessageLevel2(s, buffer2+6, MsgLength, MsgType); + + /* Sending to phone */ + sent = s->Device.Functions->WriteDevice(s,buffer2,MsgLength+6); + + free(buffer2); + + if (sent!=MsgLength+6) return ERR_DEVICEWRITEERROR; + return ERR_NONE; +} + +static GSM_Error PHONET_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET; + bool correct = false; + + if (d->MsgRXState==RX_GetMessage) { + d->Msg.Buffer[d->Msg.Count] = rx_char; + d->Msg.Count++; + + /* This is not last byte in frame */ + if (d->Msg.Count != d->Msg.Length) return ERR_NONE; + + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s); + + free(d->Msg.Buffer); + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + if (d->MsgRXState==RX_GetLength2) { + d->Msg.Length = d->Msg.Length + rx_char; + d->Msg.Buffer = (unsigned char *)malloc(d->Msg.Length); + + d->MsgRXState = RX_GetMessage; + return ERR_NONE; + } + if (d->MsgRXState==RX_GetLength1) { + d->Msg.Length = rx_char * 256; + + d->MsgRXState = RX_GetLength2; + return ERR_NONE; + } + if (d->MsgRXState==RX_GetType) { + d->Msg.Type = rx_char; + + d->MsgRXState = RX_GetLength1; + return ERR_NONE; + } + if (d->MsgRXState==RX_GetSource) { + if (rx_char != PHONET_DEVICE_PHONE) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PHONE); + } + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Source = rx_char; + + d->MsgRXState = RX_GetType; + return ERR_NONE; + } + if (d->MsgRXState==RX_GetDestination) { + switch (s->ConnectionType) { + case GCT_IRDAPHONET: + if (rx_char == PHONET_DEVICE_PC) correct = true; + break; + case GCT_PHONETBLUE: + case GCT_BLUEPHONET: + if (rx_char == PHONET_BLUE_DEVICE_PC) correct = true; + break; + default: + break; + } + if (!correct) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_DEVICE_PC); + } + d->MsgRXState = RX_Sync; + return ERR_NONE; + } + d->Msg.Destination = rx_char; + + d->MsgRXState = RX_GetSource; + return ERR_NONE; + } + if (d->MsgRXState==RX_Sync) { + switch (s->ConnectionType) { + case GCT_IRDAPHONET: + if (rx_char == PHONET_FRAME_ID) correct = true; + break; + case GCT_PHONETBLUE: + case GCT_BLUEPHONET: + if (rx_char == PHONET_BLUE_FRAME_ID) correct = true; + break; + default: + break; + } + if (!correct) { + if (s->di.dl==DL_TEXT || s->di.dl==DL_TEXTALL || s->di.dl==DL_TEXTERROR || + s->di.dl==DL_TEXTDATE || s->di.dl==DL_TEXTALLDATE || s->di.dl==DL_TEXTERRORDATE) { + smprintf(s,"[ERROR: incorrect char - %02x, not %02x]\n", rx_char, PHONET_FRAME_ID); + } + return ERR_NONE; + } + d->Msg.Count = 0; + + d->MsgRXState = RX_GetDestination; + return ERR_NONE; + } + return ERR_NONE; +} + +static GSM_Error PHONET_Initialise(GSM_StateMachine *s) +{ + int total = 0, i, n; + GSM_Protocol_PHONETData *d = &s->Protocol.Data.PHONET; + unsigned char req[50]; + + d->Msg.Length = 0; + d->Msg.Buffer = NULL; + d->MsgRXState = RX_Sync; + + if (s->ConnectionType == GCT_PHONETBLUE || s->ConnectionType == GCT_BLUEPHONET) { + /* Send frame in PHONET style */ + req[0] = PHONET_BLUE_FRAME_ID; req[1] = PHONET_DEVICE_PHONE; + req[2] = PHONET_BLUE_DEVICE_PC; req[3] = 0xD0; + req[4] = 0x00; req[5] = 0x01; + req[6] = 0x04; + if (s->Device.Functions->WriteDevice(s,req,7) != 7) return ERR_DEVICEWRITEERROR; + + while (total < 7) { + n = s->Device.Functions->ReadDevice(s, req + total, 50 - total); + total += n; + } + + /* Answer frame in PHONET style */ + req[10] = PHONET_BLUE_FRAME_ID; req[11] = PHONET_BLUE_DEVICE_PC; + req[12] = PHONET_DEVICE_PHONE; req[13] = 0xD0; + req[14] = 0x00; req[15] = 0x01; + req[16] = 0x05; + + for (i = 0; i < 7; i++) { + if (req[i] != req[10+i]) { + smprintf(s,"Incorrect byte in the answer\n"); + return ERR_UNKNOWN; + } + } + } + + return ERR_NONE; +} + +static GSM_Error PHONET_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.PHONET.Msg.Buffer); + return ERR_NONE; +} + +GSM_Protocol_Functions PHONETProtocol = { + PHONET_WriteMessage, + PHONET_StateMachine, + PHONET_Initialise, + PHONET_Terminate +}; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/nokia/phonet.h b/gammu/emb/common/protocol/nokia/phonet.h new file mode 100644 index 0000000..2f6e836 --- a/dev/null +++ b/gammu/emb/common/protocol/nokia/phonet.h @@ -0,0 +1,35 @@ +/* (c) 2002-2003 by Marcin Wiacek */ +/* based on some work from Gnokii */ + +#ifndef PHONET_h +#define PHONET_h + +#include "../protocol.h" + +#define PHONET_FRAME_ID 0x14 +#define PHONET_BLUE_FRAME_ID 0x19 +#define PHONET_DEVICE_PHONE 0x00 /* Nokia mobile phone */ +#define PHONET_DEVICE_PC 0x0c /* Our PC */ +#define PHONET_BLUE_DEVICE_PC 0x10 /* Our PC */ + +typedef struct { + int MsgRXState; + GSM_Protocol_Message Msg; +} GSM_Protocol_PHONETData; + +#if defined(GSM_ENABLE_IRDAPHONET) +# ifndef GSM_USED_IRDADEVICE +# define GSM_USED_IRDADEVICE +# endif +#endif +#if defined(GSM_ENABLE_BLUEPHONET) +# ifndef GSM_USED_BLUETOOTHDEVICE +# define GSM_USED_BLUETOOTHDEVICE +# endif +#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/obex/obex.c b/gammu/emb/common/protocol/obex/obex.c new file mode 100644 index 0000000..942c084 --- a/dev/null +++ b/gammu/emb/common/protocol/obex/obex.c @@ -0,0 +1,120 @@ +/* (c) 2003 by Marcin Wiacek */ +/* www.irda.org OBEX specs 1.3 */ + +#include "../../gsmstate.h" + +#include +#include + +#if defined(GSM_ENABLE_BLUEOBEX) || defined(GSM_ENABLE_IRDAOBEX) + +#include "../../gsmcomon.h" +#include "obex.h" + +static GSM_Error OBEX_WriteMessage (GSM_StateMachine *s, unsigned char *buffer, + int length, unsigned char type) +{ + unsigned char *out_buffer; + int current=0,sent; + + out_buffer = (unsigned char *)malloc(length + 3); + + OBEXAddBlock(out_buffer, ¤t, type, buffer, length); + + GSM_DumpMessageLevel2(s, out_buffer+3, length, type); + GSM_DumpMessageLevel3(s, out_buffer+3, length, type); + + /* Send it out... */ + sent = s->Device.Functions->WriteDevice(s,out_buffer,current); + + free(out_buffer); + + if (sent!=current) return ERR_DEVICEWRITEERROR; + return ERR_NONE; +} + +static GSM_Error OBEX_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Phone_Functions *Phone = s->Phone.Functions; + GSM_Protocol_OBEXData *d = &s->Protocol.Data.OBEX; + + switch (d->MsgRXState) { + case RX_Sync: + d->Msg.Type = rx_char; + d->MsgRXState = RX_GetLength1; + break; + case RX_GetLength1: + d->Msg.Length = rx_char * 256; + d->MsgRXState = RX_GetLength2; + break; + case RX_GetLength2: + d->Msg.Length = d->Msg.Length + rx_char - 3; + d->Msg.Count = 0; + if (d->Msg.Count == d->Msg.Length) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = Phone->DispatchMessage(s); + d->MsgRXState = RX_Sync; + } else { + if (d->Msg.BufferUsed < d->Msg.Length) { + d->Msg.BufferUsed = d->Msg.Length; + d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed); + } + d->MsgRXState = RX_GetMessage; + } + break; + case RX_GetMessage: + d->Msg.Buffer[d->Msg.Count] = rx_char; + d->Msg.Count++; + if (d->Msg.Count == d->Msg.Length) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = Phone->DispatchMessage(s); + d->MsgRXState = RX_Sync; + } + break; + } + + return ERR_NONE; +} + +static GSM_Error OBEX_Initialise(GSM_StateMachine *s) +{ + GSM_Protocol_OBEXData *d = &s->Protocol.Data.OBEX; + + d->Msg.BufferUsed = 0; + d->Msg.Buffer = NULL; + d->Msg.Length = 0; + + d->MsgRXState = RX_Sync; + + return ERR_NONE; +} + +static GSM_Error OBEX_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.OBEX.Msg.Buffer); + return ERR_NONE; +} + +GSM_Protocol_Functions OBEXProtocol = { + OBEX_WriteMessage, + OBEX_StateMachine, + OBEX_Initialise, + OBEX_Terminate +}; + +#endif + +void OBEXAddBlock(char *Buffer, int *Pos, unsigned char ID, char *AddBuffer, int AddLength) +{ + Buffer[(*Pos)++] = ID; + Buffer[(*Pos)++] = (AddLength+3)/256; + Buffer[(*Pos)++] = (AddLength+3)%256; + if (AddBuffer != NULL) { + memcpy(Buffer+(*Pos),AddBuffer,AddLength); + (*Pos) += AddLength; + } +} + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/obex/obex.h b/gammu/emb/common/protocol/obex/obex.h new file mode 100644 index 0000000..0e927c7 --- a/dev/null +++ b/gammu/emb/common/protocol/obex/obex.h @@ -0,0 +1,33 @@ +/* (c) 2003 by Marcin Wiacek */ + +#ifndef obex_h +#define obex_h + +#include "../protocol.h" + +typedef struct { + int MsgRXState; + GSM_Protocol_Message Msg; +} GSM_Protocol_OBEXData; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif +#if defined(GSM_ENABLE_BLUEOBEX) +# ifndef GSM_USED_BLUETOOTHDEVICE +# define GSM_USED_BLUETOOTHDEVICE +# endif +#endif +#if defined(GSM_ENABLE_IRDAOBEX) +# ifndef GSM_USED_IRDADEVICE +# define GSM_USED_IRDADEVICE +# endif +#endif + +void OBEXAddBlock(char *Buffer, int *Pos, unsigned char ID, char *AddBuffer, int AddLength); + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/protocol.h b/gammu/emb/common/protocol/protocol.h new file mode 100644 index 0000000..f8e1fe5 --- a/dev/null +++ b/gammu/emb/common/protocol/protocol.h @@ -0,0 +1,31 @@ +/* (c) 2002-2003 by Marcin Wiacek */ + +#ifndef protocol_common_h +#define protocol_common_h + +typedef enum { + RX_Sync, + RX_GetDestination, + RX_GetSource, + RX_GetType, + RX_GetLength1, + RX_GetLength2, + RX_GetMessage +} GSM_Protocol_RXState; + +typedef struct { + int Length; + int Count; + unsigned char Type; + unsigned char Source; + unsigned char Destination; + unsigned char *Buffer; + int BufferUsed; + unsigned char CheckSum[2]; +} GSM_Protocol_Message; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/symbian/mrouter.c b/gammu/emb/common/protocol/symbian/mrouter.c new file mode 100644 index 0000000..2ca7af1 --- a/dev/null +++ b/gammu/emb/common/protocol/symbian/mrouter.c @@ -0,0 +1,110 @@ +/* (c) 2003 by Marcin Wiacek */ + +#include "../../gsmstate.h" + +#if defined(GSM_ENABLE_MROUTERBLUE) + +#include +#include + +#include "../../gsmcomon.h" +#include "mrouter.h" + +static GSM_Error MROUTER_WriteMessage (GSM_StateMachine *s, unsigned char *buffer, + int length, unsigned char type) +{ + unsigned char *out_buffer; + int current=0,sent; + + out_buffer = (unsigned char *)malloc(length+1); + + memcpy(out_buffer,buffer,length); + out_buffer[length]=0x7E; + + GSM_DumpMessageLevel2(s, out_buffer, length, type); + GSM_DumpMessageLevel3(s, out_buffer, length, type); + + /* Send it out... */ + sent = s->Device.Functions->WriteDevice(s,out_buffer,length+1); + + free(out_buffer); + + if (sent!=current) return ERR_DEVICEWRITEERROR; + return ERR_NONE; +} + +static GSM_Error MROUTER_StateMachine(GSM_StateMachine *s, unsigned char rx_char) +{ + GSM_Phone_Functions *Phone = s->Phone.Functions; + GSM_Protocol_MROUTERData *d = &s->Protocol.Data.MROUTER; + + switch (d->MsgRXState) { + case RX_Sync: + if (rx_char == 0x7E) { + d->MsgRXState = RX_GetMessage; + d->Msg.Count = 0; + d->Msg.Length = 0; + } else smprintf(s,"Sync error: %02x\n",rx_char); + break; + case RX_GetMessage: + if (rx_char == 0x7E) { + s->Phone.Data.RequestMsg = &d->Msg; + s->Phone.Data.DispatchError = Phone->DispatchMessage(s); + d->Msg.Count = 0; + d->Msg.Length = 0; + } else { + d->Msg.BufferUsed = d->Msg.Length+1; + d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed); + + d->Msg.Buffer[d->Msg.Count] = rx_char; + d->Msg.Count++; + d->Msg.Length++; + } + break; + } + + return ERR_NONE; +} + +static GSM_Error MROUTER_Initialise(GSM_StateMachine *s) +{ + GSM_Protocol_MROUTERData *d = &s->Protocol.Data.MROUTER; +GSM_Error error; + + d->Msg.BufferUsed = 0; + d->Msg.Buffer = NULL; + d->Msg.Length = 0; + + d->MsgRXState = RX_Sync; + +// error=s->Device.Functions->DeviceSetDtrRts(s,false,false); +// if (error!=ERR_NONE) return error; + + error=s->Device.Functions->DeviceSetSpeed(s,115200); + if (error!=ERR_NONE) return error; + + +// error=s->Device.Functions->DeviceSetSpeed(s,115200); +// if (error!=ERR_NONE) return error; + + return ERR_NONE; +} + +static GSM_Error MROUTER_Terminate(GSM_StateMachine *s) +{ + free(s->Protocol.Data.MROUTER.Msg.Buffer); + return ERR_NONE; +} + +GSM_Protocol_Functions MROUTERProtocol = { + MROUTER_WriteMessage, + MROUTER_StateMachine, + MROUTER_Initialise, + MROUTER_Terminate +}; + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ diff --git a/gammu/emb/common/protocol/symbian/mrouter.h b/gammu/emb/common/protocol/symbian/mrouter.h new file mode 100644 index 0000000..7d72cdd --- a/dev/null +++ b/gammu/emb/common/protocol/symbian/mrouter.h @@ -0,0 +1,31 @@ +/* (c) 2003 by Marcin Wiacek */ + +#ifndef mrouter_h +#define mrouter_h + +#include "../protocol.h" + +typedef struct { + int MsgRXState; + GSM_Protocol_Message Msg; +} GSM_Protocol_MROUTERData; + +#ifndef GSM_USED_SERIALDEVICE +# define GSM_USED_SERIALDEVICE +#endif +//#if defined(GSM_ENABLE_BLUEOBEX) +//# ifndef GSM_USED_BLUETOOTHDEVICE +//# define GSM_USED_BLUETOOTHDEVICE +//# endif +//#endif +//#if defined(GSM_ENABLE_IRDAOBEX) +//# ifndef GSM_USED_IRDADEVICE +//# define GSM_USED_IRDADEVICE +//# endif +//#endif + +#endif + +/* How should editor hadle tabs in this file? Add editor commands here. + * vim: noexpandtab sw=8 ts=8 sts=8: + */ -- cgit v0.9.0.2