Home | History | Annotate | Download | only in ag
      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 "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 ******************************************************************************/
     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 ******************************************************************************/
     62 void 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 ******************************************************************************/
     83 void 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 ******************************************************************************/
    188 void 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 
    244