FreeCalypso > hg > fc-magnetite
view src/aci2/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 | 93999a60b835 |
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 typedef enum { DECREMENT = -1, INCREMENT } T_PHB_EXT_REF_TYPE; /* * 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; #define RDM_PHB_DATA_SIZE 6 /* ECC records */ T_PHB_ECC_RECORD phb_ecc_element[MAX_ECC_RCD]; LOCAL T_PHB_SIM_DATA pbs_data; /* Global arrays to hold Reference count for Extension records. */ UBYTE ext1_ref_count[MAX_EXT_RECORDS], ext2_ref_count[MAX_EXT_RECORDS]; UBYTE ext3_ref_count[MAX_EXT_RECORDS], ext4_ref_count[MAX_EXT_RECORDS]; UBYTE ext5_ref_count[MAX_EXT_RECORDS]; UBYTE ext_lmn_ref_count[MAX_EXT_RECORDS], ext_lrn_ref_count[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 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 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, T_PHB_EXT_REF_TYPE ref_type); LOCAL T_PHB_RETURN pb_sim_read_ext_record_for_delete(T_PHB_TYPE type, USHORT field_id, USHORT db_recno); /* +----------------------------------------------------------------------+ | 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; 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_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 (ecc_rec_num = 0; ecc_rec_num < MAX_ECC_RCD; ecc_rec_num++) { if(*data_ptr NEQ 0xff) { memset(&phb_ecc_element[ecc_rec_num],0,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; /* Check for extension records. */ 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: *ext_record_ef = ef; *ext_record_no = buffer[entry_size - 1]; break; default: *ext_record_ef = 0; *ext_record_no = 0; } /* 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; } if (buffer[0] NEQ 0xFF) { /* 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; 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,1) NEQ DB_OK) return PHB_FAIL; memset(buffer,0x00, RDM_PHB_DATA_SIZE); if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 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) { TRACE_FUNCTION("pb_sim_remove_ef()"); if(db_remove_field(pbs_data.db_handle, ef) EQ DB_OK) 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; UBYTE tag_len, max_tag_len; UBYTE data[SIM_MAX_RECORD_SIZE]; UBYTE buffer[RDM_PHB_DATA_SIZE]; T_DB_INFO_FIELD info_field; UBYTE ext_rec_cnt = 0; UBYTE ext_rec_num1, ext_rec_num2; 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; /* Read data related to LDN,LMN and LRN Phonebooks from FFS */ db_result = db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, buffer); /* Check for DB Failure. */ if(db_result < DB_OK) return PHB_FAIL; /* Information for handling Cyclic RDM Records ---------------------------------------- buffer[0] ---> Most Recent in LDN buffer[1] ---> Oldest in LDN buffer[2] ---> Most Recent in LMN buffer[3] ---> Oldest in LMN buffer[4] ---> Most Recent in LRN buffer[5] ---> Oldest in LRN ---------------------------------------- */ if(type EQ LDN) /* Circular entry handling for LDN */ { buffer[0] ++; if(buffer[0] > info_field.num_records) buffer[0] = 1; if(buffer[0] EQ buffer[1]) { buffer[1]++; if(buffer[1] > info_field.num_records) buffer[1] = 1; } phy_recno = buffer[0]; if(buffer[1] EQ 0) buffer[1] = 1; } if(type EQ LMN) /* Circular entry handling for LMN */ { buffer[2]++; if(buffer[2] > info_field.num_records) buffer[2] = 1; if(buffer[2] EQ buffer[3]) { buffer[3]++; if(buffer[3] > info_field.num_records) buffer[3] = 1; } phy_recno = buffer[2]; if(buffer[3] EQ 0) buffer[3] = 1; } if(type EQ LRN) /* Circular entry handling for LRN */ { buffer[4]++; if(buffer[4] > info_field.num_records) buffer[4] = 1; if(buffer[4] EQ buffer[5]) { buffer[5]++; if(buffer[5] > info_field.num_records) buffer[5] = 1; } phy_recno = buffer[4]; if(buffer[5] EQ 0) buffer[5] = 1; } TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]); TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]); /* Write data related to LDN,LMN and LRN Phonebooks to FFS */ db_result = db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, buffer); /* Check for DB Failure. */ if(db_result < DB_OK) return PHB_FAIL; }/* if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) */ /* 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; } } TRACE_EVENT_P1("Number = %s",entry->number); /* Check if extension records are needed */ /* 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; } /* 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_FAIL; /* Required no. of free extension records are found */ ext_rec_num1= 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(ext_rec_num1 > DB_OK) { /* Set Extension record Identifier */ 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++) { pb_sim_prepare_ext_data(data, i, (UBYTE*)entry->number, entry->len, (UBYTE*)entry->subaddr); /* Find next free record to chain the extension records. */ ext_rec_num2 = db_find_free_record( pbs_data.db_handle,ext_file_id); /* 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, INCREMENT) 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; 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_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) return PHB_FAIL; } else { /* Remove RDM data record from the list */ if(rec_affected->entries NEQ 0) { rec_affected->entries -= 2; /* Remove the record from the list */ memmove (&rec_affected->field_id[0], &rec_affected->field_id[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); memmove (&rec_affected->record[0], &rec_affected->record[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); /* Remove the record from the list */ memmove (&rec_affected->field_id[0], &rec_affected->field_id[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); memmove (&rec_affected->record[0], &rec_affected->record[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); /* Remove extension record from the list. */ if(ext_rec_cnt NEQ 0) { rec_affected->entries --; /* Remove the record from the list */ memmove (&rec_affected->field_id[0], &rec_affected->field_id[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); memmove (&rec_affected->record[0], &rec_affected->record[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); } } } return PHB_OK; } /* +--------------------------------------------------------------------+ | 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. */ T_PHB_RETURN pb_sim_del_record (T_PHB_TYPE type, USHORT phy_recno, T_DB_CHANGED *rec_affected) { USHORT field_id, ext_file_id, db_recno; UBYTE buffer[RDM_PHB_DATA_SIZE], rec_cnt; T_DB_INFO_FIELD info_field; UBYTE data[SIM_MAX_RECORD_SIZE]; TRACE_FUNCTION("pb_sim_del_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 = 0; memset(phb_ecc_element[phy_recno - 1].number, 0, 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); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); /* Get no. of records in the field */ if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK) return PHB_FAIL; /* Information for handling Cyclic RDM Records ---------------------------------------- buffer[0] ---> Most Recent in LDN buffer[1] ---> Oldest in LDN buffer[2] ---> Most Recent in LMN buffer[3] ---> Oldest in LMN buffer[4] ---> Most Recent in LRN buffer[5] ---> Oldest in LRN ---------------------------------------- */ /* Handling of LDN, LMN and LRN Phonebook records. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { /* Read data related to LDN,LMN and LRN Phonebooks from FFS */ if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK) return PHB_FAIL; if(type EQ LDN) /* Circular entry handling for LDN */ { db_recno = buffer[0]; if(phy_recno NEQ 1) { for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; } } } if(buffer[0] EQ buffer[1]) buffer[0] = buffer[1] = 0; if(buffer[0] EQ db_recno) { buffer[0]--; if(buffer[0] EQ 0) buffer[0] = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, buffer[0], 0, info_field.record_size, data) < DB_OK) { buffer[0]--; if(buffer[0] EQ 0) buffer[0] = (UBYTE)info_field.num_records; } } if(buffer[1] EQ db_recno) { buffer[1]++; if(buffer[1] EQ info_field.num_records) buffer[1] = 1; while(db_read_record(pbs_data.db_handle, field_id, buffer[1], 0, info_field.record_size, data) < DB_OK) { buffer[1]++; if(buffer[1] EQ info_field.num_records) buffer[1] = 1; } } } if(type EQ LMN) /* Circular entry handling for LMN */ { db_recno = buffer[2]; if(phy_recno NEQ 1) { for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; } } } if(buffer[2] EQ buffer[3]) buffer[2] = buffer[3] = 0; if(buffer[2] EQ db_recno) { buffer[2]--; if(buffer[2] EQ 0) buffer[2] = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, buffer[2], 0, info_field.record_size, data) < DB_OK) { buffer[2]--; if(buffer[2] EQ 0) buffer[2] = (UBYTE)info_field.num_records; } } if(buffer[3] EQ db_recno) { buffer[3]++; if(buffer[3] EQ info_field.num_records) buffer[3] = 1; while(db_read_record(pbs_data.db_handle, field_id, buffer[3], 0, info_field.record_size, data) < DB_OK) { buffer[3]++; if(buffer[3] EQ info_field.num_records) buffer[3] = 1; } } } if(type EQ LRN) /* Circular entry handling for LRN */ { db_recno = buffer[4]; if(phy_recno NEQ 1) { for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) { db_recno--; if(db_recno EQ 0) db_recno = (UBYTE)info_field.num_records; } } } if(buffer[4] EQ buffer[5]) buffer[4] = buffer[5] = 0; if(buffer[4] EQ db_recno) { buffer[4]--; if(buffer[4] EQ 0) buffer[4] = (UBYTE)info_field.num_records; while(db_read_record(pbs_data.db_handle, field_id, buffer[4], 0, info_field.record_size, data) < DB_OK) { buffer[4]--; if(buffer[4] EQ 0) buffer[4] = (UBYTE)info_field.num_records; } } if(buffer[5] EQ db_recno) { buffer[5]++; if(buffer[5] EQ info_field.num_records) buffer[5] = 1; while(db_read_record(pbs_data.db_handle, field_id, buffer[5], 0, info_field.record_size, data) < DB_OK) { buffer[5]++; if(buffer[5] EQ info_field.num_records) buffer[5] = 1; } } } TRACE_EVENT_P1("db_recno = %d ", db_recno); TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]); TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]); /* Write data related to LDN,LMN and LRN Phonebooks to FFS */ if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK) return PHB_FAIL; } else { db_recno = phy_recno; } /* Delete extension records if not referenced. */ if(pb_sim_read_ext_record_for_delete(type, field_id, db_recno) EQ PHB_FAIL) return PHB_FAIL; /* Delete record from FFS. */ if(db_delete_record(pbs_data.db_handle, field_id,db_recno) NEQ DB_OK) return PHB_FAIL; /* 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; 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_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK) return PHB_FAIL; } else { if(rec_affected->entries NEQ 0) { /* Remove RDM data record from the list */ rec_affected->entries -= 2; /* Remove the record from the list */ memmove (&rec_affected->field_id[0], &rec_affected->field_id[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); memmove (&rec_affected->record[0], &rec_affected->record[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); /* Remove the record from the list */ memmove (&rec_affected->field_id[0], &rec_affected->field_id[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); memmove (&rec_affected->record[0], &rec_affected->record[1], sizeof (USHORT) * (DB_MAX_AFFECTED - 1)); } TRACE_EVENT_P1("rec-affected = %d", rec_affected->entries); } return PHB_OK; } /* +--------------------------------------------------------------------+ | 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; USHORT db_recno; T_DB_INFO_FIELD info_field; UBYTE buffer[RDM_PHB_DATA_SIZE]; UBYTE data[SIM_MAX_RECORD_SIZE], *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)) { entry->phy_recno = phy_recno; 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; /* Information for handling Cyclic RDM Records ---------------------------------------- buffer[0] ---> Most Recent in LDN buffer[1] ---> Oldest in LDN buffer[2] ---> Most Recent in LMN buffer[3] ---> Oldest in LMN buffer[4] ---> Most Recent in LRN buffer[5] ---> Oldest in LRN ---------------------------------------- */ /* Handling of LDN, LMN and LRN Phonebook records. */ if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) { /* Read data related to LDN,LMN and LRN Phonebooks from FFS */ if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK) return PHB_FAIL; /* Since LDN, LMN and LRN records are circular entries, most recent will be the 1st record and entries increase towards the oldest one for Reading. */ if(type EQ LDN) { if(buffer[0] EQ 0) buffer[0] = 1; db_recno = buffer[0] - phy_recno + 1; db_recno = db_recno % (info_field.num_records); if(db_recno EQ 0) db_recno = (info_field.num_records); } if(type EQ LMN) { if(buffer[2] EQ 0) buffer[2] = 1; db_recno = buffer[2] - phy_recno + 1; db_recno = db_recno % (info_field.num_records); if(db_recno EQ 0) db_recno = (info_field.num_records); } if(type EQ LRN) { if(buffer[4] EQ 0) buffer[4] = 1; db_recno = buffer[4] - phy_recno + 1; db_recno = db_recno % (info_field.num_records); if(db_recno EQ 0) db_recno = (info_field.num_records); } } else db_recno = phy_recno; TRACE_EVENT_P2("db_recno = %d phy_recno = %d",db_recno, phy_recno); TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]); TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]); if(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL; /* Convert SIM data to the type T_PHB_RECORD. */ ptr = data; max_tag_len = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id), 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; 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) 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) return PHB_FAIL; 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); } } return PHB_OK; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_alpha_record | +--------------------------------------------------------------------+ PURPOSE : Read a given physical record from the flash based phonebook in alphabetical order. */ T_PHB_RETURN pb_sim_read_alpha_record (T_PHB_TYPE type, USHORT order_num, T_PHB_RECORD *entry) { int db_result; USHORT field_id, ext_file_id; TRACE_FUNCTION("pb_sim_read_alpha_record()"); /* 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 FFS. */ db_result = db_get_phy_from_idx(pbs_data.db_handle, field_id, NAME_IDX, 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; } /* +--------------------------------------------------------------------+ | PROJECT: MMI-Framework (8417) MODULE: PHB | | STATE : code ROUTINE: pb_sim_read_number_record | +--------------------------------------------------------------------+ PURPOSE : Read a given physical record from the flash based phonebook in number sorted order. */ T_PHB_RETURN pb_sim_read_number_record (T_PHB_TYPE type, USHORT order_num, T_PHB_RECORD *entry) { int db_result; USHORT field_id, ext_file_id; TRACE_FUNCTION("pb_sim_read_number_record()"); /* 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 FFS. */ db_result = db_get_phy_from_idx(pbs_data.db_handle, field_id, NUMBER_IDX, order_num); if(db_result > DB_OK) { return pb_sim_read_record(type, (USHORT)db_result, entry) ; } else if(db_result EQ DB_INVALID_INDEX) return PHB_INVALID_IDX; else return PHB_FAIL; } /* +--------------------------------------------------------------------+ | 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, ext_file_id; TRACE_FUNCTION("pb_sim_search_name()"); /* 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); 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, (UBYTE*) 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, ext_file_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)); cmp_res = pb_sim_cmpString((UBYTE*)cur_number, (UBYTE*)rev_number, cmpLen); if(cmp_res NEQ 0) return PHB_FAIL; else { return PHB_OK; } } } /* Get Elementary file ID for the Phonebook type. */ field_id = pb_sim_get_field_id(type); TRACE_EVENT_P2("type = %d field_id = %x", type, field_id); /* Get Extension file for the Phonebook type. */ ext_file_id = pb_sim_get_ext_file(type); res = db_search(pbs_data.db_handle, field_id, NUMBER_IDX, (UBYTE*)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) { T_DB_INFO_FIELD info_field; USHORT field_id; int db_result; TRACE_FUNCTION("pb_sim_read_sizes()"); /* 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); db_result = db_info_field(pbs_data.db_handle, field_id, &info_field); TRACE_EVENT_P1("db_result = %d", db_result); if(db_result EQ DB_OK) { *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); return PHB_OK; } return PHB_FAIL; } /* +--------------------------------------------------------------------+ | 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 = MINIMUM ( (info_field.record_size) - pb_sim_get_size_except_tag(field_id), 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 = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id), 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_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) { T_PHB_RECORD entry_1,entry_2; T_DB_INFO_FIELD info_field; UBYTE cmpLen = 0; UBYTE *buffer, *tmp_buffer; UBYTE ext_rcd_num; UBYTE max_tag_len; CHAR cur_number[MAX_PHB_NUM_LEN]; CHAR ref_number[MAX_PHB_NUM_LEN]; int cmp_res; USHORT file_id; TRACE_FUNCTION("pb_sim_number_cmp()"); MALLOC(buffer, sizeof(T_PHB_RECORD)); /* Store pointer to free the memory allocation. */ tmp_buffer = buffer; memset(buffer,0xFF,sizeof(T_PHB_RECORD)); 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_1, 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_1.len = *(buffer++) - 1; entry_1.ton_npi = *buffer++; memset(entry_1.number, 0xFF, PHB_PACKED_NUM_LEN); memcpy( (char*)entry_1.number, (char*)buffer, entry_1.len ); buffer += 10; entry_1.cc_id = *buffer++; if (*buffer != 0xFF) /* check for extention records */ { file_id = pb_sim_get_ext_file_id(field_id); if (file_id != 0xFFFF) { ext_rcd_num = (UBYTE)*buffer; db_info_field(db_handle, file_id, &info_field); /* Set the buffer to starting location. */ buffer = tmp_buffer; memset(buffer, 0xFF, info_field.record_size); db_read_record(db_handle, file_id, ext_rcd_num, 0, info_field.record_size,buffer); pb_sim_read_ext(buffer, &entry_1); while(*(buffer + 12) NEQ 0xFF) { memset(buffer, 0xFF, info_field.record_size); db_read_record(db_handle, file_id, *(buffer + 12), 0, info_field.record_size,buffer); pb_sim_read_ext(buffer, &entry_1); } } } /* Set the buffer to starting location. */ buffer = tmp_buffer; memset(buffer, 0xFF, sizeof(T_PHB_RECORD)); /* Read record recno_2 from the database using db_read_record() */ db_read_record(db_handle, field_id, recno_2, 0, info_field.record_size, buffer); max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id); /* Read only number from the buffer. */ buffer += max_tag_len; entry_2.len = *(buffer++) - 1; entry_2.ton_npi = *buffer++; memset(entry_2.number, 0xFF, PHB_PACKED_NUM_LEN); memcpy( (char*)entry_2.number, (char*)buffer, entry_2.len ); buffer += 10; entry_2.cc_id = *buffer++; if (*buffer != 0xFF) /* check for extention records */ { if (file_id != 0xFFFF) { ext_rcd_num = (UBYTE)*buffer; /* Set the buffer to starting location. */ buffer = tmp_buffer; memset(buffer, 0xFF,info_field.record_size); db_read_record(db_handle, file_id, ext_rcd_num, 0, info_field.record_size,buffer); pb_sim_read_ext(buffer, &entry_2); while(*(buffer + 12) NEQ 0xFF) { memset(buffer, 0xFF,info_field.record_size); db_read_record(db_handle, file_id, *(buffer + 12), 0, info_field.record_size,buffer); pb_sim_read_ext(buffer, &entry_2); } } } cmhPHB_getAdrStr(cur_number, MAX_PHB_NUM_LEN - 1, entry_1.number, entry_1.len); cmhPHB_getAdrStr(ref_number, MAX_PHB_NUM_LEN - 1, entry_2.number, entry_2.len); /* Reverse the first number to compare number from right. */ pb_sim_revString(cur_number); /* Reverse the second number to compare number from right. */ pb_sim_revString(ref_number); cmp_res = strcmp((char *)cur_number, (char *)ref_number); MFREE(tmp_buffer); return cmp_res; } /* +--------------------------------------------------------------------+ | 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; 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) cmpLen = MINIMUM(strlen(cur_number), cmpLen); TRACE_EVENT_P1("Number to be compared: %s", cur_number); TRACE_EVENT_P1("Number to be searched: %s", rev_key); cmp_res = pb_sim_cmpString((UBYTE*)cur_number, (UBYTE*)rev_key, 7); 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,0, (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"); 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; /* Avoid lint warning */ 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; /* Avoid lint warning */ break; } return ext_file_id; } /* +----------------------------------------------------------------------+ | 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; } } /* +-------------------------------------------------------------------------------+ | 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. */ LOCAL T_PHB_RETURN pb_sim_update_extn_records(USHORT ext_field_id, USHORT rec_num, T_PHB_EXT_REF_TYPE ref_type) { BOOL delete_record = FALSE; int db_result; /* Depending on the Extension file update the corresponding array. */ if(ref_type EQ DECREMENT) { switch(ext_field_id) { case SIM_EXT1: ext1_ref_count[rec_num]--; if(ext1_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case SIM_EXT2: ext2_ref_count[rec_num]--; if(ext2_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case SIM_EXT3: ext3_ref_count[rec_num]--; if(ext3_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case SIM_EXT4: ext4_ref_count[rec_num]--; if(ext4_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case SIM_EXT5: ext5_ref_count[rec_num]--; if(ext5_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case FFS_EXT_LRN: ext_lrn_ref_count[rec_num]--; if(ext_lrn_ref_count[rec_num] EQ 0) delete_record = TRUE; break; case FFS_EXT_LMN: ext_lmn_ref_count[rec_num]--; if(ext_lmn_ref_count[rec_num] EQ 0) delete_record = TRUE; break; default: return PHB_FAIL; } } if(ref_type EQ INCREMENT) { switch(ext_field_id) { case SIM_EXT1: ext1_ref_count[rec_num]++; break; case SIM_EXT2: ext2_ref_count[rec_num]++; break; case SIM_EXT3: ext3_ref_count[rec_num]++; break; case SIM_EXT4: ext4_ref_count[rec_num]++; break; case SIM_EXT5: ext5_ref_count[rec_num]++; break; case FFS_EXT_LRN: ext_lrn_ref_count[rec_num]++; break; case FFS_EXT_LMN: ext_lmn_ref_count[rec_num]++; break; default: return PHB_FAIL; } } /* Delete the extension record if it is not referenced. */ if(delete_record EQ TRUE) { db_result = db_delete_record(pbs_data.db_handle, ext_field_id, rec_num); if(db_result < DB_OK) return PHB_FAIL; } return PHB_OK; } /* +--------------------------------------------------------------------+ | PROJECT : MMI-Framework (8417) MODULE : PHB | | STATE : code ROUTINE : pb_sim_read_ext_record_for_delete | +--------------------------------------------------------------------+ PURPOSE : Read extension records and update the records. */ LOCAL T_PHB_RETURN pb_sim_read_ext_record_for_delete(T_PHB_TYPE type, USHORT field_id, USHORT db_recno) { USHORT ext_file_id; T_DB_INFO_FIELD info_field; UBYTE buffer[RDM_PHB_DATA_SIZE]; UBYTE data[SIM_MAX_RECORD_SIZE], *ptr; UBYTE max_tag_len; UBYTE ext_rcd_num; T_PHB_RECORD entry; TRACE_FUNCTION("pb_sim_read_ext_record_for_delete()"); /* 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(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK) return PHB_FAIL; /* Convert SIM data to the type T_PHB_RECORD. */ ptr = data; max_tag_len = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id), PHB_MAX_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); ++ptr; ++ptr; ptr += 10; ++ptr; 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) 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) return PHB_FAIL; if(pb_sim_update_extn_records(ext_file_id, ext_rcd_num, DECREMENT) EQ PHB_FAIL) return PHB_FAIL; 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); if(pb_sim_update_extn_records(ext_file_id, (USHORT)*(ptr+12), DECREMENT) EQ PHB_FAIL) return PHB_FAIL; pb_sim_read_ext(ptr, &entry); } } return PHB_OK; } #endif /* #ifdef TI_PS_FFS_PHB */