• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
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 "bt_common.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 ******************************************************************************/
bta_ag_at_init(tBTA_AG_AT_CB * p_cb)44 void 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 ******************************************************************************/
bta_ag_at_reinit(tBTA_AG_AT_CB * p_cb)62 void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb)
63 {
64     osi_free_and_reset((void **)&p_cb->p_cmd_buf);
65     p_cb->cmd_pos = 0;
66 }
67 
68 /******************************************************************************
69 **
70 ** Function         bta_ag_process_at
71 **
72 ** Description      Parse AT commands.  This function will take the input
73 **                  character string and parse it for AT commands according to
74 **                  the AT command table passed in the control block.
75 **
76 **
77 ** Returns          void
78 **
79 ******************************************************************************/
bta_ag_process_at(tBTA_AG_AT_CB * p_cb)80 void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
81 {
82     UINT16      idx;
83     UINT8       arg_type;
84     char        *p_arg;
85     INT16       int_arg = 0;
86     /* loop through at command table looking for match */
87     for (idx = 0; p_cb->p_at_tbl[idx].p_cmd[0] != 0; idx++)
88     {
89         if (!utl_strucmp(p_cb->p_at_tbl[idx].p_cmd, p_cb->p_cmd_buf))
90         {
91             break;
92         }
93     }
94 
95     /* if there is a match; verify argument type */
96     if (p_cb->p_at_tbl[idx].p_cmd[0] != 0)
97     {
98         /* start of argument is p + strlen matching command */
99         p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
100 
101         /* if no argument */
102         if (p_arg[0] == 0)
103         {
104             arg_type = BTA_AG_AT_NONE;
105         }
106         /* else if arg is '?' and it is last character */
107         else if (p_arg[0] == '?' && p_arg[1] == 0)
108         {
109             /* we have a read */
110             arg_type = BTA_AG_AT_READ;
111         }
112         /* else if arg is '=' */
113         else if (p_arg[0] == '=' && p_arg[1] != 0)
114         {
115             if (p_arg[1] == '?' && p_arg[2] == 0)
116             {
117                 /* we have a test */
118                 arg_type = BTA_AG_AT_TEST;
119             }
120             else
121             {
122                 /* we have a set */
123                 arg_type = BTA_AG_AT_SET;
124 
125                 /* skip past '=' */
126                 p_arg++;
127             }
128         }
129         else
130         /* else it is freeform argument */
131         {
132             arg_type = BTA_AG_AT_FREE;
133         }
134 
135         /* if arguments match command capabilities */
136         if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0)
137         {
138             /* if it's a set integer check max, min range */
139             if (arg_type == BTA_AG_AT_SET &&
140                 p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT)
141             {
142                 int_arg = utl_str2int(p_arg);
143                 if (int_arg < (INT16) p_cb->p_at_tbl[idx].min ||
144                     int_arg > (INT16) p_cb->p_at_tbl[idx].max)
145                 {
146                     /* arg out of range; error */
147                     (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
148                 }
149                 else
150                 {
151 
152                     (*p_cb->p_cmd_cback)(p_cb->p_user,
153                                          p_cb->p_at_tbl[idx].command_id,
154                                          arg_type, p_arg, int_arg);
155                 }
156             }
157             else
158             {
159                 (*p_cb->p_cmd_cback)(p_cb->p_user,
160                                      p_cb->p_at_tbl[idx].command_id,
161                                      arg_type, p_arg, int_arg);
162             }
163         }
164         /* else error */
165         else
166         {
167             (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
168         }
169     }
170     /* else no match call error callback */
171     else
172     {
173         (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
174     }
175 }
176 
177 /******************************************************************************
178 **
179 ** Function         bta_ag_at_parse
180 **
181 ** Description      Parse AT commands.  This function will take the input
182 **                  character string and parse it for AT commands according to
183 **                  the AT command table passed in the control block.
184 **
185 **
186 ** Returns          void
187 **
188 ******************************************************************************/
bta_ag_at_parse(tBTA_AG_AT_CB * p_cb,char * p_buf,UINT16 len)189 void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
190 {
191     int i = 0;
192     char* p_save;
193 
194     if (p_cb->p_cmd_buf == NULL) {
195         p_cb->p_cmd_buf = (char *)osi_malloc(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 
244