/* G N O K I I A Linux/Unix toolset and driver for Nokia mobile phones. Released under the terms of the GNU GPL, see file COPYING for more details. This file provides an API for support for FBUS3110 protocol */ /* "Turn on" prototypes in FBUS3110.h */ #define __fbus3110_c /* System header files */ #include #include #include #ifdef WIN32 #include #include "misc_win32.h" #else #include #endif /* Various header file */ #include "devices/device.h" #include "gsm-api.h" #include "protocol/fbus3110.h" #include "protocol/fbus.h" #include "newmodules/n6110.h" #include "misc.h" GSM_Protocol FBUS3110_Functions = { FBUS3110_Initialise, FBUS3110_SendMessage, FBUS3110_SendFrame, NULL_WritePhone, FBUS3110_Terminate, FBUS3110_RX_StateMachine }; /* Local variables */ enum FBUS_RX_States RX_State; u8 MessageDestination, MessageSource; u16 BufferCount; u16 MessageLength; u8 MessageType; u8 MessageBuffer[FBUS3110_MAX_RECEIVE_LENGTH * 6]; u8 RequestSequenceNumber3110=0x10; #ifdef DEBUG char *N31_PrintDevice(int Device) { switch (Device) { // case FBUS3110_DEVICE_PHONE:return _("Phone"); // case FBUS3110_DEVICE_PC :return _("PC"); default :return _("Unknown"); } } #endif /* DEBUG */ /* N61_RX_DisplayMessage is called when a message we don't know about is received so that the user can see what is going back and forth, and perhaps shed some more light/explain another message type! */ void N31_RX_DisplayMessage() { #ifdef DEBUG fprintf(stdout, _("Msg Dest: %s\n"), N31_PrintDevice(MessageDestination)); fprintf(stdout, _("Msg Source: %s\n"), N31_PrintDevice(MessageSource)); fprintf(stdout, _("Msg Type: %02x\n"), MessageType); hexdump(MessageLength-2,MessageBuffer); #endif AppendLog(MessageBuffer,MessageLength-2,true); } /* Prepares the message header and sends it, prepends the message start byte (0x1e) and other values according the value specified when called. Calculates checksum and then sends the lot down the pipe... */ int FBUS3110_SendFrame(u16 message_length, u8 message_type, u8 *buffer) { /* Originally out_buffer[FBUS3110_MAX_CONTENT_LENGTH + 2], but it made problems with MBUS */ u8 out_buffer[1000]; int count, current=0; unsigned char checksum; /* Now construct the message header. */ out_buffer[current++] = FBUS3110_FRAME_TO_PHONE; /* Start of frame */ out_buffer[current++] = message_length + 2; /* Length */ out_buffer[current++] = message_type; /* Type */ out_buffer[current++] = RequestSequenceNumber3110; /* Sequence number */ /* Copy in data if any. */ if (message_length != 0) { memcpy(out_buffer + current, buffer, message_length); current += message_length; } /* Now calculate checksum over entire message and append to message. */ checksum = 0; for (count = 0; count < current; count++) checksum ^= out_buffer[count]; out_buffer[current++] = checksum; #ifdef DEBUG NULL_TX_DisplayMessage(current, out_buffer); #endif /* DEBUG */ /* Send it out... */ if (!NULL_WritePhone(current,out_buffer)) return (false); return (true); } /* Any command we originate must have a unique SequenceNumber. Observation to date suggests that these values startx at 0x10 and cycle up to 0x17 before repeating again. Perhaps more accurately, the numbers cycle 0,1,2,3..7 with bit 4 of the byte premanently set. */ void FBUS3110_UpdateSequenceNumber(void) { RequestSequenceNumber3110++; if (RequestSequenceNumber3110 > 0x17 || RequestSequenceNumber3110 < 0x10) RequestSequenceNumber3110 = 0x10; } int FBUS3110_SendMessage(u16 message_length, u8 message_type, u8 *buffer) { FBUS3110_UpdateSequenceNumber(); return FBUS3110_SendFrame(message_length, message_type, buffer); } int FBUS3110_SendAck(u8 message_type, u8 message_seq) { return 0; } /* Applications should call FBUS3110_Terminate to shut down the FBUS3110 thread and close the serial port. */ void FBUS3110_Terminate(void) { /* Request termination of thread */ CurrentRequestTerminate = true; /* Close serial port. */ device_close(); } /* RX_State machine for receive handling. Called once for each character received from the phone/phone. */ void FBUS3110_RX_StateMachine(unsigned char rx_byte) { static int checksum; /* XOR the byte with the current checksum */ checksum ^= rx_byte; switch (RX_State) { case FBUS_RX_Discarding: if (rx_byte != 0x55) break; case FBUS_RX_Sync: if (rx_byte == 0x04 || rx_byte == 0x03) { MessageDestination=rx_byte; RX_State = FBUS_RX_GetLength1; } break; case FBUS_RX_GetLength1: MessageLength = rx_byte; RX_State = FBUS_RX_GetType; break; case FBUS_RX_GetType: MessageType=rx_byte; RX_State = FBUS_RX_GetMessage; break; case FBUS_RX_GetMessage: MessageBuffer[BufferCount] = rx_byte; BufferCount ++; if (BufferCount>FBUS3110_MAX_RECEIVE_LENGTH) { #ifdef DEBUG fprintf(stdout, "FB31: Message buffer overun - resetting\n"); #endif AppendLogText("OVERUN\n",false); RX_State = FBUS_RX_Sync; break; } /* If this is the last byte, it's the checksum. */ if (BufferCount == MessageLength) { RX_State = FBUS_RX_Sync; } break; default: break; } } /* Called by initialisation code to open comm port in asynchronous mode. */ bool FBUS3110_OpenSerial(void) { switch (CurrentConnectionType) { case GCT_FBUS3110: #ifdef DEBUG fprintf(stdout, _("Setting cable for FBUS3110 communication...\n")); #endif /* DEBUG */ device_changespeed(115200); break; default: #ifdef DEBUG fprintf(stdout,_("Wrong connection type for FBUS3110 module. Inform marcin-wiacek@topnet.pl about it\n")); #endif break; } return (true); } /* Initialise variables and state machine. */ GSM_Error FBUS3110_Initialise(char *port_device, char *initlength, GSM_ConnectionType connection, void (*rlp_callback)(RLP_F96Frame *frame)) { if (!StartConnection (port_device,false,connection)) return GE_INTERNALERROR; CurrentConnectionType = connection; if (FBUS3110_OpenSerial() != true) return GE_INTERNALERROR; return (GE_NONE); }