diff g23m/condat/ms/src/aci/cphs.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/g23m/condat/ms/src/aci/cphs.c	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,2665 @@
+/*
++--------------------------------------------------------------------+
+| PROJECT:                              $Workfile:: cphs.c          $|
+| $Author::                             $Revision::                 $|
+| CREATED:                              $Modtime::                  $|
+| STATE  : code                                                      |
++--------------------------------------------------------------------+
+
+   MODULE  : CPHS
+
+   PURPOSE : This module contains the CPHS functionalities.
+*/
+
+#ifdef FF_CPHS
+
+#ifndef CPHS_C
+#define CPHS_C
+
+/* needed for all files that are part of ACI */
+#include "aci_all.h"
+#include "aci_cmh.h"
+#include "phb.h"
+#include "cphs.h"
+
+#include "psa.h"
+#include "cmh.h" 
+#include "psa_sim.h"
+#include "dti_conn_mng.h"
+#include "cmh_sim.h" 
+
+/* Definition of records indices in association with cphs lines */
+#define CPHS_LINE1_REC     (1)
+#define CPHS_LINE2_REC     (2)
+#define CPHS_LINE_DATA_REC (3)
+#define CPHS_LINE_FAX_REC  (4)
+
+/* cphs initialising status */
+typedef enum
+{
+  CPHS_NOT_INITIALISED = 0,
+  CPHS_INITIALISING,           /* currently initialising */
+  CPHS_INITIALISED,            /* initialised, currently does nothing */
+  CPHS_REFRESHING,             /* refreshing cached data */
+  CPHS_WRITING_CFU,            /* writing new CFU status on SIM */
+  CPHS_WRITING_VWI,            /* writing new VWI status on SIM: user initiated */
+  CPHS_WRITING_VWI_IND         /* writing new VWI status on SIM: network initiated */
+} T_CPHS_STATUS;
+
+/* data send to SIM */
+static UBYTE exchData[100];
+
+/* CPHS status: provides information on what action is currently on progress */
+static T_CPHS_STATUS cphs_status = CPHS_NOT_INITIALISED;
+
+/* parameter describing at what step updating currently is */
+static UBYTE sim_cache_update_state = CPHS_SIM_NOT_UPDATING;
+
+#define CINF_SIZE (3)
+
+/* VWI and CFU tables have to have the same size */
+#define FLAG_TABLE_SIZE (2)
+#define CFU_SIZE FLAG_TABLE_SIZE
+#define VWI_SIZE FLAG_TABLE_SIZE
+
+typedef struct
+{
+  T_CPHS_USER_CB  *user_cb;                /* callback used by CPHS module to pass results to ACI */
+  UBYTE           current_record;          /* record currently read */
+  UBYTE           *sim_read_record_buffer; /* buffer for record currently read */
+
+  UBYTE           tmp_activate_state;      /* TEMP setting being currently written on SIM (CFU or VWI) */ 
+  T_CPHS_LINES    tmp_lines;               /* TEMP lines being currently written on SIM (CFU or VWI) */
+
+  UBYTE           tmp_flag_set[FLAG_TABLE_SIZE]; /* Flags Field (corresponding to tmp_lines) being currently
+                                                    written on SIM (CFU or VWI) */
+  UBYTE           tmp_info[CINF_SIZE];     /* voice mail waiting bitmask of CPHS lines */
+} T_CPHS_INTERNAL_PARAMS;
+
+LOCAL T_CPHS_INTERNAL_PARAMS *cphs_internal_params;
+
+/***** Parameters concerning ALS info ********/
+/* how many different lines are there ? line1, line2, fax, data */
+/* defines order of presentation of the lines when testing command AT%CPALS=? */
+#define LINE1_ID    (0)
+#define LINE2_ID    (1)
+#define LINEDATA_ID (2)
+#define LINEFAX_ID  (3)
+#define MAX_LINE_ID (4)
+
+#define DEFAULT_LINE1_NAME "Line 1"
+#define DEFAULT_LINE2_NAME "Line 2"
+#define DEFAULT_DATA_NAME "Data"
+#define DEFAULT_FAX_NAME "Fax"
+#define CPHS_MAX_SIZE_ALPHA (22)
+
+typedef struct
+{
+  T_CPHS_LINES line;
+  CHAR         line_desc[CPHS_MAX_SIZE_ALPHA];
+
+} T_CPHS_ALS_NAMES;
+
+
+/* structure containing the cached parameters from SIM */
+typedef struct
+{
+  UBYTE           cfu_flags[CFU_SIZE];   /* same format as on the SIM: field 6F13 */
+  UBYTE           vwi_flags[VWI_SIZE];   /* same format as on the SIM: field 6F11 */
+  UBYTE           opn_long[CPHS_MAX_OPER_LONG];   /* operator long name */
+  UBYTE           opn_short[CPHS_MAX_OPER_SHORT]; /* operator shortname */
+  T_CPHS_INF_NUM  *info_numbers;         /* contains all info numbers entries */
+  UBYTE           max_info_numbers;      /* index of last entry in info number list */
+  T_CPHS_ALS_NAMES *als;
+  UBYTE           max_als_names_entries;
+  T_CPHS_CINF     info;                  /* cphs information */
+  UBYTE           csp[CPHS_MAX_CSP];     /* same format as on the SIM: field 6F15 */
+  UBYTE           csp_length;            /* Value given by SIM after Read action */
+  UBYTE           orange_csp2[CPHS_MAX_CSP2];    /* Orange specific - same format as on the SIM: field 0x6f98 */
+  UBYTE           orange_csp2_length;            /* Orange specific - Value given by SIM after Read action */
+  T_CPHS_MB       *mb_numbers;
+  UBYTE           max_mb_numbers;
+  UBYTE           max_mb_entry_length;   /* max length for mailbox entry */
+} T_CPHS_CACHED_PARAMS;
+
+LOCAL T_CPHS_CACHED_PARAMS *cphs_cached_params; /* memory allocated at initialisation */
+
+LOCAL void cphs_cache_sim_data(UBYTE max_records, UBYTE latest_record_len);
+LOCAL void cphs_set_next_update_state(void);
+LOCAL T_CPHS_RET cphs_get_indicator_flag(UBYTE *flag_set, T_CPHS_LINES line, UBYTE indicator);
+LOCAL void cphs_write_indicator_flag(UBYTE        flag_set, 
+                                     T_CPHS_LINES lines, 
+                                     UBYTE        indicator);
+LOCAL void get_name_pointer_over_lineid(T_CPHS_LINES line, CHAR **line_desc, UBYTE max_lined);
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : Internal functions       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Set of functions used internally.
+*/
+
+/* Informs user of the result of an operation */
+GLOBAL void cphs_inform_user(T_CPHS_CB     callback_type, 
+                             T_CPHS_RET    return_value,
+                             UBYTE         set_flag,
+                             T_CPHS_LINES  line)
+{
+  T_CPHS_PARAMS user_cb_params;
+
+  TRACE_EVENT_P4("cphs_inform_user(): cb_type: %d, result: %d, flag: %d, line: %d", 
+                                      callback_type, return_value, set_flag, line);
+
+  user_cb_params.cb_type          = callback_type;
+  user_cb_params.operation_result = return_value;
+
+  user_cb_params.set_flag = set_flag;
+  user_cb_params.line     = line;
+
+  cphs_internal_params->user_cb(&user_cb_params);
+}
+
+/* Checks whether CPHS module has been initialised or if it is currently
+being used.
+
+*** All user interface function should use this function ***
+*** to check cphs_status before processing               *** */
+GLOBAL T_CPHS_RET cphs_check_status(void)
+{
+  TRACE_FUNCTION("cphs_check_status()");
+
+  switch(cphs_status)
+  {
+  case(CPHS_NOT_INITIALISED):
+    TRACE_EVENT("CPHS has not been initialised");
+    return(CPHS_NOT_INIT);
+
+  case(CPHS_INITIALISED):
+    return(CPHS_OK);
+
+  default:
+    TRACE_EVENT("CPHS is BUSY: currently processing data");
+    return(CPHS_BUSY);
+  }
+}
+
+
+/* Aborts currently processed operation */
+GLOBAL void cphs_abort_current_action(void)
+{
+  TRACE_EVENT_P1("cphs_abort_current_action(): action id: %d", cphs_status);
+
+  switch(cphs_status)
+  {
+  case(CPHS_INITIALISING):
+  case(CPHS_REFRESHING):
+    /* CPHS module was currently updating cached data from the SIM */
+    sim_cache_update_state = CPHS_SIM_NOT_UPDATING;
+
+    cphs_inform_user(CPHS_INIT_RES, CPHS_FAIL, NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+    cphs_status = CPHS_NOT_INITIALISED; /* initialising aborted */
+    return;
+
+  default:
+    cphs_status = CPHS_INITIALISED;
+    return;
+  }
+}
+
+#define RECORD_BUFF (0)
+#define INFO_BUFF   (1)
+#define ALS_BUFF    (2)
+#define MB_BUFF     (3)
+
+LOCAL void free_buffer(UBYTE buffer_id)
+{
+  switch(buffer_id)
+  {
+  case(RECORD_BUFF):
+    if(cphs_internal_params->sim_read_record_buffer NEQ NULL)
+    {
+      MFREE(cphs_internal_params->sim_read_record_buffer);
+      cphs_internal_params->sim_read_record_buffer = NULL;
+    }
+    break;
+
+  case(INFO_BUFF):
+    if(cphs_cached_params->info_numbers NEQ NULL)
+    {
+      //MFREE(cphs_cached_params->info_numbers);
+      cphs_cached_params->info_numbers = NULL;
+    }
+    break;
+
+  case(ALS_BUFF):
+    if(cphs_cached_params->als NEQ NULL)
+    {
+      MFREE(cphs_cached_params->als);
+      cphs_cached_params->als = NULL;
+    }
+    break;
+
+  case(MB_BUFF):
+    if(cphs_cached_params->mb_numbers NEQ NULL)
+    {
+      MFREE(cphs_cached_params->mb_numbers);
+      cphs_cached_params->mb_numbers = NULL;
+    }
+    break;
+  }
+}
+
+LOCAL void write_dummy_function(UBYTE info_number_index, UBYTE *sim_data, UBYTE record_len)
+{
+  TRACE_FUNCTION("write_dummy_function()");
+}
+
+LOCAL void write_info_number(UBYTE info_number_index, UBYTE *sim_data, UBYTE record_len)
+{
+  UBYTE          alpha_length, bcd_length;
+  BOOL           check_network_specific_bit,
+                 check_premium_service_bit;
+  UBYTE          *ptr;
+  T_CPHS_INF_NUM *current_info_number;
+
+  TRACE_FUNCTION("write_info_number()");
+
+  /* write data read from SIM for current_record */
+  ptr = sim_data;
+
+  /* get structure where data are to be written for this record */
+  current_info_number = &cphs_cached_params->info_numbers[info_number_index];
+
+  current_info_number->element_index = info_number_index;
+
+  /* first byte: alpha_length */
+  alpha_length = *ptr;
+  if(alpha_length EQ 0xFF)
+  {
+    /* it has to be a NULL entry: Shall be ignored (see CPHS recom.). Jump to next record */
+    return;
+  }
+
+  /* second byte */
+  ptr++;
+  check_network_specific_bit       = *ptr & 0x20;
+  check_premium_service_bit        = *ptr & 0x10;
+  current_info_number->index_level = *ptr & 0x0F;
+
+  if(check_network_specific_bit)
+  {
+    /* info number is network specific */
+    current_info_number->network_flag = TRUE;
+  }
+  else
+    current_info_number->network_flag = FALSE;
+
+  if(check_premium_service_bit)
+  {
+    /* info number is network specific */
+    current_info_number->premium_flag = TRUE;
+  }
+  else
+    current_info_number->premium_flag = FALSE;
+
+  /* third byte to alpha_len+2 */
+  /* Check 03.40 ?? */
+  ptr++;
+
+  if(alpha_length > sizeof(current_info_number->alpha_tag))
+  {
+    alpha_length = sizeof(current_info_number->alpha_tag);
+  }
+
+  /* initialize with 0s */
+  memset(current_info_number->alpha_tag,
+         0,
+         sizeof(current_info_number->alpha_tag));
+  memcpy(current_info_number->alpha_tag, ptr, alpha_length);
+
+  /* Length of BCD byte */     /*********** ignore ??? ***************/
+  ptr += alpha_length;
+  if(*ptr EQ 0xFF)
+  {
+    /* this is a folder: no number information */
+    bcd_length = 1; /* TON/NPI */
+  }
+  else
+    bcd_length = *ptr;
+
+  /* TON and NPI byte */
+  ptr++;
+  current_info_number->type_of_address = *ptr;
+  bcd_length--;  /* TON and NPI are counted in bcd length */
+
+  /* Digits section */
+  ptr++;
+  /* initialize with 0s */
+  memset(current_info_number->number,
+         0,
+         sizeof(current_info_number->number));
+  if(2*bcd_length > sizeof(current_info_number->number))
+  {
+    bcd_length = sizeof(current_info_number->number);
+  }
+  cphs_bcd2number(current_info_number->number, ptr, bcd_length);
+
+
+  /*********** Trace info number read: ****************/
+  TRACE_EVENT_P7("Info Number: add: %d, index: %d, alpha: %s, number: %s, index_level: %d, premium: %d, network: %d",
+                 current_info_number,
+                 current_info_number->element_index,
+                 current_info_number->alpha_tag,
+                 current_info_number->number,
+                 current_info_number->index_level,
+                 current_info_number->premium_flag,
+                 current_info_number->network_flag);
+}
+
+LOCAL T_CPHS_LINES translate_index2line(UBYTE index)
+{
+  switch(index - 1)
+  {
+    case(LINE1_ID):
+      return(CPHS_LINE1);
+
+    case(LINE2_ID):
+      return(CPHS_LINE2);
+
+    case(LINEDATA_ID):
+      return(CPHS_LINE_DATA);
+
+    case(LINEFAX_ID):
+      return(CPHS_LINE_FAX);
+
+    default:
+      TRACE_EVENT_P1("wrong index: %d", index);
+      return(CPHS_LINE_NULL);
+  }
+}
+
+LOCAL void write_als_names(UBYTE number_index, UBYTE *sim_data, UBYTE record_len)
+{
+  UBYTE max_entries, alpha_length;
+  UBYTE i;
+  CHAR  *line_desc;
+  T_CPHS_LINES lineid;
+
+  TRACE_FUNCTION("write_als_names( )");
+
+  max_entries = cphs_cached_params->max_als_names_entries;
+
+  lineid = translate_index2line(number_index);
+  get_name_pointer_over_lineid(lineid, &line_desc, max_entries);
+
+  if(line_desc EQ NULL)
+  {
+    TRACE_ERROR("line_desc is NULL");
+    return;
+  }
+
+  alpha_length = 0;
+  for(i=0 ; i<(record_len - CPHS_MIN_MB_LEN); i++)
+  {
+    if(sim_data[i] EQ 0xFF)
+    {
+      TRACE_EVENT_P1("length: %d", i);
+      break;
+    }
+    alpha_length++;
+  }
+
+  if(alpha_length EQ 0)
+  {
+    TRACE_EVENT("No alpha tag on SIM");
+    return;
+  }
+  memcpy(line_desc, sim_data, MINIMUM(alpha_length,CPHS_MAX_SIZE_ALPHA));
+  line_desc[alpha_length] = '\0';
+
+  /*********** Trace  ****************/
+  TRACE_EVENT_P3("index: %d, line: %d, alpha: %s",
+                 number_index,
+                 lineid,
+                 line_desc); 
+}
+
+LOCAL void write_mb_number(UBYTE number_index, UBYTE *sim_data, UBYTE record_len)
+{
+  UBYTE     i;
+  UBYTE     pos;
+  UBYTE     bcd_len;
+  T_CPHS_MB *current_number;
+
+  TRACE_FUNCTION("write_mb_number()");
+
+  TRACE_EVENT_P3("idx: %d, ln: %d, data: %s", 
+                 number_index, record_len, sim_data);
+
+  /* get structure where data are to be written for this record */
+  current_number = &cphs_cached_params->mb_numbers[number_index-1];
+  memset(current_number->alpha_id, 0, sizeof(current_number->alpha_id));
+  memset(current_number->number, 0, sizeof(current_number->number));
+
+  if (cphs_cached_params->max_mb_numbers < number_index)
+  {
+    cphs_cached_params->max_mb_numbers = number_index;
+  }
+
+  /* map record index to lines */
+  switch(number_index)
+  {
+  case CPHS_LINE1_REC:
+    current_number->line = CPHS_LINE1;
+    break;
+  case CPHS_LINE2_REC:
+    current_number->line = CPHS_LINE2;
+    break;
+  case CPHS_LINE_DATA_REC:
+    current_number->line = CPHS_LINE_DATA;
+    break;
+  case CPHS_LINE_FAX_REC:
+    current_number->line = CPHS_LINE_FAX;
+    break;
+  default:
+    TRACE_EVENT("unexpected record index of cphs mailbox number");
+    break;
+  }
+  
+  /* get alpha identifier, if available */
+  pos = record_len - CPHS_MIN_MB_LEN;
+  if ( ( pos > 0 ) AND ( sim_data[0] NEQ 0xFF ) )
+  {
+    for (i=0; i<pos; i++)
+    {
+      if (sim_data[i] NEQ 0xFF)
+        current_number->alpha_id[i] = sim_data[i];
+    }
+  }
+  else
+  {
+    TRACE_EVENT("empty MB alpha");
+  }
+    
+  /* get length of bcd */
+  bcd_len = sim_data[pos];
+
+  if ( bcd_len EQ 0xFF )
+  {
+    /* empty MB number */
+    TRACE_EVENT_P2("empty MB number, pos: %d, bcd_len:%d", 
+                   pos, bcd_len);
+    
+    current_number->toa = NOT_PRESENT_8BIT;
+    return;
+  }
+
+  /* TON and NPI byte */
+  pos++;
+  current_number->toa = sim_data[pos];
+  bcd_len--;  /* TON and NPI are counted in bcd length */
+
+  /* Digits section */
+  pos++;
+  if(2*bcd_len > sizeof(current_number->number))
+  {
+    bcd_len = sizeof(current_number->number);
+  }
+  cphs_bcd2number(current_number->number, &(sim_data[pos]), bcd_len);
+
+
+  /*********** Trace mailbox number read: ****************/
+  TRACE_EVENT_P5("index: %d, line: %d, alpha: %s, number: %s, toa: %d",
+                 number_index,
+                 current_number->line,
+                 current_number->alpha_id,
+                 current_number->number,
+                 current_number->toa);
+}
+
+LOCAL void write_csp_ok(UBYTE *sim_data, UBYTE record_len)
+{
+  TRACE_FUNCTION("write_csp_ok()");
+
+  if( sim_data NEQ NULL )
+  {
+    memcpy(cphs_cached_params->csp, sim_data, record_len );
+  }
+}
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_first_free          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Find first free location in mailbox list
+*/
+GLOBAL T_CPHS_RET cphs_first_free(
+  UBYTE *first_free)
+{
+  UBYTE rec_id;
+
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params==NULL");
+    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_OpNotAllow);
+    return(CPHS_FAIL);
+  }
+
+  if (cphs_cached_params->mb_numbers EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params->mb_numbers==NULL");
+    ACI_ERR_DESC(ACI_ERR_CLASS_Cme,CME_ERR_OpNotAllow);
+    return(CPHS_FAIL);
+  }
+
+  for (rec_id=0;rec_id<cphs_cached_params->max_mb_numbers;rec_id++)
+  {
+    if (cphs_cached_params->mb_numbers[rec_id].number[0] EQ 0)
+    {
+      *first_free=(UBYTE)(rec_id+1);
+      return(CPHS_OK);
+    }
+  }
+
+  /*
+  *   List is full, indicate this with 0.
+  */
+  *first_free=0;
+  return(CPHS_OK);
+}
+
+/* temp until we use lists */
+/* Size has to be set to 600 considering the length alignment of the datastrct*/
+UBYTE info_numbers_buffer[600];
+
+LOCAL void cphs_init_records_info(UBYTE max_records)
+{
+  TRACE_FUNCTION("cphs_init_records_info( )");
+  
+  if(cphs_cached_params->info_numbers EQ NULL)    // should only be checked for first entry
+  {
+    /* This should happen only once: on the SIM are more records than thought at first.
+    structure size has to be increased (and this has to be done before 1st entry is copied !!) */
+    TRACE_EVENT_P1("cphs_cached_params->info_numbers list size: %d records on SIM", max_records);
+
+/******* use lists !!!!!!!!!!!!! *****/        
+    //MALLOC(cphs_cached_params->info_numbers, (ULONG)(max_records*sizeof(T_CPHS_INF_NUM)));
+    cphs_cached_params->info_numbers = (T_CPHS_INF_NUM*)&info_numbers_buffer;
+    cphs_cached_params->max_info_numbers = max_records;
+  }
+      
+  /* First entry should be "ROOT" with index 0 */
+  cphs_cached_params->info_numbers[0].element_index = 0;
+  cphs_cached_params->info_numbers[0].index_level   = 0;
+  sprintf(cphs_cached_params->info_numbers[0].alpha_tag, "ROOT");
+  memset(cphs_cached_params->info_numbers[0].number,
+         0,
+         sizeof(cphs_cached_params->info_numbers[0].number));
+}
+
+LOCAL void cphs_init_records_mailbox(UBYTE max_records)
+{
+  TRACE_FUNCTION("cphs_init_records_mailbox( )");
+
+  if(cphs_cached_params->mb_numbers EQ NULL)    // should only be checked for first entry
+  {
+    
+  /* This should happen only once: on the SIM are more records than thought at first.
+    structure size has to be increased (and this has to be done before 1st entry is copied !!) */
+    TRACE_EVENT_P1("cphs_cached_params->mb_numbers list size: %d records on SIM", max_records);
+
+    MALLOC(cphs_cached_params->mb_numbers, (USHORT)(max_records*sizeof(T_CPHS_MB)));
+
+    cphs_cached_params->max_mb_numbers     = max_records;
+  }
+  
+  cphs_cached_params->mb_numbers[0].line = CPHS_LINE_NULL;
+  cphs_cached_params->mb_numbers[0].toa  = NOT_PRESENT_8BIT;
+  memset(cphs_cached_params->mb_numbers[0].number, 0,
+         sizeof(cphs_cached_params->info_numbers[0].number));
+  memset(cphs_cached_params->mb_numbers[0].alpha_id, 0,
+         sizeof(cphs_cached_params->mb_numbers[0].alpha_id));
+}
+
+LOCAL void initialize_als_info(UBYTE als_max_records)
+{
+  CHAR *line_desc;
+
+  TRACE_FUNCTION("initialize_als_info( )");
+
+  MALLOC(cphs_cached_params->als, (USHORT)(als_max_records* sizeof(T_CPHS_ALS_NAMES)));
+  cphs_cached_params->max_als_names_entries = als_max_records;
+
+  /* for SIMs with als_max_records > MAX_LINE_ID */
+  if (als_max_records > MAX_LINE_ID)
+      als_max_records = MAX_LINE_ID;
+
+  switch (als_max_records)
+  {
+    case (LINEFAX_ID+1):
+      cphs_cached_params->als[LINEFAX_ID].line = CPHS_LINE_FAX;
+      get_name_pointer_over_lineid(CPHS_LINE_FAX, &line_desc, als_max_records);
+      sprintf(line_desc, DEFAULT_FAX_NAME);
+	  //lint -fallthrough
+    case (LINEDATA_ID+1):
+      cphs_cached_params->als[LINEDATA_ID].line = CPHS_LINE_DATA;
+      get_name_pointer_over_lineid(CPHS_LINE_DATA, &line_desc, als_max_records);
+      sprintf(line_desc, DEFAULT_DATA_NAME);
+	  //lint -fallthrough
+    case (LINE2_ID+1):
+      cphs_cached_params->als[LINE2_ID].line = CPHS_LINE2;
+      get_name_pointer_over_lineid(CPHS_LINE2, &line_desc, als_max_records);
+      sprintf(line_desc, DEFAULT_LINE2_NAME);
+	  //lint -fallthrough
+    case (LINE1_ID+1):
+      cphs_cached_params->als[LINE1_ID].line = CPHS_LINE1;
+      get_name_pointer_over_lineid(CPHS_LINE1, &line_desc, als_max_records);
+      sprintf(line_desc, DEFAULT_LINE1_NAME);
+  }
+}
+
+LOCAL void cphs_init_records_alsnames(UBYTE max_records)
+{
+  TRACE_FUNCTION("cphs_init_records_alsnames( )");
+
+  TRACE_EVENT_P1("cphs_cached_params->als list size: %d records on SIM", max_records);
+
+  if(cphs_cached_params->als EQ NULL)
+  {
+  /* This should happen only once: on the SIM are more records than thought at first.
+    structure size has to be increased (and this has to be done before 1st entry is copied !!) */
+
+    /* init als name structure */
+    initialize_als_info(max_records);
+  }
+}
+
+LOCAL void cphs_init_records(UBYTE max_records, UBYTE sim_update_type)
+{
+  TRACE_FUNCTION("cphs_init_records( )");
+  
+  switch (sim_update_type)
+  {
+    case(CPHS_SIM_INFO_NUMS):
+    case(CPHS_SIM_INFO_NUMS_EA01):
+      cphs_init_records_info(max_records);
+      break;
+
+    case(CPHS_SIM_MB):
+      cphs_init_records_mailbox(max_records);
+      break;
+
+    case(CPHS_SIM_ALSNAMES):
+      cphs_init_records_alsnames(max_records);
+      break;
+
+    default:
+      TRACE_EVENT_P1("Wrong sim_update_state: %d", sim_update_type);
+      break;
+  }
+
+}
+
+
+#define DEFAULT_MAXSIZE_OF_RECORD (100)
+typedef void T_CPHS_WRITE_NUMBER_FCT (UBYTE number_index, UBYTE *sim_data, UBYTE record_len);
+
+LOCAL T_CPHS_WRITE_NUMBER_FCT *get_the_specific_data_update_type_dependant(UBYTE sim_update_type, 
+                                                                           UBYTE *max_number)
+{
+  switch(sim_update_type)
+  {
+    case(CPHS_SIM_INFO_NUMS):
+    case(CPHS_SIM_INFO_NUMS_EA01):
+      TRACE_EVENT("Information Numbers");
+      *max_number = cphs_cached_params->max_info_numbers;
+      return(write_info_number);
+
+    case(CPHS_SIM_MB):
+      TRACE_EVENT("Mailbox Numbers");
+      *max_number = cphs_cached_params->max_mb_numbers;
+      return(write_mb_number);
+
+    case(CPHS_SIM_ALSNAMES):
+      TRACE_EVENT("MSISDN Names");
+      *max_number = cphs_cached_params->max_als_names_entries;
+      return(write_als_names);
+
+    default:
+      TRACE_ERROR("wrong sim_update_type value");
+      break;
+  }
+  return(write_dummy_function);
+}
+
+/* returns TRUE if all records have been read... */
+LOCAL BOOL cphs_read_sim_records(UBYTE max_records, 
+                                 UBYTE sim_update_type, 
+                                 UBYTE latest_record_len)
+{
+  UBYTE *current_record = &cphs_internal_params->current_record;
+  UBYTE *number_exdata  = cphs_internal_params->sim_read_record_buffer; /* buffer for the SIM to write data: temporary buffer */
+  T_CPHS_WRITE_NUMBER_FCT *write_number;
+  UBYTE                   max_numbers;
+
+  TRACE_FUNCTION("cphs_read_sim_records()");
+
+  write_number = get_the_specific_data_update_type_dependant(sim_update_type, &max_numbers);
+
+  switch(*current_record)
+  {
+  case(0):
+    TRACE_EVENT("CPHS read records: START !!!");
+
+    /* Begin of reading of the Information Numbers */
+    if(cphs_internal_params->sim_read_record_buffer EQ NULL)
+    {
+      MALLOC(cphs_internal_params->sim_read_record_buffer, DEFAULT_MAXSIZE_OF_RECORD);   // buffer for the SIM to write data: temporary buffer
+    }
+    else
+    {
+      TRACE_EVENT("sim_read_record_buffer should be NULL: weird indeed...");
+    }
+    break;
+
+  case(1):  
+    cphs_init_records(max_records, sim_update_type);
+	  //lint -fallthrough
+  
+  default:
+    TRACE_EVENT_P1("number retrieved from SIM: record %d read", *current_record);
+    if (write_number NEQ NULL)
+    {
+      write_number(*current_record, cphs_internal_params->sim_read_record_buffer, latest_record_len);
+    }
+    break;
+  }
+
+  /* last record read ?? */
+  if(*current_record EQ max_records) 
+  {
+    *current_record = 0;
+    free_buffer(RECORD_BUFF);
+    return(TRUE);
+  }
+
+   
+  /* Read next record */
+  (*current_record)++;
+
+  cphs_sim_access_data( CPHS_SIM_READ_RECORD,
+                        sim_update_type,
+                        *current_record,
+                        cphs_internal_params->sim_read_record_buffer,
+                        DEFAULT_MAXSIZE_OF_RECORD );
+
+  return(FALSE);
+}
+
+LOCAL void get_name_pointer_over_lineid(T_CPHS_LINES line, CHAR **line_desc, UBYTE max_lined)
+{
+  UBYTE i;
+  T_CPHS_ALS_NAMES *current_als;
+
+  TRACE_FUNCTION("get_name_pointer_over_lineid()");
+
+  for(i=0; i<max_lined; i++)
+  {
+    current_als = &(cphs_cached_params->als[i]);
+    if(current_als->line EQ line)
+    {
+      *line_desc = current_als->line_desc;
+      return;
+    }
+  }
+
+  TRACE_ERROR("Ugly error: wrong line type");
+  *line_desc = NULL;
+}
+
+/* Read data to be cached from SIM */
+/* param_max_records: when reading first record, SIM return the number of records to be found
+on the SIM: thus CPHS module can check whether allocated memory is enough */
+LOCAL void cphs_cache_sim_data(UBYTE max_records, UBYTE latest_record_len)
+{
+  BOOL end_of_read;
+
+  TRACE_FUNCTION("cphs_cache_sim_data()");
+
+  /* operation to be performed */
+  switch(sim_cache_update_state)
+  {
+  case(CPHS_SIM_NOT_UPDATING):
+    /* START UPDATING !!! */
+    cphs_set_next_update_state();
+    cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+    return;
+  
+  case(CPHS_SIM_CFU):
+    /* Read Call Forwarding Flag */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_CFU,
+                          0,
+                          cphs_cached_params->cfu_flags,
+                          CFU_SIZE );
+    return;
+
+  case(CPHS_SIM_VWI):
+    /* read waiting flags on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_VWI,
+                          0,
+                          cphs_cached_params->vwi_flags,
+                          VWI_SIZE);
+    return;
+
+  case(CPHS_SIM_CINF):
+    /* read cphs info on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_CINF,
+                          0,
+                          cphs_internal_params->tmp_info,
+                          CINF_SIZE);
+    return;
+
+  case(CPHS_SIM_CSP):
+    /* read customer service profile on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_CSP,
+                          0,
+                          cphs_cached_params->csp,
+                          CPHS_MAX_CSP);
+    return;
+
+  /* Add support for Orange SIM's  */
+  case(CPHS_SIM_ORANGE_CSP):
+    /* read customer service profile on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_ORANGE_CSP,
+                          0,
+                          cphs_cached_params->orange_csp2,
+                          CPHS_MAX_CSP2);
+    return;
+
+  case(CPHS_SIM_OPNLONG):
+    /* read operator name string on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_OPNLONG,
+                          0,
+                          cphs_cached_params->opn_long,
+                          CPHS_MAX_OPER_LONG);
+    return;
+
+  case(CPHS_SIM_OPNSHORT):
+    /* read operator name short string on SIM */
+    cphs_sim_access_data( CPHS_SIM_READ_TRANSP_EF,
+                          CPHS_SIM_OPNSHORT,
+                          0,
+                          cphs_cached_params->opn_short,
+                          CPHS_MAX_OPER_SHORT);
+    return;
+
+  case(CPHS_SIM_ALSNAMES):
+  case(CPHS_SIM_MB):
+  case(CPHS_SIM_INFO_NUMS):
+  case(CPHS_SIM_INFO_NUMS_EA01):
+    /* Read mailbox/information numbers */
+
+    end_of_read = cphs_read_sim_records(max_records, sim_cache_update_state, latest_record_len);
+
+    if(end_of_read)
+    {
+      /* END of mailbox/information numbers initialising */
+      TRACE_EVENT("End of Reading Numbers");
+      cphs_set_next_update_state();
+      cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+    }
+    return;
+
+  case(CPHS_SIM_STOP_INIT):
+  default:
+    break;
+  }
+
+  /* End of update */
+  if(sim_cache_update_state NEQ CPHS_SIM_NOT_UPDATING)
+  {
+    TRACE_ERROR("wrong sim_cache_update_state state");
+  }
+  else
+  {
+    TRACE_EVENT("End of initialisation: Success");
+    sim_cache_update_state = CPHS_SIM_NOT_UPDATING;
+  }
+
+  /* reset states */
+  cphs_set_next_update_state();
+  cphs_status = CPHS_INITIALISED;
+
+  cphs_inform_user(CPHS_INIT_RES, CPHS_OK, NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+}
+
+LOCAL void cphs_set_next_update_state(void)
+{
+  switch(sim_cache_update_state)
+  {
+    /****** Mandatory Fields *******/
+  case(CPHS_SIM_NOT_UPDATING): /* START ! */
+    sim_cache_update_state = CPHS_SIM_CFU;
+    return;
+
+  case(CPHS_SIM_CFU):
+    sim_cache_update_state = CPHS_SIM_VWI;
+    return;
+
+  case(CPHS_SIM_VWI):
+    sim_cache_update_state = CPHS_SIM_OPNLONG;
+    return;
+    
+  case(CPHS_SIM_OPNLONG):
+    sim_cache_update_state = CPHS_SIM_CINF;
+    return;
+    
+    /****** Optional Fields *******/
+  case(CPHS_SIM_CINF):  
+    sim_cache_update_state = CPHS_SIM_CSP;
+    return;
+
+  case(CPHS_SIM_CSP):
+    sim_cache_update_state = CPHS_SIM_ORANGE_CSP;
+    return;
+
+  /* Add support for Orange SIM's  */
+  case(CPHS_SIM_ORANGE_CSP):
+    sim_cache_update_state = CPHS_SIM_OPNSHORT;
+    return;
+
+  case(CPHS_SIM_OPNSHORT):
+    sim_cache_update_state = CPHS_SIM_MB;    
+    return;
+
+  case(CPHS_SIM_MB):
+    sim_cache_update_state = CPHS_SIM_INFO_NUMS;    
+    return;
+
+  case(CPHS_SIM_INFO_NUMS):
+  case(CPHS_SIM_INFO_NUMS_EA01):
+    sim_cache_update_state = CPHS_SIM_ALSNAMES;
+    break;
+
+  case(CPHS_SIM_ALSNAMES):
+    sim_cache_update_state = CPHS_SIM_STOP_INIT;
+    break;
+
+  case(CPHS_SIM_STOP_INIT):
+  default:
+    sim_cache_update_state = CPHS_SIM_NOT_UPDATING;
+    break;
+  }
+}
+
+/* Should action (e.g cache updating) be aborted if field
+is not present ? */
+LOCAL BOOL is_cphs_field_mandatory(UBYTE field_type)
+{
+  TRACE_FUNCTION("is_cphs_field_mandatory()");
+  
+  switch(field_type)
+  {
+    /****** Mandatory Fields *******/
+  case(CPHS_SIM_CFU):
+  case(CPHS_SIM_VWI):
+  case(CPHS_SIM_CINF):
+  case(CPHS_SIM_OPNLONG):
+    return(TRUE);
+
+    /****** Optional fields ********/
+  case(CPHS_SIM_OPNSHORT):
+  case(CPHS_SIM_MB):
+  case(CPHS_SIM_INFO_NUMS):
+  case(CPHS_SIM_INFO_NUMS_EA01):
+  case(CPHS_SIM_ALSNAMES):
+  case(CPHS_SIM_CSP):
+    /* Add support for Orange SIM's  */
+  case(CPHS_SIM_ORANGE_CSP):
+    return(FALSE);
+
+  default:
+    TRACE_EVENT_P1("Unexpected field type: %d", field_type);
+    return(TRUE);
+  }
+}
+
+/* Positive Result of data SIM data access while updating cached data */
+LOCAL void cphs_init_sim_ok(UBYTE max_records, UBYTE sim_data_len)
+{
+  UBYTE i;
+  BOOL set_next_state = TRUE;
+  USHORT temp_sst_ushort2;
+  
+  TRACE_FUNCTION("cphs_init_sim_ok()");
+
+  TRACE_EVENT_P1("cphs_init_sim_ok(): data_len: %d", sim_data_len);
+
+  /* set next operation if needed */
+  switch(sim_cache_update_state)
+  {
+  case(CPHS_SIM_CFU):
+    TRACE_EVENT_P2("cfu_flags: %02X, %02X", cphs_cached_params->cfu_flags[0], cphs_cached_params->cfu_flags[1]);
+    if(sim_data_len < CFU_SIZE)
+    {
+      /* Typically there are 2 bytes in CFU Ef_File: Yet only the first one is
+      mandatory. Set non-present optional bytes to 0x00 */
+      for(i=sim_data_len; i<CFU_SIZE; i++)
+      {
+        cphs_cached_params->cfu_flags[i] = 0x00;        
+      }
+    }
+    break;
+
+  case(CPHS_SIM_VWI):
+    TRACE_EVENT_P2("vwi_flags: %02X, %02X", cphs_cached_params->vwi_flags[0], cphs_cached_params->vwi_flags[1]);
+    if(sim_data_len < VWI_SIZE)
+    {
+      /* Typically there are 2 bytes in VWI Ef_File: Yet only the first one is
+      mandatory. Set non-present optional bytes to 0x00 */
+      for(i=sim_data_len; i<VWI_SIZE; i++)
+      {
+        cphs_cached_params->vwi_flags[i] = 0x00;        
+      }
+    }
+    break;
+
+  case(CPHS_SIM_MB):
+    TRACE_EVENT_P1("store max_mb_entry_length: %d",sim_data_len);
+    cphs_cached_params->max_mb_entry_length = sim_data_len;
+    set_next_state = FALSE;
+    break;
+  case(CPHS_SIM_ALSNAMES):
+  case(CPHS_SIM_INFO_NUMS):
+  case(CPHS_SIM_INFO_NUMS_EA01):
+    /* decision is made within cphs_cache_sim_data( )
+       whether next action should be started */
+    set_next_state = FALSE;
+    break;
+
+  case(CPHS_SIM_CSP):
+    if(sim_data_len > CPHS_MAX_CSP)
+    {
+      TRACE_EVENT_P1("Risk of loss of CSP data: sim_data_len: %d", sim_data_len);
+      cphs_cached_params->csp_length = CPHS_MAX_CSP;
+    }
+    else
+    {
+      cphs_cached_params->csp_length = sim_data_len;
+      TRACE_EVENT_P1("cphs_cached_params->csp_length: %d", 
+                     cphs_cached_params->csp_length);
+    }
+    break;
+
+    /* Add support for Orange SIM's  */
+  case(CPHS_SIM_ORANGE_CSP):
+    if(sim_data_len > CPHS_MAX_CSP2)
+    {
+      TRACE_EVENT_P1("Risk of loss of Orange CSP2 data: sim_data_len: %d", sim_data_len);
+      cphs_cached_params->orange_csp2_length = CPHS_MAX_CSP2;
+    }
+    else
+    {
+      cphs_cached_params->orange_csp2_length = sim_data_len;
+      TRACE_EVENT_P1("cphs_cached_params->orange_csp2_length: %d", 
+                     cphs_cached_params->orange_csp2_length);
+    }
+    break;
+
+  case(CPHS_SIM_CINF):
+    TRACE_EVENT_P3("CPHS info phase: %d sst: %02X, %02X", 
+                   cphs_internal_params->tmp_info[0],
+                   cphs_internal_params->tmp_info[1],
+                   cphs_internal_params->tmp_info[2]);
+
+    cphs_cached_params->info.phase = cphs_internal_params->tmp_info[0];
+    
+    cphs_cached_params->info.sst = 0x0000;
+
+    if(sim_data_len > 1)
+    {
+      cphs_cached_params->info.sst = (cphs_internal_params->tmp_info[1] << 8);
+    }
+    
+    if(sim_data_len < CINF_SIZE)
+    {
+      /* Typically there should be at least 3 bytes in CPHS information Ef_File:
+      however, there are some SIMs with only 2 bytes... :-( Maybe with Phase 3 ?? */
+    }
+    else
+    {
+      temp_sst_ushort2 = 0x00FF & (USHORT)(cphs_internal_params->tmp_info[2]);
+      cphs_cached_params->info.sst |= temp_sst_ushort2; 
+    }
+
+    TRACE_EVENT_P1("cphs_cached_params->info.sst: %04X", 
+                   cphs_cached_params->info.sst);
+    break;
+  }
+
+  if(set_next_state)
+  {
+    cphs_set_next_update_state();
+  }
+
+  /* Continue cache from SIM */
+  cphs_cache_sim_data(max_records, sim_data_len);
+}
+
+LOCAL void writing_vwi_ok(void)
+{
+  TRACE_FUNCTION("writing_vwi_ok()");
+  
+  memcpy(cphs_cached_params->vwi_flags, cphs_internal_params->tmp_flag_set, VWI_SIZE);
+
+  TRACE_EVENT_P2("vwi_flags: %02X %02X", cphs_cached_params->vwi_flags[0], 
+                                         cphs_cached_params->vwi_flags[1]);
+
+  if(cphs_status EQ CPHS_WRITING_VWI)
+  {
+    /* if this was initiated by user, then send final result */
+    cphs_inform_user(CPHS_VOICE_MAIL_RES, CPHS_OK, NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+  }
+  else
+  {
+    /* if this was initiated by network (upon receiving of an SMS, then send indication
+    to the user */
+    cphs_inform_user( CPHS_VOICE_MAIL_IND, CPHS_OK, cphs_internal_params->tmp_activate_state, 
+                                                    cphs_internal_params->tmp_lines );
+  }
+}
+
+LOCAL void writing_cfu_ok(void)
+{
+  TRACE_FUNCTION("writing_cfu_ok()");
+
+  memcpy(cphs_cached_params->cfu_flags, cphs_internal_params->tmp_flag_set, CFU_SIZE);
+  
+  TRACE_EVENT_P2("cfu_flags: %02X %02X", cphs_cached_params->cfu_flags[0], 
+                                         cphs_cached_params->cfu_flags[1]);
+
+  cphs_inform_user(CPHS_CFU_RES, CPHS_OK, NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+}
+
+/* Positive Result of data SIM data access */
+GLOBAL void cphs_sim_data_accessed(UBYTE max_records, UBYTE data_len)
+{
+  TRACE_FUNCTION("cphs_sim_data_accessed()");
+
+  switch(cphs_status)
+  {
+  case(CPHS_INITIALISING):
+  case(CPHS_REFRESHING):
+    cphs_init_sim_ok(max_records, data_len);
+    return;
+
+  case(CPHS_WRITING_VWI_IND):
+  case(CPHS_WRITING_VWI):
+    TRACE_EVENT_P1("vwi_flags length: %d bytes", data_len);
+    writing_vwi_ok();
+    cphs_status = CPHS_INITIALISED;
+    return;
+  
+  case(CPHS_WRITING_CFU):
+    /* cfu_flags is only updated if writing on SIM has been successful */
+    TRACE_EVENT_P1("cfu_flags: %d bytes length", data_len);
+    writing_cfu_ok();
+    cphs_status = CPHS_INITIALISED;
+    return;
+
+  default:
+    TRACE_EVENT("cphs_sim_data_accessed(): unexpected status");
+    cphs_status = CPHS_INITIALISED;
+    return;
+  }
+}
+
+LOCAL void cphs_init_sim_failure(void)
+{
+  TRACE_FUNCTION("cphs_init_sim_failure()");
+
+  /* set next operation if needed */
+  switch(sim_cache_update_state)
+  {
+  case(CPHS_SIM_INFO_NUMS):
+    /* Special case: when reading information number, if file 6F19
+       is not present, another try should be done with EA01 for old SIMs */
+    cphs_internal_params->current_record = 0;
+    free_buffer(RECORD_BUFF);
+    free_buffer(INFO_BUFF);
+    sim_cache_update_state = CPHS_SIM_INFO_NUMS_EA01;
+    cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+    return;
+
+  case(CPHS_SIM_INFO_NUMS_EA01):
+    cphs_internal_params->current_record = 0;
+    free_buffer(RECORD_BUFF);
+    free_buffer(INFO_BUFF);
+    /* No information numbers found... */
+    cphs_cached_params->max_info_numbers = NOT_PRESENT_8BIT;
+    break;
+
+  case(CPHS_SIM_ALSNAMES):
+    cphs_internal_params->current_record = 0;
+    free_buffer(ALS_BUFF);
+    initialize_als_info(MAX_LINE_ID);
+    break;
+
+  case(CPHS_SIM_MB):
+    cphs_internal_params->current_record = 0;
+    free_buffer(RECORD_BUFF);
+    free_buffer(MB_BUFF);
+    /* No mailbox numbers found... */
+    cphs_cached_params->max_mb_numbers = NOT_PRESENT_8BIT;
+    break;
+  }
+
+  if(is_cphs_field_mandatory(sim_cache_update_state))
+  {
+    cphs_abort_current_action( );
+    return;
+  }
+
+  cphs_set_next_update_state();
+  cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+}
+
+/* Failure Result of data SIM data access */
+GLOBAL void cphs_sim_data_failure(void)
+{
+  TRACE_FUNCTION("cphs_sim_data_failure()");
+
+  switch(cphs_status)
+  {
+  case(CPHS_INITIALISING):
+  case(CPHS_REFRESHING):
+    cphs_init_sim_failure();
+    break;
+
+  case(CPHS_WRITING_VWI):
+    TRACE_ERROR("Voice Mail Indicator setting: SIM FAILURE !!!!");
+    cphs_status = CPHS_INITIALISED;
+    cphs_inform_user(CPHS_VOICE_MAIL_RES, CPHS_FAIL, 
+                     NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+    return;
+  
+  case(CPHS_WRITING_VWI_IND):
+    TRACE_ERROR("Voice Mail Indication: SIM FAILURE !!!!");
+    cphs_status = CPHS_INITIALISED;
+    return;
+
+  case(CPHS_WRITING_CFU):
+    TRACE_ERROR("Call Fwd Flags: SIM FAILURE !!!!");
+    cphs_inform_user(CPHS_CFU_RES, CPHS_FAIL, 
+                     NOT_PRESENT_8BIT, CPHS_LINE_NULL);
+    cphs_status = CPHS_INITIALISED;
+    return;
+
+  default:
+    TRACE_EVENT("cphs_sim_data_failure(): unexpected status");
+    return;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : starts/ends/refreshes    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Set of functions enabling initialising, ending or refreshing
+            the CPHS module.
+*/
+
+GLOBAL T_CPHS_RET cphs_start (T_CPHS_USER_CB *cphs_user_cb)
+{
+  TRACE_FUNCTION("cphs_start()");
+
+  /* Check CPHS status */
+  switch(cphs_status)
+  {
+  case(CPHS_NOT_INITIALISED):
+    TRACE_EVENT("CPHS starting !!!");
+    break;
+
+  case(CPHS_INITIALISED):
+    TRACE_EVENT("cphs_start: CPHS module already initialised");
+    return(CPHS_OK);
+
+  default:
+    TRACE_EVENT("cphs_start: CPHS has already been initialised: BUSY !!!");
+    return(CPHS_BUSY);
+  }
+
+  if(cphs_user_cb EQ NULL)
+  {
+    TRACE_ERROR("cphs_start: cphs_user_cb is NULL. CPHS module cannot be initialised");
+    return(CPHS_FAIL);
+  }
+
+  /* allocate memory for parameters to be cached from the SIM */
+  MALLOC(cphs_cached_params, sizeof(T_CPHS_CACHED_PARAMS));
+
+  cphs_cached_params->max_mb_numbers         = NOT_PRESENT_8BIT; //MAX_LINE_ID;
+  cphs_cached_params->mb_numbers             = NULL;
+  cphs_cached_params->max_info_numbers       = NOT_PRESENT_8BIT;
+  cphs_cached_params->info_numbers           = NULL;
+  cphs_cached_params->als                    = NULL;
+  cphs_cached_params->max_als_names_entries  = NOT_PRESENT_8BIT;
+
+  memset(cphs_cached_params->opn_long,  0, sizeof(cphs_cached_params->opn_long));
+  memset(cphs_cached_params->opn_short, 0, sizeof(cphs_cached_params->opn_short));
+  memset(cphs_cached_params->csp,       0, sizeof(cphs_cached_params->csp));
+  /* Add support for Orange SIM's  */
+  memset(cphs_cached_params->orange_csp2,  0, sizeof(cphs_cached_params->orange_csp2));
+  cphs_cached_params->orange_csp2_length = 0; /* Set this to 0, will indicate if vaild */
+  
+  MALLOC(cphs_internal_params, sizeof(T_CPHS_INTERNAL_PARAMS));
+  /* Set user callback */
+  cphs_internal_params->user_cb = cphs_user_cb;
+
+  cphs_internal_params->current_record         = 0;
+  cphs_internal_params->sim_read_record_buffer = NULL;
+
+
+  /****** Get params from SIM *******/
+  cphs_status = CPHS_INITIALISING;
+
+  cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+
+  return(CPHS_EXEC);
+}
+
+
+GLOBAL T_CPHS_RET cphs_refresh_data (void)
+{
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_refresh_data()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  cphs_status = CPHS_REFRESHING;
+
+  /****** Get params from SIM *******/
+  cphs_cache_sim_data(NOT_PRESENT_8BIT, NOT_PRESENT_8BIT);
+
+  return(CPHS_EXEC);
+}
+
+GLOBAL T_CPHS_RET cphs_stop (void)
+{
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_stop()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  /* abort current action */
+  cphs_abort_current_action( );
+
+  /* reinitialise CPHS status */
+  cphs_status = CPHS_NOT_INITIALISED;
+
+  /* free memory allocated for CPHS */
+  free_buffer(INFO_BUFF);
+  free_buffer(ALS_BUFF);
+  free_buffer(MB_BUFF);
+
+  MFREE(cphs_cached_params);
+  MFREE(cphs_internal_params);
+
+  return(CPHS_OK);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE :                          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Functions related to CPHS information numbers.
+*/
+
+/*
+  Returns elements contained in a folder.
+
+  element_idx     Index of folder element to be explored
+  inf_num_list    returns list of indexes of elements contained in folder
+  max_elmts	      limits amount of bytes to be written in inf_num_indexes.
+                  If numbers of elements to be written is bigger, then function returns
+                  with CPHS_EXEC and amount of elements will be written in max_elmts
+                  (so that function caller knows how many memory it has to allocate
+                  to retrieve the whole list).     */
+
+GLOBAL T_CPHS_RET cphs_explore_info_nbs(UBYTE element_idx, UBYTE *inf_num_indexes, UBYTE *max_elmts)
+{
+  T_CPHS_RET     ret_status;
+  T_CPHS_INF_NUM *explored_folder,
+                 *try_element;
+  UBYTE          i = 0, index;
+
+  TRACE_FUNCTION("cphs_explore_info_nbs()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    /* CPHS status not initialized, set error as CME_ERR_OpNotAllow */
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
+    return(ret_status);
+  }
+  else
+    ret_status = CPHS_OK;   // unless we then find out buffer was too small...
+
+  if(cphs_cached_params EQ NULL OR
+     inf_num_indexes    EQ NULL OR
+     max_elmts          EQ NULL)
+  {
+    TRACE_ERROR("cphs_explore_info_nbs: some needed pointers have value NULL");
+    return(CPHS_FAIL);
+  }
+
+  /* init */
+  *inf_num_indexes = 0;
+
+  if(element_idx > cphs_cached_params->max_info_numbers)
+  {
+    TRACE_ERROR("wrong element_idx");
+    return(CPHS_FAIL);
+  }
+
+  /* Check for info_numbers, set CME_ERR_NotFound return CPHS_FAIL */
+  if (cphs_cached_params->info_numbers EQ NULL)
+  {
+    /* information numbers have not been read from SIM */
+    *max_elmts = 0;
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NotFound );
+    return (CPHS_FAIL);
+  }
+
+  explored_folder = &cphs_cached_params->info_numbers[element_idx];
+
+  if(explored_folder->number[0] NEQ 0)
+  {
+    TRACE_EVENT_P1("Cannot explore: element %d is not a folder", element_idx);
+    return(CPHS_FAIL);
+  }
+
+  index = element_idx + 1;
+  try_element = &cphs_cached_params->info_numbers[index];
+
+  while(try_element->index_level NEQ explored_folder->index_level) // search for next element of same index_level
+  {
+    if( try_element->index_level EQ (explored_folder->index_level+1) )  // element is direct under folder
+    {
+      if(i < *max_elmts)
+      {
+        inf_num_indexes[i] = index;
+      }
+      else
+        ret_status = CPHS_EXEC; // buffer is too small: but we need to count how many bytes are then needed
+
+      i++;
+    }
+    index++;
+    try_element = &cphs_cached_params->info_numbers[index];
+
+    if(index > cphs_cached_params->max_info_numbers)
+    {
+      break; /* end of list: can happen, e.g when exploring the last folder of a given index_level */
+    }
+  }
+
+  *max_elmts = i;
+  return(ret_status);
+}
+
+/*
+  Returns information related to element id
+
+  element_idx   Index of element chosen
+  inf_num		    structure containing information related to an element */
+
+GLOBAL T_CPHS_RET cphs_read_info_nb (UBYTE element_idx, T_CPHS_INF_NUM *inf_num)
+{
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_read_info_nb()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    /* CPHS status not initialized, set error as CME_ERR_OpNotAllow */
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
+    return(ret_status);
+  }
+
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params EQ NULL");
+    return(CPHS_FAIL);
+  }
+  
+  /* Check Information numbers are cached or not */
+  if(cphs_cached_params->info_numbers EQ NULL)
+  {
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NotFound );
+    return(CPHS_FAIL);    
+  }
+  
+  if(element_idx < 1             OR
+     element_idx > cphs_cached_params->max_info_numbers)
+  {
+    TRACE_ERROR("wrong element_idx");
+    /* Element index not in the range, set CME_ERR_InvIdx */
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx );
+    return(CPHS_FAIL);
+  }
+
+  memcpy(inf_num, &cphs_cached_params->info_numbers[element_idx], sizeof(T_CPHS_INF_NUM));
+
+  return(CPHS_OK);
+}
+
+GLOBAL T_CPHS_RET cphs_info_num_get_max(UBYTE *max_index)
+{
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_info_num_get_max()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    /* CPHS status not initialized, set error as CME_ERR_OpNotAllow */
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
+    return(ret_status);
+  }
+
+  if(cphs_cached_params NEQ NULL                             AND
+     cphs_cached_params->max_info_numbers NEQ NOT_PRESENT_8BIT)
+  {
+    *max_index = cphs_cached_params->max_info_numbers;
+    return(CPHS_OK);
+  }
+  
+  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NotFound );
+  return(CPHS_FAIL);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE :                          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Functions related to CPHS alternate line service.
+*/
+
+/*
+  Returns elements contained in a folder.
+
+  call_id         call id of line being queried. This value is the same as the call id
+                  described in GSM 02.30 subclause 4.5.5.1 (also see AT+CLCC). If not present
+                  (value 255), then current active line is to be returned.
+  line		        contains line of queried call, or current active line.
+  line_desc	      line identification in SIM
+  max_line_desc	  maximal length of line_desc:
+                      IN: should contain the size of memory allocated for line_desc.
+                      OUT: If memory is not enough, then function returns with CPHS_FAIL
+                           and max_line_desc will contain the amount of memory needed.
+                           Otherwise contains amount of written characters. */
+
+
+GLOBAL T_CPHS_RET cphs_get_line(UBYTE srcId, UBYTE call_id, T_CPHS_LINES *line, 
+                                CHAR *line_desc, UBYTE *max_line_desc)
+{
+  T_CPHS_RET      ret_status;
+  T_CPHS_LINES    call_line;
+  CHAR            *cached_line_name;
+
+  TRACE_FUNCTION("cphs_get_line()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  if(line EQ NULL)
+  {
+    TRACE_ERROR("wrong parameter: line is NULL");
+    return(CPHS_FAIL);
+  }
+
+  if(call_id EQ NOT_PRESENT_8BIT)
+  {
+    /* Get current active line */
+    cphs_get_als_active_line(srcId, &call_line);
+  }
+  else
+  {
+    /* get line associated to call_id */
+    call_line = als_get_call_info(call_id);
+  }
+
+  if( call_line EQ CPHS_LINE_NULL )
+  {
+    TRACE_ERROR("als_get_call_info: not a valid call");
+    return(CPHS_FAIL);
+  }
+  *line = call_line;
+
+  if(max_line_desc EQ NULL)
+  {
+    TRACE_ERROR("max_line_desc EQ NULL");
+    return(CPHS_FAIL);
+  }
+
+  if(*max_line_desc < CPHS_MAX_SIZE_ALPHA)
+  {
+    // buffer too small
+    *max_line_desc = CPHS_MAX_SIZE_ALPHA;
+    return(CPHS_EXEC);
+  }
+
+  get_name_pointer_over_lineid(call_line, &cached_line_name,
+                               cphs_cached_params->max_als_names_entries);
+  if(cached_line_name NEQ NULL)
+  {
+    memcpy(line_desc, cached_line_name, *max_line_desc);
+    return(CPHS_OK);
+  }
+  else
+  {
+    memset(line_desc, 0, *max_line_desc);
+    return(CPHS_FAIL);
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_roaming_ind         |
++--------------------------------------------------------------------+
+
+  PURPOSE :
+*/
+
+GLOBAL void cphs_roaming_ind(UBYTE roaming_status)
+{
+  T_CPHS_RET ret_status;
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return;
+  }
+
+  TRACE_FUNCTION("cphs_roaming_ind()");
+
+  /* inform user */
+  cphs_inform_user(CPHS_ROAM_IND, CPHS_OK, roaming_status, CPHS_LINE_NULL);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_voice_mail_ind      |
++--------------------------------------------------------------------+
+
+  PURPOSE :
+*/
+
+GLOBAL void cphs_voice_mail_ind (UBYTE flag_set, USHORT line)
+{
+  T_CPHS_RET      ret_status;
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    TRACE_ERROR("cannot proceed Voice Mail Indication: CPHS module is busy");
+    return;
+  }
+
+  TRACE_FUNCTION("cphs_voice_mail_ind()");
+
+  /* write to SIM and in cached data */
+  cphs_status = CPHS_WRITING_VWI_IND;
+
+  cphs_write_indicator_flag(flag_set, line, CPHS_SIM_VWI);
+
+  return;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_set_waiting_flag    |
++--------------------------------------------------------------------+
+
+  PURPOSE : set/clear waiting flag for given lines
+*/
+
+GLOBAL T_CPHS_RET cphs_set_waiting_flag(UBYTE flag_set, T_CPHS_LINES lines)
+{
+  T_CPHS_RET   ret_status;
+
+  TRACE_FUNCTION("cphs_set_waiting_flag()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    TRACE_ERROR("cannot proceed SET of Voice Mail Indicator: CPHS module is busy");
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
+    return(ret_status);
+  }
+
+  cphs_status = CPHS_WRITING_VWI;
+
+  cphs_write_indicator_flag(flag_set, lines, CPHS_SIM_VWI);
+
+  return(CPHS_EXEC);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_get_waiting_flag    |
++--------------------------------------------------------------------+
+
+  PURPOSE : look up if waiting flag for queried line is set
+*/
+
+GLOBAL T_CPHS_RET cphs_get_waiting_flag(UBYTE *flag_set, T_CPHS_LINES line)
+{
+  UBYTE      setting = 0;
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_get_waiting_flag()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  ret_status = cphs_get_indicator_flag(flag_set, line, CPHS_SIM_VWI);
+
+  return(ret_status);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_get_opn             |
++--------------------------------------------------------------------+
+
+  PURPOSE : look up operator name string and if available operator
+            name short string
+*/
+
+GLOBAL T_CPHS_RET cphs_get_opn( CHAR  *longname,
+                                UBYTE *max_longname,
+                                CHAR  *shortname,
+                                UBYTE *max_shortname)
+
+{
+  UBYTE      len, i;
+  T_CPHS_RET ret_status;
+  BOOL       buffer_too_small = FALSE;
+
+  TRACE_FUNCTION("cphs_get_opn()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
+    return(ret_status);
+  }
+
+  /* Length of Long Operator Name */
+  len = strlen((CHAR *)cphs_cached_params->opn_long);
+  for(i=0; i<len; i++)
+  {
+    if(cphs_cached_params->opn_long[i] EQ 0xFF)
+    {
+      len = i;
+      break;
+    }
+  }
+
+  TRACE_EVENT_P1("opn_long length %d", len);
+  
+  if( len > *max_longname )
+  {
+    TRACE_EVENT_P1("buffer for long name is not big enough: needed: %d", len);
+    *max_longname = len;
+    buffer_too_small = TRUE;
+  }
+  else
+  {
+    *max_longname = len;
+    memcpy(longname, cphs_cached_params->opn_long, (int) len);
+    longname[len] = '\0';
+  }
+
+  /* Length of SHORT Operator Name */
+  len = strlen((CHAR *)cphs_cached_params->opn_short);
+  for(i=0; i<len; i++)
+  {
+    if(cphs_cached_params->opn_short[i] EQ 0xFF)
+    {
+      len = i;
+      break;
+    }
+  }
+
+  TRACE_EVENT_P1("opn_short length %d", len);
+
+  if( len > *max_shortname )
+  {
+    TRACE_EVENT_P1("buffer for short name is not big enough: needed: %d", len);
+    *max_shortname = len;
+    buffer_too_small = TRUE;
+  }
+  else
+  {
+    *max_shortname = len;
+    memcpy(shortname, cphs_cached_params->opn_short, (int) len);
+    shortname[len] = '\0';
+  }
+
+  if(buffer_too_small)
+  {
+    return(CPHS_FAIL);
+  }
+  else
+    return(CPHS_OK);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_get_cphs_info       |
++--------------------------------------------------------------------+
+
+  PURPOSE : look up cphs info
+*/
+
+GLOBAL T_CPHS_RET cphs_get_cphs_info( UBYTE  *phase,
+                                      USHORT *sst)
+{ 
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_get_cphs_info()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  *phase = cphs_cached_params->info.phase;
+  *sst   = cphs_cached_params->info.sst;
+ 
+  return CPHS_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_parse_csp           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Look up CSP information
+*/
+LOCAL T_CPHS_RET cphs_parse_csp ( UBYTE  *cached_csp,
+                                  CHAR   *parsed_csp,
+                                  UBYTE  cached_csp_length,
+                                  UBYTE  *parsed_csp_length)
+{ 
+  UBYTE pos;
+  T_CPHS_RET ret_val = CPHS_OK;
+
+  TRACE_FUNCTION("cphs_parse_csp()");
+
+  /* Cached CSP not present return CPHS_FAIL */
+  if (cached_csp EQ NULL)
+  {
+    return(CPHS_FAIL);
+  }
+
+  /* analyze max size of csp hex string */
+  if(*parsed_csp_length < (2*cached_csp_length + 1))
+  {
+    TRACE_EVENT_P1("buffer for CSP is too small: needed : %d", 
+                    cached_csp_length);
+    *parsed_csp_length = (2*cached_csp_length + 1);
+    return(CPHS_FAIL);
+  }
+
+  /* convert to hex string */
+  for(pos=0,*parsed_csp_length = 0; pos < cached_csp_length; pos++,*parsed_csp_length = pos*2)
+  {
+    sprintf(parsed_csp + (*parsed_csp_length), "%02X", cached_csp[pos]);
+  }
+
+  /* terminate string */
+  parsed_csp[*parsed_csp_length] = 0;
+
+  /* set actual size of csp hex string */
+  *parsed_csp_length++;
+  
+  return CPHS_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_get_csprof          |
++--------------------------------------------------------------------+
+
+  PURPOSE : look up cphs info
+*/
+
+GLOBAL T_CPHS_RET cphs_get_csprof( CHAR  *csp,
+                                   CHAR  *csp2,
+                                   UBYTE *max_csp_length,
+                                   UBYTE *max_csp2_length)
+{ 
+  T_CPHS_RET ret_val = CPHS_OK;
+
+  TRACE_FUNCTION("cphs_get_csprof()");
+
+  ret_val = cphs_parse_csp( cphs_cached_params->csp,
+                            csp,
+                            cphs_cached_params->csp_length,
+                            max_csp_length);
+
+  if (ret_val EQ CPHS_OK)
+  {
+    ret_val = cphs_parse_csp( cphs_cached_params->orange_csp2,
+                              csp2,
+                              cphs_cached_params->orange_csp2_length,
+                              max_csp2_length);
+  }
+  return ret_val;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_read_mb_number      |
++--------------------------------------------------------------------+
+
+  PURPOSE : read mailbox number for given record id
+*/
+
+GLOBAL T_CPHS_RET cphs_read_mb_number( UBYTE     rec_id, 
+                                       T_CPHS_MB *mailbox_entry)
+{ 
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_read_mb_number()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow);
+    return(ret_status);
+  }
+  
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params EQ NULL");
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_Unknown);
+    return CPHS_FAIL;
+  }
+
+  if ( (rec_id < 1) OR (rec_id > cphs_cached_params->max_mb_numbers) )
+  {
+    TRACE_ERROR("invalid record id, return CPHS_FAIL");
+    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx);
+    return CPHS_FAIL;
+  }
+
+  if (cphs_cached_params->mb_numbers NEQ NULL)
+  {
+    memcpy(mailbox_entry, 
+           &cphs_cached_params->mb_numbers[rec_id-1], 
+           sizeof(T_CPHS_MB));
+  }
+  else
+  { /* requested mb number has not been read from SIM, 
+       return empty mb number */
+    memset(mailbox_entry, 0, sizeof(T_CPHS_MB));
+  }
+
+  return CPHS_OK;
+}
+
+/*
++----------------------------------------------------------------------+
+| PROJECT : GSM-F&D (8411)              MODULE  : CPHS                 |
+| STATE   : code                        ROUTINE : cphs_state_indication|  
++----------------------------------------------------------------------+
+
+  PURPOSE : state the result to the user 
+*/
+
+GLOBAL SHORT cphs_state_indication ( UBYTE psaStatus, SHORT cmeError )
+{
+  UBYTE cmdBuf;
+  UBYTE ownBuf;
+  T_PHB_CMD_PRM * pPHBCmdPrm;
+  
+  TRACE_FUNCTION ("cphs_state_indication()");
+
+  cmdBuf = simEntStat.curCmd;
+  ownBuf = simEntStat.entOwn;
+
+  switch ( psaStatus )
+  {
+    case ( CPHS_SIM_WRITE_OK ): 
+    {
+      R_AT (RAT_OK, ownBuf) (cmdBuf);
+      break;
+    }
+    case ( CPHS_SIM_WRITE_FAIL ): 
+    {
+      TRACE_EVENT("cphs_state_indication: SIM write failed");
+      R_AT( RAT_CME, ownBuf)( cmdBuf, cmeError );
+      break;
+    }   
+    default:
+    {
+      TRACE_EVENT("FATAL ERROR in cmhCHPS_StatIndication"); 
+      return -1;
+    }
+  }
+
+  /* trigger RAT indications to the user */
+  /*
+  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
+  {
+    R_AT( RAT_PHB_STATUS, idx )( cmhStatus );
+  }
+  */
+  simEntStat.curCmd = AT_CMD_NONE;
+  simEntStat.entOwn = simShrdPrm.owner = CMD_SRC_NONE;
+  
+  return 0;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_write_mb_number_cb  |
++--------------------------------------------------------------------+
+
+  PURPOSE : write mailbox entry callback 
+  
+*/
+
+GLOBAL void cphs_write_mb_number_cb( SHORT table_id )
+{
+
+  TRACE_FUNCTION("cphs_write_mb_number_cb()");
+
+  simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
+
+  if (simShrdPrm.atb[table_id].errCode NEQ SIM_NO_ERROR)
+  {
+    TRACE_ERROR("cphs_write_mb_number_cb(): error for writing");
+    cphs_state_indication( CPHS_SIM_WRITE_FAIL,
+                           (SHORT)cmhSIM_GetCmeFromSim( simShrdPrm.atb[table_id].errCode ));
+    return;
+  }
+  else
+  {  
+    /* write to ME cache */
+    write_mb_number(simShrdPrm.atb[table_id].recNr, 
+                    exchData, 
+                    cphs_cached_params->max_mb_entry_length);
+    /* reset exchange data */
+    memset(exchData, 0xFF, 100);
+    cphs_state_indication ( CPHS_SIM_WRITE_OK, CME_ERR_NotPresent );
+  }
+  return;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_write_mb_number      |
++--------------------------------------------------------------------+
+
+  PURPOSE : write mailbox number for given record id
+*/
+
+GLOBAL T_CPHS_RET cphs_write_mb_number( UBYTE         srcId,
+                                        UBYTE         rec_id,
+                                        UBYTE        *tag,
+                                        UBYTE         tag_len,
+                                        UBYTE         bcd_len,
+                                        UBYTE        *number,
+                                        UBYTE         ton_npi)
+{ 
+  UBYTE tmp_tag_len   = 0;
+  UBYTE max_aplha_len = 0;
+  UBYTE max_entry_len = 0;
+
+  T_ACI_RETURN result;
+
+  TRACE_FUNCTION("cphs_write_mb_number()");
+
+  /* test state of CPHS */
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params EQ NULL");
+    return CPHS_NOT_INIT;
+  }
+
+  max_aplha_len = cphs_cached_params->max_mb_entry_length - CPHS_MIN_MB_LEN;
+  max_entry_len = cphs_cached_params->max_mb_entry_length;
+
+  /* test whether alpha tag is too long */
+  if ( tag_len > max_aplha_len )
+  {
+    return CPHS_FAIL;
+  }
+  
+  /* test if mb numbers are supported/initialized */
+  if ((cphs_cached_params->mb_numbers NEQ NULL) &&
+      ( rec_id <= cphs_cached_params->max_mb_numbers ))
+  {
+    
+    /* write mb number to SIM - prepare data */     
+    /* get length of alpha tag */    
+    tmp_tag_len = pb_get_entry_len( tag, max_aplha_len );
+
+    /* reset exchData */
+    memset(exchData, 0xFF, DEFAULT_MAXSIZE_OF_RECORD);
+    if ((number NEQ NULL)||(tag NEQ NULL)) /* NULL causes delete of record */
+    {
+      /* alpha tag */
+      memcpy(exchData, tag, tmp_tag_len);
+      /* length of bcd number content */
+      exchData[max_aplha_len] = bcd_len+1;
+      /* ton_npi */
+      exchData[max_aplha_len+1] = ton_npi;
+      /* BCD number */
+      if (number NEQ NULL)
+      {
+        memcpy((char *)&exchData[max_aplha_len+2], 
+            (char *)number, CPHS_MAX_MB_NUMBER_BYTES);
+      }
+      /* Capability field (empty) */
+      exchData[max_aplha_len+12] = NOT_PRESENT_8BIT; 
+    }
+    /* write to SIM */    
+    result= cmhSIM_WriteRecordEF( srcId,
+                                  AT_CMD_CPMBW,
+                                  SIM_CPHS_MBXN,
+                                  rec_id,
+                                  max_entry_len,
+                                  exchData,
+                                  cphs_write_mb_number_cb );    
+    
+    /* write to ME cache */
+    if (result EQ AT_EXCT)
+    {
+      write_mb_number(rec_id, exchData, max_entry_len);
+    }
+  }
+  else /* no mb supported */
+  {
+    return CPHS_NOT_INIT;
+  }
+  return CPHS_EXEC;
+}
+
+
+/*
++----------------------------------------------------------------------+
+| PROJECT : GSM-F&D (8411)              MODULE  : CPHS                 |
+| STATE   : code                        ROUTINE : cphs_get_mb_parameter|  
++----------------------------------------------------------------------+
+
+  PURPOSE : replies the CPHS mailbox parameters for test command 
+*/
+
+GLOBAL T_CPHS_RET cphs_get_mb_parameter (SHORT*        firstIdx,
+                                         SHORT*        lastIdx,
+                                         UBYTE*        nlength,
+                                         UBYTE*        tlength )
+{
+
+  UBYTE max_entry_len = 0;
+  UBYTE max_entries  = 0;
+  
+  TRACE_FUNCTION ("cphs_get_mb_parameter()");
+  
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params EQ NULL");
+    return CPHS_NOT_INIT;
+  }
+
+  max_entries = cphs_cached_params->max_mb_numbers;
+  max_entry_len = cphs_cached_params->max_mb_entry_length;
+
+  /* handle index */
+  if ( max_entries > 0 )
+  {
+    *firstIdx = (SHORT) CPHS_MIN_MB_ENTRIES;
+    *lastIdx =  (SHORT) max_entries;
+  }
+  else
+  {
+    *lastIdx = *firstIdx = 0;
+  }
+  /* handle entry length */
+  if ( max_entry_len >= CPHS_MIN_MB_LEN )
+  {
+    *tlength = max_entry_len - CPHS_MIN_MB_LEN;
+  }
+  else
+  {
+    *tlength = 0;
+  }
+
+  /* handle number length */
+  
+  *nlength = CPHS_MAX_MB_NUMBER_BYTES;
+
+  return CPHS_OK;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_get_fwd_flag        |
++--------------------------------------------------------------------+
+
+  PURPOSE : returns setting of CFU flag for given line
+*/
+
+#define SIM_FLAG_ON   (0x0A)
+#define SIM_FLAG_OFF  (0x05)
+#define SIM_FLAG_NONE (0x00)
+
+/* if nibble = 0 (1st nibble)
+#define GET_FLAG_VALUE(flag, nibble) ( (flag & (0xF0))  >>  4 )
+if nibble=1 (2nd nibble)
+#define GET_FLAG_VALUE(flag, nibble) (flag & 0x0F)
+*/
+#define GET_FLAG_VALUE(flag, nibble) ( (flag & (0x0F << (4 * (nibble ? 0 : 1))))  \
+                                                               >>  (4 * (nibble ? 0 : 1)) )
+
+LOCAL void get_relevant_flag_struct(UBYTE indicator, UBYTE **flag_table /*, UBYTE **temp_flag_table*/)
+{
+  UBYTE *intern_flag_table;
+
+  switch(indicator)
+  {
+  case(CPHS_SIM_CFU):
+    intern_flag_table      = cphs_cached_params->cfu_flags;
+    break;
+
+  case(CPHS_SIM_VWI):
+    intern_flag_table = cphs_cached_params->vwi_flags;
+    break;
+
+  default:     /* shall be eventually removed ! */
+    TRACE_ERROR("tttt: Wrong indicator value !!!");
+    return;
+  }
+
+  if(flag_table NEQ NULL)
+  {
+    *flag_table = intern_flag_table;
+  }
+}
+
+LOCAL void get_byte_index_and_nibble(T_CPHS_LINES line, UBYTE *byte_index, UBYTE *nibble)
+{
+  /* byte: nibble1/nibble2   (nibble1 has value 0, 
+                               nibble2 has value 1) */
+  /* first byte: line1/line2 (first  byte has value byte_index 0)*/
+  /* second byte: fax/data   (second byte has value byte_index 1)*/
+  switch(line)
+  {
+  case(CPHS_LINE1):
+    *byte_index = 0;
+    *nibble = 0;
+    break;
+
+  case(CPHS_LINE2):
+    *byte_index = 0;
+    *nibble = 1;
+    break;
+  
+  case(CPHS_LINE_FAX):
+    *byte_index = 1;
+    *nibble = 0;
+    break;
+
+  case(CPHS_LINE_DATA):
+    *byte_index = 1;
+    *nibble = 1;
+    break;
+  }
+}
+
+LOCAL T_CPHS_RET cphs_get_indicator_flag(UBYTE *flag_set, T_CPHS_LINES line, UBYTE indicator)
+{
+  UBYTE      setting;
+  UBYTE      byte_index, nibble;
+  UBYTE      *flag_table;
+
+  TRACE_FUNCTION("cphs_get_indicator_flag()");
+
+  if(!cphs_line_makes_sense(line))
+  {
+    TRACE_EVENT_P1("Queried line %d does not exist", line);
+    return(CPHS_FAIL);
+  }
+
+  get_byte_index_and_nibble(line, &byte_index, &nibble);
+
+  get_relevant_flag_struct(indicator, &flag_table /*, NULL*/ );
+
+  setting = GET_FLAG_VALUE(flag_table[byte_index], nibble);
+
+  switch(setting)
+  {
+  case(SIM_FLAG_ON):
+    *flag_set = CPHS_FLAG_ACTIVATED;
+    break;
+  
+  case(SIM_FLAG_OFF):
+    *flag_set = CPHS_FLAG_DEACTIVATED;
+    break;
+  
+  case(SIM_FLAG_NONE):
+    *flag_set = CPHS_FLAG_NOT_PRESENT;
+    break;
+  
+  default:
+    TRACE_EVENT_P1("cphs: get flag value unexpected: %02X", setting);
+    *flag_set = CPHS_FLAG_ERROR;
+    return(CPHS_FAIL);
+  }
+
+  TRACE_EVENT_P3("Get Indicator Flag: line: %d, setting: %X, flag_set: %d", line, setting, *flag_set);
+
+  return(CPHS_OK);
+}
+
+GLOBAL T_CPHS_RET cphs_get_fwd_flag(UBYTE *cfu_set, T_CPHS_LINES line)
+{
+  UBYTE      setting = 0;
+  T_CPHS_RET ret_status;
+
+  TRACE_FUNCTION("cphs_get_fwd_flag()");
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    return(ret_status);
+  }
+
+  return(cphs_get_indicator_flag(cfu_set, line, CPHS_SIM_CFU));
+}
+
+
+#define WRITE_FLAG_VALUE(flag, nibble, sim_state) \
+                         (flag = (flag & (0x0F << (4 * nibble))) | \
+                                 (sim_state  << (4 * (nibble ? 0 : 1)))) 
+/*
+#define WRITE_FLAG_VALUE(cfu, 0, state) (cfu = (cfu & 0x0F) | (state << 4))
+#define WRITE_FLAG_VALUE(cfu, 1, state) (cfu = (cfu & 0xF0) | state)
+*/
+
+LOCAL void cphs_write_indicator_flag(UBYTE        flag_set, 
+                                     T_CPHS_LINES lines, 
+                                     UBYTE        indicator)
+{
+  UBYTE setting;
+  UBYTE byte_index, nibble, table_length, i, sim_flag_status;
+  UBYTE *flag_table;
+  T_CPHS_LINES tested_line;
+  T_CPHS_LINES really_written_lines;
+
+  TRACE_FUNCTION("cphs_write_indicator_flag()");
+
+  really_written_lines = CPHS_LINE_NULL; /* init */
+
+  if(flag_set EQ CPHS_FLAG_ACTIVATED)
+  {
+    sim_flag_status = SIM_FLAG_ON;
+  }
+  else
+    sim_flag_status = SIM_FLAG_OFF;
+
+  get_relevant_flag_struct(indicator, &flag_table);
+
+  /* init temp flags */
+  memcpy(cphs_internal_params->tmp_flag_set, flag_table, FLAG_TABLE_SIZE);
+
+  if(flag_table[1] EQ 0x00)
+  {
+    /* this means the optional FAX and DATA part is not present: write only 1st byte ! */
+    table_length = 1;
+  }
+  else
+  {
+    table_length = FLAG_TABLE_SIZE;
+  }
+
+  for(i=0;i<8*sizeof(T_CPHS_LINES);i++)
+  {
+    tested_line = CPHS_LINE1 << i;
+    
+    if(tested_line & lines          AND
+       cphs_line_makes_sense(tested_line) )
+    {
+      get_byte_index_and_nibble(tested_line, &byte_index, &nibble);
+
+      setting = GET_FLAG_VALUE(flag_table[byte_index], nibble);
+
+      /* Only fields with an expected value (A or 5) can be written... It is assumed
+      here that other values mean the corresponding Indicator class is not relevant.
+      Therefore it will be ignored */
+      if(setting EQ SIM_FLAG_ON OR
+         setting EQ SIM_FLAG_OFF)
+      {
+        WRITE_FLAG_VALUE(cphs_internal_params->tmp_flag_set[byte_index], 
+                         nibble, sim_flag_status);
+        really_written_lines |= tested_line;
+      }
+      else
+      {
+        TRACE_EVENT_P2("Unexpected value for this indicator: Writing ignored: line: %d, setting: %X", 
+                       tested_line, setting);
+      }
+    }
+  }
+
+  /* This is what will be shown to the user when writing on SIM has been successful */
+  cphs_internal_params->tmp_activate_state = flag_set;
+  cphs_internal_params->tmp_lines          = really_written_lines; 
+    
+  cphs_sim_access_data( CPHS_SIM_WRITE_TRANSP_EF,
+                        indicator,
+                        0,
+                        cphs_internal_params->tmp_flag_set,
+                        table_length );
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_set_cfu_flag        |
++--------------------------------------------------------------------+
+
+  PURPOSE : set/clear cfu flag for given lines
+*/
+
+GLOBAL T_CPHS_RET cphs_set_cfu_flag(UBYTE cfu_set, T_CPHS_LINES lines)
+{
+  T_CPHS_RET ret_status;
+
+  /* Check CPHS status */
+  if((ret_status = cphs_check_status( )) NEQ CPHS_OK)
+  {
+    TRACE_ERROR("cannot proceed SET of Diverted Call Flag: CPHS module is busy");
+    return(ret_status);
+  }
+
+  TRACE_FUNCTION("cphs_set_cfu_flag()");
+
+  /* write to SIM and in cached data */
+  cphs_status = CPHS_WRITING_CFU;
+
+  cphs_write_indicator_flag(cfu_set, lines, CPHS_SIM_CFU);
+
+  return(CPHS_EXEC);
+}
+
+GLOBAL BOOL cphs_line_makes_sense(T_CPHS_LINES line)
+{
+  switch(line)
+  {
+  case(CPHS_LINE1):
+  case(CPHS_LINE2):
+  case(CPHS_LINE_DATA):
+  case(CPHS_LINE_FAX):
+    return(TRUE);
+
+  }
+
+  return(FALSE);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_write_csp_cb        |
++--------------------------------------------------------------------+
+
+  PURPOSE : write CSP entry callback 
+  
+*/
+GLOBAL void cphs_write_csp_cb(SHORT table_id)
+{
+  TRACE_FUNCTION("cphs_write_csp_cb()");
+
+  simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
+
+  if (simShrdPrm.atb[table_id].errCode NEQ SIM_NO_ERROR)
+  {
+    TRACE_ERROR("cphs_write_csp_cb(): error for writing");
+    cphs_state_indication( CPHS_SIM_WRITE_FAIL,
+                           (SHORT)cmhSIM_GetCmeFromSim( simShrdPrm.atb[table_id].errCode ));
+  }
+  else
+  {  
+    /* write to ME cache */
+    write_csp_ok(exchData,
+                 cphs_cached_params->csp_length);
+    /* reset exchange data */
+    memset(exchData, 0xFF, sizeof(exchData));
+    cphs_state_indication ( CPHS_SIM_WRITE_OK, CME_ERR_NotPresent );
+  }
+}
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : CPHS                     |
+| STATE   : code                  ROUTINE : cphs_set_csp_value       |
++--------------------------------------------------------------------+
+
+  PURPOSE : write customer service profile
+*/
+GLOBAL T_CPHS_RET cphs_set_csp_value(UBYTE srcId,
+                                     UBYTE  *csp,
+                                     UBYTE  csp_len)
+{
+  T_ACI_RETURN result;
+  USHORT i,j;
+  UBYTE max_csp_len = 0;
+  TRACE_FUNCTION("cphs_set_csp_value()");
+
+  /* test state of CPHS */
+  if(cphs_cached_params EQ NULL)
+  {
+    TRACE_ERROR("cphs_cached_params EQ NULL");
+    return CPHS_NOT_INIT;
+  }
+  
+  /* set exchData and max csp length*/
+  max_csp_len = cphs_cached_params->csp_length;
+  memset(exchData, 0xFF, DEFAULT_MAXSIZE_OF_RECORD);
+  memcpy(exchData, cphs_cached_params->csp, max_csp_len );
+
+  /*
+     only for valid service groups, associated services are written to SIM
+   */
+  if( csp NEQ NULL )
+  {
+    for( i=0; i < csp_len; i+=2 )
+    {
+      for( j=0; j < max_csp_len; j+=2 )
+      {
+        if ( csp[i] EQ exchData[j] )
+        {
+          exchData[j+1] = csp[i+1];
+        }
+      }
+    }
+  }
+
+  /* write to SIM */
+    result = cmhSIM_WriteTranspEF(srcId,
+                                  AT_CMD_CPINF,
+                                  SIM_CPHS_CSP,
+                                  0,
+                                  max_csp_len,
+                                  exchData,
+                                  cphs_write_csp_cb );
+    
+  /* If error occured while writing to SIM */
+  if (result EQ AT_FAIL)
+  {
+    return(CPHS_FAIL);
+  }
+  return(CPHS_EXEC);
+}
+
+#endif /* CPHS_C */
+#endif /* FF_CPHS */
+
+