blob: 74d39482e29275576eac51353d13f725ef1d0681 [file] [log] [blame]
Hemant Gupta3fe1b492014-04-29 16:23:59 +05301/******************************************************************************
2 *
3 * Copyright (C) 2004-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * BTA AG AT command interpreter.
22 *
23 ******************************************************************************/
24
25#include <string.h>
26#include "gki.h"
27#include "bta_ag_at.h"
28#include "utl.h"
29
30/*****************************************************************************
31** Constants
32*****************************************************************************/
33
34/******************************************************************************
35**
36** Function bta_ag_at_init
37**
38** Description Initialize the AT command parser control block.
39**
40**
41** Returns void
42**
43******************************************************************************/
44void bta_ag_at_init(tBTA_AG_AT_CB *p_cb)
45{
46 p_cb->p_cmd_buf = NULL;
47 p_cb->cmd_pos = 0;
48}
49
50/******************************************************************************
51**
52** Function bta_ag_at_reinit
53**
54** Description Re-initialize the AT command parser control block. This
55** function resets the AT command parser state and frees
56** any GKI buffer.
57**
58**
59** Returns void
60**
61******************************************************************************/
62void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb)
63{
64 if (p_cb->p_cmd_buf != NULL)
65 {
66 GKI_freebuf(p_cb->p_cmd_buf);
67 p_cb->p_cmd_buf = NULL;
68 }
69 p_cb->cmd_pos = 0;
70}
71/******************************************************************************
72**
73** Function bta_ag_process_at
74**
75** Description Parse AT commands. This function will take the input
76** character string and parse it for AT commands according to
77** the AT command table passed in the control block.
78**
79**
80** Returns void
81**
82******************************************************************************/
83void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
84{
85 UINT16 idx;
86 UINT8 arg_type;
87 char *p_arg;
88 INT16 int_arg = 0;
89 /* loop through at command table looking for match */
90 for (idx = 0; p_cb->p_at_tbl[idx].p_cmd[0] != 0; idx++)
91 {
92 if (!utl_strucmp(p_cb->p_at_tbl[idx].p_cmd, p_cb->p_cmd_buf))
93 {
94 break;
95 }
96 }
97
98 /* if there is a match; verify argument type */
99 if (p_cb->p_at_tbl[idx].p_cmd[0] != 0)
100 {
101 /* start of argument is p + strlen matching command */
102 p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
103
104 /* if no argument */
105 if (p_arg[0] == 0)
106 {
107 arg_type = BTA_AG_AT_NONE;
108 }
109 /* else if arg is '?' and it is last character */
110 else if (p_arg[0] == '?' && p_arg[1] == 0)
111 {
112 /* we have a read */
113 arg_type = BTA_AG_AT_READ;
114 }
115 /* else if arg is '=' */
116 else if (p_arg[0] == '=' && p_arg[1] != 0)
117 {
118 if (p_arg[1] == '?' && p_arg[2] == 0)
119 {
120 /* we have a test */
121 arg_type = BTA_AG_AT_TEST;
122 }
123 else
124 {
125 /* we have a set */
126 arg_type = BTA_AG_AT_SET;
127
128 /* skip past '=' */
129 p_arg++;
130 }
131 }
132 else
133 /* else it is freeform argument */
134 {
135 arg_type = BTA_AG_AT_FREE;
136 }
137
138 /* if arguments match command capabilities */
139 if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0)
140 {
141 /* if it's a set integer check max, min range */
142 if (arg_type == BTA_AG_AT_SET &&
143 p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT)
144 {
145 int_arg = utl_str2int(p_arg);
146 if (int_arg < (INT16) p_cb->p_at_tbl[idx].min ||
147 int_arg > (INT16) p_cb->p_at_tbl[idx].max)
148 {
149 /* arg out of range; error */
150 (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
151 }
152 else
153 {
154
155 (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
156 }
157 }
158 else
159 {
160 (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
161 }
162 }
163 /* else error */
164 else
165 {
166 (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
167 }
168 }
169 /* else no match call error callback */
170 else
171 {
172 (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
173 }
174}
175
176/******************************************************************************
177**
178** Function bta_ag_at_parse
179**
180** Description Parse AT commands. This function will take the input
181** character string and parse it for AT commands according to
182** the AT command table passed in the control block.
183**
184**
185** Returns void
186**
187******************************************************************************/
188void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
189{
190 int i = 0;
191 char* p_save;
192
193 if (p_cb->p_cmd_buf == NULL)
194 {
195 p_cb->p_cmd_buf = (char *) GKI_getbuf(p_cb->cmd_max_len);
196 p_cb->cmd_pos = 0;
197 }
198
199 for (i = 0; i < len;)
200 {
201 while (p_cb->cmd_pos < p_cb->cmd_max_len-1 && i < len)
202 {
203 /* Skip null characters between AT commands. */
204 if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0))
205 {
206 i++;
207 continue;
208 }
209
210 p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
211 if ( p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n')
212 {
213 p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
214 if ((p_cb->cmd_pos > 2) &&
215 (p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
216 (p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
217 {
218 p_save = p_cb->p_cmd_buf;
219 p_cb->p_cmd_buf += 2;
220 bta_ag_process_at(p_cb);
221 p_cb->p_cmd_buf = p_save;
222 }
223
224 p_cb->cmd_pos = 0;
225
226 }
227 else if( p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B )
228 {
229 p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
230 (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
231 p_cb->cmd_pos = 0;
232 }
233 else
234 {
235 ++p_cb->cmd_pos;
236 }
237 }
238
239 if (i < len)
240 p_cb->cmd_pos = 0;
241 }
242}
243