First version, development moved to 5110-connected machine
[gnokii.git] / common / protocol / fbusirda.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 fbusirda protocol
10
11 */
12
13 #include "config.h"
14
15 /* "Turn on" prototypes in fbusirda.h */
16 #define __fbusirda_c 
17
18 /* System header files */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 #ifdef WIN32
25   #include <windows.h>
26   #include "misc_win32.h"
27 #else
28   #include <ctype.h>
29 #endif
30  
31 /* Various header file */
32 #include "devices/device.h"
33 #include "gsm-api.h"
34 #include "protocol/fbusirda.h"
35 #include "protocol/fbus.h"
36 #include "misc.h"
37
38 GSM_Protocol FBUSIRDA_Functions = {
39   FBUSIRDA_Initialise,
40   FBUSIRDA_SendMessage,
41   FBUSIRDA_SendFrame,
42   FBUSIRDA_WritePhone,
43   FBUSIRDA_Terminate,
44   FBUSIRDA_RX_StateMachine
45 };
46
47 /* Local variables */
48 enum FBUS_RX_States RX_State;
49
50 u8 MessageDestination, MessageSource;
51
52 u16 BufferCount;
53
54 u16 MessageLength;
55
56 u8 MessageType;
57
58 u8 MessageBuffer[FBUS_MAX_RECEIVE_LENGTH * 6];
59
60 #ifdef DEBUG
61 char *FBUSIRDA_PrintDevice(int Device)
62 {
63   switch (Device) {
64
65   case FBUS_DEVICE_PHONE:
66     return _("Phone");
67
68   case FBUS_DEVICE_PC:
69     return _("PC");
70
71   default:
72     return _("Unknown");
73
74   }
75 }
76
77 /* FBUSIRDA_RX_DisplayMessage is called when a message we don't know about is
78    received so that the user can see what is going back and forth, and perhaps
79    shed some more light/explain another message type! */
80 void FBUSIRDA_RX_DisplayMessage()
81 {
82   fprintf(stdout, _("Msg Source: %s\n"), FBUSIRDA_PrintDevice(MessageSource));
83   fprintf(stdout, _("Msg Dest: %s\n"), FBUSIRDA_PrintDevice(MessageDestination));
84   fprintf(stdout, _("Msg Type: %02x\n"), MessageType);
85
86   hexdump( MessageLength, MessageBuffer);
87 }
88 #endif /* DEBUG */
89
90 /* Prepares the message header and sends it, prepends the message start byte
91            (0x1e) and other values according the value specified when called.
92            Calculates checksum and then sends the lot down the pipe... */
93 int FBUSIRDA_SendFrame(u16 message_length, u8 message_type, u8 *buffer) {
94   u8 out_buffer[FBUSIRDA_MAX_CONTENT_LENGTH + 2];
95   
96   int current=0;
97   int header=0;
98
99   /* FIXME - we should check for the message length ... */
100
101   /* Now construct the message header. */
102
103   out_buffer[current++] = FBUSIRDA_FRAME_ID;    /* Start of the frame indicator */
104
105   out_buffer[current++] = FBUS_DEVICE_PHONE; /* Destination */
106
107   out_buffer[current++] = FBUS_DEVICE_PC;    /* Source */
108
109   out_buffer[current++] = message_type; /* Type */
110
111   out_buffer[current++] = message_length/256; /* Length1 */
112   out_buffer[current++] = message_length%256; /* Length2 */
113
114   /* Copy in data if any. */    
115         
116   if (message_length != 0) {
117     memcpy(out_buffer + current, buffer, message_length);
118     header = current;
119     current+=message_length;
120   }
121
122 #ifdef DEBUG
123   NULL_TX_DisplayMessage( current, out_buffer);
124 #endif /* DEBUG */
125
126   /* Send it out... */
127   return ( FBUSIRDA_WritePhone(current,out_buffer) - header);
128
129 }
130
131 int FBUSIRDA_SendMessage(u16 message_length, u8 message_type, u8 *buffer) {
132   
133   u8 frame_buffer[FBUSIRDA_MAX_CONTENT_LENGTH + 2];
134   u16 ret;
135
136     memcpy(frame_buffer, buffer, message_length);
137     ret = FBUSIRDA_SendFrame(message_length, message_type, frame_buffer);
138
139     if (ret != message_length)
140       {
141        printf("CAUTION:  FBUSIRDA_SendFrame return written %d bytes of %d !\n",ret, message_length);
142        return(false);
143       }
144     else
145       return (true);
146 }
147
148 int FBUSIRDA_SendAck(u8 message_type, u8 message_seq) {
149   return(true);
150 }
151
152 /* Applications should call MBUS_Terminate to shut down the MBUS thread and
153    close the serial port. */
154 void FBUSIRDA_Terminate(void)
155 {  
156   /* Request termination of thread */
157   CurrentRequestTerminate = true;
158
159   /* Close serial port. */
160   device_close();
161 }
162
163 /* RX_State machine for receive handling.  Called once for each character
164    received from the phone/phone. */
165 void FBUSIRDA_RX_StateMachine(unsigned char rx_byte) {
166
167   unsigned char max;
168
169   int i;
170
171   i=0;
172
173   switch (RX_State) {
174
175   case FBUS_RX_Discarding:
176     break;
177     
178   /* Messages from the phone start with an 0x14 (IRDA, Nokia:PhoNet).
179      We use this to "synchronise" with the incoming data stream. */
180
181   case FBUS_RX_Sync:
182
183     if (rx_byte == FBUSIRDA_FRAME_ID) {
184       BufferCount = 0;  
185       RX_State = FBUS_RX_GetDestination;
186     }
187     
188     break;
189
190   case FBUS_RX_GetDestination:
191
192     MessageDestination=rx_byte;
193     RX_State = FBUS_RX_GetSource;
194
195  /* When there is a checksum error and things get out of sync we have to manage to resync */
196     /* If doing a data call at the time, finding a 0x1e etc is really quite likely in the data stream */
197     /* Then all sorts of horrible things happen because the packet length etc is wrong... */
198     /* Therefore we test here for a destination of 0x0c and return to the top if it is not */
199
200 #ifdef DEBUG
201     if (strstr(GSM_Info->IrdaModels,"decode")!=NULL)
202      {
203        if (rx_byte!=FBUS_DEVICE_PC && rx_byte!=FBUS_DEVICE_PHONE )
204         {
205           RX_State=FBUS_RX_Sync;
206           fprintf(stdout,"decode: expected FBUS_DEVICE_PC/FBUS_DEVICE_PHONE, got %2x\n",rx_byte);
207         }
208      }//decode Model
209     else
210      {
211 #endif
212        if (rx_byte!=FBUS_DEVICE_PC)
213        {
214           RX_State=FBUS_RX_Sync;
215 #ifdef DEBUG
216           fprintf(stdout,"The FBUSIRDA stream is out of sync - expected FBUS_DEVICE_PC, got %2x\n",rx_byte);
217 #endif
218        }
219 #ifdef DEBUG
220      }//not decode Model
221 #endif
222
223     break;
224
225   case FBUS_RX_GetSource:
226
227     MessageSource=rx_byte;
228     RX_State = FBUS_RX_GetType;
229
230 #ifdef DEBUG
231     if (strstr(GSM_Info->IrdaModels,"decode")!=NULL)
232      {
233        if (rx_byte!=FBUS_DEVICE_PC && rx_byte!=FBUS_DEVICE_PHONE )
234         {
235           RX_State=FBUS_RX_Sync;
236           fprintf(stdout,"decode: expected FBUS_DEVICE_PC/FBUS_DEVICE_PHONE, got %2x\n",rx_byte);
237         }
238      }//decode Model
239     else
240      {
241 #endif
242        if (rx_byte!=FBUS_DEVICE_PHONE)
243         {
244           RX_State=FBUS_RX_Sync;
245 #ifdef DEBUG
246           fprintf(stdout,"The FBUSIRDA stream is out of sync - expected FBUS_DEVICE_PHONE, got %2x\n",rx_byte);
247 #endif
248         }
249 #ifdef DEBUG
250      }//not decode Model
251 #endif
252
253     break;
254
255   case FBUS_RX_GetType:
256
257     MessageType=rx_byte;
258     RX_State = FBUS_RX_GetLength1;
259
260     break;
261
262   case FBUS_RX_GetLength1:
263
264     MessageLength=0;
265
266     /* MW:Here are problems with conversion. For chars 0-127 it's OK, for
267        higher not (probably because rx_byte is char type) - improtant
268        for MBUS. So, I make it double and strange - generally it should be
269        more simple and make simple convert rx_byte into MessageLength */
270     if (rx_byte!=0) {
271       max=rx_byte;
272       MessageLength=max*256;
273     }
274
275     RX_State = FBUS_RX_GetLength2;
276     
277     break;
278     
279   case FBUS_RX_GetLength2:
280
281     /* MW:Here are problems with conversion. For chars 0-127 it's OK, for
282        higher not (probably because rx_byte is char type) - important
283        for MBUS. So, I make it double and strange - generally it should be
284        more simple and make simple convert rx_byte into MessageLength */      
285 #if defined(__svr4__) || defined(__FreeBSD__)
286     if (rx_byte!=0) {
287       for (i=0;i<rx_byte;i++)
288         MessageLength=MessageLength++;
289     }
290 #else
291     if (rx_byte!=0) {
292       max=rx_byte;
293       MessageLength=MessageLength+max;
294     }
295 #endif
296     
297     RX_State = FBUS_RX_GetMessage;
298
299     break;
300
301   case FBUS_RX_GetMessage:
302
303     MessageBuffer[BufferCount] = rx_byte;
304     BufferCount ++;
305
306     if (BufferCount == MessageLength)
307        {        
308         if (MessageSource == FBUS_DEVICE_PHONE)
309          {
310 #ifdef DEBUG
311            FBUSIRDA_RX_DisplayMessage();
312 #endif /* DEBUG */
313            GSM->DispatchMessage(MessageLength, MessageBuffer, MessageType);
314          }
315         else
316          {
317 #ifdef DEBUG
318            /* for --decodefile */
319            fprintf(stdout, _("Msg Source: %s\n"), FBUSIRDA_PrintDevice(MessageSource));
320            fprintf(stdout, _("Msg Dest: %s\n"), FBUSIRDA_PrintDevice(MessageDestination));
321            fprintf(stdout, _("Msg Type: %02x\n"), MessageType);
322            hexdump( MessageLength, MessageBuffer);
323 #endif /* DEBUG */
324          }
325       
326       RX_State = FBUS_RX_Sync;
327     }
328     break;
329   }
330 }
331
332 /* Called by initialisation code to open comm port in asynchronous mode. */
333 bool FBUSIRDA_OpenSerial(void)
334 {
335 #ifdef DEBUG
336   fprintf(stdout, _("Setting FBUS Irda communication...\n"));
337 #endif /* DEBUG */
338
339   return (true);
340
341 }
342
343 /* Initialise variables and state machine. */
344 GSM_Error FBUSIRDA_Initialise(char *port_device, char *initlength,
345                             GSM_ConnectionType connection,
346                             void (*rlp_callback)(RLP_F96Frame *frame))
347 {
348   CurrentConnectionType = connection;
349
350   if (!StartConnection(port_device,false,connection)) {
351     return GE_INTERNALERROR;
352   }
353   RX_State=FBUS_RX_Sync;
354   
355   return (GE_NONE);
356 }
357
358 bool FBUSIRDA_WritePhone (u16 length, u8 *buffer) {
359
360   if (!CurrentDisableKeepAlive)
361     usleep(150);
362
363   return (device_write(buffer,length));
364 }