下面五个步骤是mc接到命令的流程
1、ph_stat_ptr->chg_type = PROT_PH_STAT_CHG_NAM
2、cmd_ptr->hdr.cmd = MC_MMGSDI_CLIENT_ID_REG_CNF_F
3、ph_stat_ptr->chg_type = PROT_PH_STAT_CHG_OPRT_MODE
chang mode to online
4、ph_stat_ptr->chg_type = PROT_PH_STAT_CHG_SUBSC
5、cmd_ptr->hdr.cmd = MC_CDMA_PROT_ACT_CMD_F
插入讲讲第五部之前的流程
MC_CDMA_PROT_ACT_CMD_F这个命令是mmoc通过函数mmoc_send_ph_stat_chgd_cmd发给mc的,其中change_type是操作模式的变化,在代码里是如下:
if ( mmoc_send_ph_stat_chgd_cmd( chg_type,mmoc_info_ptr)
{
/* Phone status changed command sent, so wait for ack.
*/
mmoc_update_trans_state( MMOC_TRANS_STATE_WAIT_PH_STAT_CNF,
mmoc_info_ptr
);
return MMOC_EVT_STATUS_CONSUMED;
}
发完这个change命令后,mmoc会进入等待CNF,MC只是进行了reg_power的处理,从nv里面读取一些参数。MMOC一旦CNF接受到,继续这之后的处理
if ( mmoc_info_ptr->is_sd_initialized )
{
/* SD subscription init wassuccessful, start from pwr_up.
*/
if (mmoc_activate_prot_online_ss_main( sd_ss_ind_user_pwr_up(NULL),
mmoc_info_ptr
)
==MMOC_EVT_STATUS_NOT_CONSUMED
)
{
/* Invoke the newtransaction handler.
*/
returnMMOC_EVT_STATUS_NOT_CONSUMED;
}
}
这个是激活指定协议的过程,会交给SD去裁决。其中
sd_ss_ind_user_pwr_up
会返回一个action(也就是裁决结果)告诉我们该做什么。接下来我们看看这个sd是怎么处理的
sd_ss_ind_user_pwr_up-->sd_ss_event_proc(SD_SS_MAIN, SDSS_EVT_USER_PWR_UP, RTRN_ACT_PTR)-->sdss_event_proc(event, iact_ptr)
ss_ptr->true_event = event ;
ss_ptr->is_true_event_processed = false ;
sdss_eng_stack_proc( ...) /* call on the engines to process this event */这个函数是脚本引擎的处理入口,会根据脚本构建一条条顺序执行。在下面会写到。
ss_ptr->is_true_event_processed = false ;/*updata the ss state and inform the front of the current ss-state
sdss_state_next() //截图*/
此时返回的rtrn_iact_ptr->act = SDSS_IACT_ACQUIRE;截图
所以将获取需要的参数保存到system selection参数里面,供 mc task使用
ss->ptr_list = rtrn_iact_ptr->prm.acq.list //获取表
ss->ptr_list = rtrn_iact_ptr->prm.acq.pos //表中的位置
然后
ss_ptr->scr_ctrl_cnt++ //这里很重要,每次将控制权交给front了 这个参数就加1
接着前面sdss_eng_stack_proc写首先要根据这个event找到脚本表中对应的项目
sdss_evg_stack_scr_act
{
找到event属于哪个事件群 event_group = sdss_map_event_to_group( event );
然后在这个事件群里依此比较脚本构建里面的条件是否为真 sdssscr_get_reg(group, i)-->sdss_eng_scr_cond_is_true
如果为真,则用这个脚本来初始化脚本分析器 :
sdss_eng_init(&eng, ss_ptr, scr_ref, event_group, i)
{
简略记录重要的参数:
eng_ptr->acq.state = SDSS_ACQ_STT_NONE ;
eng_ptr->scr_evt_grp = event_group ; //属于哪个脚本群
eng_ptr->scr_tbl_idx = scr_tbl_idx //脚本群中的index
}
然后push到stack里面sdsseng_stack_push(stack_ptr, &eng )等待处理 //截图
}
接下来是个循环
while(true)
{
sdss_eng_stack_top(stack_ptr) //从数组里面取出一个脚本parse
sdss_eng_event_proc(eng_prt, event ,rtrn_iacr_ptr); //这里面就是一个个的script construct 处理
下面是分析上面处理完函数的返回值
}
cdma_entry.entry = MCC_ACQUISITION
这里返回的action: ss_act_param.act = SD_SS_ACT_ACQ_CDMA,
mmoc_activate_prot_online_ss_main
{
case SD_SS_ACT_ACQ_CDMA:
mc_cdma_activate_protocol(PROT_ACT_ONLINE_ACQ); //这个函数会给MC 发MC_CDMA_PROT_ACT_CMD_F命令激活协议,act_reason =PROT_ACT_ONLINE_ACQ协议激活原因
mmoc_update_prot_state(PROT_STATE_ONLINE_ACQ,SD_SS_MAIN,)
}
MCTASK的处理如下:
mc_process_cmd()---> mc_cdma_prot_activate(),这里会有一个
log MSG_MED("Rxed MC_CDMA_PROT_ACT_CDM_F", 0 , 0, 0)
--->mc_online_digital_state()
在这个函数里会一直循环等待mcc_subtask(&cdma_entry)的退出,底层的选网就是在这个subtask里面进行的。subtask里面有四种大的状态,依次是
CDMA_ENTER:进入cdma模式的初始化
CMDA_INIT :选网在这个里面就会执行完
CDMA_IDLE:空闲状态
CDMA_SYS_ACC:系统接入状态
CDMA_TC:处在业务信道状态
进入mcc_subtask(...)之后,第一个状态是cdma.curr_state=CDMA_ENTRY,所以进入cdma_enter()函数处理如下:
cdma.entry_ptr->entry= MCC_ACQUISITION
mcc_rx_buf.cdma.hdr.command= RXC_CDMA_F; //send request to Receive task to go to CDMA mode
然后转到下一个状态:next_state = CDMA_PIL_ACQ;导频获取,其中CDMA_PIL_ACQ =CDMA_INIT,所以,实际进入CDMA_INIT
进入cdma_init()函数处理如下:
cdma.curr_state=CDMA_PIL_ACQ
1、Request Searcher task to enter Acquire mode
mcc_srch_buf.acq.hdr.cmd = SRCH_ACQ_F
mcc_srch_buf .acq.band_class=cdma.band_class;//要搜索的频带
mcc_srch_buf .acq.cdma_freq=cdma.cdmach;//要搜索的频点
mcc_srch_cmd( &mcc_srch_buf );//发送到搜索模块
之后进入循环等待srch task的回复,接到MCC_SRCH_Q_SIG信号之后进入下一个状态,去获取同步信道,从同步信道上获取sid/nid
next_state=CDMA_SYNC_ACQ(256),处理如下
2、
/*request the receive task enter sync mode*/
mcc_rx_buf.sc.hdr.command=RXC_SC_F;
mcc_rxc_cmd(&mcc_rx_buf);
/* request that Searcher task enter Sync mode */
mcc_srch_buf.sc.hdr.cmd = SRCH_SC_F;
mcc_srch_cmd( &mcc_srch_buf );3、之后进入CDMA_SYNC_MSG
cdma_sync_msg函数处理:
3GPP 的规定是这样的
If REDIRECTIONs and NDSS_ORIGs are equal to disabled, the mobile station may enter the System Determination Substate with a reselection indication.
If REDIRECTIONs is equal to enabled, the EXPECTED_SID field of REDIRECT_RECs is not equal to 0, and SIDr is not equal to EXPECTED_SID, the mobile station shall enter the System Determination Substate with a wrong system indication (see 6.6.1.1). 如果重定向已经打开了,请求的sid和获得的系统的sid不相同,就会给出一个错误系统的指示
If REDIRECTIONs is equal to enabled, the EXPECTED_NID field of REDIRECT_RECs is not equal to 65535, and NIDr is not equal to EXPECTED_NID, the mobile station shall enter the System Determination Substate with a wrong network indication.如果重定向打开了,请求的nid不等于获取到的系统的NID也会给出错误系统的指示。
具体的处理在如下
等待lower layer的回复,当收到MCC_RXTX_Q_SIG时,表示同步信号信息收到,保存同步信道的时间在parm_oth_sys_time里面
将这个同步信息保存在cur_bs_ptr中,同时保存在bs_info_id[i]里面,曾加一条项目或者更新已有的条目。这些信息包含PN偏置,当前的信道号(频率)=PRI_PAGECH主寻呼信道、
并且之后的开机登记也是在这里初始化 mccreg_acq_init() 将mcc_reg_vars.reg_enable设为false;
mcc_layer2.ack_seq = 7; /* Binary '111' */
mcc_layer2.ack_type = 0;跳转到下一个状态 next_state =CDMA_JUMP;
4、CDMA_JUMPfuction:cdma_jump()处理如下:
先给srch发一个ARCH_SLEW_F命令,实现ms与基站的同步,然后循环等待同步完成,当接到SRCH_SLEW_R时,next_state = CDMA_IDLE 退出循环,进行进入cdma idle状态之前的初始化
mccidle_init_channel_monitoring(void) 监听寻呼信道
mccreg_idle_init(): 此时mccreg_vars.reg_status = MCCREG_REG_NEEDED , mccreg_vars.powering_up=1,表示需要开机登记
所以开启开机登记计时器timer_reg(..., cai_tmo.t57m) mccreg_powerup_timer 和 timer for zone based timer timer_reg(mccreg_zone_timer cai_tmo.t57m)
然后调用mcc_continue_on_curr_sys.这个函数的描述如下:
consult with system determination whether we should continue on the current system。其主要调用的是sd_ss_ind_cdma_acq_schm4 -->
-->sd_ss_ind_cdma_acq_schm2来决策:
这个函数会根据从同步信道中获取到的SID/NID和prl系统表中条目去比较,如果有匹配的会有一条log
PRL match sys_idx=%d, level=%d 表示找到匹配的项目了,否则直接在sdprl_get_info_base函数中返回。之后会建立三张表格,geo_list(同一地理区域)、pref_list(更优的列表)、 colloc_list
然后判断匹配等级,如果匹配实拍,就返回SD_SS_ACT_CONTINUE.
--> act = sd_ss_event_proc(SD_SS_MAIN, SDSS_EVT_CDMA_ACQ_SCHM, rtrn_act_ptr) 给sd发这个事件
根据这个事件的处理返回值有两种去向,如果是SD_SS_ACT_CONTINUEN
第二种是我们的返回方式SD_SS_ACT_ACQ_CDMA.他会调用sd_si_update-->CM 层注册的事件通知函数,告诉CM服务已经获得。
si_ptr->si_info_cb_func = cm_si_cb
在此之前会有两条log如下
SD_MSG_HIGH("Srv change, mode= %d,band=%d,roam=%d");模式表示获取到的系统是那种模式cdma或其他,roam是指漫游只是是否打开
SD_MSG_HIGH("Srv change, realign_hdr=%d,is_colloc=%d, prot=%d")
如果对应成功的话就是下面的log了。同时cdma进入CDMA_IDLE状态
LOG :
mccdma.c 里的cdma_enter_init(...)函数进入cdma的获取 对应的log是: CDMA Acquisition entry
log: mc->srch cmd=1 表示mc给 srch task 发一个获取导频的信号。
log: mc->srch cmd=2 表示mc给 srch tash 发一个获取同步信道的信号。
当获取到了所有的系统消息之后,交给SD根据PRL去决策是不是我们想要的网络。如果是会给SD 一个304 的event ,304= SDSS_EVT_CDMA_ACQ_SCHM 表示成功的获得了同步信道消息,并且协议版本号与ms兼容。对应的log为:
sd.c =SD= =======sd_ss_ind_cdma_qcq_schm4=====
sdss.c =SD= >>> Proc CDMA acq event=304 >>>
SD报告cm LOG如下:=CM= CM<< SD 501 :0 这里501=CM_SRV_IND_INFO_F。
到这里就代表已经选到网了。
要开启mc的log只要打开digital call processing 选项就可以。