This commit was generated by cvs2svn to compensate for changes in r161,
[gnokii.git] / common / protocol / fbus3110.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9   This file provides an API for support for FBUS3110 protocol
10
11 */
12
13 /* "Turn on" prototypes in FBUS3110.h */
14 #define __fbus3110_c 
15
16 /* System header files */
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20  
21 #ifdef WIN32
22   #include <windows.h>
23   #include "misc_win32.h"
24 #else
25   #include <ctype.h>
26 #endif
27
28 /* Various header file */
29 #include "devices/device.h"
30 #include "gsm-api.h"
31 #include "protocol/fbus3110.h"
32 #include "protocol/fbus.h"
33 #include "newmodules/n6110.h"
34 #include "misc.h"
35
36 GSM_Protocol FBUS3110_Functions = {
37   FBUS3110_Initialise,
38   FBUS3110_SendMessage,
39   FBUS3110_SendFrame,
40   NULL_WritePhone,
41   FBUS3110_Terminate,
42   FBUS3110_RX_StateMachine
43 };
44
45 /* Local variables */
46 enum FBUS_RX_States RX_State;
47
48 u8 MessageDestination, MessageSource;
49
50 u16 BufferCount;
51
52 u16 MessageLength;
53
54 u8 MessageType;
55
56 u8 MessageBuffer[FBUS3110_MAX_RECEIVE_LENGTH * 6];
57
58 u8 RequestSequenceNumber3110=0x10;
59
60 #ifdef DEBUG    
61 char *N31_PrintDevice(int Device)
62 {
63   switch (Device) {
64
65 //  case FBUS3110_DEVICE_PHONE:return _("Phone");
66 //  case FBUS3110_DEVICE_PC   :return _("PC");
67   default               :return _("Unknown");
68   }
69 }
70 #endif /* DEBUG */
71
72 /* N61_RX_DisplayMessage is called when a message we don't know about is
73    received so that the user can see what is going back and forth, and perhaps
74    shed some more light/explain another message type! */
75 void N31_RX_DisplayMessage()
76 {
77 #ifdef DEBUG
78   fprintf(stdout, _("Msg Dest: %s\n"), N31_PrintDevice(MessageDestination));
79   fprintf(stdout, _("Msg Source: %s\n"), N31_PrintDevice(MessageSource));
80   fprintf(stdout, _("Msg Type: %02x\n"), MessageType);
81
82   hexdump(MessageLength-2,MessageBuffer);
83 #endif
84
85   AppendLog(MessageBuffer,MessageLength-2,true);
86 }
87
88 /* Prepares the message header and sends it, prepends the message start byte
89            (0x1e) and other values according the value specified when called.
90            Calculates checksum and then sends the lot down the pipe... */
91 int FBUS3110_SendFrame(u16 message_length, u8 message_type, u8 *buffer) {
92
93   /* Originally out_buffer[FBUS3110_MAX_CONTENT_LENGTH + 2],
94      but it made problems with MBUS */
95   u8 out_buffer[1000];
96   
97   int count, current=0;
98   unsigned char checksum;
99
100   /* Now construct the message header. */
101   out_buffer[current++] = FBUS3110_FRAME_TO_PHONE;   /* Start of frame */
102   out_buffer[current++] = message_length + 2;        /* Length */
103   out_buffer[current++] = message_type;              /* Type */
104   out_buffer[current++] = RequestSequenceNumber3110; /* Sequence number */
105
106   /* Copy in data if any. */
107   if (message_length != 0) {
108     memcpy(out_buffer + current, buffer, message_length);
109     current += message_length;
110   }
111
112   /* Now calculate checksum over entire message and append to message. */
113   checksum = 0;
114   for (count = 0; count < current; count++) checksum ^= out_buffer[count];
115   out_buffer[current++] = checksum;
116
117 #ifdef DEBUG
118   NULL_TX_DisplayMessage(current, out_buffer);
119 #endif /* DEBUG */
120
121   /* Send it out... */
122   if (!NULL_WritePhone(current,out_buffer)) return (false);
123
124   return (true);
125 }
126
127 /* Any command we originate must have a unique SequenceNumber.
128    Observation to date suggests that these values startx at 0x10
129    and cycle up to 0x17 before repeating again.  Perhaps more
130    accurately, the numbers cycle 0,1,2,3..7 with bit 4 of the byte
131    premanently set. */
132
133 void FBUS3110_UpdateSequenceNumber(void)
134 {
135   RequestSequenceNumber3110++;
136
137   if (RequestSequenceNumber3110 > 0x17 || RequestSequenceNumber3110 < 0x10)
138     RequestSequenceNumber3110 = 0x10;
139 }
140
141 int FBUS3110_SendMessage(u16 message_length, u8 message_type, u8 *buffer) {
142
143   FBUS3110_UpdateSequenceNumber();
144
145   return FBUS3110_SendFrame(message_length, message_type, buffer);
146 }
147
148 int FBUS3110_SendAck(u8 message_type, u8 message_seq) {
149
150   return 0;
151 }
152
153 /* Applications should call FBUS3110_Terminate to shut down the FBUS3110 thread and
154    close the serial port. */
155 void FBUS3110_Terminate(void)
156 {
157   /* Request termination of thread */
158   CurrentRequestTerminate = true;
159
160   /* Close serial port. */
161   device_close();
162 }
163
164 /* RX_State machine for receive handling.  Called once for each character
165    received from the phone/phone. */
166
167 void FBUS3110_RX_StateMachine(unsigned char rx_byte) {
168
169   static int checksum;
170   
171   /* XOR the byte with the current checksum */
172   checksum ^= rx_byte;
173
174   switch (RX_State) {
175         
176   case FBUS_RX_Discarding:
177     if (rx_byte != 0x55) break;
178
179   case FBUS_RX_Sync:
180
181     if (rx_byte == 0x04 || rx_byte == 0x03) {
182       MessageDestination=rx_byte;
183       RX_State = FBUS_RX_GetLength1;
184     }
185     break;
186
187   case FBUS_RX_GetLength1:
188
189     MessageLength = rx_byte;
190     RX_State = FBUS_RX_GetType;
191     
192     break;
193
194   case FBUS_RX_GetType:
195
196     MessageType=rx_byte;
197     RX_State = FBUS_RX_GetMessage;
198
199     break;
200
201   case FBUS_RX_GetMessage:
202
203     MessageBuffer[BufferCount] = rx_byte;
204     BufferCount ++;
205     
206     if (BufferCount>FBUS3110_MAX_RECEIVE_LENGTH) {
207 #ifdef DEBUG
208       fprintf(stdout, "FB31: Message buffer overun - resetting\n");
209 #endif
210       AppendLogText("OVERUN\n",false);
211       RX_State = FBUS_RX_Sync;
212       break;
213     }
214
215     /* If this is the last byte, it's the checksum. */
216     if (BufferCount == MessageLength) {
217
218       RX_State = FBUS_RX_Sync;    
219     }
220     break;
221   default:
222     break;
223   }
224 }
225   
226 /* Called by initialisation code to open comm port in asynchronous mode. */
227 bool FBUS3110_OpenSerial(void)
228 {
229   switch (CurrentConnectionType) {
230      case GCT_FBUS3110:
231
232 #ifdef DEBUG
233        fprintf(stdout, _("Setting cable for FBUS3110 communication...\n"));
234 #endif /* DEBUG */
235
236        device_changespeed(115200);   
237        break;
238      default:
239 #ifdef DEBUG
240        fprintf(stdout,_("Wrong connection type for FBUS3110 module. Inform marcin-wiacek@topnet.pl about it\n"));
241 #endif
242        break;
243   }
244
245   return (true);
246 }
247
248 /* Initialise variables and state machine. */
249 GSM_Error FBUS3110_Initialise(char *port_device, char *initlength,
250                           GSM_ConnectionType connection,
251                           void (*rlp_callback)(RLP_F96Frame *frame))
252 {
253   if (!StartConnection (port_device,false,connection))
254     return GE_INTERNALERROR;
255       
256   CurrentConnectionType = connection;
257
258   if (FBUS3110_OpenSerial() != true) return GE_INTERNALERROR;
259
260   return (GE_NONE);
261 }