First version, development moved to 5110-connected machine
[gnokii.git] / common / protocol / at.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 AT protocol
10
11 */
12
13 #include "config.h"
14
15 /* "Turn on" prototypes in AT.h */
16 #define __AT_c 
17
18 /* System header files */
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22  
23 #ifdef WIN32
24   #include <windows.h>
25   #include "misc_win32.h"
26 #else
27   #include <ctype.h>
28 #endif
29
30 /* Various header file */
31 #include "devices/device.h"
32 #include "gsm-api.h"
33 #include "protocol/at.h"
34
35 GSM_Protocol AT_Functions = {
36   AT_Initialise,
37   AT_SendMessage,
38   AT_SendFrame,
39   AT_WritePhone,
40   AT_Terminate,
41   AT_RX_StateMachine
42 };
43
44 /* Local variables */
45 u16 BufferCount;
46
47 static u16 MessageLength;
48
49 u8 MessageBuffer[AT_MAX_RECEIVE_LENGTH * 6];
50
51 static bool wascrlf = false;
52 static char *linestart = MessageBuffer;
53
54 /* N61_RX_DisplayMessage is called when a message we don't know about is
55    received so that the user can see what is going back and forth, and perhaps
56    shed some more light/explain another message type! */
57
58 #ifdef DEBUG    
59 void AT_RX_DisplayMessage()
60 {
61   fprintf(stdout, _("Phone\n"));
62
63   hexdump(MessageLength,MessageBuffer);
64 }
65 #endif /* DEBUG */
66
67 /* Prepares the message header and sends it, prepends the message start byte
68            (0x1e) and other values according the value specified when called.
69            Calculates checksum and then sends the lot down the pipe... */
70 int AT_SendFrame(u16 message_length, u8 message_type, u8 *buffer) {
71
72 #ifdef DEBUG
73   int count;
74 #endif
75   
76   /* FIXME - we should check for the message length ... */
77
78 #ifdef DEBUG
79   fprintf(stdout, _("PC: "));
80
81   for (count = 0; count < message_length-1; count++)
82     fprintf(stdout, "%c", buffer[count]);
83
84   fprintf(stdout, "\n");
85 #endif /* DEBUG */
86
87   /* Send it out... */
88   if (!AT_WritePhone(message_length,buffer))
89     return (false);
90
91   return (true);
92 }
93
94 int AT_SendMessage(u16 message_length, u8 message_type, u8 *buffer) {
95   
96   AT_SendFrame(message_length, message_type, buffer);
97
98   return (true);
99 }
100
101 int AT_SendAck(u8 message_type, u8 message_seq) {
102
103   return true;
104 }
105
106 /* Applications should call AT_Terminate to shut down the AT thread and
107    close the serial port. */
108 void AT_Terminate(void)
109 {
110   /* Request termination of thread */
111   CurrentRequestTerminate = true;
112
113   /* Close serial port. */
114   device_close();
115 }
116
117 /* RX_State machine for receive handling.  Called once for each character
118    received from the phone/phone. */
119
120 void AT_RX_StateMachine(unsigned char rx_byte) {
121
122   /* FIXME: Check for overflow */
123   MessageBuffer[BufferCount] = rx_byte;
124   MessageBuffer[BufferCount + 1] = '\0';
125
126 //  fprintf(stdout,_("%02x %c\n"),rx_byte,rx_byte);
127
128   if (wascrlf && (rx_byte != 10 && rx_byte != 13)) {
129     linestart = MessageBuffer + BufferCount;
130     wascrlf = false;
131   }
132
133   if ((rx_byte== 10 || rx_byte==13)) wascrlf = true;
134
135   if ((BufferCount > 0) && (10 == MessageBuffer[BufferCount])
136        && (13 == MessageBuffer[BufferCount-1])
137        && ((0 == strncmp("OK", linestart, 2))
138        || (0 == strncmp("ERROR", linestart, 5))
139        || (0 == strncmp("+CME ERROR:", linestart, 11))
140        || (0 == strncmp("+CMS ERROR:", linestart, 11)))) {
141
142     MessageLength=BufferCount;
143
144 #ifdef DEBUG
145     AT_RX_DisplayMessage();
146 #endif
147
148     GSM->DispatchMessage(MessageLength,MessageBuffer, 0x00);
149
150     BufferCount = 0;
151     linestart = MessageBuffer;
152     wascrlf = false;
153
154   } else BufferCount++;
155 }
156   
157 /* Called by initialisation code to open comm port in asynchronous mode. */
158 bool AT_OpenSerial(void)
159 {
160 //  device_changespeed(115200);
161
162   device_changespeed(19200);
163
164   return (true);
165 }
166
167 /* Initialise variables and state machine. */
168 GSM_Error AT_Initialise(char *port_device, char *initlength,
169                           GSM_ConnectionType connection,
170                           void (*rlp_callback)(RLP_F96Frame *frame))
171 {
172
173   if (!StartConnection (port_device,false,connection))
174     return GE_INTERNALERROR;
175       
176   CurrentConnectionType = connection;
177
178   if (AT_OpenSerial() != true) return GE_INTERNALERROR;
179
180   BufferCount=0;
181
182   return (GE_NONE);
183 }
184
185 bool AT_WritePhone (u16 length, u8 *buffer) {
186   int i;
187
188   for (i=0;i<length;i++) {
189     if (device_write(buffer+i,1)!=1) return false;
190     /* For some phones like Siemens M20 we need to wait a little
191        after writing each char. Possible reason: these phones
192        can't receive so fast chars or there is bug here in mygnokii */
193     usleep(1);
194   }
195
196   return true;
197 }