view src/aci2/aci/aci_bat_phb.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 93999a60b835
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GSM-F&D (8411)
|  Modul   :  ACI_BAT
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved. 
|
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This BAT wrapper modul is ...
| 
+----------------------------------------------------------------------------- 
*/ 
 
#include "aci_all.h"     /* includes prim.h, which includes p_bat.h */ 
#include "aci_cmh.h"     /* prototypes of sAT_,qAT_,tAT_    */ 
#include "aci_bat_cmh.h" /* prototypes of sBAT_,qBAT_,tBAT_ */ 
#include "aci_bat.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#include "aci_mem.h"     /* MAKROS ACI_MALLOC, ACI_MFREE*/


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PercentPBCF     |
+--------------------------------------------------------------------+

  PURPOSE : Select Phonebook Configuration.
*/

GLOBAL T_ACI_BAT_RSLT sBAT_PercentPBCF (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                        T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_PBCF_LDN ldn = PBCF_LDN_NotPresent;
  T_ACI_PBCF_LRN lrn = PBCF_LRN_NotPresent;
  T_ACI_PBCF_LMN lmn = PBCF_LMN_NotPresent;

  TRACE_FUNCTION ("sBAT_PercentPBCF()");

  ldn = (T_ACI_PBCF_LDN)cmd->params.ptr_set_percent_pbcf->ldn;
  lrn = (T_ACI_PBCF_LRN)cmd->params.ptr_set_percent_pbcf->lrn;
  lmn = (T_ACI_PBCF_LMN)cmd->params.ptr_set_percent_pbcf->lmn;

  /*
  *   Call the corresponding sAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  /* for BAT we use the old spec, which means the third param is not supported */
  ret = (T_ACI_BAT_RSLT)sAT_PercentPBCF(src_infos_psi->srcId, ldn, lrn, lmn);

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : qBAT_PlusCPBS        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT qBAT_PercentPBCF (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                        T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_PBCF_LDN ldn = PBCF_LDN_NotPresent;
  T_ACI_PBCF_LRN lrn = PBCF_LRN_NotPresent;
  T_ACI_PBCF_LMN lmn = PBCF_LMN_NotPresent;

  TRACE_FUNCTION ("qBAT_PercentPBCF()");

  /*
  *   Call the corresponding qAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)qAT_PercentPBCF(src_infos_psi->srcId, &ldn, &lrn, &lmn);

  /*
  *   If the query completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_que_percent_pbcf pbcf_data;
 
    resp.ctrl_response=BAT_RES_QUE_PERCENT_PBCF;
    resp.response.ptr_que_percent_pbcf = &pbcf_data;

    /*
    *   This relies on T_BAT_percent_pbcf_ldn being identical to 
    *   T_ACI_PBCF_LDN and so forth for LRN and LMN.
    */
    pbcf_data.ldn=(T_BAT_percent_pbcf_ldn)ldn; 
    pbcf_data.lrn=(T_BAT_percent_pbcf_ldn)lrn; 
    pbcf_data.lmn=(T_BAT_percent_pbcf_ldn)lmn; 

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCPBS        |
+--------------------------------------------------------------------+

  PURPOSE : Select phonebook memory storage.
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBS (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_PB_STOR stor;

  TRACE_FUNCTION ("sBAT_PlusCPBS()");

  /*
  *   This relies on T_BAT_storage being identical to 
  *   T_ACI_PB_STOR.
  */
  stor=(T_ACI_PB_STOR)cmd->params.ptr_set_plus_cpbs->storage;

  /*
  *   Call the corresponding sAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  /* for BAT we use the old spec, which means the third param is not supported */
  ret=(T_ACI_BAT_RSLT)sAT_PlusCPBS(src_infos_psi->srcId,stor, NULL);

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : qBAT_PlusCPBS        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT qBAT_PlusCPBS (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_PB_STOR stor;
  SHORT used;
  SHORT total;

  TRACE_FUNCTION ("qBAT_PlusCPBS()");

  /*
  *   Call the corresponding qAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)qAT_PlusCPBS(src_infos_psi->srcId,&stor,&used,&total);

  /*
  *   If the query completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_que_plus_cpbs cpbs_data;
 
    resp.ctrl_response=BAT_RES_QUE_PLUS_CPBS;
    resp.response.ptr_que_plus_cpbs=&cpbs_data;

    /*
    *   This relies on T_BAT_storage being identical to 
    *   T_ACI_PB_STOR.
    */
    cpbs_data.storage=(T_BAT_storage)stor; 

    cpbs_data.total=(S16)total;
    cpbs_data.used=(S16)used;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : qBAT_PercentCPBS     |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT qBAT_PercentCPBS (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                        T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_PB_STOR stor;
  SHORT used;
  SHORT total;
  SHORT first;

  TRACE_FUNCTION ("qBAT_PercentCPBS()");

  /*
  *   Call the corresponding qAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)qAT_PercentCPBS(src_infos_psi->srcId,&stor,&used,&total,&first);

  /*
  *   If the query completes, send the response now.
  */
  if (ret EQ ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_que_percent_cpbs cpbs_data;
 
    resp.ctrl_response=BAT_RES_QUE_PERCENT_CPBS;
    resp.response.ptr_que_percent_cpbs=&cpbs_data;

    /*
    *   This relies on T_BAT_storage being identical to 
    *   T_ACI_PB_STOR.
    */
    cpbs_data.storage=(T_BAT_storage)stor; 

    cpbs_data.total=(S16)total;
    cpbs_data.used=(S16)used;
    cpbs_data.first=(S16)first;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCPBW        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBW (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  SHORT index;
  CHAR number[BAT_MAX_CPBW_NUMBER_LEN+1];
  CHAR *p_number;
  T_ACI_TOA toa;
  T_ACI_TOA *p_toa;
  T_ACI_PB_TEXT text;
  T_ACI_PB_TEXT *p_text;
  T_ACI_VP_ABS dmy_date_time;
  T_BAT_cmd_set_plus_cpbw *cpbw;

  TRACE_FUNCTION ("sBAT_PlusCPBW()");

  /*
  *   Get a pointer to the CPBW structure for convenience.
  */
  cpbw=cmd->params.ptr_set_plus_cpbw;

  index=(SHORT)cpbw->index;

  if (cpbw->v_number==TRUE)
  {
    /*
    *   The idea here is to get the 'number' parameter into a
    *   null terminated string, which is what sAT_PlusCPBW() expects, but
    *   is not guaranteed by BAT.
    */
    memset(number,0,sizeof(number));
    memcpy(number,cpbw->number,cpbw->c_number);
    p_number=number;

    /*
    *   BAT stores the type of address in a single value.
    */
    if (cpbw->type!=-1)
    {
      toa=toa_demerge(cpbw->type);
      p_toa=&toa;
    }
    else
    {
      p_toa=NULL;
    }
  }
  else
  {
    p_number=NULL;
    p_toa=NULL;
  } 

  /*
  *   Associated text
  */
  if (cpbw->v_text==TRUE)
  {
    USHORT len;

    /*
    *   Convert from the currently selected character set into the
    *   SIM format.
    */
    utl_chsetToSim(
      (UBYTE *)cpbw->text,
      (USHORT)cpbw->c_text,
      (UBYTE *)text.data,
      &len,
      GSM_ALPHA_Def);
          
    /*
    *   Set the length. Note that we cannot do this by passing a
    *   reference to text.len into utl_chsetToSim() because it is
    *   the wrong type.
    */
    text.len=(UBYTE)len;      
    
    text.cs=CS_Sim;

    p_text=&text;
  }
  else
  {
    p_text=NULL;
  }

  /*
  *   Call the corresponding sAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=sAT_PlusCPBW(
    src_infos_psi->srcId,
    index,
    p_number,
    p_toa,
    p_text,
    &dmy_date_time);

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : tBAT_PlusCPBW        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT tBAT_PlusCPBW        (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                            T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  SHORT first;
  SHORT last;
  UBYTE nlength;
  UBYTE tlength;

  TRACE_FUNCTION ("tBAT_PlusCPBW()");

  /*
  *   Call the corresponding tAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)tAT_PlusCPBW(src_infos_psi->srcId,&first,&last,&nlength,&tlength);

  /*
  *   If the command completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_tst_plus_cpbw cpbw_data;
 
    resp.ctrl_response=BAT_RES_TST_PLUS_CPBW;
    resp.response.ptr_tst_plus_cpbw=&cpbw_data;

    cpbw_data.index1=(U8)first;
    cpbw_data.index2=(U8)last;
    cpbw_data.nlength=(S16)nlength;
    cpbw_data.tlength=(S16)tlength;

#pragma message(__TODO__"+CPBW types")    
    cpbw_data.c_types=0;
    cpbw_data.types[0]=0;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCPBR        |
+--------------------------------------------------------------------+

  PURPOSE : Read phonebook entries. If the application wants to read
            more than ACI_BAT_MAX_RESPONSES, then the responses are
            sent block by block (one block = ACI_BAT_MAX_RESPONSES).
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBR_CB (T_ACI_DTI_PRC_PSI *src_infos_psi)
{
  T_BAT_cmd_send cmd;
  T_BAT_cmd_set_plus_cpbr cpbr;

  cmd.ctrl_params = BAT_CMD_SET_PLUS_CPBR;
  cmd.params.ptr_set_plus_cpbr = &cpbr;

  cpbr.index1 = (U8)src_infos_psi->index1;
  cpbr.index2 = (S16)src_infos_psi->index2;

  return (sBAT_PlusCPBR(src_infos_psi, &cmd));
}


GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBR (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  SHORT          start_idx;
  SHORT          stop_idx;
  SHORT          last_idx = ACI_NumParmNotPresent;
  T_ACI_PB_ENTR  pb_lst[MAX_PB_ENTR];

  TRACE_FUNCTION ("sBAT_PlusCPBR()");

  /* define here the variables, which are passed as parameters to sAT_PlusCPBR */
  start_idx = (SHORT)cmd->params.ptr_set_plus_cpbr->index1;
  stop_idx  = (SHORT)cmd->params.ptr_set_plus_cpbr->index2;
  
  ret = (T_ACI_BAT_RSLT)sAT_PlusCPBR(src_infos_psi->srcId, start_idx, stop_idx, &last_idx, &pb_lst[0]);
  if (ret EQ ACI_BAT_CMPL)
  {
    SHORT i;
    T_BAT_cmd_response resp;
    T_BAT_res_set_plus_cpbr cpbr_data;
  
    resp.ctrl_response = BAT_RES_SET_PLUS_CPBR;
    resp.response.ptr_set_plus_cpbr = &cpbr_data;
  
    /*
     * sAT_PlusCPBR() provides in pb_lst[] up to five entries (MAX_PB_ENTR)
     */
    for (i = 0; ((i < MAX_PB_ENTR) AND (pb_lst[i].index NEQ ACI_NumParmNotPresent)); i++)
    {
      USHORT len_cvtd_text=0;
 
      cpbr_data.index = (U8)pb_lst[i].index;
  
      cpbr_data.c_number = strlen((CHAR*)pb_lst[i].number);
      
      cpbr_data.c_number = (cpbr_data.c_number > BAT_MAX_CPBR_NUMBER_LEN) 
                            ? BAT_MAX_CPBR_NUMBER_LEN 
                            : cpbr_data.c_number;

      strncpy((CHAR*)cpbr_data.number, pb_lst[i].number, cpbr_data.c_number+1);  /* Include null terminator for Resp_.. () */
  
      /* BAT stores the type of address in a single 8-bit value. */
      cpbr_data.type = toa_merge(pb_lst[i].type);
     
      /*
      *   Convert the data read from the SIM into the currently 
      *   selected character set.
      */
      utl_chsetFromSim(
        (UBYTE *)pb_lst[i].text.data,
        pb_lst[i].text.len,
        (UBYTE *)cpbr_data.text,
        BAT_MAX_CPBR_TEXT_LEN,
        &len_cvtd_text,
        GSM_ALPHA_Def);

      cpbr_data.c_text=(U8)len_cvtd_text;

      TRACE_EVENT_P2("sBAT_PlusCPBR(): index = %i c_text = %d", cpbr_data.index, cpbr_data.c_text);  
      
      /* vsi_t_sleep (aci_handle, 500); */
      aci_bat_send(src_infos_psi,&resp);
    }
    /* remember updated start index and initial stop index for possible next block of entries to send to APP */
    src_infos_psi->index1 = last_idx + 1;
    src_infos_psi->index2 = stop_idx;
  }
  else
  {
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_Unknown);
    return(ACI_BAT_FAIL);      
  }

  if (last_idx < stop_idx)
  {
    src_infos_psi->large_type = TRUE;
    return (ACI_BAT_EXCT);
  }

  src_infos_psi->large_type = FALSE;
  return (ACI_BAT_CMPL);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : tBAT_PlusCPBR        |
+--------------------------------------------------------------------+

  PURPOSE :
*/

GLOBAL T_ACI_BAT_RSLT tBAT_PlusCPBR (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret=ACI_BAT_FAIL;
  SHORT first;
  SHORT last;
  UBYTE nlength;
  UBYTE tlength;

  TRACE_FUNCTION ("tBAT_PlusCPBR()");

  /*
  *   Call the corresponding tAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)tAT_PlusCPBR(src_infos_psi->srcId,&first,&last,&nlength,&tlength);

  /*
  *   If the command completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_tst_plus_cpbr cpbr_data;
 
    resp.ctrl_response=BAT_RES_TST_PLUS_CPBR;
    resp.response.ptr_tst_plus_cpbr=&cpbr_data;

    cpbr_data.index_f=(U8)first;
    cpbr_data.index_l=(U8)last;
    cpbr_data.nlength=(S16)nlength;
    cpbr_data.tlength=(S16)tlength;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCPBF        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBF_CB (T_ACI_DTI_PRC_PSI *src_infos_psi)
{
  T_BAT_cmd_send cmd;
  T_BAT_cmd_set_plus_cpbf cpbf;

  cmd.ctrl_params = BAT_CMD_SET_PLUS_CPBF;
  cmd.params.ptr_set_plus_cpbf = &cpbf;

  TRACE_FUNCTION ("sBAT_PlusCPBF_CB()");

  /* restore search string if ongoing command */
  if ( src_infos_psi->search_str_ptr NEQ NULL )
  {
    TRACE_EVENT("Restore search string"); 
    /* index 1 stores the length of the string in the case of cpbf */
    cpbf.c_findtext = (U8)src_infos_psi->index1;
    memcpy(cpbf.findtext, src_infos_psi->search_str_ptr, BAT_MAX_CPBF_FIND_TEXT_LEN);
  }
  return (sBAT_PlusCPBF(src_infos_psi, &cmd));
}
  
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCPBF (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_PB_TEXT pbtext;
  USHORT len;
  T_ACI_BAT_RSLT ret;
  T_BAT_cmd_set_plus_cpbf *cpbf_cmd;
  SHORT found = -1;
  T_ACI_PB_ENTR pb[MAX_PB_ENTR];
  SHORT i;
  T_ACI_CPBF_MOD search_mode; // replaced by global var
  T_BAT_cmd_response resp;
  T_BAT_res_set_plus_cpbf cpbf_rsp;

  TRACE_FUNCTION ("sBAT_PlusCPBF()");

  resp.ctrl_response = BAT_RES_SET_PLUS_CPBF;
  resp.response.ptr_set_plus_cpbf = &cpbf_rsp;

  /*
  *   Get a pointer to the CPBF data for convenience.
  */
  cpbf_cmd = cmd->params.ptr_set_plus_cpbf;

  /*
  *   We may have to call sAT_PlusCPBF() more than once, if there are
  *   more than MAX_PB_ENTR entries found. The search mode is used
  *   to tell the ACI whether this is a new search or a continuation of
  *   the old one.
  *   If there has been a valid string pointer saved to the search_str_ptr
  *   the seek has to be continued. 
  */

  if  ((src_infos_psi->search_str_ptr NEQ NULL)
   AND (strncmp(src_infos_psi->search_str_ptr, cpbf_cmd->findtext, cpbf_cmd->c_findtext) EQ 0))
  {
    found = src_infos_psi->index2; /* recover number found*/
    search_mode = CPBF_MOD_NextSearch;
    TRACE_EVENT_P1("Stored Search string: %s", src_infos_psi->search_str_ptr);
    TRACE_EVENT_P1("Stored String length: %d", src_infos_psi->index1);
  }
  else
  {
    search_mode = CPBF_MOD_NewSearch;
  }
  
  /*
  *   If the search string has zero length or is larger than the ACI function
  *   can handle then there's no point continuing.
  *   In fact there should be a differentiation between UCS2 and 8bit based coding schemes. 
  *   Additionally it has to be considered that the string given within the BAT command is ACSII encoded. 
  */
 if (((ati_user_output_cfg[src_infos_psi->srcId].cscsChset EQ CSCS_CHSET_Ucs2)
        && ((cpbf_cmd->c_findtext>BAT_MAX_CPBF_FIND_TEXT_LEN)||(cpbf_cmd->c_findtext<1)) )
      ||
      ((ati_user_output_cfg[src_infos_psi->srcId].cscsChset NEQ CSCS_CHSET_Ucs2)
        && ((cpbf_cmd->c_findtext>MAX_PHB_NUM_LEN)||(cpbf_cmd->c_findtext<1)) ) )
  {
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_Unknown);
    return(ACI_BAT_FAIL);
  }

  TRACE_EVENT_P1("Search string: %s", cpbf_cmd->findtext);
  TRACE_EVENT_P1("String length: %d", cpbf_cmd->c_findtext);

  utl_chsetToSim(
    (UBYTE *)cpbf_cmd->findtext,
    (USHORT)cpbf_cmd->c_findtext,
    (UBYTE *)pbtext.data,
    &len,
    GSM_ALPHA_Def);

  if (len > MAX_PHB_NUM_LEN)
  {
    /*
    *   Shouldn't get here as that would mean that memory has been
    *   overwritten. Currently utl_chsetToSim() has no specific mechanism
    *   to prevent this.
    */
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_TxtToLong);
    return(ACI_BAT_FAIL);
  }

  pbtext.len = (UBYTE)len;
  pbtext.cs  = (T_ACI_CS)CS_Sim;

  
  /*
  *   Call the corresponding sAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */

  TRACE_EVENT_P1("search_mode: %d", search_mode);  
  TRACE_EVENT_P1("pbtext.data: %s", pbtext.data);
  TRACE_EVENT_P1("pbtext.len:  %d", pbtext.len);


  /* found is not overwritten in the case of NEXT_SEARCH */
  ret=(T_ACI_BAT_RSLT)sAT_PlusCPBF(
    src_infos_psi->srcId,
    &pbtext,
    search_mode,
    &found,
    pb);

  TRACE_EVENT_P1("sAT_PlusCPBF returns: %d", ret);
  TRACE_EVENT_P1("-- found entries: %d", found);

  /*
  *   If the command fails, get out now.
  */
  if (ret!=ACI_BAT_CMPL)
    return(ret);

  /*
  *   We have received a list, however the BAT response only
  *   allows for single items. So we must send each one 
  *   individually.
  */
  for (i=0;((i<found) && (i<MAX_PB_ENTR));i++)
  {
    USHORT len_cvtd_text=0;

    cpbf_rsp.index=(U8)pb[i].index;

    TRACE_EVENT("send the found entry"); 
    strncpy((CHAR*)cpbf_rsp.number,pb[i].number,BAT_MAX_CPBF_NUMBER_LEN);
    cpbf_rsp.c_number=strlen((CHAR*)cpbf_rsp.number);

    /*
    *   BAT stores the type of address in a single 8-bit value.
    */
    cpbf_rsp.type=toa_merge(pb[i].type);

    /*
    *   Convert the data read from the SIM into the currently 
    *   selected character set.
    */
    utl_chsetFromSim(
      (UBYTE *)pb[i].text.data,
      pb[i].text.len,
      (UBYTE *)cpbf_rsp.text,
      BAT_MAX_CPBF_TEXT_LEN,
      &len_cvtd_text,
      GSM_ALPHA_Def);

    cpbf_rsp.c_text=(U8)len_cvtd_text;

    /* vsi_t_sleep (aci_handle, 500); */

    aci_bat_send(src_infos_psi,&resp);
  }

  /*
  *   Set the search mode for the next iteration, should there be
  *   one.
  */
   
  if (found>MAX_PB_ENTR)
  {
    TRACE_EVENT("More entries found"); 
    /* remember the string to search for (only necessary for first iteration)*/
    if (search_mode EQ CPBF_MOD_NewSearch)
    {
      TRACE_EVENT("Store string"); 
      src_infos_psi->index1 = (U16)cpbf_cmd->c_findtext; /* str length */
      ACI_MALLOC(src_infos_psi->search_str_ptr, BAT_MAX_CPBF_FIND_TEXT_LEN); 
      memcpy(src_infos_psi->search_str_ptr, cpbf_cmd->findtext, BAT_MAX_CPBF_FIND_TEXT_LEN);
    }
    /* This is a multi-line response */
    src_infos_psi->large_type = TRUE;
    /* Save the number of found items - MAX_PB_ENTR send to user */
    src_infos_psi->index2 = found - MAX_PB_ENTR; 
    /* Still executing */
    ret = ACI_BAT_EXCT;
  }
  else /* no further entries to find */
  {
    TRACE_EVENT("reset search string"); 
    /* reset search string info for iterations */
    src_infos_psi->index1 = 0; /* str length reset */
    src_infos_psi->index2 = 0; /* number found reset */
    if (src_infos_psi->search_str_ptr NEQ NULL) /* str mem reset, if necessary */
    {
      ACI_MFREE(src_infos_psi->search_str_ptr);
      src_infos_psi->search_str_ptr = NULL;
    }
    /* This is NO multiline response */
    src_infos_psi->large_type = FALSE;
    /* completed */
    ret = ACI_BAT_CMPL;
  }
  
  return (ret);  
  
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : tBAT_PlusCPBF        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT tBAT_PlusCPBF (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  UBYTE nlength;
  UBYTE tlength;

  TRACE_FUNCTION ("tBAT_PlusCPBF()");

  /*
  *   Call the corresponding ACI function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)tAT_PlusCPBF(src_infos_psi->srcId,&nlength,&tlength);

  /*
  *   If the command completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_tst_plus_cpbf cpbf_data;
 
    resp.ctrl_response=BAT_RES_TST_PLUS_CPBF;
    resp.response.ptr_tst_plus_cpbf=&cpbf_data;

    cpbf_data.nlength=(S16)nlength;
    cpbf_data.tlength=(S16)tlength;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCSVM        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCSVM (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_TOA toa;
  CHAR number[BAT_MAX_CSVM_NUMBER_LEN+1];
  CHAR *pnumber;
  T_ACI_CSVM_MOD mode;
  T_BAT_cmd_set_plus_csvm *csvm;
  UBYTE num_len;

  TRACE_FUNCTION ("sBAT_PlusCSVM()");

  /*
  *   Get a pointer to the BAT structure for convenience.
  */
  csvm=cmd->params.ptr_set_plus_csvm;

  /*
  *   This assumes that T_ACI_CSVM_MOD and T_BAT_plus_csvm_mode are
  *   equivalent. They are, except that the ACI version has a
  *   NotPresent value - this is not a problem here as we are converting
  *   from BAT format to ACI format.
  */
  mode=(T_ACI_CSVM_MOD)csvm->mode;

  if (csvm->v_number==TRUE)
  {
    /*
    *   I don't think that CSVM requires a null-terminated string, but
    *   it's best to err on the side of caution.
    */
    pnumber=number;
    memset(number,0,sizeof(number));
    memcpy(number,csvm->number,BAT_MAX_CSVM_NUMBER_LEN);

    if (csvm->c_number>BAT_MAX_CSVM_NUMBER_LEN)
      num_len=(UBYTE)BAT_MAX_CSVM_NUMBER_LEN;
    else
      num_len=(UBYTE)csvm->c_number;
  }
  else
  {
    pnumber=NULL;
    num_len=0;
  }

  /*
  *   BAT stores the type of address in a single 8-bit value. We need to
  *   convert this to the ACI format.
  */
  toa=toa_demerge(csvm->type);

  /*
  *   Call the corresponding ACI function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)sAT_PlusCSVM(src_infos_psi->srcId,mode,pnumber,num_len,&toa);

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : qBAT_PlusCSVM        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT qBAT_PlusCSVM (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret = ACI_BAT_FAIL;
  T_ACI_CSVM_MOD mode;
  CHAR number[BAT_MAX_CSVM_NUMBER_LEN+1];
  SHORT toa_val;

  TRACE_FUNCTION ("qBAT_PlusCSVM()");

  /*
  *   Call the corresponding qAT function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)qAT_PlusCSVM(
    src_infos_psi->srcId,
    &mode,
    number,
    BAT_MAX_CSVM_NUMBER_LEN,
    &toa_val);

  /*
  *   If the query completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    T_BAT_cmd_response resp;
    T_BAT_res_que_plus_csvm csvm_data;
 
    resp.ctrl_response=BAT_RES_QUE_PLUS_CSVM;
    resp.response.ptr_que_plus_csvm=&csvm_data;

    /*
    *   We can't just cast the ACI value to the BAT value as it
    *   might be CSVM_MOD_NotPresent, for which the BAT has no
    *   equivalent.
    */
    csvm_data.mode=(mode==CSVM_MOD_Enable) ? BAT_CSVM_MODE_ENABLE:BAT_CSVM_MODE_DISABLE;

    /*
    *   We trust the ACI to give us a null-terminated string.
    */
    strcpy((CHAR*)csvm_data.number,number);
    csvm_data.c_number=strlen((CHAR*)csvm_data.number);

    /*
    *   Note that in this instance the ACI is giving us the TOA as
    *   a single number, rather than in its usual T_ACI_TOA format.
    */
    csvm_data.type=(U8)toa_val;

    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : sBAT_PlusCLAN        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT sBAT_PlusCLAN (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_LAN_SUP lng;
  CHAR str[BAT_MAX_CLAN_CODE_LEN+1];
  USHORT i;

  TRACE_FUNCTION ("sBAT_PlusCLAN()");

  /*
  *   Ensure that we have a null-terminated string.
  */
  memset(str,0,sizeof(str));
  memcpy(str,cmd->params.ptr_set_plus_clan->code,BAT_MAX_CLAN_CODE_LEN);

  lng.str=NULL;

  /*
  *   The BAT provides the language in string form only, we must also
  *   calculate the corresponding value. To do this we use the lookup
  *   table "lngs".
  *
  *   GSM 07.07 says that "AUTO" should be used for automatic mode, but
  *   the (ATI) code uses "au". Here we want to accept both.
  */  
  if (!strcmp(str,"AUTO"))
  {
    lng.lng=CLAN_LNG_AUT;
    lng.str="AUTO";
  }
  else
  {
    for (i=0;lngs[i].str;i++)
    {
      if (!strcmp(lngs[i].str,str))
      {
        lng.str=lngs[i].str;
        lng.lng=lngs[i].lng;
        break;
      }
    }
  }

  if (lng.str==NULL)
  {
    /*
    *   Can't work out the language so give up.
    */
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_OpNotSupp);
    return(ACI_BAT_FAIL);
  }

  /*
  *   Call the corresponding ACI function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)sAT_PlusCLAN(src_infos_psi->srcId,&lng);

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : qBAT_PlusCLAN        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT qBAT_PlusCLAN (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_LAN_SUP lng;
  T_BAT_cmd_response resp;
  T_BAT_res_que_plus_clan clan_data;

  TRACE_FUNCTION ("qBAT_PlusCLAN()");

  resp.ctrl_response=BAT_RES_QUE_PLUS_CLAN;
  resp.response.ptr_que_plus_clan=&clan_data;

  memset(&clan_data,0,sizeof(clan_data));
  lng.str=(CHAR *)clan_data.code;

  /*
  *   Call the corresponding ACI function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  *   We are trusting this function not to deliver too long
  *   a string. At the time of writing, it can only give us two
  *   characters, which we easily have room for in the BAT
  *   message.
  */
  ret=(T_ACI_BAT_RSLT)qAT_PlusCLAN(src_infos_psi->srcId,&lng);

  /*
  *   If the query completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    clan_data.c_code=strlen(lng.str);
    aci_bat_send(src_infos_psi,&resp);
  }

  return(ret);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-F&D (8411)            MODULE  : ACI_BAT              |
| STATE   : code                      ROUTINE : tBAT_PlusCLAN        |
+--------------------------------------------------------------------+

  PURPOSE : 
*/
GLOBAL T_ACI_BAT_RSLT tBAT_PlusCLAN (T_ACI_DTI_PRC_PSI *src_infos_psi,
                                     T_BAT_cmd_send    *cmd)
{
  T_ACI_BAT_RSLT ret;
  T_ACI_LAN_SUP lng[MAX_LAN];
  SHORT last_idx;

  TRACE_FUNCTION ("tBAT_PlusCLAN()");

  /*
  *   Call the corresponding ACI function. T_ACI_BAT_RSLT is
  *   assumed to be equivalent to T_ACI_RESULT.
  */
  ret=(T_ACI_BAT_RSLT)tAT_PlusCLAN(src_infos_psi->srcId,&last_idx,lng);

  /*
  *   If the command completes, send the response now.
  */
  if (ret==ACI_BAT_CMPL)
  {
    USHORT i;
    T_BAT_cmd_response resp;
    T_BAT_res_tst_plus_clan clan_data;
 
    resp.ctrl_response=BAT_RES_TST_PLUS_CLAN;
    resp.response.ptr_tst_plus_clan=&clan_data;

    /*
    *   We have received a list, however the BAT response only
    *   allows for single items. So we must send each one 
    *   individually.
    */
    for (i=0;i<last_idx;i++)
    {
      clan_data.c_code=strlen(lng[i].str);

      /*
      *   Discard any languages for which the string is too long for
      *   BAT (this should never happen).
      */
      if (clan_data.c_code<=BAT_MAX_CLAN_CODE_LEN)
      {
        memcpy(clan_data.code,lng[i].str,BAT_MAX_CLAN_CODE_LEN);
        aci_bat_send(src_infos_psi,&resp);
      }
    }
  }

  return(ret);
}