选网
来源:互联网 发布:二级代理软件下载 编辑:程序博客网 时间:2024/04/28 07:10
/*红字为log
ds3gcmif.c 03720Rx'ed CM_CALL_CONNECTED_CMD
ds3gi_process_cm_call_connected_cmd
ds_3gpp_pdn_context.c 08954 Setting up TypeIP V4 PS Iface
调用ds_pdn_cntxt_setup_ipv4_ps_iface
ps_iface.c 02256 Setting iface 0x8004:0 IPAddress to 10.44.84.90
ps_iface_set_v4_addr
ds_3gpp_pdn_context.c :Setting up Type PDP-IP stack
ds_pdn_cntxt_setupIPv6PSIface
ps_ifacei_event.c00359 Phys link evt 2 on iface=0x8004:0
ps_ifacei_phys_link_event_cback .这个函数会再次调用ps_ifacei_invoke_event_cbacks来调用事件回调处理函数
event=2= IFACE_PHYS_LINK_UP_EV
0x8004是iface的名字,即UMTS_IFACE
:0表示instance0或者1
ps_flow.c00994 FLOW ACTIVATE IND 0x2F121D14, state 0x1, info code 0
ps_flow_activate_ind()
ps_ifacei_event.c02284 IFACE UP IND 0x8004:0, state 4
ps_iface_up_ind
state 4= IFACE_COMING_UP表示当前的iface的状态
ds3gcmif.c03798 Data call connected
ds3gi_process_cm_call_connected_cmd
这个函数和最上面的第一条log是对应的,因为那个函数处理之后一直跳转到其他函数去处理里,在这个地方菜真正返回到原来的函数
此时ds3gi_call_info[call_inst].call_state =DS3G_CALL_ACTIVE_CALL_STATE;
桥接上rm
ps_iface.c01899 bridging iface 0x8008:0 in state 4 to iface 0x8004:0
ps_iface_set_bridge
8008=SIO_IFACE是要桥接的iface的名字
8004=UMTS_IFACE桥接iface的名字
ps_ifacei_event.c02448 IFACE PHYS LINK UP IND 0x8008:0, state 4
ps_iface_phys_link_up_ind
ds_qmi_wds.c20481 Sending call status Client 4 (wds_sp) 2f899ef0
*/
前面注释了
http://www.doc88.com/p-978197088893.html:gsm 搜网流程log
搜网相关的专业词汇解释
LCF:last camped freq
rrccsp: rrc cell selection procedure
rrcmcm : rrc mode controll module
rrcllc : RRC Lower Layer Controller Interface
Addl chl:additional channel
oos:OUT_OF_SERVICE_AREA_SCAN
oc:ordered_config
pscan:power scan
ARFCN :绝对无线频道编号 (Absolute Radio Frequency Channel Number
#define RRC_UL_BAND_A_UARFCN_MIN 9612 //每个band对应的频点号的范围在此定义
#define RRC_CSP_PCS_BAND 0x0001 //1900 MHz ,band的定义
选网NAS层
start_plmn_selection(rplmn)
NAS层有很多的模块,每个模块对应一个文件夹,根据发给nas不同的模块来选择不同的处理函数
如发给nas层的mm模块的命令处理函数入口为mm_process_messages(...)---》mmcoord_route_mm_message(...)
在这个函数里会根据message->cmd.hdr.message_set消息集分配给不同的处理模块。如选网时,nas层的reg模块会调用reg_send_mmr_reg_req函数给MM发消息集是MS_MM_REG,且message->cmd.hdr.message_id=MMR_REG_REQ
则调用mmcoord_process_mmr_reg_req( message );。所以先通过消息集过滤,在通过id号
mmcoord_process_mmr_reg_req_now在这个函数里会检查mm_rat_change_pending和mm_serv_change_pending是否为1,即rat技术是否改变或者请求的服务域是否变化,跟踪到的mm_serv_change_pending=1,所以会走下面三步:
mm_handle_message ( message ); gmm_handle_message( message ); /* ------------------------------------------------------------------------ ** Continue with Registration if RAT change or service domain change is ** not requested. Otherwise the RAT/Service change is performed first and ** the LU procedure is initiated. ** -----------------------------------------------------------------------*/ mmcoord_process_lu_procedure( message );
mm_handle_message--mm_handle_registration由于mm_serv_change_pending=1,所以执行mm_handle_rat_change,此时mm_serving_plmn.info.reg_service_domain=SYS_SRV_DOMAIN_NO_SRV
所以执行mm_change_service_domain--mmcoord_process_lu_procedure,此时还没有附着上网,所以进入mm_substate_control( MM_STD_PLMN_SEARCH )函数处理
此时mm_idle_substate=MM_NO_IMSI,所以next_substate=MM_PLMN_SEARCH
mm_serving_plmn.ms_op_mode=SYS_SRV_DOMAIN_CS_PS,所以gmm_set_substate(GMM_PLMN_SEARCH);但gmm_state == GMM_NULL所以不会改变状态
然后mm_send_service_req(...)里面包含了请求的参数SYS_RAT_GSM_RADIO_ACCESS或者SYS_RAT_UMTS_RADIO_ACCESS。这个函数通过函数rrc_get_mm_cmd_buf往rrc层发的命令参数是:
rrc_cmd->cmd_hdr.cmd_id = <span style="color:#cc0000;">RRC_SERVICE_REQ</span>rrc_cmd->cmd.rrc_service_req.requested_plmn.plmn_type =RRC_GSM_MAP_ANY_PLMN_REQ;message->cmd.mmr_reg_req.new_scan=1rrc_cmd->cmd.rrc_service_req.use_timer=1rrc_cmd->cmd.rrc_service_req.wcdma_scan_time = message->cmd.mmr_reg_req.scan_time=1000(void) rex_set_sigs(&rrc_tcb, RRC_MM_CMD_Q_SIG);
rrc层的命令接受入口点在文件rrc_task.c文件里的rrc_task(...)->rrc_dispatcher(...),整个循环都在rrc_dispatcher里面
1、wcdma选网流程
从NAS层的MM通过mm_send_service_req函数发送RRC_SERVICE_REQ命令给rrc层,接下来在rrc里面处理这个命令。由于是mm层送下来的命令,所以派遣函数调用
rrc_dispatch_mm_commands->rrcmcm_event_handler
此时rrcmcm_state=RRCMCM_INITIAL 所以执行rrcmcm_initial_substate_event_handler,且rrc_mode=RRC_MODE_INACTIVE
rrcmcm_cmd_store.rrcmcm_mm_req_cmd = *cmd_ptr; /* Send a Start WCDMA mode request to L1 */ rrcmcm_send_start_wcdma_req(); rrcmcm_cmd_store.rrcmcm_cmd_flag = RRCMCM_CMD_SERVICE_REQ; rrcmcm_state = RRCMCM_WAIT_START_CNF;
给L1层发Start WCDMA mode相关的命令,且保存当前RRC_SERVICE_REQ这个未处理完的命令,改变rrcmcm的状态。
之后便等待从L1层返回RRC_CPHY_START_WCDMA_MODE_CNF命令。
如果此时已经是RRC_MODE_ACTIVE状态,则直接开始cell selection,通过调用rrc_cell_selection_procedure函数。
当从L1返回后,L1会给rrc发回一个RRC_CPHY_START_WCDMA_MODE_CNF的确认命令。由于是L1层返回的命令,所以调用的是
rrc_dispatch_l1_commands->rrcmcm_event_handler-rrcmcm_wait_start_cnf_substate_event_handler,此时的
cmd_ptr->cmd_hdr.cmd_id = RRC_CPHY_START_WCDMA_MODE_CNF
接下来处理之前未处理完保存起来的RRC_SERVICE_REQ命令。主要包括几步操作
rrcmcm_update_mode(RRC_MODE_ACTIVE);将rrc_mode状态变为RRC_MODE_ACTIVE rrc_dual_mode_enabled=1 /* Forward inter-RAT PLMN search request to CSP */ rrc_cell_selection_procedure((rrc_cmd_type*)&rrcmcm_cmd_store.rrcmcm_mm_req_cmd);开始选cell /* Start the RSSI reporting timer */ rrctmr_start_timer( RRCTMR_RSSI_BER_TIMER, RRCTMR_RSSI_BER_REPORT_TIME ); rrcmcm_init_data(INIT_ALL);
rrcmcm_state = RRCMCM_INITIAL; 改变mcm的状态为initial stop_cause = RRC_RAT_CHANGE; rrcmcm_est_req_saved_flag = FALSE; rrcmcm_send_stop_cnf_to_mm_flag = FALSE;
memset(&rrcmcm_cmd_store,0,sizeof(rrcmcm_cmd_store)); rrcmcm_cmd_store.rrcmcm_abort_flag = RRCMCM_RR_ABORT_NONE; rrcmcm_cmd_store.rrcmcm_cmd_flag = RRCMCM_CMD_NONE; //指示是否有命令等待处理 rrcmcm_cmd_store.rrcmcm_change_mode_req.mode = RRC_MODE_MAX;
上面
rrc_cell_selection_procedure((rrc_cmd_type*)&rrcmcm_cmd_store.rrcmcm_mm_req_cmd)里面参数
rrcmcm_cmd_store.rrcmcm_mm_req_cmd
保存的是服务请求的命令,所以进入default里面处理,此时rrc_csp_substate=RRCCSP_NO_CELL_SELECTED这个变量代表的是当然是否选择上小区了
rrc_csp_substate = rrccsp_no_cell_selected_hdlr (cmd_ptr);
rrc_curr_state = RRC_STATE_DISCONNECTED,这个变量代表的rrc连接状态,很显然现在没有建立rrc连接
next_substate = rrccsp_no_cell_sel_srvc_req( cmd_ptr );这个函数在代码里面的描述是这样的:
This function processes a Service Request when in RRCCSP_NO_CELL_SELECTED substate. It verifies contents of Service Request and sends an Acq.Req to L1.
Note that the Stored Acquisition database will have to be searched for the requested PLMN.正式开始选网
首选进入rrccsp_cleanup_bplmn_state函数处理,因为rrc_csp_int_data.bplmn_guard_srch_tmr_expired初始化为1所以没做处理。
{
此时rrc_csp_int_data.curr_scan = RRC_CSP_CELL_SELECTION_SCAN /* Scan triggered by one of MM commands (Service Req/Act Req etc) */}
rrc_csp_init_data_from_service_req(&cmd_ptr->cmd.rrc_service_req)
{
This function stores the data passed in RRC_SERVICE_REQ and initializes RRC data and CSP local data with the passed data.
实际上是初始化rrc_csp_int_data结构体里面的一些数据
}
由于此时rrc_csp_int_data.ue_in_deep_sleep=0,所以进入next_substate = rrc_csp_start_sel_on_mm_req();
rrc_csp_start_sel_on_mm_req
{
/* Look for a frequency for this PLMN in RRC CSP Acquisition database now.
* Store the Acq. entry and type returned by Stored and Initial Selection
* Controller in the Internal Data.
*/
This function starts a cell selection in response to a newly received service request from MM。
The acquisition type is initialized based on therequested PLMN type.
The current scan is set to Cell selection scan.
Based on the returned frequency scan type, a CSP substate is returned.根据返回的频率扫描类型(RRC_CSP_ACQ_SCAN orRRC_CSP_FINE_SCAN or other)csp的子状态也不同
rrc_csp_int_data.curr_scan = RRC_CSP_CELL_SELECTION_SCAN;
/* Update GSM with UE's band preference */
rr_rrc_set_band_pref(rrc_csp_int_data.band_pref);
rrc_csp_curr_select_data.next_band_mask = rrc_csp_int_data.wcdma_band_mask;//下一个要扫描的频带
rrc_csp_start_cell_selection(&rrc_csp_int_data.curr_req_plmn,
&rrc_csp_int_data.curr_type_acq, // RRC_CSP_ANY_PLMN 想要获取的plmn的类型,这里是non-barred, non-forbidden reg area cell of any PLMN
&rrc_csp_int_data.curr_acq_entry,
&type_freq_scan
rrc_csp_continue_stored_initial_select_ctrl
接下来给L1发命令
rrc_csp_send_next_freq_to_l1(&rrc_csp_int_data.curr_acq_entry, type_freq_scan)
{
这个函数会根据type_freq_scan频率扫描类型给L1发CPHY_ACQ_REQ(如果type_freq_scan=RRC_CSP_ACQ_SCAN)或者CPHY_FREQ_SCAN_REQ
当发CPHY_ACQ_REQ请求时
rrc_csp_int_data.acq_mode = L1_WCDMA_ACQ_DET_LIST;//可以获得一系列的扰码,一个扰码对应一个小区,就是说可以扫描出一个频率上的多个小区
rrc_csp_int_data.acq_type = L1_WCDMA_FREQ_ONLY;//仅根据频率来获取小区
实际上这个请求在得到CNF时ms也是不知道小区的很多的信息的,只是知道了扰码组0,之后通过读取sib信息才能获取plmn以及cell_id等
}
next_substate = RRCCSP_CELL_SEL_WT_FREQ_SCAN_CNF; /* Start waiting for Frequency scan Confirmation */
}
rrc_csp_send_next_freq_to_l1(&rrc_csp_int_data.curr_acq_entry, type_freq_scan); //type_freq_scan = RRC_CSP_RAW_SCAN他会先给L1发一个RRC_RESET_L1_REQ,紧接着再发一个频率扫描请求:
rrc_csp_send_l1_freq_scan_cmd(RRC_PROCEDURE_CSP,acq_entry_ptr->freq,type_freq_scan)
进入等待扫描结果后的处理函数rrccsp_cell_sel_wait_freq_scan_cnf_hdlr--->case :RRC_LLC_CMD_CNF--RRC_LL_CPHY_FREQ_SCAN_CNF.
next_substate = rrccsp_cell_sel_wait_freq_scan_cnf_recvd( cmd_ptr );rrc_csp_update_freq_scan_entry(&cmd_ptr->cmd.rrc_llc_cnf.cnf.freq_scan_cnf)首先保存扫描到的数据,本次扫描是 rrc_csp_curr_select_data.scan_info.type_freq_scan == RRC_CSP_RAW_SCAN freq_scan_cnf->step == L1_FREQ_LIST_SCAN rrc_csp_curr_select_data.scan_info.raw_scan.freq_result[i] = freq_scan_cnf->freq_result[i];next_substate = rrc_csp_continue_cell_selection(){rrc_csp_continue_stored_initial_select_ctrl ( &rrc_csp_int_data.curr_type_acq, //RRC_CSP_ANY_PLMN &rrc_csp_int_data.curr_acq_entry,//已经初始化些参数了,如搜索频率的起点 &type_freq_scan //RRC_CSP_NO_SCAN )
</pre><pre name="code" class="cpp">由于此时的扫描类型是RRC_CSP_RAW_SCAN,rrc_csp_curr_select_data.acq_type=RRC_CSP_ANY_PLMN
rrc_csp_get_next_freq_scan_entry(&ret_freq)
</pre><pre name="code" class="cpp">/* This macro picks the first frequency from raw scan list in current * selection data and returns the frequency for <span style="color:#cc0000;"><strong>fine scan</strong></span>. It also * initializes the fine scan list and sets the <strong><span style="color:#cc0000;">type of scan to Fine Scan</span></strong>. */从raw 搜索里面挑选第一个频率来进行fine scan
RRC_CSP_PICK_FIRST_RAW_FREQ_FOR_FINE_SCAN();
/* The next L1 cmd depends on the current frequency scan type */ *ret_type_freq_scan = rrc_csp_curr_select_data.scan_info.type_freq_scan;
<span style="font-family: Arial, Helvetica, sans-serif;"> rrc_csp_curr_select_data.scan_info.fine_scan_completed = FALSE; \ rrc_csp_curr_select_data.scan_info.fine_scan.curr_freq_index = 0; \ rrc_csp_curr_select_data.scan_info.fine_scan.num_freq = 0; \ rrc_csp_curr_select_data.scan_info.type_freq_scan = RRC_CSP_FINE_SCAN; \这里就转变了csp搜索类型为fine 搜索</span>
<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
这个函数返回后rrc_csp_send_next_freq_to_l1(&rrc_csp_int_data.curr_acq_entry, type_freq_scan)
由于返回的type_freq_scan == RRC_CSP_ACQ_SCAN,所以
next_substate = RRCCSP_CELL_SEL_WT_FREQ_SCAN_CNF;
FINE扫描确认后的处理:
rrccsp_cell_sel_wait_freq_scan_cnf_recvd()
rrc_csp_update_freq_scan_entry(&cmd_ptr->cmd.rrc_llc_cnf.cnf.freq_scan_cnf)用扫描后获取到的数据来更新urrent selection data and list frequency scan
{
1、 if((rrc_csp_curr_select_data.scan_info.type_freq_scan == RRC_CSP_RAW_SCAN) &&
(freq_scan_cnf->step == L1_FREQ_RAW_SCAN))他会根据扫描类型以及这个cnf是哪个扫描的结果来进行相应的处理
2、 if((rrc_csp_curr_select_data.scan_info.type_freq_scan == RRC_CSP_FINE_SCAN) &&
/*lint -e506*/
(freq_scan_cnf->step == L1_FREQ_FINE_SCAN))
rrc_csp_curr_select_data.scan_info.fine_scan_completed = TRUE;
rrc_csp_curr_select_data.scan_info.fine_scan.freq_result[i] = freq_scan_cnf->freq_result[i];//将获取到的频率保存起来
然后进入next_substate = rrc_csp_continue_cell_selection();//这个函数的处理如下
}
rrc_csp_continue_cell_selection
这个函数里有两个很重要,其中第一个是主要的:
1、rrc_csp_continue_stored_initial_select_ctrl
(
&rrc_csp_int_data.curr_type_acq,
&rrc_csp_int_data.curr_acq_entry,
&type_freq_scan
) //其主要的作用是要获取一个和plmn相关的频率来扫描或者获取
2、rrc_csp_send_next_freq_to_l1(&rrc_csp_int_data.curr_acq_entry, type_freq_scan);根据扫描类型给L1发命令
rrc_csp_continue_stored_initial_select_ctrl函数的处理主要流程如下:
{
switch(rrc_csp_curr_select_data.acq_type)根据获取类型RRC_CSP_SPEC_PLMN or RRC_CSP_ANY_PLMN
case RRC_CSP_ANY_PLMN
rrc_csp_get_next_freq_scan_entry(&ret_freq)
{
rrc_csp_curr_select_data.scan_info.type_freq_scan=RRC_CSP_FINE_SCAN
}
}
CPHY_CELL_SELECTION_REQ : then next_state=RRCCSP_SUIT_CELL_SEL_WT_SERV_S
RRC_LL_CPHY_CELL_SELECTION_CNF: rrc_llc_cnf.cnf.cell_sel_cnf.evaluated=true表示L1层已经对小区参数进行了评估,通过下面两个参数:
rrc_llc_cnf.cnf.cell_sel_cnf.s_qual /* Cell Selection quality Value */
rrc_llc_cnf.cnf.cell_sel_cnf.s_rxlev /* Cell Selection RX Level Value */
如果这两个参数都大于零,表示evaluate 通过了,然后会选择去驻留在这个小区
RRC_CELL_CHANGE_REQ :then next_substate = RRCCSP_SUIT_CELL_SEL_WT_CAMP
RRC_CELL_CHANGE_CNF:里面会提示是否驻留在这个小区(Camped on a Cell )cell_change_cnf.cell_change_status=RRC_CELL_CHANGE_SUCCESS
rrccsp给MM发送RRC_SERVICE_CNF并且当rrc_service_cnf.service_status=MM_AS_NO_SERVICE时
** If the PLMN was not found then send the available list to REG
** in the MMR_REG_CNF
MSG NAS MM/High 00:00:18.522 mmplmnsel.c 00368 MM sent RR_PLMN_SELECT_REQ :进行GSM的选网
GSM选网
rr_control函数里面也有个大循环,while,跟下面的rr_selection_control函数是一样的
{
if: rr_state=RR_GOING_ACTIVE and
rr_event == EV_GSM_MODE_ACTIVATED then
if ( rr_process_panic_reset_saved_msg(&new_message_ptr) == EV_INPUT_MESSAGE )
{
rr_state = RR_NO_CHANNELS;
new_rr_event = EV_INPUT_MESSAGE;
}
然后进入下一轮的处理,注意此时的rr_state = RR_NO_CHANNELS;
}
rr_selection_control函数里面有个大的循环while
循环最后的处理时这样的
while (cell_select_event != EV_NO_EVENT){ ... ... ... if (new_cell_select_event != EV_NO_EVENT) { cell_select_event = new_cell_select_event; new_cell_select_event = EV_NO_EVENT; } else { cell_select_event = EV_NO_EVENT; }}rr_selection_control{if :cell_select_event=EV_INPUT_MESSAGE and cell_select_state=RR_SELECTION_IDLE and message_set == MS_MM_RR and message_id=RR_PLMN_SELECT_REQ then rr_process_plmn_select_req -->return RR_EV_PROCESS_PLMN_SELECT_REQ;}rr_selection_control {case: cell_select_event:RR_EV_PROCESS_PLMN_SELECT_REQ and cell_select_state =RR_SELECTION_IDLE then rr_perform_plmn_select_req_selection-->rr_selection_start_cell_selection -->MPH_POWER_SCAN_REQ
TD-SCDMA :下行的同步
上行链路同步是UE发起一个业务呼叫前必须的过程,如果UE仅驻留在某小区而没有呼叫业务时,UE不用启动上行同步过程。
在下行链路上UE和系统取得同步后,由于UE和NODE-B的距离关系,系统还不能正确接受UE发送的消息。为了避免在不恰当的时间发送消息而对系统造成干扰,UE在上行方向首先要在UpPTS时隙上发送SYNC_UL(突发脉冲)。UpPTS时隙专用于UE和系统的上行同步,没有用户的业务数据。
按照系统设置,每个DwPTS序列号对应8个SYNC_UL码字,UE根据收到的DwPTS信息,随机决定将使用的上行SYNC_UL码字。与UE决定SYNC_DL的方式类似,Node-B可以采用逐个做相关运算的办法,判断UE当前使用的是哪个上行同步码字。
系统收到UE发送的SYNC_UL,就可得到SYNC_UL的定时和功率信息。并由此决定UE应该使用的发送功率和时间调整值,在接下来的4个子帧中的某一子帧通过F-PACH信道发送给UE。在F-PACH信道中还包含UE初选的SYNC-UL码字信息以及Node-B接收到SYNC_UL的相对时间,以区分在同一时间段内使用不同SYNC-UL的UE,以及不同时间段内使用相同SYNC-UL的UE。UE在F-PACH上接收到这些信息控制命令后,就可得知自己的上行同步请求是否已经被系统接受。