FreeCalypso > hg > fc-magnetite
view src/g23m-aci/aci/phb_sim.c @ 337:0df0668f8bea
FCHG: task core function implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 14 Dec 2017 21:47:40 +0000 |
parents | 53929b40109c |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : MMI-Framework (8417) | Modul : PHB +----------------------------------------------------------------------------- | 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 modul contains the functions to establish the phone book. +----------------------------------------------------------------------------- */ #ifdef TI_PS_FFS_PHB #include "aci_all.h" #include "aci_cmh.h" #include "aci_mem.h" #include "phb_sim.h" #include "phb_aci.h" #include "ffs/ffs.h" #ifdef SIM_TOOLKIT #include "psa.h" #include "psa_sim.h" #include "psa_cc.h" #include "psa_sat.h" #endif /* #ifdef SIM_TOOLKIT */ #include "cmh.h" #include "cmh_phb.h" #include "pcm.h" /* * Constants and enumerations */ #define MAX_ECC_RCD 5 #define FFS_IMSI_SIZE 8 #define MAX_EXTNS_PER_RECORD 9 #define MAX_ELEM_FILES 15 #define SIM_MAX_RECORD_SIZE 256 /* Maximum size of a SIM record */ #define RDM_DATA_FILE_ID 0xff04 /* File ID to store data related to LDN, LMN and LRN Phonebooks */ #define SIZE_DATA_DATE_TIME 12 #define MAX_EXT_RECORDS 10 #define PHB_PHY_NUM_LENGTH 10 /* * Type definitions */ typedef struct { /* Handle for the Database */ int db_handle; /* Maximum number of records */ UBYTE max_record[MAX_PHONEBOOK]; /* Number of used records */ UBYTE used_record[MAX_PHONEBOOK]; /* Records sizes */ USHORT record_size[MAX_PHONEBOOK]; } T_PHB_SIM_DATA; /* Maximum no of records for LRN, LDN and LMN Phonebooks. */ #define RDM_PHB_DATA_SIZE 10 /* Record numbers for LDN, LMN and LRN Phonebook data. */ #define LDN_DATA_RECNO 1 #define LMN_DATA_RECNO 2 #define LRN_DATA_RECNO 3 EXTERN UBYTE cphs_mb_ext_record_num[]; /* ECC records */ T_PHB_ECC_RECORD phb_ecc_element[MAX_ECC_RCD]; LOCAL T_PHB_SIM_DATA pbs_data; /* Array to hold Reference count for Extension records. */ LOCAL UBYTE ext_ref_count[MAX_PHB_EXT][MAX_EXT_RECORDS]; /* Prototypes for search and compare functions */ int pb_sim_search_alpha_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num); int pb_sim_search_num_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num); int pb_sim_alpha_cmp (int db_handle, USHORT field_id, USHORT recno_1, USHORT recno_2, ULONG flags); int pb_sim_number_cmp (int db_handle, USHORT field_id,USHORT recno_1,USHORT recno_2, ULONG flags); /* * Prototypes for local functions */ LOCAL BOOL pb_sim_record_empty (USHORT field_id, USHORT entry_size, const UBYTE *buffer); LOCAL void pb_sim_read_eeprom_ecc (void); LOCAL int pb_sim_nibblecopy (UBYTE dest[], int destlen, UBYTE src[], int count); LOCAL void pb_sim_revString(char *); LOCAL void pb_sim_read_ext(UBYTE *buffer, T_PHB_RECORD *entry); LOCAL void pb_sim_prepare_ext_data(UBYTE *ext_data, int ext_count, UBYTE *number, UBYTE no_len, UBYTE *subaddr); LOCAL USHORT pb_sim_get_field_id (T_PHB_TYPE type); LOCAL USHORT pb_sim_get_ext_file (T_PHB_TYPE type); LOCAL USHORT pb_sim_get_ext_file_id (USHORT field_id); LOCAL T_EXT_TYPE pb_sim_get_ext_type (USHORT field_id); LOCAL USHORT pb_sim_get_size_except_tag (USHORT field_id); LOCAL int pb_sim_cmpString ( UBYTE* cur_tag, UBYTE* check_tag, UBYTE cmpLen ); LOCAL void pb_sim_cvt_alpha_for_cmp ( UBYTE* entry_tag, UBYTE* cur_tag, UBYTE len ); LOCAL int pb_sim_cmp2Bytes(UBYTE *s1, UBYTE *s2, UBYTE len, UBYTE flag); LOCAL T_PHB_RETURN pb_sim_update_extn_records(USHORT ext_field_id, USHORT rec_num, SHORT ref_type); LOCAL T_PHB_RETURN pb_sim_del_ext_records(T_PHB_TYPE type, USHORT field_id, USHORT db_recno); LOCAL USHORT pb_sim_retrieve_rdm_recno (T_PHB_TYPE type); LOCAL T_PHB_RETURN pb_sim_del_record_internal (T_PHB_TYPE type, USHORT phy_recno, T_DB_CHANGED *rec_affected, BOOL replacement); LOCAL BOOL pb_sim_ext_records_used (T_PHB_TYPE type, USHORT field_id, USHORT db_recno); LOCAL T_PHB_RETURN pb_sim_update_index (T_PHB_TYPE type, T_DB_CHANGED *rec_affected, USHORT field_id, UBYTE ext_rec_cnt); /* +----------------------------------------------------------------------+ | PROJECT: MMI-Framework MODULE : PHB | | STATE : code ROUTINE: pb_sim_init | +----------------------------------------------------------------------+ PURPOSE : Initializes internal data structures for SIM Phonebook. */ void pb_sim_init (void) { USHORT i; TRACE_FUNCTION ("pb_sim_init()"); db_init(); /* Initialise the data structures. */ /* Initialise ECC Phonebook to contain no records. */ for(i = 0; i < MAX_ECC_RCD; i++) { phb_ecc_element[i].phy_idx = 0; memset(phb_ecc_element[i].number,0xFF,ECC_NUM_LEN); } return; } /* +----------------------------------------------------------------------+ | PROJECT: MMI-Framework MODULE : PHB | | STATE : code ROUTINE: pb_sim_exit | +----------------------------------------------------------------------+ PURPOSE : This function is called by pb_exit() to inform the SIM part of the phonebook to shut down. */ void pb_sim_exit (void) { TRACE_FUNCTION ("pb_sim_exit()"); db_exit(); return; } /* +----------------------------------------------------------------------+ | PROJECT: MMI-Framework MODULE : PHB | | STATE : code ROUTINE: pb_sim_record_empty | +----------------------------------------------------------------------+ PURPOSE : This function is used to determine if a record is considered as empty. */ LOCAL BOOL pb_sim_record_empty (USHORT field_id, USHORT entry_size, const UBYTE *data) { USHORT alpha_len; /* TRACE_FUNCTION ("pb_sim_record_empty()"); */ /* Trace load */ /* If the entry contains an alpha identifier it is not empty */ if (data[0] NEQ 0xFF) return FALSE; alpha_len = entry_size - pb_sim_get_size_except_tag (field_id); //TISH for MMISIM sometime entry_size = 0, then alpha_len < 0; #ifdef WIN32 if (entry_size == 0) { return TRUE; } #endif if ((data[alpha_len] NEQ 0x00) AND (data[alpha_len + 2] NEQ 0xff)) return FALSE; return TRUE; /* No alpha identifier and no phone number => record empty */ } /* +----------------------------------------------------------------------+ | PROJECT: MMI-Framework MODULE : PHB | | STATE : code ROUTINE: pb_sim_set_ecc | +----------------------------------------------------------------------+ PURPOSE : The emergency call numbers are read from SIM card and written to FFS. */ T_PHB_RETURN pb_sim_set_ecc (UBYTE ecc_len, const UBYTE *sim_ecc) { USHORT ecc_rec_num; UBYTE *data_ptr; TRACE_FUNCTION ("pb_sim_set_ecc()"); /* Initialise used records for ECC. */ pbs_data.used_record[ECC] = 0; /* if SIM ECC data is not empty, copy SIM ECC data to phonebook */ if ( ecc_len NEQ 0) { data_ptr = ( UBYTE *) sim_ecc; pbs_data.max_record[ECC] = (SHORT)((ecc_len/ECC_NUM_LEN) > MAX_ECC_RCD)? MAX_ECC_RCD: ecc_len/ECC_NUM_LEN; pbs_data.record_size[ECC] = ECC_NUM_LEN; /* Store ECC into RAM, since ECC records will be less in number. */ /* * For the Issue OMAPS00081622 * Replaced MAX_ECC_RCD with pbs_data.max_record[ECC] in the for loop */ for (ecc_rec_num = 0; ecc_rec_num < pbs_data.max_record[ECC]; ecc_rec_num++) { if(*data_ptr NEQ 0xff) { memset(&phb_ecc_element[ecc_rec_num],0xFF,sizeof(T_PHB_ECC_RECORD)); phb_ecc_element[ecc_rec_num].phy_idx = ecc_rec_num + 1; memcpy(phb_ecc_element[ecc_rec_num].number, data_ptr, ECC_NUM_LEN); data_ptr += ECC_NUM_LEN; (pbs_data.used_record[ECC])++; } } } else { pb_sim_read_eeprom_ecc(); } return PHB_OK; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_create_ef | +--------------------------------------------------------------------+ PURPOSE : Creates a SIM elementary file. */ T_PHB_RETURN pb_sim_create_ef (USHORT ef, USHORT record_size, USHORT records) { T_DB_INFO_FIELD field_info; T_DB_TYPE db_type; int db_result; TRACE_FUNCTION ("pb_sim_create_ef()"); TRACE_EVENT_P1("Elementary file ID = %x",ef); db_result = db_info_field(pbs_data.db_handle, ef, &field_info); /* Check whether file already exists. */ if(db_result EQ DB_OK) { /* Check for Record size and No. of records in the present field. */ if((field_info.record_size EQ record_size) AND (field_info.num_records EQ records)) return PHB_OK; /* Preserve the existing field. */ else { if(pb_sim_remove_ef(ef) EQ PHB_FAIL) /* Remove the existing file and recreate the field. */ return PHB_FAIL; } } /* Set DB_TYPE depending on the Elementary file. */ switch(ef) { case SIM_ADN: case SIM_FDN: case SIM_BDN: case SIM_SDN: case SIM_EXT1: case SIM_EXT2: case SIM_EXT3: case SIM_EXT4: case SIM_LND: case SIM_OCI: //case SIM_ICI: case FFS_LRN: case FFS_LMN: case FFS_EXT_LRN: case FFS_EXT_LMN: case SIM_EXT5: db_type = DB_FREELIST; break; case SIM_MSISDN: case SIM_IMSI: db_type = DB_UNMANAGED; break; default: TRACE_ERROR("Invalid ef passed to pb_sim_create_ef()"); return PHB_FAIL; } db_result = db_create_field(pbs_data.db_handle, db_type, ef, record_size, records); if(db_result EQ DB_OK) return PHB_OK; /* Return PHB_FAIL since DB has failed to create File. */ return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_write_ef | +--------------------------------------------------------------------+ PURPOSE : Writes entry_size bytes content of buffer at index to the elementary file ef. */ T_PHB_RETURN pb_sim_write_ef (USHORT ef, USHORT phy_recno, USHORT entry_size, const UBYTE *buffer, BOOL *changed, USHORT *ext_record_ef, UBYTE *ext_record_no) { int i; T_DB_CHANGED records_affected; TRACE_FUNCTION ("pb_sim_write_ef()"); /* Initialise changed to FALSE. */ *changed = FALSE; /* Default is no extension record */ *ext_record_ef = 0; *ext_record_no = 0; /* Check for extension records. */ if (!pb_sim_record_empty(ef, entry_size, buffer)) { /* The record is not empty (deleted) */ switch (ef) { case SIM_ADN: case SIM_MSISDN: case SIM_LND: *ext_record_ef = SIM_EXT1; *ext_record_no = buffer[entry_size - 1]; break; case SIM_FDN: *ext_record_ef = SIM_EXT2; *ext_record_no = buffer[entry_size - 1]; break; case SIM_SDN: *ext_record_ef = SIM_EXT3; *ext_record_no = buffer[entry_size - 1]; break; case SIM_BDN: *ext_record_ef = SIM_EXT4; *ext_record_no = buffer[entry_size - 1]; break; case FFS_LRN: case FFS_LMN: case SIM_OCI: /* Release 1999 and above 31.102 clause 4.2.34 */ *ext_record_ef = SIM_EXT5; *ext_record_no = buffer[entry_size - 15]; // Jirli, please check, 14 instead of 15? break; case SIM_EXT1: /* Extension records can reference other extension records */ case SIM_EXT2: case SIM_EXT3: case SIM_EXT4: case SIM_EXT5: case FFS_EXT_LRN: case FFS_EXT_LMN: //TISH, patch for OMAPS00124850 #if 0 *ext_record_ef = ef; *ext_record_no = buffer[entry_size - 1]; #else if (buffer[entry_size - 1] EQ 255 OR buffer[entry_size-1] EQ (UBYTE)phy_recno) { *ext_record_ef =0; *ext_record_no=0; } else { *ext_record_ef = ef; *ext_record_no = buffer[entry_size - 1]; } #endif //end break; default: /* No extension record defined for this field */ break; } /* Record is not referring any extensions. So set ef and record_no to ZERO. */ if (*ext_record_no EQ 0xff) { *ext_record_ef = 0; *ext_record_no = 0; } /* Handle usage counter of extension records */ pb_sim_update_extn_records (*ext_record_ef, *ext_record_no, 1); /* Write record into FFS */ if(db_write_record(pbs_data.db_handle, ef, phy_recno, 0, entry_size, buffer) > DB_OK) { if(db_read_change_log(pbs_data.db_handle, &records_affected) EQ DB_OK) { for(i = 0; i < records_affected.entries; i++) { /* Checking whether Elementary file in the database is changed. */ if((records_affected.field_id[i] EQ ef) AND (records_affected.record[i] EQ phy_recno)) { *changed = TRUE; return PHB_OK; } } /* Write operation has not changed File in the database. So returning PHB_OK */ return PHB_OK; } else /* Unable to read change log from DB. So returning PHB_FAIL. */ return PHB_FAIL; } else /* Write failure in DB. So returning PHB_FAIL */ return PHB_FAIL; } else { /* Empty record */ if (db_delete_record (pbs_data.db_handle, ef, phy_recno) NEQ DB_OK) return PHB_FAIL; if(db_read_change_log (pbs_data.db_handle, &records_affected) NEQ DB_OK) return PHB_FAIL; *changed = (records_affected.entries NEQ 0); return PHB_OK; } } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_open | +--------------------------------------------------------------------+ PURPOSE : Opens the SIM phonebook for the given SIM determined by the IMSI. */ T_PHB_RETURN pb_sim_open (const T_imsi_field *imsi_field, BOOL *changed) { T_DB_INFO database_info; UBYTE ffsIMSI[MAX_IMSI_LEN+1]; UBYTE simIMSI[MAX_IMSI_LEN+1]; UBYTE imsi[FFS_IMSI_SIZE]; int db_result,rec_num; UBYTE buffer[RDM_PHB_DATA_SIZE]; TRACE_FUNCTION("pb_sim_open()"); /* Initially set SIM changed as TRUE. */ *changed = TRUE; /* Open the database. */ db_result = db_open(FFS_PHB_DIR); TRACE_EVENT_P1("DB handle is %d",db_result); if(db_result >= DB_OK) { pbs_data.db_handle = db_result; /* Get database info. */ db_result = db_info(pbs_data.db_handle, &database_info); /* Read IMSI from the FFS if Database is clean. */ if((db_result EQ DB_OK) AND (database_info.clean EQ TRUE)) { db_result = db_read_record(pbs_data.db_handle, SIM_IMSI, 1, 0, FFS_IMSI_SIZE, imsi); /* Compare IMSI read from FFS with IMSI got from SIM. */ if(db_result > DB_OK) { psaSIM_decodeIMSI ((UBYTE*) imsi_field->field,(UBYTE)imsi_field->c_field, (char *)simIMSI); psaSIM_decodeIMSI (imsi, FFS_IMSI_SIZE, (char *)ffsIMSI); if (!strcmp((char *)simIMSI, (char *)ffsIMSI)) { *changed = FALSE; return PHB_OK; } } else { /* Unable to read IMSI, regenerate database */ *changed = TRUE; } } /* Remove database whenever database is Inconsistent and SIM is changed. */ if(db_close(pbs_data.db_handle) NEQ DB_OK) return PHB_FAIL; if(db_remove(FFS_PHB_DIR) NEQ DB_OK) return PHB_FAIL; }/* if(db_result >= DB_OK) */ /* Create database: For the first time, whenever SIM is changed and whenever database is Inconsistent. */ db_result = db_create(FFS_PHB_DIR, MAX_ELEM_FILES, TRUE); TRACE_EVENT_P1("DB handle is %d",db_result); /* Creating DB is successful and valid db_handle is returned */ if(db_result >= DB_OK) { if(db_create_field(pbs_data.db_handle, DB_UNMANAGED, SIM_IMSI, imsi_field->c_field, 1) NEQ DB_OK) return PHB_FAIL; if(db_write_record(pbs_data.db_handle, SIM_IMSI, 1, 0, imsi_field->c_field, imsi_field->field) < DB_OK) return PHB_FAIL; /* Create Elementary file to store RDM Phonebook data */ if(db_create_field(pbs_data.db_handle, DB_UNMANAGED, RDM_DATA_FILE_ID,RDM_PHB_DATA_SIZE,3) NEQ DB_OK) return PHB_FAIL; /* Initialise data for Recent call lists */ for(rec_num = 1; rec_num <= 3; rec_num++) { memset(buffer,0x00, RDM_PHB_DATA_SIZE); if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, rec_num, 0, RDM_PHB_DATA_SIZE, buffer) < DB_OK) return PHB_FAIL; } return PHB_OK; } /* Unable to create Database. So returning PHB_FAIL. */ return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_ef | +--------------------------------------------------------------------+ PURPOSE : Reads *buffer from elementary file ef at index. */ T_PHB_RETURN pb_sim_read_ef (USHORT ef, USHORT recno, USHORT *entry_size, UBYTE *buffer) { int db_result; T_DB_INFO_FIELD field_info; TRACE_FUNCTION("pb_sim_read_ef()"); if(db_info_field(pbs_data.db_handle, ef, &field_info) EQ DB_OK) { *entry_size = field_info.record_size; db_result = db_read_record (pbs_data.db_handle, ef, recno, 0, field_info.record_size, buffer); if (db_result > DB_OK) return PHB_OK; /* Successfully read */ if (db_result EQ DB_EMPTY_RECORD) { /* Return a deleted record content */ memset (buffer, 0xff, *entry_size); return PHB_OK; } return PHB_FAIL; /* Some problem reading record */ } /* Returning PHB_FAIL, since DB has failed to give Info about the field. */ return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_remove_ef | +--------------------------------------------------------------------+ PURPOSE : Removes elementary file. */ T_PHB_RETURN pb_sim_remove_ef (USHORT ef) { T_EXT_TYPE ext_type; USHORT rec_num; TRACE_FUNCTION("pb_sim_remove_ef()"); if(db_remove_field(pbs_data.db_handle, ef) EQ DB_OK) { /* Get EXT Type for elementary file */ ext_type = pb_sim_get_ext_type(ef); /* Reset reference count for extension records */ if(ext_type NEQ INVALID_EXT) { for(rec_num = 0; rec_num < MAX_EXT_RECORDS; rec_num++) { ext_ref_count[ext_type][rec_num] = 0; } } return PHB_OK; } return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_build_index | +--------------------------------------------------------------------+ PURPOSE : Builds index for the given phonebook. */ T_PHB_RETURN pb_sim_build_index (T_PHB_TYPE type) { USHORT field_id; TRACE_FUNCTION("pb_sim_build_index()"); field_id = pb_sim_get_field_id(type); if(db_update_index(pbs_data.db_handle, field_id, NAME_IDX, pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) return PHB_FAIL; if(db_update_index(pbs_data.db_handle, field_id, NUMBER_IDX, pb_sim_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) return PHB_FAIL; return PHB_OK; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_flush_data | +--------------------------------------------------------------------+ PURPOSE : This function informs the SIM phonebook that SIM reading has become finished and we reached a consistent state. */ T_PHB_RETURN pb_sim_flush_data (void) { TRACE_FUNCTION("pb_sim_flush_data()"); if(db_flush(pbs_data.db_handle) EQ DB_OK) return PHB_OK; return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_add_record | +--------------------------------------------------------------------+ PURPOSE : Add a given record at index to the given phonebook. */ T_PHB_RETURN pb_sim_add_record (T_PHB_TYPE type, USHORT phy_recno, const T_PHB_RECORD *entry, T_DB_CHANGED *rec_affected) { USHORT field_id, ext_file_id, rec_no; UBYTE tag_len, max_tag_len; UBYTE data[SIM_MAX_RECORD_SIZE]; UBYTE buffer[RDM_PHB_DATA_SIZE]; T_DB_INFO_FIELD info_field, ext_info_field; UBYTE ext_rec_cnt = 0; UBYTE ext_rec_num1, ext_rec_num2; BOOL record_empty; int db_result,i; TRACE_FUNCTION("pb_sim_add_record()"); /* Handling of ECC Phonebook */ if(type EQ ECC) { if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD)) { phb_ecc_element[phy_recno - 1].phy_idx = phy_recno; memcpy(phb_ecc_element[phy_recno - 1].number,entry->number, ECC_NUM_LEN); return PHB_OK; } else return PHB_FAIL; } /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); TRACE_EVENT_P1("pb_sim_get_field_id->Field_id: %x", field_id); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); TRACE_EVENT_P1("Ext_Field_id: %x", ext_file_id); db_result = db_info_field(pbs_data.db_handle, field_id, &info_field); /* Get record size to calculate alpha_len for the entry */ if(db_result NEQ DB_OK) { TRACE_EVENT_P1("db_result = %d",db_result); return PHB_FAIL; } /* Handling of LDN, LMN and LRN Phonebook records. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { if(phy_recno NEQ 1) return PHB_FAIL; /* Find free record in the elementary file. */ db_result = db_find_free_record( pbs_data.db_handle, field_id); /* Get record number for the type of Phonebook. */ rec_no = pb_sim_retrieve_rdm_recno(type); /* Error handling. */ if(rec_no EQ 0) return PHB_FAIL; /* Read data related to LDN, LMN and LRN Phonebook from FFS */ if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, rec_no, 0, RDM_PHB_DATA_SIZE, buffer) < DB_OK) return PHB_FAIL; /* Database is unable to find the free record. So overwrite the oldest one. */ if(db_result < 0) phy_recno = buffer[RDM_PHB_DATA_SIZE - 1]; else phy_recno = db_result; if(info_field.used_records EQ RDM_PHB_DATA_SIZE) i = RDM_PHB_DATA_SIZE - 1; else i = info_field.used_records; /* Move the records as new record has to be added. */ for(; i > 0; i--) { buffer[i] = buffer[i-1]; } /* Update the record number of new entry. */ buffer[0] = (UBYTE) phy_recno; /* Write back RDM data back into the database. */ if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, rec_no, 0, RDM_PHB_DATA_SIZE, buffer) < DB_OK) return PHB_FAIL; /* Drop information about changed RDM records from the database. */ (void)db_read_change_log(pbs_data.db_handle, rec_affected); rec_affected->entries = 0; } /* Convert T_PHB_TYPE into data structures as described in ETSI 11.11 */ /* Bytes Description M/O Length | ---------------------------------------------------------------------- 1 to X Alpha Identifier O X bytes X+1 Length of BCD number/SSC contents M 1 byte X+2 TON and NPI M 1 byte X+3 to X+12 Dialling Number/SSC String M 10 bytes X+13 Capability/Configuration Identifier M 1 byte X+14 Extension Record Identifier M 1 byte ------------------------------------------------------- Extra fields for LDN, LMN, and LMN Phonebook records (As per 31.102) ------------------------------------------------------- X+15 to X+21 Outgoing call date and time M 7 bytes X+22 to X+24 Outgoing call duration M 3 bytes X+26 Line of the call M 1 byte (New field added to store line of call) ----------------------------------------------------------------------*/ tag_len = pb_sim_get_entry_len(entry->tag, PHB_MAX_TAG_LEN); max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); if(tag_len > max_tag_len) return PHB_TAG_EXCEEDED; memset(data, 0xFF, sizeof(data)); memcpy(data, entry->tag, tag_len); if(entry->number[10] NEQ 0xFF) { data[max_tag_len] = 11; /* max. length */ } else { data[max_tag_len] = entry->len + 1; } data[max_tag_len+1] = entry->ton_npi; memcpy((char *)&data[max_tag_len+2], (char *)entry->number, 10); data[max_tag_len+12] = entry->cc_id; /* Copy data specific to records of Phonebook Types (LRN, LDN and LMN). */ if((type EQ LDN) OR (type EQ LRN) OR (type EQ LMN)) { if(entry->v_time) { data[max_tag_len+14] = entry->time.year; data[max_tag_len+15] = entry->time.month; data[max_tag_len+16] = entry->time.day; data[max_tag_len+17] = entry->time.hour; data[max_tag_len+18] = entry->time.minute; data[max_tag_len+19] = entry->time.second; data[max_tag_len+20] = entry->time.time_zone; data[max_tag_len+21] = (UBYTE)((entry->time.duration >> 16) & 0xff); data[max_tag_len+22] = (UBYTE)((entry->time.duration >> 8) & 0xff); data[max_tag_len+23] = (UBYTE)((entry->time.duration) & 0xff); } if(entry->v_line) { data[max_tag_len+24] = entry->line; } } /* Check how many extension records are needed for number */ if(entry->number[10] NEQ 0xFF) { ext_rec_cnt = entry ->len - 10; if(ext_rec_cnt % 10) ext_rec_cnt = (ext_rec_cnt / 10) + 1; else ext_rec_cnt = (ext_rec_cnt / 10); } /* Check how many extension records are needed for subaddress */ if(entry->subaddr[0] NEQ 0xFF) { ext_rec_cnt++; } if(entry->subaddr[11] NEQ 0xFF) { ext_rec_cnt++; } TRACE_EVENT_P1("phy_recno = %d",phy_recno); TRACE_EVENT_P2("no_rec = %d, used_rec = %d",info_field.num_records,info_field.used_records); /* If record number is not mentioned, search for the free record and add the entry. */ if(phy_recno EQ 0) { db_result = db_find_free_record( pbs_data.db_handle, field_id); /* Database is unable to find the free record. So returning PHB_FULL. */ if(db_result EQ DB_RECORD_NOT_FOUND) return PHB_FULL; if(db_result < DB_OK) return PHB_FAIL; /* Database has returned the free record number. */ phy_recno = db_result; } else { /* * Delete the record, if present to get rid of associated * ext records. This has the effect that when we afterwards are unable to * create the new record (e.g. lack of extension records) the original * record remains deleted. Probably this is not a problem, at least it * should not be a big one. */ db_result = db_record_empty (pbs_data.db_handle, field_id, phy_recno, &record_empty); if ((db_result EQ DB_OK) AND !record_empty) { /* * In case ext_rec is needed and the existing record is not using EXT, * check if there is ext_rec available before deleting the existing entry * ext_info_field is used to get this info */ if (ext_rec_cnt NEQ 0 AND !pb_sim_ext_records_used(type, field_id,phy_recno)) { db_result = db_info_field(pbs_data.db_handle, ext_file_id, &ext_info_field); TRACE_EVENT_P3("before delelet rec; db_result = %d, ext_info_field.num_records = %d, ext_info_field.used_records = %d", db_result, ext_info_field.num_records, ext_info_field.used_records); if((ext_info_field.num_records - ext_info_field.used_records) < ext_rec_cnt) return PHB_EXT_FULL; } (void)pb_sim_del_record_internal (type, phy_recno, rec_affected, TRUE); } } /* Write record if entry does not require extension records */ if(ext_rec_cnt EQ 0) { /* Write record into FFS */ if(db_write_record(pbs_data.db_handle, field_id, phy_recno, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL; /* For LDN record also write to SIM_LDN (without date and time Details */ if(type EQ LDN) { memset(&data[max_tag_len + pb_sim_get_size_except_tag(field_id)], 0xFF, SIZE_DATA_DATE_TIME); /* if(db_info_field(pbs_data.db_handle, SIM_LND, &info_field) NEQ DB_OK) return PHB_FAIL; if(db_write_record(pbs_data.db_handle, SIM_LND, phy_recno, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL;*/ } } else /* We need to find free extension record. */ { TRACE_EVENT_P1("Extension records = %d",ext_rec_cnt); /* Search for free extension records */ /* Check whether extension file has required no. of free records. */ db_result = db_info_field(pbs_data.db_handle, ext_file_id, &info_field); if((info_field.num_records - info_field.used_records) < ext_rec_cnt) { return PHB_EXT_FULL; } /* Required no. of free extension records are found */ db_result = db_find_free_record( pbs_data.db_handle,ext_file_id); /* DB has returned non-zero positive number. (Valid record number which is free). */ if(db_result EQ DB_RECORD_NOT_FOUND) { return PHB_EXT_FULL; } if(db_result > DB_OK) { /* Set Extension record Identifier */ ext_rec_num1 = db_result; data[max_tag_len+13] = ext_rec_num1; db_result = db_info_field(pbs_data.db_handle, field_id, &info_field); /* Write record into FFS */ if(db_write_record(pbs_data.db_handle, field_id, phy_recno, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL; } else return PHB_FAIL; db_result = db_info_field(pbs_data.db_handle, ext_file_id, &info_field); /* Prepare extension data and write into Extension file after finding the free records. */ for(i = 0; i < ext_rec_cnt; i++) { //TISH, patch for ASTec34494, added by Jinshu Wang, 2007-08-09 //start memset(data,0xff,SIM_MAX_RECORD_SIZE); //end pb_sim_prepare_ext_data(data, i, (UBYTE*)entry->number, entry->len, (UBYTE*)entry->subaddr); /* Find next free record to chain the extension records. */ db_result = db_find_free_record( pbs_data.db_handle,ext_file_id); if(db_result EQ DB_RECORD_NOT_FOUND) { return PHB_EXT_FULL; } if(db_result > DB_OK) { ext_rec_num2 = db_result; } else { return PHB_FAIL; } /* Chain extension records and set last link to "FF" */ if(i NEQ (ext_rec_cnt - 1)) data[12] = ext_rec_num2; /* Write extension record into FFS */ if(db_write_record(pbs_data.db_handle, ext_file_id, ext_rec_num1, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL; if(pb_sim_update_extn_records(ext_file_id, ext_rec_num1, 1) EQ PHB_FAIL) return PHB_FAIL; /* Preserve the previous free record number. */ ext_rec_num1 = ext_rec_num2; } } /* Get information about changed records from the database. */ if(db_read_change_log(pbs_data.db_handle, rec_affected) NEQ DB_OK) return PHB_FAIL; /* Implements Measure #167 */ return pb_sim_update_index ( type, rec_affected,field_id, ext_rec_cnt); } /* +----------------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_del_record_internal | +----------------------------------------------------------------------------+ PURPOSE : Delete a given record at phy_recno from the given phonebook. If this function is called internally by a replacement operation on the phonebook this is indicated by the replacement parameter, in this case neither the change log are read nor the ring buffer management is touched in case of circular phonebooks. */ LOCAL T_PHB_RETURN pb_sim_del_record_internal (T_PHB_TYPE type, USHORT phy_recno, T_DB_CHANGED *rec_affected, BOOL replacement) { USHORT field_id, db_recno, rec_no; UBYTE buffer[RDM_PHB_DATA_SIZE], rec_cnt; TRACE_FUNCTION("pb_sim_del_record_internal()"); /* Handling of ECC Phonebook */ if(type EQ ECC) { if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD)) { phb_ecc_element[phy_recno - 1].phy_idx = 0; memset(phb_ecc_element[phy_recno - 1].number, 0xFF, ECC_NUM_LEN); return PHB_OK; } else return PHB_FAIL; } TRACE_EVENT_P1("phy_recno = %d", phy_recno); /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); /* Handling of LDN, LMN and LRN Phonebook records. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { /* Get record number for the type of Phonebook. */ rec_no = pb_sim_retrieve_rdm_recno(type); /* Error handling. */ if(rec_no EQ 0) return PHB_FAIL; /* Read data related to LDN, LMN and LRN Phonebook from FFS */ if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID,rec_no, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK) return PHB_FAIL; /* Retrieve record number in Database from the buffer. */ if((buffer[phy_recno - 1] EQ 0) OR (buffer[phy_recno - 1] > RDM_PHB_DATA_SIZE)) return PHB_FAIL; db_recno = buffer[phy_recno - 1]; if (!replacement) { /* Move the records */ for(rec_cnt = phy_recno -1; rec_cnt < RDM_PHB_DATA_SIZE - 1; rec_cnt ++) { buffer[rec_cnt] = buffer[rec_cnt + 1]; } /* Update the deleted entry record number. */ buffer[RDM_PHB_DATA_SIZE - 1] = 0; /* Write back RDM data back into the database. */ if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, rec_no, 0, RDM_PHB_DATA_SIZE, buffer) < DB_OK) return PHB_FAIL; /* Drop information about changed RDM records from the database. */ (void)db_read_change_log(pbs_data.db_handle, rec_affected); rec_affected->entries = 0; } } else { db_recno = phy_recno; } /* Delete extension records if not referenced. */ (void)pb_sim_del_ext_records(type, field_id, db_recno); /* Delete record from FFS. */ if(db_delete_record(pbs_data.db_handle, field_id,db_recno) NEQ DB_OK) return PHB_FAIL; /* Get final information about changed records from the database. */ if (!replacement) { if(db_read_change_log(pbs_data.db_handle, rec_affected) NEQ DB_OK) return PHB_FAIL; } /* Implements Measure #167 */ return pb_sim_update_index ( type, rec_affected,field_id, 0); } /* +----------------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_del_record | +----------------------------------------------------------------------------+ PURPOSE : Delete a given record at phy_recno from the given phonebook. This function reads the change log. */ T_PHB_RETURN pb_sim_del_record (T_PHB_TYPE type, USHORT phy_recno, T_DB_CHANGED *rec_affected) { TRACE_FUNCTION ("pb_sim_del_record()"); return (pb_sim_del_record_internal (type, phy_recno, rec_affected, FALSE)); } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_record | +--------------------------------------------------------------------+ PURPOSE : Read a given physical record from the flash based phonebook. */ T_PHB_RETURN pb_sim_read_record (T_PHB_TYPE type, USHORT phy_recno, T_PHB_RECORD *entry) { USHORT field_id, ext_file_id, rec_no; USHORT db_recno; T_DB_INFO_FIELD info_field; UBYTE buffer[RDM_PHB_DATA_SIZE]; UBYTE *data=NULL, *ptr; UBYTE max_tag_len; UBYTE ext_rcd_num; TRACE_FUNCTION("pb_sim_read_record()"); /* Handling of ECC Phonebook */ if(type EQ ECC) { if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD)) { memset(entry,0xFF,sizeof(T_PHB_RECORD)); /* Return PHB_FAIL whenever ECC entry is empty */ if((phb_ecc_element[phy_recno - 1].number[0] & 0x0F) EQ 0x0F) { return PHB_FAIL; } else { entry->phy_recno = phy_recno; entry->len = ECC_NUM_LEN; memcpy(entry->number, phb_ecc_element[phy_recno - 1].number, ECC_NUM_LEN); return PHB_OK; } } else return PHB_FAIL; } /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); /* Read record from the database. */ if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK) return PHB_FAIL; if((phy_recno EQ 0 ) OR (phy_recno > info_field.num_records)) return PHB_FAIL; /* Handling of LDN, LMN and LRN Phonebook records. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { /* Get record number for the type of Phonebook. */ rec_no = pb_sim_retrieve_rdm_recno(type); /* Error handling. */ if(rec_no EQ 0) return PHB_FAIL; /* Read data related to LDN,LMN and LRN Phonebook from FFS */ if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, rec_no, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK) return PHB_FAIL; db_recno = buffer[phy_recno - 1]; } else db_recno = phy_recno; ACI_MALLOC(data,SIM_MAX_RECORD_SIZE); if(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) { ACI_MFREE(data); return PHB_FAIL; } /* Convert SIM data to the type T_PHB_RECORD. */ ptr = data; max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); if (max_tag_len > PHB_MAX_TAG_LEN) max_tag_len = PHB_MAX_TAG_LEN; entry->phy_recno = phy_recno; entry->tag_len = (UBYTE)pb_sim_get_entry_len(ptr, max_tag_len); memset(entry->tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */ memcpy ( (char*)entry->tag, (char*)ptr, entry->tag_len ); ptr += (info_field.record_size) - pb_sim_get_size_except_tag(field_id); max_tag_len = (info_field.record_size) - pb_sim_get_size_except_tag(field_id); entry->len = *ptr - 1; ++ptr; entry->ton_npi = *ptr; ++ptr; /* * This error handling is done to avoid the accidental incorrect * record length stored in the test SIMs */ if (entry->len > PHB_PACKED_NUM_LEN) { entry->len = PHB_PACKED_NUM_LEN; } memset(entry->number, 0xFF, PHB_PACKED_NUM_LEN); memcpy( (char*)entry->number, (char*)ptr, entry->len ); ptr += 10; entry->cc_id = *ptr; ++ptr; /* Copy data specific to records of LDN, LMN, and LRN phonebook types. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { entry->v_time = 1; entry->time.year=data[max_tag_len+14] ; entry->time.month=data[max_tag_len+15]; entry->time.day=data[max_tag_len+16]; entry->time.hour=data[max_tag_len+17] ; entry->time.minute= data[max_tag_len+18]; entry->time.second=data[max_tag_len+19] ; entry->time.time_zone=data[max_tag_len+20]; entry->time.duration = (data[max_tag_len+21] << 16) + (data[max_tag_len+22] << 8) + (data[max_tag_len+23] ); entry->v_line = 1; entry->line=data[max_tag_len+24]; } if (*ptr NEQ 0xFF) /* check for extention records */ { ext_rcd_num =(UBYTE)*ptr; if(db_info_field(pbs_data.db_handle, ext_file_id, &info_field) NEQ DB_OK) { ACI_MFREE(data); return PHB_FAIL; } /* Reset pointer to start location. */ ptr = data; memset(ptr, 0xFF, info_field.record_size); if(db_read_record(pbs_data.db_handle, ext_file_id, ext_rcd_num, 0, info_field.record_size, ptr) < DB_OK) { ACI_MFREE(data); //TISH, patch for OMAPS00123396 //start // return PHB_FAIL; return PHB_OK; //end } pb_sim_read_ext(ptr, entry); while(*(ptr + 12) NEQ 0xFF) /* check if a further EXT entry exists */ { memset(ptr, 0xFF, info_field.record_size); db_read_record(pbs_data.db_handle, ext_file_id, (USHORT)*(ptr+12), 0, info_field.record_size,ptr); pb_sim_read_ext(ptr, entry); } } ACI_MFREE(data); return PHB_OK; } /* Implements Measure #30 */ /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_search_name | +--------------------------------------------------------------------+ PURPOSE : Finds the first entry matching the search tag. */ T_PHB_RETURN pb_sim_search_name (T_PHB_TYPE type, T_PHB_MATCH match, const T_ACI_PB_TEXT *search_tag, SHORT *order_num) { T_ACI_PB_TEXT key; int res; USHORT field_id; TRACE_FUNCTION("pb_sim_search_name()"); /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); key.len = search_tag->len; key.cs = search_tag->cs; pb_sim_cvt_alpha_for_cmp ((UBYTE*) search_tag->data, (UBYTE*) key.data, search_tag->len); res = db_search(pbs_data.db_handle, field_id, NAME_IDX, order_num, pb_sim_search_alpha_func, match, (const UBYTE*)&key); if(res > DB_OK) { return PHB_OK; } return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_search_number | +--------------------------------------------------------------------+ PURPOSE : Finds the first entry matching the number. */ T_PHB_RETURN pb_sim_search_number (T_PHB_TYPE type, const UBYTE *number, SHORT *order_num) { int res, i; CHAR cur_number[MAX_PHB_NUM_LEN]; CHAR rev_number[MAX_PHB_NUM_LEN]; int cmpLen, cmp_res; USHORT field_id; TRACE_FUNCTION("pb_sim_search_number()"); /* Handling for ECC Phonebook. */ if(type EQ ECC) { for(i = 0; i < pbs_data.max_record[ECC]; i++) { cmhPHB_getAdrStr(cur_number, MAX_PHB_NUM_LEN - 1,phb_ecc_element[i].number,pbs_data.record_size[ECC]); pb_sim_revString(cur_number); strcpy( rev_number,(const char*)number); pb_sim_revString(rev_number); /*cmpLen = MINIMUM(strlen((const char*) cur_number), strlen((const char*)number));*/ cmpLen = strlen((const char*)number); if(cmpLen > 7) { cmpLen = 7; cmp_res = pb_sim_cmpString((UBYTE*)cur_number, (UBYTE*)rev_number, cmpLen); } else { cmp_res = strcmp(cur_number,rev_number); } /*patch for ASTec29800 EFECC by dongfeng*/ if(cmp_res EQ 0) return PHB_OK; } return PHB_FAIL; } /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); res = db_search(pbs_data.db_handle, field_id, NUMBER_IDX, order_num, pb_sim_search_num_func, PHB_MATCH_PARTIAL, number); if(res > DB_OK) { return PHB_OK; } return PHB_FAIL; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_sizes | +--------------------------------------------------------------------+ PURPOSE : Reads the sizes of a given phonebook. */ T_PHB_RETURN pb_sim_read_sizes (T_PHB_TYPE type, SHORT *max_rcd, SHORT *used_rcd, UBYTE *tag_len, SHORT *max_ext, SHORT *used_ext) { T_DB_INFO_FIELD info_field; USHORT field_id; T_DB_CODE db_result; TRACE_FUNCTION("pb_sim_read_sizes()"); /* Set every output parameter to zero for (not there) */ *max_rcd = 0; *used_rcd = 0; *tag_len = 0; *max_ext = 0; *used_ext = 0; /* Handling for ECC Phonebook */ if(type EQ ECC) { *max_rcd = pbs_data.max_record[ECC]; *used_rcd = pbs_data.used_record[ECC]; *tag_len = 0; /* To Do:Alpha tag will not be there for ECC. So assigning zero here */ return PHB_OK; } /* Get elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id (type); /* Query the database about the field */ db_result = db_info_field (pbs_data.db_handle, field_id, &info_field); if (db_result EQ DB_OK) { /* We got results for the main phonebook entries. */ *max_rcd = info_field.num_records; *used_rcd = info_field.used_records; *tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); /* Get elementary file ID for the respective extension. */ field_id = pb_sim_get_ext_file (type); if (field_id NEQ 0) { /* * Extension records may exist for this kind of phonebook. * Query the database about the ext records. */ db_result = db_info_field (pbs_data.db_handle, field_id, &info_field); if (db_result EQ DB_OK) { /* There are also extension records present in the database. */ *max_ext = info_field.num_records; *used_ext = info_field.used_records; } /* There is no else as it is not a problem if there are no extension * records for the phonebook on the SIM as those are optional only. */ } return PHB_OK; } return PHB_FAIL; /* The phonebook does not exist */ } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_get_entry_len | +--------------------------------------------------------------------+ PURPOSE : Used to get the length in bytes of a given entry which is coded as given in 11.11 Annex B. */ int pb_sim_get_entry_len (const UBYTE *pb_tag, UBYTE max_pb_len) { int pb_len = 0; UBYTE inc_count = 1; BOOL ucs2 = FALSE; UBYTE chars = 0; TRACE_FUNCTION("pb_sim_get_entry_len()"); if (*pb_tag EQ 0x80) { ucs2 = TRUE; inc_count = 2; /* check two bytes */ pb_len = 1; /* skip the 0x80 */ } else if (*pb_tag EQ 0x81 OR *pb_tag EQ 0x82) { if (*pb_tag EQ 0x81) pb_len = 3; /* 0x80 + len + pointer */ else pb_len = 4; /* 0x80 + len + 2xpointer */ chars = pb_tag[1]; pb_tag += pb_len; /* go to data */ while (chars) { if (*pb_tag++ & 0x80) pb_len+=2; else pb_len+=1; pb_tag++; chars--; } return MINIMUM(pb_len,max_pb_len); } while (pb_len < max_pb_len) { if (ucs2 EQ TRUE) { if (!(pb_len+1 < max_pb_len)) /* Check also if we traverse the upper bound */ break; /* so only a "half" UCS2 element is remaining */ } if (pb_tag[pb_len] EQ 0xFF) { /* one 0xFF indicates the end of a non UCS2 string */ if (ucs2 EQ FALSE) { break; } /* two 0xFF indicates the end of a UCS2 string */ if (pb_tag[pb_len + 1] EQ 0xFF) { break; } } pb_len += inc_count; } return (pb_len); } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_alpha_cmp | +--------------------------------------------------------------------+ PURPOSE : Compares alpha identifier of two records. */ int pb_sim_alpha_cmp (int db_handle, USHORT field_id, USHORT recno_1, USHORT recno_2, ULONG flags) { T_PHB_RECORD entry_1,entry_2; UBYTE cmpLen = 0; UBYTE *buffer; UBYTE max_tag_len; UBYTE cur_tag[PHB_MAX_TAG_LEN], check_tag[PHB_MAX_TAG_LEN]; int cmp_res; T_DB_INFO_FIELD info_field; TRACE_FUNCTION("pb_sim_alpha_cmp()"); db_info_field(db_handle, field_id, &info_field); MALLOC(buffer, info_field.record_size); /* Read the first record. */ db_read_record(db_handle, field_id, recno_1, 0, info_field.record_size, buffer); /* Unpack record 1 to do a string comparison on the alpha identifier field */ max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); if (max_tag_len > PHB_MAX_TAG_LEN) max_tag_len = PHB_MAX_TAG_LEN; entry_1.tag_len = (UBYTE)pb_sim_get_entry_len(buffer, max_tag_len); memset(entry_1.tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */ memcpy ( (char*)entry_1.tag, (char*)buffer, entry_1.tag_len ); pb_sim_cvt_alpha_for_cmp ( entry_1.tag, cur_tag, entry_1.tag_len ); memset(buffer, 0, info_field.record_size); /* Read the second record. */ db_read_record(db_handle, field_id, recno_2, 0, info_field.record_size, buffer); /* Unpack record 2 to do a string comparison on the alpha identifier field */ max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); if (max_tag_len > PHB_MAX_TAG_LEN) max_tag_len = PHB_MAX_TAG_LEN; entry_2.tag_len = (UBYTE)pb_sim_get_entry_len(buffer, max_tag_len); memset(entry_2.tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */ memcpy ( (char*)entry_2.tag, (char*)buffer, entry_2.tag_len ); pb_sim_cvt_alpha_for_cmp ( entry_2.tag, check_tag, entry_2.tag_len ); cmpLen = MINIMUM ( entry_1.tag_len, entry_2.tag_len ); TRACE_EVENT_P1("%d", cmpLen); cmp_res = pb_sim_cmpString ( cur_tag, check_tag, cmpLen ); if (cmp_res EQ 0) { /* Correct result when length was different, ACIPHB201 */ if (entry_1.tag_len < entry_2.tag_len) cmp_res = -1; else if (entry_1.tag_len > entry_2.tag_len) cmp_res = 1; } MFREE(buffer); return cmp_res; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_number | +--------------------------------------------------------------------+ PURPOSE : Reads a phine number from a given record */ LOCAL void pb_sim_read_number (int db_handle, USHORT field_id, USHORT recno, CHAR *number) { T_PHB_RECORD entry; T_DB_INFO_FIELD info_field; UBYTE *sim_buffer, *buffer; UBYTE ext_rcd_num; unsigned ext_rec_cnt; USHORT ext_id; TRACE_FUNCTION("pb_sim_read_number()"); ACI_MALLOC(sim_buffer, SIM_MAX_RECORD_SIZE); buffer = sim_buffer; db_info_field(db_handle, field_id, &info_field); /* Read record recno_1 from the database using db_read_record() */ db_read_record (db_handle, field_id, recno, 0, info_field.record_size, buffer); /* Read only number from the buffer. */ buffer += (info_field.record_size) - pb_sim_get_size_except_tag(field_id); entry.len = *(buffer++) - 1; entry.ton_npi = *buffer++; /* * This error handling is done to avoid the accidental incorrect * record length stored in the test SIMs */ if (entry.len > PHB_PHY_NUM_LENGTH) { entry.len = PHB_PHY_NUM_LENGTH; } memset (entry.number, 0xFF, PHB_PACKED_NUM_LEN); memcpy (entry.number, buffer, entry.len); buffer += 10; entry.cc_id = *buffer++; ext_rcd_num = (UBYTE)*buffer; ext_id = pb_sim_get_ext_file_id (field_id); if ((ext_id NEQ 0) AND (db_info_field (db_handle, ext_id, &info_field) EQ DB_OK)) { /* Extension records exist and we can obtain information about it */ ext_rec_cnt = 0; while ((ext_rcd_num NEQ 0xFF) AND (ext_rcd_num NEQ 0) AND (ext_rcd_num <= info_field.num_records) AND (ext_rec_cnt < info_field.num_records)) { /* * Record not empty, in range 1..max num of ext records * Impossible to have read all records (avoid infinite loop) */ ext_rec_cnt++; (void)db_read_record (db_handle, ext_id, ext_rcd_num, 0, info_field.record_size, buffer); pb_sim_read_ext (buffer, &entry); ext_rcd_num = sim_buffer[12]; } } cmhPHB_getAdrStr(number, MAX_PHB_NUM_LEN - 1, entry.number, entry.len); ACI_MFREE (sim_buffer); } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_number_cmp | +--------------------------------------------------------------------+ PURPOSE : Compares two numbers of two records. */ int pb_sim_number_cmp (int db_handle, USHORT field_id, USHORT recno_1, USHORT recno_2, ULONG flags) { CHAR cur_number[MAX_PHB_NUM_LEN]; CHAR ref_number[MAX_PHB_NUM_LEN]; TRACE_FUNCTION("pb_sim_number_cmp()"); /* Read the numbers */ pb_sim_read_number (db_handle, field_id, recno_1, cur_number); pb_sim_read_number (db_handle, field_id, recno_2, ref_number); /* Reverse the numbers to compare number from right. */ pb_sim_revString(cur_number); pb_sim_revString(ref_number); return pb_sim_cmpWild ((char *)cur_number, (char *)ref_number, MAX_PHB_NUM_LEN); } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_ext | +--------------------------------------------------------------------+ PURPOSE : Reads extension records from the database and copies them to number. */ /* Extesion records will be stored as per 11.11. Bytes Description M/O Length -------------------------------------- 1 Record type M 1 byte 2 to 12 Extension data M 11 bytes 13 Identifier M 1 byte --------------------------------------*/ void pb_sim_read_ext(UBYTE *buffer, T_PHB_RECORD *entry) { UBYTE data_len; UBYTE data_type; UBYTE *data; TRACE_FUNCTION("pb_sim_read_ext()"); /* If this extension record is not empty, it is written in phonebook. */ data = buffer; data_type = *data; data_len = *(data+1); switch (data_type) { case 1: /* Called Party Subaddress */ { int sa_len = 0; while (sa_len<PHB_PACKED_NUM_LEN) /* get length of possible already stored subaddr if more than one EXT is used */ { if (entry->subaddr[sa_len] EQ 0xFF) break; else if ((entry->subaddr[sa_len] & 0xF0) EQ 0xF0) { sa_len++; break; } else sa_len++; } pb_sim_nibblecopy (entry->subaddr, sa_len, data + 2, data_len); } break; case 2: /* Additional data */ entry->len = pb_sim_nibblecopy (entry->number, entry->len, data + 2, data_len); break; default: /* unknown type */ break; } return; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_revString | +--------------------------------------------------------------------+ PURPOSE : Reverses a string within the same variable. */ void pb_sim_revString(char *str) { UBYTE i, j,str_len; char ch; TRACE_FUNCTION("pb_sim_revString()"); str_len = strlen(str); for(i = 0, j = str_len - 1;i < (str_len / 2); i++, j--) { ch = *(str + i); *(str + i) = *(str + j); *(str + j) = ch; } } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_search_alpha_func | +--------------------------------------------------------------------+ PURPOSE : Searches for a given alpha key in the database. */ int pb_sim_search_alpha_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num) { T_ACI_PB_TEXT *search_key; T_PHB_RECORD entry; UBYTE cmpLen = 0; T_PHB_TYPE phb_type; UBYTE cur_tag[PHB_MAX_TAG_LEN]; int cmp_res; TRACE_FUNCTION("pb_sim_search_alpha_func()"); /* Cast search key to appropriate data structure */ search_key = (T_ACI_PB_TEXT *)key; /* Get PHB type from field ID using PHB_ACI function. */ phb_type = pb_get_phb_type_from_ef(field_id); /* Read record from the database. */ pb_sim_read_record(phb_type, rec_num, &entry); pb_sim_cvt_alpha_for_cmp ( entry.tag, cur_tag, entry.tag_len ); cmpLen = search_key->len; if(flags EQ PHB_MATCH_PARTIAL) cmpLen = MINIMUM ( entry.tag_len, cmpLen); TRACE_EVENT_P1( "cmpLen=%d", cmpLen ); cmp_res = pb_sim_cmpString ( cur_tag, search_key->data, cmpLen ); return cmp_res; } /* +----------------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_search_num_func | +----------------------------------------------------------------------------+ PURPOSE : Searches for a given number key in the database. */ int pb_sim_search_num_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num) { T_PHB_RECORD entry; UBYTE cmpLen = 0; T_PHB_TYPE phb_type; CHAR cur_number[MAX_PHB_NUM_LEN]; CHAR rev_key[MAX_PHB_NUM_LEN]; int cmp_res; size_t strg_len; TRACE_FUNCTION("pb_sim_search_num_func()"); /* Get PHB type from field ID using PHB_ACI function. */ phb_type = pb_get_phb_type_from_ef(field_id); /* Read record from the database. */ if(pb_sim_read_record(phb_type, rec_num, &entry) NEQ PHB_OK) return -1; cmhPHB_getAdrStr(cur_number, MAX_PHB_NUM_LEN - 1, entry.number, entry.len); /* Reverse the first number to compare number from right. */ pb_sim_revString(cur_number); /* Reverse the second number to compare number from right. */ strcpy (rev_key, (const char*) key); pb_sim_revString(rev_key); cmpLen = strlen(rev_key); if(flags EQ PHB_MATCH_PARTIAL) { strg_len = strlen(cur_number); cmpLen = MINIMUM(strg_len, cmpLen); } TRACE_EVENT_P1("Number to be compared: %s", cur_number); TRACE_EVENT_P1("Number to be searched: %s", rev_key); if(cmpLen > 7) { cmpLen = 7; } cmp_res = pb_sim_cmpWild((char*)cur_number, (char*)rev_key, cmpLen); TRACE_EVENT_P1("Result of the comparison: %d", cmp_res); return cmp_res; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_nibblecopy | +--------------------------------------------------------------------+ PURPOSE : Used to convert BCD nibbles to string. */ LOCAL int pb_sim_nibblecopy (UBYTE dest[], int destlen, UBYTE src[], int count) { int i; int nibble; int destnibble=destlen*2; TRACE_FUNCTION("pb_sim_nibblecopy()"); if (destnibble) { if ((dest[destlen-1] & 0xF0) == 0xF0) /* check if there is space in last nibble */ destnibble--; } for ( i=0; i<count*2; i++ ) { /* check if we access out of bounds */ if (destnibble/2 >= PHB_PACKED_NUM_LEN) return PHB_PACKED_NUM_LEN; /* get nibble */ if (i%2 == 0) nibble = src[i/2] & 0x0F; else nibble = (src[i/2] & 0xF0) >> 4; if (nibble == 0xF) /* end of number detected */ break; /* put nibble */ if (destnibble%2 == 0) { dest[destnibble/2] &= 0xF0; dest[destnibble/2] |= nibble; } else { dest[destnibble/2] &= 0x0F; dest[destnibble/2] |= nibble << 4; } destnibble++; } return destnibble/2 + destnibble%2; /* round up */ } /* +------------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE : pb_sim_read_eeprom_ecc | +------------------------------------------------------------------------+ PURPOSE : Read EC number from EEPROM. */ LOCAL void pb_sim_read_eeprom_ecc (void) { EF_ECC efecc; UBYTE *data_ptr; UBYTE version; int rec_ctr; TRACE_FUNCTION("pb_sim_read_eeprom_ecc()"); /* Initialise ECC Phonebook Info. */ pbs_data.max_record[ECC] = MAX_ECC_RCD; pbs_data.used_record[ECC] = 0; if (pcm_ReadFile((UBYTE *)EF_ECC_ID, SIZE_EF_ECC, (UBYTE *)&efecc, &version) EQ DRV_OK) { { /* workaround when invalid data stored on PCM */ CHAR ecc_number[MAX_PHB_NUM_LEN]; int num_len; data_ptr = efecc.ecc1; for (rec_ctr=0; rec_ctr < pbs_data.max_record[ECC]; rec_ctr++) { if (*data_ptr NEQ 0xFF) { cmhPHB_getAdrStr (ecc_number, MAX_PHB_NUM_LEN - 1, data_ptr, ECC_NUM_LEN); for (num_len = 0; num_len < ECC_NUM_LEN; num_len++) { if (!isdigit (ecc_number[num_len])) { TRACE_EVENT_P2 ("[ERR] pb_read_eeprom_ecc(): invalid character found %c (%d)", ecc_number[num_len], rec_ctr); return; } } } data_ptr += ECC_NUM_LEN; } } /* workaround end */ data_ptr = &efecc.ecc1[0]; memset( phb_ecc_element,0xFF, (pbs_data.max_record[ECC] * sizeof(T_PHB_ECC_RECORD)) ); for (rec_ctr=0; rec_ctr < pbs_data.max_record[ECC]; rec_ctr++) { if(*data_ptr NEQ 0xff) { phb_ecc_element[rec_ctr].phy_idx = rec_ctr + 1; memcpy(phb_ecc_element[rec_ctr].number, data_ptr, ECC_NUM_LEN); data_ptr += ECC_NUM_LEN; (pbs_data.used_record[ECC])++; } } } } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_prepare_ext_data | +----------------------------------------------------------------------+ PURPOSE : Prepare the data for the extention record. If NULL pointer is given for number and subaddress then the extention record will marked as unused */ /* Extesion records will be stored as per 11.11. Bytes Description M/O Length -------------------------------------- 1 Record type M 1 byte 2 to 12 Extension data M 11 bytes 13 Identifier M 1 byte --------------------------------------*/ LOCAL void pb_sim_prepare_ext_data(UBYTE *ext_data, int ext_count, UBYTE *number, UBYTE no_len, UBYTE *subaddr) { UBYTE *data_num = NULL; UBYTE *data_subadd = NULL; TRACE_FUNCTION("pb_sim_prepare_ext_data()"); if(number[10] NEQ 0xFF) data_num = number + ((ext_count + 1) * 10); data_subadd = subaddr + (ext_count * 11); memset(ext_data, 0xFF, sizeof(ext_data)); if ((data_num NEQ NULL) AND (*data_num NEQ 0xFF)) { /* Set record type to 2 which corresponds to Additional data. Record type as per 11.11 */ ext_data[0] = 2; ext_data[1] = no_len - ((ext_count + 1) * 10); memcpy (ext_data + 2, data_num, 10); } else if ((data_subadd NEQ NULL) AND (*data_subadd NEQ 0xFF)) { TRACE_EVENT ("SUBADDRESS EXTENTION"); /* Set record type to 1 which corresponds to Called Party Subaddress. Record type as per 11.11 */ ext_data[0] = 1; memcpy (ext_data + 1, data_subadd, 11); } } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_get_field_id | +----------------------------------------------------------------------+ PURPOSE : Returns field ID for the corresponding Phonebook type. */ LOCAL USHORT pb_sim_get_field_id (T_PHB_TYPE type) { USHORT field_id; TRACE_FUNCTION("pb_sim_get_field_id()"); /* Get Elementary file ID for the Phonebook type. */ switch(type) { case ADN: field_id = SIM_ADN; break; case LDN: field_id = SIM_OCI; break; case LRN: field_id = FFS_LRN; break; case LMN: field_id = FFS_LMN; break; case UPN: field_id = SIM_MSISDN; break; case FDN: field_id = SIM_FDN; break; case SDN: field_id = SIM_SDN; break; case BDN: field_id = SIM_BDN; break; default: TRACE_ERROR ("No such field"); TRACE_EVENT_P1 ("No such field for type = %04X", type); field_id = 0; break; } return field_id; } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_get_ext_file | +----------------------------------------------------------------------+ PURPOSE : Returns field ID for the corresponding Phonebook type. */ LOCAL USHORT pb_sim_get_ext_file (T_PHB_TYPE type) { USHORT ext_file_id; TRACE_FUNCTION("pb_sim_get_ext_file()"); /* Get Extension Elementary file ID for the Phonebook type. */ switch(type) { case ADN: case UPN: ext_file_id = SIM_EXT1; break; case FDN: ext_file_id = SIM_EXT2; break; case SDN: ext_file_id = SIM_EXT3; break; case BDN: ext_file_id = SIM_EXT4; break; case LDN: ext_file_id = SIM_EXT5; break; case LRN: ext_file_id = FFS_EXT_LRN; break; case LMN: ext_file_id = FFS_EXT_LMN; break; default: ext_file_id = 0; /* No extension records available */ break; } return ext_file_id; } /* +---------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_cvt_alpha_for_cmp | +---------------------------------------------------------------------+ PURPOSE : convert alpha to lower case when not unicode */ LOCAL void pb_sim_cvt_alpha_for_cmp ( UBYTE *src, UBYTE *dst, UBYTE len ) { int i; TRACE_FUNCTION("pb_sim_cvt_alpha_for_cmp()"); if (*src NEQ 0x80) /* 11.11 Annex B 0x80 is the UCS2 indicator */ { for ( i = 0; i < len; i++ ) dst[i] = (UBYTE)tolower((int)src[i]); } else { memcpy (dst, src, len); } } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_get_ext_file_id | +----------------------------------------------------------------------+ PURPOSE : Returns Extension field ID for the corresponding field ID of a Phonebook. */ LOCAL USHORT pb_sim_get_ext_file_id (USHORT field_id) { USHORT ext_file_id; TRACE_FUNCTION("pb_sim_get_ext_file_id()"); /* Get Extension Elementary file ID for the Phonebook type. */ switch(field_id) { case SIM_ADN: case SIM_LND: case SIM_MSISDN: ext_file_id = SIM_EXT1; break; case SIM_FDN: ext_file_id = SIM_EXT2; break; case SIM_SDN: ext_file_id = SIM_EXT3; break; case SIM_BDN: ext_file_id = SIM_EXT4; break; case SIM_OCI: ext_file_id = SIM_EXT5; break; case FFS_LRN: ext_file_id = FFS_EXT_LRN; break; case FFS_LMN: ext_file_id = FFS_EXT_LMN; break; default: ext_file_id = 0; break; } return ext_file_id; } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_get_ext_type | +----------------------------------------------------------------------+ PURPOSE : Returns Extension Type ID for the corresponding field ID of a Phonebook. */ LOCAL T_EXT_TYPE pb_sim_get_ext_type (USHORT field_id) { T_EXT_TYPE ext_type; /* Get Extension Type for the Phonebook field ID. */ switch(field_id) { case SIM_ADN: case SIM_LND: case SIM_MSISDN: ext_type = EXT1; break; case SIM_FDN: ext_type = EXT2; break; case SIM_SDN: ext_type = EXT3; break; case SIM_BDN: ext_type = EXT4; break; case SIM_OCI: ext_type = EXT5; break; case FFS_LRN: ext_type = EXT_LRN; break; case FFS_LMN: ext_type = EXT_LMN; break; default: ext_type = INVALID_EXT; break; } return ext_type; } /* +----------------------------------------------------------------------+ | PROJECT : MODULE : PHB | | STATE : code ROUTINE : pb_sim_find_free_record | +----------------------------------------------------------------------+ PURPOSE : Returns free record number for the Phonebook type. */ GLOBAL int pb_sim_find_free_record (T_PHB_TYPE type) { int db_result; unsigned i; USHORT field_id; TRACE_FUNCTION("pb_sim_find_free_record()"); switch (type) { case ECC: /* ECC not stored in DB, special handling */ for (i = 0; i < pbs_data.max_record[ECC]; i++) { if (phb_ecc_element[i].phy_idx EQ 0) return i + 1; } return 0; /* No free record found */ case LDN: case LRN: case LMN: return 1; /* For cyclic entries always the first */ default: /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); db_result = db_find_free_record(pbs_data.db_handle, field_id); if (db_result <= 0) return 0; /* No free record */ return db_result; } } GLOBAL int pb_sim_find_free_ext_record () { int db_result; unsigned i; USHORT field_id; TRACE_FUNCTION("pb_find_ext_free_record()"); field_id =SIM_EXT1; db_result = db_find_free_record(pbs_data.db_handle, field_id); if (db_result <= 0) return 0; /* No free record */ return db_result; } /* +-------------------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_get_size_except_tag | +-------------------------------------------------------------------------------+ PURPOSE : Returns size of data excluding length of tag (alpha identifier) */ USHORT pb_sim_get_size_except_tag (USHORT field_id) { TRACE_FUNCTION("pb_sim_get_size_except_tag()"); switch(field_id) { case SIM_ADN: case SIM_FDN: case SIM_BDN: case SIM_MSISDN: case SIM_SDN: return 14; /* 11.11 */ case FFS_LRN: case FFS_LMN: case SIM_OCI: return 27; /* Using EF_OCI, 31.102 4.2.34 */ //case SIM_ICI: // return 28; /* Using EF_ICI, 31.102 4.2.33 */ default: TRACE_ERROR("Invalid field ID passed !"); return 0; } } /* +--------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_cmpString | +--------------------------------------------------------------------+ PURPOSE : compare two strings. if s1 < s2 return value < 0 if s1 = s2 return value = 0 if s1 > s2 return value > 0 */ static int pb_sim_cmpString ( UBYTE *s1, UBYTE *s2, UBYTE len ) { int n = 0; /* TRACE_FUNCTION("pb_sim_cmpString()"); */ /* Called too often to trace */ if ((*s1 EQ 0x80) AND (*s2 NEQ 0x80) ) { s1++; len--; return pb_sim_cmp2Bytes(s1, s2, len, 1); } else if ((*s1 NEQ 0x80) AND (*s2 EQ 0x80) ) { s2++; len--; return pb_sim_cmp2Bytes(s1, s2, len, 2); } else { while (*s1 EQ *s2) { if (*s1 EQ 0xff) return 0; s1++; s2++; n++; if (n EQ len) return 0; } if ((*s1 > *s2) AND (*s1 NEQ 0xff)) return 1; return -1; } } /* +--------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_cmp2Bytes | +--------------------------------------------------------------------+ PURPOSE : compare two strings. if s1 < s2 return value < 0 if s1 = s2 return value = 0 if s1 > s2 return value > 0 flag = 1, s1 is unicode flag = 2, s2 is unicode */ LOCAL int pb_sim_cmp2Bytes(UBYTE *s1, UBYTE *s2, UBYTE len, UBYTE flag) { int n = 0; /* TRACE_FUNCTION("pb_sim_cmp2Bytes()"); */ if (flag EQ 1) { while ( (*s1 EQ 0x00 OR *s1 EQ 0xFF ) AND ( *(s1+1) EQ *s2) ) { if (*s1 EQ 0xff AND *(s1+1) EQ 0xFF) return 0; s1 += 2; s2++; n += 2; if (n >= len) return 0; } if ( ( *s1 > 0 AND *s1 NEQ 0xff ) OR ( !*s1 AND ( *(s1+1) > *s2 ) ) ) return 1; return -1; } if (flag EQ 2) { while ((*s2 EQ 0x00 OR *s2 EQ 0xFF) AND (*s1 EQ *(s2+1))) { if (*s2 EQ 0xff AND *(s2+1) EQ 0xFF) return 0; s1++; s2 += 2; n += 2; if (n >= len) return 0; } if ((*s2 > 0 AND *s2 NEQ 0xff) OR (!*s2 AND (*(s2+1) > *s1)) ) return -1; return 1; } return -1; } /* +----------------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_update_extn_records | +----------------------------------------------------------------------------+ PURPOSE : Update reference count for extension record and delete if record is not referenced at all. ETSI 11.11 clause 11.5.1 states that reference counts not only have to be maintained for EXT1 but also for other EXT records. */ LOCAL T_PHB_RETURN pb_sim_update_extn_records(USHORT ext_field_id, USHORT rec_num, SHORT ref_type) { T_EXT_TYPE ext_type; UBYTE *refptr; int db_result; UBYTE dummy_ref; switch (ext_field_id) { case SIM_EXT1: ext_type = EXT1; break; case SIM_EXT2: ext_type = EXT2; break; case SIM_EXT3: ext_type = EXT3; break; case SIM_EXT4: ext_type = EXT4; break; case SIM_EXT5: ext_type = EXT5; break; case FFS_EXT_LRN: ext_type = EXT_LRN; break; case FFS_EXT_LMN: ext_type = EXT_LMN; break; default: return PHB_FAIL; } if (rec_num <= MAX_EXT_RECORDS) { refptr = &ext_ref_count[ext_type][rec_num - 1]; } else { /* Could become improved by using dynamic memory but better as using an * illegal array index. Only ref counters will have a problem here. */ TRACE_ERROR ("SIM exceeds MAX_EXT_RECORDS"); dummy_ref = 1; refptr = &dummy_ref; } if (ref_type EQ -1) { /* Decrement usage counter */ if (*refptr > 0) { *refptr += ref_type; } else { TRACE_ERROR ("EXT usage counter below zero"); } if (*refptr EQ 0) { db_result = db_delete_record(pbs_data.db_handle, ext_field_id, rec_num); if(db_result < DB_OK) return PHB_FAIL; } } else if (ref_type EQ 1) { *refptr += ref_type; } else return PHB_FAIL; /* add_val not in -1, +1 */ TRACE_EVENT_P3 ("Usage count of EXT %04X, record %d = %d", ext_field_id, rec_num, *refptr); return PHB_OK; } /* +----------------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_del_ext_records | +----------------------------------------------------------------------------+ PURPOSE : Read extension records and update the records. */ #define RETURN(x) { retVal = x; goto cleanup_exit; } /*lint -e{801} Use of goto*/ LOCAL T_PHB_RETURN pb_sim_del_ext_records (T_PHB_TYPE type, USHORT field_id, USHORT db_recno) { int db_result; T_PHB_RETURN retVal; USHORT ext_file_id; T_DB_INFO_FIELD info_field; UBYTE *data; UBYTE ext_rcd_num; TRACE_FUNCTION("pb_sim_del_ext_records()"); ACI_MALLOC (data, SIM_MAX_RECORD_SIZE); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); /* Read record from the database. */ if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK) RETURN (PHB_FAIL) db_result = db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data); if (db_result EQ DB_EMPTY_RECORD) RETURN (PHB_OK) /* Nothing to do */ if (db_result < DB_OK) RETURN (PHB_FAIL) /* Some other problem */ /* Get extension record identifier */ ext_rcd_num = data[info_field.record_size - 1]; while (ext_rcd_num NEQ 0xFF) /* check for extension records */ { if(db_info_field (pbs_data.db_handle, ext_file_id, &info_field) NEQ DB_OK) RETURN (PHB_FAIL) if ((ext_rcd_num EQ 0) OR (ext_rcd_num > info_field.num_records)) { TRACE_EVENT_P1 ("illegal ext record number %d ignored", ext_rcd_num); RETURN (PHB_OK) } if(db_read_record(pbs_data.db_handle, ext_file_id, ext_rcd_num, 0, info_field.record_size, data) < DB_OK) RETURN (PHB_FAIL) if (pb_sim_update_extn_records(ext_file_id, ext_rcd_num, -1) EQ PHB_FAIL) RETURN (PHB_FAIL) ext_rcd_num = data[12]; } RETURN (PHB_OK) cleanup_exit: ACI_MFREE (data); return retVal; } #undef RETURN /* +----------------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_ext_records_used | +----------------------------------------------------------------------------+ PURPOSE : check if extension records is used by one phone book record (ADN & FDN). */ #define RETURN(x) { retVal = x; goto cleanup_exit; } /*lint -e{801} Use of goto*/ LOCAL BOOL pb_sim_ext_records_used (T_PHB_TYPE type, USHORT field_id, USHORT db_recno) { int db_result; BOOL retVal; USHORT ext_file_id; T_DB_INFO_FIELD info_field; UBYTE *data; UBYTE ext_rcd_num; TRACE_FUNCTION("pb_sim_ext_records_used()"); ACI_MALLOC (data, SIM_MAX_RECORD_SIZE); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); /* Read record from the database. */ if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK) RETURN (FALSE) db_result = db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data); if (db_result < DB_OK) RETURN (FALSE) /* record can not be read - so no EXTn used */ /* Get extension record identifier */ ext_rcd_num = data[info_field.record_size - 1]; TRACE_EVENT_P1("pb_sim_ext_records_used() --1-- ext_rcd_num = %d", ext_rcd_num); if (ext_rcd_num NEQ 0xFF) /* check for extension records */ { if(db_info_field (pbs_data.db_handle, ext_file_id, &info_field) NEQ DB_OK) RETURN (FALSE) if ((ext_rcd_num EQ 0) OR (ext_rcd_num > info_field.num_records)) { TRACE_EVENT_P1 ("illegal ext record number %d ignored", ext_rcd_num); RETURN (FALSE) } if(db_read_record(pbs_data.db_handle, ext_file_id, ext_rcd_num, 0, info_field.record_size, data) < DB_OK) RETURN (FALSE) ext_rcd_num = data[12]; TRACE_EVENT_P1("pb_sim_ext_records_used() --2-- ext_rcd_num = %d", ext_rcd_num); RETURN (TRUE) //return TRUE here since ext_rcd_num is valid } else { RETURN (FALSE) } cleanup_exit: ACI_MFREE (data); return retVal; } #undef RETURN /* +--------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_retrieve_rdm_recno | +--------------------------------------------------------------------+ PURPOSE : Retrieving record number for LDN, LMN and LRN Phonebook. */ LOCAL USHORT pb_sim_retrieve_rdm_recno (T_PHB_TYPE type) { USHORT rec_no; TRACE_FUNCTION("pb_sim_retrieve_rdm_recno()"); switch(type) { case LDN: rec_no = LDN_DATA_RECNO; break; case LMN: rec_no = LMN_DATA_RECNO; break; case LRN: rec_no = LRN_DATA_RECNO; break; default: rec_no = 0; break; } return rec_no; } /* +--------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_cmpWild | +--------------------------------------------------------------------+ PURPOSE : compare two strings considering wildcard. if s1 < s2 return value < 0 if s1 = s2 return value = 0 if s1 > s2 return value > 0 */ GLOBAL int pb_sim_cmpWild ( const char *s1, const char *s2, size_t cmp_len ) { TRACE_FUNCTION("pb_sim_cmpWild()"); if (cmp_len EQ 0) return 0; /* Nothing to compare */ while ((*s1 EQ *s2) OR (*s1 EQ PHB_WILD_CRD) OR (*s2 EQ PHB_WILD_CRD)) { /* Character matches */ cmp_len--; if (cmp_len EQ 0) return 0; if ((*s1 EQ '\0') AND (*s2 EQ '\0')) return 0; if (*s2 EQ '\0') /* Means *s1 > '\0' */ return 1; if (*s1 EQ '\0') /* Means *s2 > '\0' */ return -1; s1++; s2++; } /* Character does not match */ if (*s1 > *s2) return 1; else return -1; } /* Implements Measure #30 */ /* +------------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_alpha_num_record | +------------------------------------------------------------------------+ PURPOSE : Read a given physical record from the flash based phonebook in alphabetical order Or in number sorted order */ GLOBAL T_PHB_RETURN pb_sim_read_alpha_num_record (T_PHB_TYPE type, USHORT order_num, T_PHB_RECORD *entry, UBYTE sort_index) { int db_result; USHORT field_id; TRACE_FUNCTION("pb_sim_read_alpha_num_record()"); /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); /* Read record from the FFS. */ db_result = db_get_phy_from_idx(pbs_data.db_handle, field_id, sort_index, order_num); if(db_result > DB_OK) { return pb_sim_read_record(type, (USHORT)db_result, entry) ; } /* Check whether index is vaild. */ if(db_result EQ DB_INVALID_INDEX) { return PHB_INVALID_IDX; } /* * Unable to get record from the database. * Hence returning PHB_FAIL. */ return PHB_FAIL; } /* Implements Measure #167 */ /* +------------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_alpha_num_record | +------------------------------------------------------------------------+ PURPOSE : Function check for extention records */ LOCAL T_PHB_RETURN pb_sim_update_index (T_PHB_TYPE type, T_DB_CHANGED *rec_affected, USHORT field_id, UBYTE ext_rec_cnt) { TRACE_FUNCTION("pb_sim_update_index()"); if((type NEQ LDN) AND (type NEQ LMN) AND (type NEQ LRN)) { /* Update the sorted indexes. */ if(db_update_index(pbs_data.db_handle, field_id, NAME_IDX, pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) { return PHB_FAIL; } if(db_update_index(pbs_data.db_handle, field_id, NUMBER_IDX, pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) { return PHB_FAIL; } } return PHB_OK; } void pb_update_cphs_mb_ext_record(void) { UBYTE i; USHORT ext_file_id; /* Get Extension file for the Phonebook type. */ ext_file_id = SIM_EXT1; for(i =0; i< 4; i++) { if(cphs_mb_ext_record_num[i] NEQ 0xff) { db_update_ext_bitmap(pbs_data.db_handle,ext_file_id,cphs_mb_ext_record_num[i],TRUE); pb_sim_update_extn_records(ext_file_id, cphs_mb_ext_record_num[i], 1); } } } GLOBAL void pb_sim_update_ext_bitmap(UBYTE rec_num, BOOL flag) { USHORT ext_file_id; /* Get Extension file for the Phonebook type. */ ext_file_id = SIM_EXT1; db_update_ext_bitmap(pbs_data.db_handle,ext_file_id,rec_num, flag); if(flag EQ TRUE) { pb_sim_update_extn_records(ext_file_id, rec_num, 1); } else { pb_sim_update_extn_records(ext_file_id, rec_num, -1); } } #endif /* #ifdef TI_PS_FFS_PHB */