summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/protocol/at/at.c
Unidiff
Diffstat (limited to 'gammu/emb/common/protocol/at/at.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/protocol/at/at.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/gammu/emb/common/protocol/at/at.c b/gammu/emb/common/protocol/at/at.c
new file mode 100644
index 0000000..f4a75b7
--- a/dev/null
+++ b/gammu/emb/common/protocol/at/at.c
@@ -0,0 +1,229 @@
1/* (c) 2002-2004 by Marcin Wiacek and Michal Cihar */
2
3#include "../../gsmstate.h"
4
5#if defined(GSM_ENABLE_AT) || defined(GSM_ENABLE_BLUEAT) || defined(GSM_ENABLE_IRDAAT)
6
7#include <stdio.h>
8#include <string.h>
9
10#include "../../gsmcomon.h"
11#include "at.h"
12
13static GSM_Error AT_WriteMessage (GSM_StateMachine *s, unsigned char *buffer,
14 int length, unsigned char type)
15{
16 int i,sent = 0;
17
18 GSM_DumpMessageLevel2(s, buffer, length, type);
19 GSM_DumpMessageLevel3(s, buffer, length, type);
20 if (s->Protocol.Data.AT.FastWrite) {
21 while (sent != length) {
22 if ((i = s->Device.Functions->WriteDevice(s,buffer + sent, length - sent)) == 0) {
23 return ERR_DEVICEWRITEERROR;
24 }
25 sent += i;
26 }
27 } else {
28 for (i=0;i<length;i++) {
29 if (s->Device.Functions->WriteDevice(s,buffer+i,1)!=1) return ERR_DEVICEWRITEERROR;
30 /* For some phones like Siemens M20 we need to wait a little
31 * after writing each char. Possible reason: these phones
32 * can't receive so fast chars or there is bug here in Gammu */
33 my_sleep(1);
34 }
35 my_sleep(400);
36 }
37
38 return ERR_NONE;
39}
40
41typedef struct {
42 char*text;
43 intlines;
44} SpecialAnswersStruct;
45
46static GSM_Error AT_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
47{
48 GSM_Protocol_Message Msg2;
49 GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
50 int i;
51
52 /* These are lines with end of "normal" answers */
53 static char *StartStrings[] = {
54 "OK" , "ERROR" ,
55 "+CME ERROR:" , "+CMS ERROR:",
56
57 "+CPIN: " ,/*A2D issue*/
58
59 NULL};
60
61 /* Some info from phone can be inside "normal" answers
62 * It starts with strings written here
63 */
64 static SpecialAnswersStructSpecialAnswers[] = {
65 {"_OSIGQ:" ,1}, {"_OBS:",1},
66 {"^SCN:" ,1}, {"+CGREG:",1},
67 {"+CBM:" ,1}, {"+CMT:",2},
68 {"+CMTI:" ,1}, {"+CDS:",2},
69 {"+CREG:",1},
70
71 {"RING" ,1}, {"NO CARRIER",1},
72 {"NO ANSWER" ,1}, {"+COLP",1},
73 {"+CLIP",1},
74
75 {NULL ,1}};
76
77 /* Ignore leading CR, LF and ESC */
78 if (d->Msg.Length == 0) {
79 if (rx_char == 10 || rx_char == 13 || rx_char == 27) return ERR_NONE;
80 d->LineStart = d->Msg.Length;
81 }
82
83 if (d->Msg.BufferUsed < d->Msg.Length + 2) {
84 d->Msg.BufferUsed= d->Msg.Length + 2;
85 d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
86 }
87 d->Msg.Buffer[d->Msg.Length++] = rx_char;
88 d->Msg.Buffer[d->Msg.Length ] = 0;
89
90 switch (rx_char) {
91 case 0:
92 break;
93 case 10:
94 case 13:
95 if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
96 d->wascrlf = true;
97 if (d->Msg.Length > 0 && rx_char == 10 && d->Msg.Buffer[d->Msg.Length-2]==13) {
98 i = 0;
99 while (StartStrings[i] != NULL) {
100 if (strncmp(StartStrings[i],d->Msg.Buffer+d->LineStart,strlen(StartStrings[i])) == 0) {
101 s->Phone.Data.RequestMsg= &d->Msg;
102 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
103 d->Msg.Length = 0;
104 break;
105 }
106 i++;
107 }
108 if (d->Msg.Length == 0) break;
109
110 i = 0;
111 while (SpecialAnswers[i].text != NULL) {
112 if (strncmp(SpecialAnswers[i].text,d->Msg.Buffer+d->LineStart,strlen(SpecialAnswers[i].text)) == 0) {
113 /* We need something better here */
114 if (s->Phone.Data.RequestID == ID_GetNetworkInfo && strncmp(SpecialAnswers[i].text,"+CREG:",6) == 0) {
115 i++;
116 continue;
117 }
118 d->SpecialAnswerStart = d->LineStart;
119 d->SpecialAnswerLines= SpecialAnswers[i].lines;
120 }
121 i++;
122 }
123
124
125 if (d->SpecialAnswerLines == 1) {
126 /* This is end of special answer. We copy it and send to phone module */
127 Msg2.Buffer = malloc(d->LineEnd - d->SpecialAnswerStart + 3);
128 memcpy(Msg2.Buffer,d->Msg.Buffer+d->SpecialAnswerStart,d->LineEnd - d->SpecialAnswerStart + 2);
129 Msg2.Length = d->LineEnd - d->SpecialAnswerStart + 2;
130 Msg2.Buffer[Msg2.Length] = 0;
131
132 s->Phone.Data.RequestMsg= &Msg2;
133 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
134 free(Msg2.Buffer);
135
136 /* We cut special answer from main buffer */
137 d->Msg.Length = d->SpecialAnswerStart;
138 if (d->Msg.Length != 0) d->Msg.Length = d->Msg.Length - 2;
139
140 /* We need to find earlier values of all variables */
141 d->wascrlf = false;
142 d->LineStart = 0;
143 for (i=0;i<d->Msg.Length;i++) {
144 switch(d->Msg.Buffer[i]) {
145 case 0:
146 break;
147 case 10:
148 case 13:
149 if (!d->wascrlf) d->LineEnd = d->Msg.Length-1;
150 d->wascrlf = true;
151 break;
152 default:
153 if (d->wascrlf) {
154 d->LineStart= d->Msg.Length-1;
155 d->wascrlf = false;
156 }
157 }
158 }
159 d->Msg.Buffer[d->Msg.Length] = 0;
160 }
161 if (d->SpecialAnswerLines > 0) d->SpecialAnswerLines--;
162 }
163 break;
164 case 'T':
165 /* When CONNECT string received, we know there will not follow
166 * anything AT related, after CONNECT can follow ppp data, alcabus
167 * data and also other things.
168 */
169 if (strncmp(d->Msg.Buffer+d->LineStart, "CONNECT", 7) == 0) {
170 s->Phone.Data.RequestMsg = &d->Msg;
171 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
172 d->LineStart = -1;
173 d->Msg.Length = 0;
174 break;
175 }
176 default:
177 if (d->wascrlf) {
178 d->LineStart= d->Msg.Length-1;
179 d->wascrlf = false;
180 }
181 if (d->EditMode) {
182 if (strlen(d->Msg.Buffer+d->LineStart) == 2 && strncmp(d->Msg.Buffer+d->LineStart,"> ",2)==0) {
183 s->Phone.Data.RequestMsg= &d->Msg;
184 s->Phone.Data.DispatchError= s->Phone.Functions->DispatchMessage(s);
185 }
186 }
187 }
188 return ERR_NONE;
189}
190
191static GSM_Error AT_Initialise(GSM_StateMachine *s)
192{
193 GSM_Protocol_ATData *d = &s->Protocol.Data.AT;
194
195 d->Msg.Buffer = NULL;
196 d->Msg.BufferUsed= 0;
197 d->Msg.Length = 0;
198 d->Msg.Type = 0;
199
200 d->SpecialAnswerLines= 0;
201 d->LineStart = -1;
202 d->LineEnd = -1;
203 d->wascrlf = false;
204 d->EditMode = false;
205 d->FastWrite = false;
206
207 s->Device.Functions->DeviceSetDtrRts(s,true,true);
208
209 return s->Device.Functions->DeviceSetSpeed(s,s->Speed);
210}
211
212static GSM_Error AT_Terminate(GSM_StateMachine *s)
213{
214 free(s->Protocol.Data.AT.Msg.Buffer);
215 return ERR_NONE;
216}
217
218GSM_Protocol_Functions ATProtocol = {
219 AT_WriteMessage,
220 AT_StateMachine,
221 AT_Initialise,
222 AT_Terminate
223};
224
225#endif
226
227/* How should editor hadle tabs in this file? Add editor commands here.
228 * vim: noexpandtab sw=8 ts=8 sts=8:
229 */