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