/***************************************************************************** * FUNCTION * phb_search_handler * DESCRIPTION * This is phb_search_handler function of PHB module. * Handles write request from L4C. * PARAMETERS * ilm_ptr [IN] The primitives * control_block [?] * RETURNS * void *****************************************************************************/ void phb_search_handler(ilm_struct *ilm_ptr, control_block_type *control_block) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ kal_trace(TRACE_FUNC, FUNC_PHB_SEARCH); if (ilm_ptr != NULL) { l4cphb_search_req_struct *l4cphb_search_req; l4cphb_search_req = (l4cphb_search_req_struct*) ilm_ptr->local_para_ptr; /* Cannot allocate, means that PHB is still operating. Reject request! */ control_block = phb_alloc_control_block(); if (control_block == NULL) { phb_search_confirm(PHB_ERRNO_BUSY, 0, l4cphb_search_req->src_id, MSG_ID_INVALID_TYPE, control_block); return; } control_block->src_id = l4cphb_search_req->src_id; /* Retain msg_id */ control_block->cnf_msg_id = ilm_ptr->msg_id; if ((phb_ptr->state == PHB_STATE_READY) && ((l4cphb_search_req->type == PHB_PHONEBOOK) || (l4cphb_search_req->type == PHB_FDN) || (l4cphb_search_req->type == PHB_BDN)) && ((l4cphb_search_req->pattern_tag == PHB_BYNAME) || #ifdef __PHB_SORT_ENABLE__ (l4cphb_search_req->pattern_tag == PHB_BYNAME_EXACT) || #endif (l4cphb_search_req->pattern_tag == PHB_BYNUMBER))) { if (control_block->proc_stage == SEARCH_NONE) { kal_bool is_more_candidates; l4_name_struct *alpha_id; #ifdef __PHB_SORT_ENABLE__ l4_addr_bcd_struct *tel_number; #endif /** * Here we borrow total_piggyback to store pattern_tag. * When used!? */ /* control_block->total_piggyback = l4cphb_search_req->pattern_tag; */ control_block->total_piggyback = l4cphb_search_req->total; /* Search by name, valid for both of PHB_PHONEBOOK, PHB_FDN and PHB_BDN */ if ((l4cphb_search_req->pattern_tag == PHB_BYNAME) || (l4cphb_search_req->pattern_tag == PHB_BYNAME_EXACT)) { alpha_id = &l4cphb_search_req->pattern_value.alpha_id; control_block->candidate_name_num_index = phb_se_search_by_name( l4cphb_search_req->type, (alpha_id_type*) alpha_id, &control_block->candidate, &is_more_candidates); /** * For SEARCH_BYNAME, no candidate is impossible. * Because a nearest one is always found, * therefore candidate_count is at least 1. */ } #ifdef __PHB_SORT_ENABLE__ /* Search by telephone number, only valid for PHB_PHONEBOOK */ else if ((l4cphb_search_req->pattern_tag == PHB_BYNUMBER) && (l4cphb_search_req->type == PHB_PHONEBOOK)) { tel_number = &l4cphb_search_req->pattern_value.tel_number; control_block->candidate_name_num_index = phb_se_search_by_tel_num( l4cphb_search_req->type, tel_number, &control_block->candidate, &is_more_candidates); } #endif /* __PHB_SORT_ENABLE__ */ /* Illegal comination of parameters. */ else { phb_search_err_handler(NULL, control_block); return; } /* Search telephone number in phonebook: nvram_ef_phb_lid and ADN */ /* No candidate, great!! */ if ((control_block->candidate == (kal_uint16) PHB_INVALID_VALUE) || (control_block->candidate_name_num_index == NULL)) { control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_SUCCESS, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); return; } /* Exactly only one candidate is found! Great!! */ /** * Q: The query pattern may exceeds ALPHA_ID_DEPTH, * why NOT exact match alpha_id, then retrieves the following * entries begun from the index to that one? * * A: Though exact matching is possible, retrieves from that index is * non-sense, because the sorted array is not precise, that means * the following entries begun from that index could be erroneous. */ if (l4cphb_search_req->pattern_tag == PHB_BYNAME) { kal_uint16 index; /** * Search BYNAME, if alpha_id.name_length <= PHB_ALPHA_ID_DEPTH, * then there must be exactly one nearest hit! * * Note: hit must start from 1. */ index = control_block->candidate; if (l4cphb_search_req->total < 1) { l4cphb_search_req->total = 1; } phb_control_block_set_IO(control_block, l4cphb_search_req->type, ++index, l4cphb_search_req->total); if (phb_se_is_in_range(control_block->type, index, &control_block->total) == KAL_FALSE) { control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_FAIL, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); return; } /* Piggyback is ALWAYS required. */ /** * Now we have to transform the state to a *FAKE* read state. * The fakes status ALWAYS read from index, instead of specific record. */ /* If any critial error occured. read_err_handler will handle it. */ if (phb_read_fake(control_block, NULL) == KAL_FALSE) { return; } /* Finally, faking complete....Now continue reading */ phb_read_continue(NULL, control_block); return; } #ifdef __PHB_SORT_ENABLE__ else if (l4cphb_search_req->pattern_tag == PHB_BYNAME_EXACT) { kal_uint16 i, start, count = 0; pindex_type *name_index; data_entry_table_type *desc_table; if (l4cphb_search_req->type == PHB_PHONEBOOK) { control_block->type = l4cphb_search_req->type; name_index = (pindex_type*) & phb_ptr->indices.phb_index.name_index; desc_table = (data_entry_table_type*) & phb_ptr->indices.phb_index.data_entry_table; } else { control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_FAIL, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); return; } for (i = control_block->candidate; i < name_index->used_count; i++) if (phb_is_prefix( (alpha_id_type*) & l4cphb_search_req->pattern_value.alpha_id, (alpha_id_type*) & desc_table->table[name_index->table[i].position]. alpha_id)) { break; } if (i == name_index->used_count) { /* NOT found any match */ control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_SUCCESS, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); return; } count++; start = i; for (i = start + 1; i < name_index->used_count; i++) if (phb_is_prefix( (alpha_id_type*) & l4cphb_search_req->pattern_value.alpha_id, (alpha_id_type*) & desc_table->table[name_index->table[i].position]. alpha_id)) { count++; } /* total "count" matches starting from "start" */ control_block->index = start + 1; control_block->record_index = (kal_uint16) PHB_INVALID_VALUE; if (count > 15) { count = 15; } control_block->total = count; /* If any critial error occured. read_err_handler will handle it. */ if (phb_read_fake(control_block, NULL) == KAL_FALSE) { return; } /* Finally, faking complete....Now continue reading */ phb_read_continue(NULL, control_block); return; } #endif /* __PHB_SORT_ENABLE__ */ /* For PHB_BYNAME, more than 1 candidate exists, sigh, verification is necessary */ /** * Even only exactly one candidate is found for searching BYNUMBER, * verification is still needed. */ /** * Only search of PHB_BYNUMBER can reach here. * * Candidates of searching telephone number are selected. * Now verify them. So lousy.. */ /** * Initialize hit and same_count of control_block, also * increment index to candidate, since it begins from 1. */ control_block->match_result = MATCH_FAIL; phb_search_fake( control_block, ilm_ptr, l4cphb_search_req->type, &l4cphb_search_req->pattern_value.tel_number); phb_search_continue(NULL, control_block); } /* error */ else { phb_search_err_handler(NULL, control_block); return; } } /* error, either STATE_NOT_READY or incorrect type requested for searching */ else { kal_trace(TRACE_ERROR, ERROR_PHB_STATE); if (phb_ptr->state != PHB_STATE_READY) { control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_NOT_READY, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); } else { phb_search_err_handler(NULL, control_block); } return; } } else { /* Verification over. */ if (control_block->proc_stage == SEARCH_CONTINUE) { /** * Only search of PHB_BYNUMBER can reach here. * And no piggyback is provided, so confirmation can be sent back now. * Hence, if found, actual_count is 1 and will be transfered to `total' field of * confirmation primitive; otherwise it is 0. */ /* No candidate matches! */ if (control_block->actual_count == 0) { control_block->actual_count = 0; phb_search_confirm( PHB_ERRNO_FAIL, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); } else { name_num_index_type *name_num_index = (name_num_index_type*) control_block->candidate_name_num_index; data_entry_struct *data_entry; l4cphb_phb_entry_array_struct *phb_entry_array; kal_uint8 *pdu_ptr; kal_uint16 pdu_length; data_entry = &name_num_index->data_entry_table.table[name_num_index->num_index.table[control_block->candidate]. position]; /** * To reduce code size, another possible function which * searches index to name_index by index to num_index * is not implemented . */ pdu_ptr = get_pdu_ptr(control_block->peer_buf_ptr, &pdu_length); phb_entry_array = ((l4cphb_phb_entry_array_struct*) get_32bits_aligned_val(pdu_ptr)); phb_entry_array->array[0].index = phb_se_search_by_record_index_name( control_block->type, data_entry->storage, data_entry->record_index, &data_entry->alpha_id); phb_entry_array->array[0].index++; control_block->actual_count = 1; phb_search_confirm( PHB_ERRNO_SUCCESS, control_block->actual_count, control_block->src_id, control_block->cnf_msg_id, control_block); } } /* error */ else { phb_search_err_handler(NULL, control_block); return; } } } /* end of phb_search_handler */
/***************************************************************************** * FUNCTION * phb_sat_file_change_handler * DESCRIPTION * In current implementation, all related EF's will be rescanned. * Hence, actually the file_change request will be forwarded to * startup_handler(). * PARAMETERS * ilm_ptr [IN] The primitives * control_block [?] * RETURNS * void *****************************************************************************/ void phb_sat_file_change_handler(ilm_struct *ilm_ptr, control_block_type *control_block) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ kal_trace(TRACE_FUNC, FUNC_PHB_SAT_FILE_CHANGE); if (ilm_ptr != NULL) { kal_uint16 i; kal_bool need_reset_flag = KAL_FALSE; sat_file_change_ind_struct *sat_file_change_ind; sat_file_change_ind = (sat_file_change_ind_struct*) ilm_ptr->local_para_ptr; /** * Since sat_file_change is an implicit reset, there 2 ways to implement this: * * 1. Interrupts other being processed operations and forbids * other further requests to PHB, except approve and search: * In this implementation, * startup handler should always uses the first control_block, * and lock all control_blocks are locked temporarily; * thus prevent other operations, except approve and search, * from accessing PHB while it is busy. * * 2. Allow all other operations to provide maximum possible * concurrency degrees. * * Curretly, solution 1 is implemented. * Control_blocks are all locked to interrupt all other in-processing * operations and reject all further requests, to prevent * multiple access to PHB when it is not ready. */ /* LN not ready means phb haven't been inited yet */ if (phb_ptr->state == PHB_STATE_LN_NOT_READY) { } else if (sat_file_change_ind->is_full_changed) { need_reset_flag = KAL_TRUE; } else { for (i = 0; i < sat_file_change_ind->num_of_file; i++) { switch (sat_file_change_ind->file_list[i]) { case FILE_ADN_IDX: case FILE_ECC_IDX: case FILE_EXT1_IDX: #ifdef __PHB_USIM_SUPPORT__ need_reset_flag = KAL_TRUE; /* MUST: Break CAN'T BE REMOVED */ break; case FILE_U_ECC_IDX: case FILE_G_ADN_IDX: case FILE_U_ADN_IDX: case FILE_G_PBR_IDX: case FILE_U_PBR_IDX: case FILE_G_EXT1_IDX: case FILE_U_EXT1_IDX: case FILE_U_FDN_IDX: case FILE_U_SDN_IDX: case FILE_U_EXT2_IDX: case FILE_U_EXT3_IDX: case FILE_U_BDN_IDX: case FILE_U_EXT4_IDX: case FILE_U_MSISDN_IDX: case FILE_U_EXT5_IDX: #ifdef __PHB_USIM_ADDITIONAL_SUPPORT__ case FILE_G_IAP_IDX: case FILE_U_IAP_IDX: case FILE_G_ANR_IDX: case FILE_U_ANR_IDX: case FILE_G_EMAIL_IDX: case FILE_U_EMAIL_IDX: case FILE_G_SNE_IDX: case FILE_U_SNE_IDX: case FILE_G_GAS_IDX: case FILE_U_GAS_IDX: case FILE_G_AAS_IDX: case FILE_U_AAS_IDX: case FILE_G_GRP_IDX: case FILE_U_GRP_IDX: #endif /* __PHB_USIM_ADDITIONAL_SUPPORT__ */ ASSERT(is_usim_type(PHB_WHICH_SIM)); #endif /* __PHB_USIM_SUPPORT__ */ case FILE_FDN_IDX: case FILE_SDN_IDX: case FILE_EXT2_IDX: case FILE_EXT3_IDX: case FILE_BDN_IDX: case FILE_EXT4_IDX: case FILE_MSISDN_IDX: need_reset_flag = KAL_TRUE; break; default: break; } } } if (need_reset_flag) { for (i = 0; i < PHB_CONCURRENCY_DEGREE; i++) { if (phb_ptr->control_block[i].is_allocated == KAL_TRUE) { phb_ptr->control_block[i].err_handler(NULL, &(phb_ptr->control_block[i])); } } phb_reset_all_control_blocks(); control_block = phb_alloc_control_block(); ASSERT(control_block != NULL); control_block->src_id = sat_file_change_ind->src_id; /* Retain msg_id */ control_block->cnf_msg_id = ilm_ptr->msg_id; phb_is_sim_file_support(); } phb_ptr->dn_type = l4csmu_get_dial_mode(); if (need_reset_flag == KAL_FALSE) { phb_sat_file_change_confirm(PHB_ERRNO_SUCCESS, sat_file_change_ind->src_id, NULL); } else if ((phb_ptr->state == PHB_STATE_READY) || (phb_ptr->state == PHB_STATE_NOT_READY_FDN_READY) || (phb_ptr->state == PHB_STATE_NOT_READY)) { /** * Assume data descriptor obtained from nvram_get_infor() and * sim_service_table_query() remains consistent, DO NOT reset it. * What needs to be reset is their free_count! */ phb_data_desc_reset(); phb_se_reset(); /* Reset context */ kal_mem_set(&phb_ptr->ecc, 0, sizeof(sim_ecc_struct)); phb_ptr->state = PHB_STATE_NOT_READY; #ifdef __PHB_USIM_SUPPORT__ phb_ptr->is_global = KAL_TRUE; #endif kal_trace(TRACE_STATE, STATE_PHB_NOT_READY); // TODO: need to be able to reload specific files /* * Since SIM file changed, need to reload file info, and MMI also need to reload * send begin inication to MMI, MMI will clear it's variable and reload phonebook. */ { #if !defined(__PHB_STORAGE_BY_MMI__) kal_uint16 phb_total, phb_size; if (nvram_get_info(NVRAM_EF_PHB_LID, &phb_total, &phb_size) == NVRAM_ERRNO_SUCCESS) { phb_data_desc_set_is_support(DATA_DESC_PHB, KAL_TRUE); /* * MAX_ENTRIES_COUNT must NOT be exceeded. See comment * of phb_get_info_set_value() for detail. */ if (phb_total > NVRAM_PHB_INDEX_MAX_ENTRIES_COUNT) { phb_total = NVRAM_PHB_INDEX_MAX_ENTRIES_COUNT; } phb_data_desc_set(DATA_DESC_PHB, phb_total, phb_size); } else #endif /* __PHB_STORAGE_BY_MMI__ */ { phb_data_desc_set_is_support(DATA_DESC_PHB, KAL_FALSE); } } /* phb_get_info() will return to startup_handler() */ control_block->proc_stage = startup_none; #if defined(__GEMINI__) || defined(GEMINI_PLUS) l4csmu_get_chv_info_status(NULL, &chv_status[phb_current_mod - MOD_PHB]); phb_query_count[phb_current_mod - MOD_PHB] = 0; #else l4csmu_get_chv_info_status(NULL, &chv_status[0]); phb_query_count[0] = 0; #endif phb_send_ilm(MOD_L4C, MSG_ID_L4CPHB_STARTUP_BEGIN_IND, NULL, NULL); phb_get_info(ilm_ptr, control_block); } /* error */ else { kal_trace(TRACE_ERROR, ERROR_PHB_STATE); phb_sat_file_change_confirm(PHB_ERRNO_FAIL, control_block->src_id, control_block); return; } } else { kal_trace(TRACE_ERROR, ERROR_PHB_STATE); control_block->cnf_msg_id = MSG_ID_SAT_FILE_CHANGE_IND; phb_sat_file_change_confirm(PHB_ERRNO_FAIL, control_block->src_id, control_block); return; } } /* end of phb_sat_file_change_handler function */