summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/protocol/nokia/mbus2.c
Side-by-side diff
Diffstat (limited to 'gammu/emb/common/protocol/nokia/mbus2.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/protocol/nokia/mbus2.c252
1 files changed, 252 insertions, 0 deletions
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 <stdio.h>
+#include <string.h>
+
+#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:
+ */