Avatar

所有内容是根据http://blog.csdn.net/moonsunearth/archive/2007/09/25/1800790.aspx整理得来的。

首先Windows mobile自带的camera程序是不支持双camera的,如果要加入双camera一个方法是在原来的程序中插入一个菜单来实现调用(经验证菜单的加入是可以实现的),另一个比较推荐的做法是使用directshow自己写一个camera程序。

切换的关键部分是通过directshow控制camera,然后驱动对切换消息进行响应,切换sensor。

Directshow对camera控制的接口如下:

LRESULT hr;

     CComPtr<IAMCameraControl> pCameraControl;

long lCurrentVal,lCurrentFlags;

long CameraControl_Switch=CameraControl_Flash+0xff;

if(sensor>=SENSOR_MAX)
return FALSE;

     CHK(m_pVideoCapFilter->QueryInterface(&pCameraControl));

     CHK(pCameraControl->Get(CameraControl_Switch, &lCurrentVal, &lCurrentFlags));
if(lCurrentVal == sensor)
…{
//return TRUE;
     }
   CHK(pCameraControl->Set(CameraControl_Switch, sensor, CameraControl_Flags_Manual));

IAMCameraControl::Set函数会调用CAM_IOControl,Ioctl=IOCTL_CS_PROPERTY这个是让驱动进行响应的关键。

在CAM_IOControl函数中对应的IOCTL_CS_PROPERTY中的部分是

else if ( TRUE == IsEqualGUID( pCsProp->Set, PROPSETID_VIDCAP_CAMERACONTROL ) )

{

dwErr = pCamDevice->AdapterHandleCamControlRequests( pInBuf,InBufLen, pOutBuf, OutBufLen, pdwBytesTransferred );

}

对于我们代码的添加一个是在这里添加一个自己的customer函数,另一个方法是继续向上层走,然后在上层添加自己的函数。不过因为这里是mdd层,所以最好不要修改,放到pdd层。

整个的流程的修改基本上就是这么多了。

在驱动层需要实现不同camera sensor的切换,然后上层通过directshow的IAMStreamConfig实现。

CComPtr<IAMStreamConfig> pStremConfig;

    CHK(m_pCapGraphBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, 0, m_pVideoCapFilter, IID_IAMStreamConfig, (void **)&pStremConfig))

    CHK(pStremConfig->GetNumberOfCapabilities(&iCount, &iSize));

if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
…{
for (int iFormat = 0; iFormat < iCount; iFormat++)
…{
            VIDEO_STREAM_CONFIG_CAPS scc;
            AM_MEDIA_TYPE *pmtConfig;

CHK(pStremConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc));
if (SUCCEEDED(hr))
…{
if(scc.MinOutputSize.cx == pSize->cx && scc.MinOutputSize.cy == pSize->cy)
…{
                    CHK(pStremConfig->SetFormat(pmtConfig));
                    DeleteMediaType(pmtConfig);
break;
                }
                DeleteMediaType(pmtConfig);
            }
        }
    }

Tagged with: .
Avatar

MMR_NREG_REQ

需要发送MMR_NREG_REQ的情况有如下3种。CS_SIM_REM,CS_POW_OFF,CS_SOFT_OFF。

这个过程将会进行如下操作

TIMERSTOP (T3212);

然后调用mm_mmr_nreg_req函数进行处理。

对于此时MM处于不同的状态,MM会执行对应的操作。

MM_NULL:

CS_POW_OFF和CS_SOFT_OFF会先清除register data,复制sim发给mm的sim_insert_info到mm的register data中,然后清除sim_insert_info然后向GMM发送MMGMM_NREG_CNF原语。

CS_SIM_REM也会清除register data,然后会对是否需要再次注册进行判断,然后向GMM发送MMGMM_NREG_IND原语,最后如果STATE_REG_TYPE为REG_REMOTE_CONTROLLED的话,会将STATE_REG_TYPE设置为REG_CELL_SEARCH_ONLY,STATE_GPRS_CM_EST为CM_GPRS_EST_IDLE。

MM_LUP_INITIATED,MM_LUP_REJECTED:

先向RR发送RR_SYNC_REQ,然后设置状态为MM无效的update state。然后执行同MM状态为MM_WAIT_FOR_OUTG_MM_CONN,MM_CONN_ACTIVE,MM_PROCESS_PROMPT,MM_WAIT_FOR_NW_CMD一样的操作。

MM_WAIT_FOR_OUTG_MM_CONN,MM_CONN_ACTIVE,MM_PROCESS_PROMPT,MM_WAIT_FOR_NW_CMD:

如果MM此时允许attach,ms已经updated,detach_done为MMGMM_PERFORM_DETACH则进行如下操作

先将所有CM connections的类型为CM_NOT_IDLE的连接释放。停止timer T3210,T3211,T3212,T3213,T3230,T3240,然后向RR发送imsi_detach_message,启动timer T3220,将MM状态设置为MM_IMSI_DETACH_INIT。

如果MM状态不满足要求则执行同MM状态为MM_WAIT_FOR_RR_CONN_LUP,MM_WAIT_FOR_RR_CONN_MM,MM_WAIT_FOR_REESTABLISH一样的操作。

MM_WAIT_FOR_RR_CONN_LUP,MM_WAIT_FOR_RR_CONN_MM,MM_WAIT_FOR_REESTABLISH:

依然先将所有CM connections的类型为CM_NOT_IDLE的连接释放,停止timer T3210,T3211,T3212,T3213,T3230,T3240,如果是CS_POW_OFF和CS_SOFT_OFF则会向RR发送RR_ABORT_REQ,原因设置为normal abort,而CS_SIM_REM则会将原因设置为sim remove。最后将MM状态设置为MM_IMSI_DETACH_INIT。

MM_IMSI_DETACH_INIT,MM_WAIT_FOR_RR_CONN_DETACH:

设置mm_data->nreg_cause = nreg_cause;

MM_WAIT_FOR_RR_ACTIVE:RR is searching for a cell

为什么此时RR is searching for a cell?根据04.08

“If no RR connection exists, the MM sublayer within the mobile

* station will request the RR sublayer to establish a RR

* connection. If establishment of the RR connection is not possible

* because a suitable cell is not (or not yet) available then, the

* mobile station shall try for a period of at least 5 seconds and for

* not more than a period of 20 seconds to find a suitable cell. If a

* suitable cell is found during this time then, the mobile station shall

* request the RR sublayer to establish an RR connection, otherwise the

* IMSI detach is aborted.

CS_POW_OFF和CS_SOFT_OFF向DL层发送MDL_RELEASE_REQ(SAPI 0),这个其实应该是RR层做的。接着向RR发送RR_DEACTIVATE_REQ,清除register data,停止所有MM timer,最后将MM状态设置为MM_NULL。最后还会执行MM状态为MM_NULL同样的操作。

CS_SIM_REM先向RR发送RR_ABORT_REQ,原因是sim remove,然后执行MM状态为MM_NULL同样的操作。

MM_LOCATION_UPDATING_PENDING,MM_IMSI_DETACH_PENDING,MM_IDLE_LUP_NEEDED,
MM_IDLE_NORMAL_SERVICE,MM_IDLE_ATTEMPT_TO_UPDATE:

停止timer T3212,T3213。如果MM此时允许attach,ms已经updated,detach_done为MMGMM_PERFORM_DETACH则创建imsi_detach_message,然后处理mobile originated call by SS or SMS,设置状态为MM_WAIT_FOR_RR_CONN_DETACH。

如果MM状态不满足要求则执行同MM状态为MM_IDLE_LIMITED_SERVICE,MM_IDLE_NO_IMSI同样的操作。

MM_IDLE_LIMITED_SERVICE,MM_IDLE_NO_IMSI:

停止timer T3211,T3212,T3213。CS_POW_OFF和CS_SOFT_OFF先向DL层发送MDL_RELEASE_REQ(SAPI 0),接着向RR发送RR_DEACTIVATE_REQ,清除register data,设置MM状态为NO_SERVICE。

CS_SIM_REM先向DL层发送MDL_RELEASE_REQ(SAPI 0),然后向RR发送RR_ABORT_REQ,原因是sim remove,清除register data,如果(mm_data->mm_idle_no_imsi_marker EQ 0)则mm_data->mm_idle_no_imsi_marker = 17;设置MM状态为MM_IDLE_NO_IMSI,执行同MM状态为MM_NULL同样的操作,不过将service改为LIMITED_SERVICE。

MM_IDLE_NO_CELL_AVAILABLE:

基本上同MM_IDLE_LIMITED_SERVICE,MM_IDLE_NO_IMSI一样,只是CS_SIM_REM最后的service不是LIMITED_SERVICE而是NO_SERVICE。

MM_IDLE_PLMN_SEARCH,MM_PLMN_SEARCH_NORMAL_SERVICE:

返回network search开始时MM的状态

SET_STATE (STATE_MM, mm_data->idle_substate);

然后再次调用本函数进行状态处理。

mm_mmr_nreg_req (nreg_cause, detach_done);

Tagged with: , .
Avatar

GLOBAL const void mm_rr_activate_cnf (T_RR_ACTIVATE_CNF *rr_activate_cnf)

{

mm_data->rf_power = rr_activate_cnf->power;

mm_data->reg.new_cell_ind = TRUE;

//如果mnc和mcc是请求的则复制plmn。

if (reg_plmn_equal_eqv (&rr_activate_cnf->plmn, &mm_data->reg.actual_plmn))

{

mm_data->reg.actual_plmn = rr_activate_cnf->plmn; /* Struct copy */

}

//此时MM的状态如果是MM_WAIT_FOR_RR_ACTIVE,同时(mm_data->reg.op.func EQ rr_activate_cnf->op.func)

//rr_activate_cnf->op.service中返回了当前的service类型是LIMITED_SERVICE或FULL_SERVICE。

//当时FULL_SERVICE时会进行如下的操作。

//将mm_info,lai,lac,cid,gprs_indication赋值到MM对应的变量中。

mm_copy_rr_act_cnf_data (rr_activate_cnf);

//此时会判断需不需要location updating,判读函数如下

mm_normal_upd_needed()

if (mm_data->reg.update_stat EQ MS_UPDATED AND

mm_check_lai (&mm_data->reg.lai, &mm_data->mm.lai))

return FALSE;

return TRUE;

mm_attach_upd_needed()

if (mm_data->mm.mm_info.att EQ ATT_ALLOW AND mm_data->first_attach) 

return TRUE;

return FALSE;

mm_periodic_upd_needed (void)

if (mm_data->t3212_timeout AND mm_data->mm.mm_info.t3212 NEQ 0)

return TRUE;

return FALSE;

当不需要location updating时

{

TIMERSTOP (T3213);

mm_data->t3213_restart = 0;

mm_change_t3212();

//然后向GMM发送MMGMM_REG_CNF原语

reg_mm_success (FULL_SERVICE);

//向SIM发送 SIM_MM_UPDATE_REQ 原语 其中主要需要更新的有loc_info,bcch_info,forb_plmns,kc。

reg_build_sim_update (); /* Update cell id */

//同时如果不是gsm only此时还要向GMM发送MMGMM_ACTIVATE_IND。传递的参数有plmn,lac,cid,status, gprs_indicator,同时3212timer时间如下设置

if (mm_data->t3212_cfg_counter NEQ 0 AND 

mm_data->mm.mm_info.t3212 NEQ 0)

mmgmm_activate_ind->t3212_val = mm_data->t3212_cfg_counter * 10000;

else

mmgmm_activate_ind->t3212_val = mm_data->mm.mm_info.t3212 * 360000;

mm_mmgmm_activate_ind (MMGMM_FULL_SERVICE);

/* Back to MM_IDLE_NORMAL_SERVICE */

mm_data->idle_entry = RRCS_INT_NOT_PRESENT;

/* Remember MM doesn't need any IMSI ATTACH anymore */

if (mm_lup_allowed_by_gmm() AND mm_data->first_attach )

{

mm_data->first_attach_mem = mm_data->first_attach;

mm_data->first_attach = FALSE;

}

mm_data->t3212_timeout = FALSE;

mm_data->loc_upd_type.lut = NOT_RUNNING;

SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE);

/* Check HPLMN timer state */

reg_check_hplmn_tim (mm_data->reg.thplmn);

USE_STORED_ENTRIES();

//当需要location updating时进行如下操作。

reg_mm_cell_selected ();//gsm only情况下

mm_data->attempt_cnt = 0;

//然后判断mm_normal_upd_needed()还是mm_attach_upd_needed()还是其他

if (mm_normal_upd_needed())

{

/*

* If updating is allowed by GMM, start procedure,

* otherwise enter state MM_IDLE_LUP_NEEDED.

*/

mm_normal_loc_upd ();

//如果GMM允许location update,此时会向RR发送RR_ESTABLISH_REQ原语,当然此时需要一个RR的连接。

mm_rr_est_req (ESTCS_SERV_REQ_BY_MM, NO_CM_SERVICE, 0);

TIMERSTOP (T3211);

TIMERSTOP (T3213);

mm_data->t3213_restart = 0;

SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_LUP);

}

else if (mm_attach_upd_needed())

{

/*

* If updating is allowed by GMM, start procedure,

* otherwise enter state MM_IDLE_LUP_NEEDED.

*/

mm_attach_loc_upd ();

//此时同mm_normal_upd_needed一样,只是mm_start_loc_upd的参数由NORMAL_LUP变为了IMSI_ATTACH_LUP,依然是发送RR_ESTABLISH_REQ原语

}

//除了mm_normal_upd_needed和mm_attach_upd_needed其他情况mm_start_loc_upd的参数变为了PERIODIC_LUP。

//最后也会进行如下调用

mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE);

}

总的从代码中看来,当MM接收到从RR传送过来的RR_ACTIVATE_CNF原语后,MM会存储RR传过来的一些诸如plmn,lac,mm_info等信息,同时会通知SIM更新plmn,bcch,kc等等信息,如果此时不需要location update,MM会向GMM发送MMGMM_ACTIVATE_IND,此时是MMGMM_FULL_SERVICE。当需要location update时,根据update的类型,向RR发送RR_ESTABLISH_REQ原语。

MM接收到该原语后会根据自己当前的状态进行状态的更新,MM_IDLE_NORMAL_SERVICE或MMGMM_WAIT_FOR_UPDATE,或者没有sim或sim无效的MM_IDLE_LIMITED_SERVICE,MM_IDLE_NO_IMSI。

Tagged with: , .
Avatar

Registration

因为TI的代码中是定义了GPRS的,当有GMM模块时,网络的注册是和单纯只有MM模块是不一样的,我们先只看当没有GMM时,MM是如何进行网络注册的。

MMI最后会调用GLOBAL SHORT psaMM_Registrate ( void )来进行网络注册。


GLOBAL SHORT psaMM_Registrate ( void )

{

psaMM_SetRegMode ( MODE_AUTO );

PALLOC (mmr_reg_req, MMR_REG_REQ);

//根据sim的状态来决定当前的网络服务。

if (simShrdPrm.imei_blocked EQ TRUE)

{

mmr_reg_req->service_mode = SERVICE_MODE_LIMITED;

}

else

{

mmr_reg_req->service_mode = SERVICE_MODE_FULL;

}

//以下代码实现了向MM发送了一个MMR_REG_REQ原语。

PSENDX (MM, mmr_reg_req);

}

frstFlg = FALSE;

return 0;

}

MMR_REG_REQ原语在MM的处理函数是reg_mmr_reg_req。这个函数中只有一个调用

mm_func_mmgmm_reg_req (mmr_reg_req->service_mode, 

REG_GPRS_INACTIVE,

MMGMM_CLASS_CC);

因为我们跟踪的代码是GSM only,所以现在的网络类型是MMGMM_CLASS_CC即GSM only

网络的类型定义如下:


#define VAL_MOBILE_CLASS___DEF (0x0) /* Combined GPRS attach */

#define MMGMM_CLASS_A (0x1) /* Combined GPRS */

#define MMGMM_CLASS_B (0x2) /* GPRS and GSM */

#define MMGMM_CLASS_BC (0x3) /* Combined GPRS if possible, otherwise GSM only */

#define MMGMM_CLASS_BG (0x4) /* Combined GPRS if possible, otherwise GPRS only */

#define MMGMM_CLASS_CC (0x5) /* GSM-only */

#define MMGMM_CLASS_CG (0x6) /* GPRS-only */

mm_func_mmgmm_reg_req函数中如果是GSM only则会调用 mm_reg_gsm_only_req (service_mode); Read the rest of this post »

Tagged with: , .
Avatar

最终目的是实现一个类似可运行程序的框架的东西。
难点:如何生成这个可运行的程序数据。1.函数的跳转使用一个固定的地址中的函数指针实现。2.将程序数据解析成一行行的执行代码。
同时应该同应用程序的编译平台的实现有着直接的联系。
现在看起来第二种方式的实现应该还是简单点,同时可以做到不同平台的开发。当一个应用调试完成后,可以使用特殊的处理将源文件生成一个数组,然后在不同的另一个平台上只需要对该数组进行一次解析,将对应的数据转化为对应的具体平台的函数调用就可以实现同开发平台上同样的运行效果了。

对于第一种实现方式,主要的难点是需要对所有可能调用的api都要进行地址固定。这个可以通过一个全局的函数指针数组来实现跳转,开发时必须使用函数指针进行。在进行平台移植时,这个函数指针数组必须指定一个绝对的地址,同时这个地址与开发的应用程序或动态加载系统实现的对应的lib中的地址必须要一致,否则函数会跳转到错误的地址上。
分析下来看来都是可以实现的,个人觉得第二种方式可能会简单一点。

Tagged with: .
Avatar

本节描述了SIM向GSM的MM和GMM提供的信息。

在GSM协议11.11中对GSM操作的前提有如下描述

For a SIM of Phase 2 or greater, GSM operation shall only start if one of the two following conditions is

fulfilled:

- if EFIMSI and EFLOCI are not invalidated, the GSM operation shall start immediately;

- if EFIMSI and EFLOCI are invalidated, the ME rehabilitates these two EFs.

那么SIM应该提供哪些信息呢?流程是什么样的呢?

Afterwards, the ME runs the following procedures:

- Administrative Information request;

- SIM Service Table request;

- IMSI request;

- Access Control request;

- HPLMN Search Period request;

- PLMN selector request;

- Location Information request;

- Cipher Key request;

- BCCH information request;

- Forbidden PLMN request;

- CBMID request;

- Depersonalisation Control Keys request

- Network’s indication of alerting request (if $(NIA)$ is supported)

好了,我们来看看TI是如何实现这部分协议栈的代码的吧。

总的流程如下(app_sim_read_parameters函数中)


result = app_fdn_bdn_procedures (sim_mmi_insert_ind);

if ((result EQ SIM_NO_OPERATION) OR

!app_sim_mm_insert_ind (sim_mmi_insert_ind))

app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);

else

app_sim_mmi_insert_ind (sim_mmi_insert_ind, result);

PSENDX (MMI, sim_mmi_insert_ind);

if (result NEQ SIM_NO_OPERATION)

app_sim_sms_insert_ind ();

在app_fdn_bdn_procedures函数中会对SIM的IMSI和LOCI是否支持进行判断,同时对bdn和fdn进行判断。

当然一般的SIM卡肯定不会是SIM_NO_OPERATION的,所以必然会进行app_sim_mm_insert_ind (sim_mmi_insert_ind)。

GLOBAL UBYTE app_sim_mm_insert_ind (T_SIM_MMI_INSERT_IND * sim_mmi_insert_ind)

{

//首先分配一个SIMMM协议原语

PALLOC (sim_mm_insert_ind, SIM_MM_INSERT_IND);

SIM_CLEAR_FLAG (TEST_SIM_INSERTED);

//读取administrative data

if (FKT_Select (SIM_AD, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)

sim_mm_insert_ind->c_ad = (UBYTE)length;

if(FKT_ReadBinary ((UBYTE *)&sim_mm_insert_ind->ad, 0, length) EQ SIM_NO_ERROR)

//如果ad[0]&0x80为真表示这是一张测试卡

if(sim_mm_insert_ind->ad[0] & 0x80)

{

SIM_SET_FLAG (TEST_SIM_INSERTED);

#if defined SIM_TOOLKIT

SIM_SET_FLAG (TEST_MODE_POLLING);

#endif

}

/*

* read IMSI (set to zero in case of error)

*/

memset (&sim_mmi_insert_ind->imsi_field, 0, sizeof (T_imsi_field));

if (FKT_Select (SIM_IMSI, NULL, 0) EQ SIM_NO_ERROR)

{

if (FKT_ReadBinary ((UBYTE *)&sim_mm_insert_ind->imsi_field, 0, MAX_IMSI)

…………..

}

/*

* Modify polling algorithm in case of HPLMN == Test Network

*/

if ((sim_mm_insert_ind->imsi_field.c_field >= 3) AND

((sim_mm_insert_ind->imsi_field.field[0] & 0xF7) EQ 0x01) AND

(sim_mm_insert_ind->imsi_field.field[1] EQ 0x10) AND

(sim_mm_insert_ind->imsi_field.field[2] EQ 0x10))

{

SIM_SET_FLAG (TEST_SIM_INSERTED);

#if defined SIM_TOOLKIT

SIM_SET_FLAG (TEST_MODE_POLLING);

#endif

}

/*

* read location information

*/

if (FKT_Select (SIM_LOCI, NULL, 0) EQ SIM_NO_ERROR)

/*

* Access control classes

*/

if (FKT_Select (SIM_ACC, NULL, 0) EQ SIM_NO_ERROR)

/*

* BCCH information

*/

if (FKT_Select (SIM_BCCH, NULL, 0) EQ SIM_NO_ERROR)

/*

* KC and cipher key sequence number

*/

if (FKT_Select (SIM_KC, NULL, 0) EQ SIM_NO_ERROR)

/*

* Read Preferred PLMNs

*/

if (SIM_IS_FLAG_SET (SERVICE_7_SUPPORT))

{

if (FKT_Select (SIM_PLMNSEL, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)

/*

* Read forbidden PLMNs

*/

if (FKT_Select (SIM_FPLMN, NULL, 0) EQ SIM_NO_ERROR)

/*

* Read Acting HPLMN 

*/

FileSelRes = FKT_Select(SIM_CING_AHPLMN, NULL, 0);

#if defined (GPRS)

gprs_gmm_insert_ind (sim_mm_insert_ind);

#endif

/*

* send information to mobility management

*/

PSENDX (MM, sim_mm_insert_ind);

SIM_SET_FLAG (MM_KNOWS_FROM_SIM);

}
Tagged with: , .
Avatar

SIM协议栈实体在系统启动时会进行什么样的初始化步骤呢?以下以TI的协议栈实现来分析。

在app_init_sim_data这个函数中注册了SIM的insert和remove的hook函数。

simdrv_register(app_sim_insert, app_sim_remove);

GLOBAL void app_sim_insert( T_SIMDRV_atr_string_info *atr_string_info,

U8 config_requested,

T_SIMDRV_config_characteristics *config_characteristics)

{

//在ATR处理完成后,首先将当前dir设为MF

sim_data.act_directory = SIM_MF;

//首先选择DFgsm

error = FKT_Select (SIM_DF_GSM, response, SIM_MIN_DMF_ST_LEN);

//如果成功选择将返回信息存入dir_status中,并设置标识

SIM_SET_FLAG (GSM_DATAFIELD);

//否则选择DF1800

error = FKT_Select (SIM_DF_1800, response, SIM_MIN_DMF_ST_LEN);

SIM_CLEAR_FLAG (GSM_DATAFIELD);

然后分配一个协议原语

T_SIM_ACTIVATE_CNF * sim_activate_cnf;

if (SIM_IS_FLAG_SET (ACTIVATION_STARTED))

{

PALLOC (sim_activate, SIM_ACTIVATE_CNF);

sim_activate_cnf = sim_activate;

}

else

{

PALLOC (sim_activate, SIM_ACTIVATE_IND);

sim_activate_cnf = (T_SIM_ACTIVATE_CNF *)sim_activate;

}

//然后读取ECC

if (FKT_Select (SIM_ECC, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)

FKT_ReadBinary (sim_activate_cnf->ec_code, 0, length);

//然后读取LP

if (FKT_Select (SIM_LP, response, SIM_MIN_EF_ST_LEN) EQ SIM_NO_ERROR)

FKT_ReadBinary (sim_activate_cnf->pref_lang, 0, length);

//将atr也放入协议原语中

memcpy (sim_activate_cnf->atr, atr_string_info->atr_string, length);

//接着检查PIN与PUk的状态

SIM_CLEAR_FLAG (SIM_PIN_FLAG);

sim_activate_cnf->pin_cnt = FKT_check_pin_count (dir_status.pinstatus);

sim_activate_cnf->puk_cnt = FKT_check_pin_count (dir_status.unbstatus);

sim_activate_cnf->pin2_cnt = FKT_check_pin_count (dir_status.pin2status);

sim_activate_cnf->puk2_cnt = FKT_check_pin_count (dir_status.unb2status);

//然后根据pin与puk的状态设置

sim_activate_cnf->cause = SIM_CAUSE_PIN1_EXPECT/SIM_CAUSE_PIN1_EXPECT;

//如果是SIM_CAUSE_PUK1_BLOCKED则向mmi发送消息后直接返回,不在继续向MM和GMM发送消息的过程。

TRACE_EVENT (”Card blocked”);

sim_activate_cnf->cause = SIM_CAUSE_PUK1_BLOCKED;

SIM_EM_SIM_ACTIVATION_RESULT;

PSENDX (MMI, sim_activate_cnf);

SIM_CLEAR_FLAG (ACTIVATION_STARTED);

return;

//如果pin与puk不需要则继续向下执行,否则等待pin与puk的验证。

if (SIM_IS_FLAG_CLEARED (SIM_PIN_FLAG))

/*

* PIN entering is not necessary

*/

{

SIM_SET_FLAG(PIN1_VERIFIED);

TRACE_EVENT (”Read the rest of Parameters”);

app_sim_read_parameters ();

app_start_status_timer (TRUE);

}

else

{

TRACE_EVENT (”Wait for PIN/PUK entering”);

SIM_CLEAR_FLAG (MM_KNOWS_FROM_SIM);

vsi_t_stop (VSI_CALLER SIM_TIMER);

}

app_sim_read_parameters ()

{

//分配SIM_MMI_INSERT_IND协议原语

PALLOC (sim_mmi_insert_ind, SIM_MMI_INSERT_IND);

接着读取SIM的Phase

error = FKT_Select (SIM_PHASE, NULL, 0);

if (error EQ SIM_NO_ERROR)

error = FKT_ReadBinary (&sim_data.sim_phase, 0, 1);

if (sim_data.sim_phase EQ 0)

sim_data.sim_phase = 1;

if (sim_data.sim_phase > 3)

sim_data.sim_phase = 3;

Phase为1的情况下会进行如下操作

// try to read the SIM service table

if (!app_read_sim_service_table(sim_mmi_insert_ind))

{

app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);

return;

}

if (app_sim_mm_insert_ind (sim_mmi_insert_ind) EQ FALSE)

app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);

else

app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_ADN_ENABLED) ;

PSENDX (MMI, sim_mmi_insert_ind);

app_sim_sms_insert_ind ();

Phase为2+的情况说明该sim卡支持STK服务。

stk_perform_profile_download ();

/* Update the Terminal Support table*/

if(FKT_Select(SIM_CING_TRMST, NULL, 0) EQ SIM_NO_ERROR)

{

FKT_UpdateBinary (sim_data.trmst, MAX_TRMST, 0);

}

Phase 2和2+会接着进行如下的操作

result = app_fdn_bdn_procedures (sim_mmi_insert_ind);

if ((result EQ SIM_NO_OPERATION) OR

!app_sim_mm_insert_ind (sim_mmi_insert_ind))

app_sim_mmi_insert_ind (sim_mmi_insert_ind, SIM_NO_OPERATION);

else

app_sim_mmi_insert_ind (sim_mmi_insert_ind, result);

PSENDX (MMI, sim_mmi_insert_ind);

if (result NEQ SIM_NO_OPERATION)

app_sim_sms_insert_ind ();

}

}

Tagged with: , .
Avatar

以data abort 为例

Data_Abort_ISR
MOV      a1,#DATA_EXCEPTION_TYPE         ; Set type DATA_ABORT (4)
MOV      a2,lr

saveException
MRS     a3,CPSR                          ; Pickup current CPSR
BIC     a3,a3,#MODE_MASK                 ; Clear the mode bits
ORR     a3,a3,#SUP_MODE                  ; Prepare to switch to supervisor mode (SVC)
MSR     CPSR_cxsf,a3                     ; Switch to supervisor mode (SVC)

LDR     a4, SYSTEM_FATAL_ERROR
BX      a4

SYSTEM_FATAL_ERROR实际是函数stack_system_error的地址
在stack_system_error函数中,首先会切换sp到一个专门为异常处理预留的内存地址上,然后根据异常传入的类型填充必要的参数后调用fatal_error_handler。

kal_fatal_error_handler(kal_char *error_message_ptr, kal_uint32 error_code, kal_uint32 os_error_code)
{
DisableIRQ();
error_param_g.param1 = (kal_uint32)error_message_ptr;
error_param_g.param2 = (kal_uint32)error_code;
error_param_g.param3 = (kal_uint32)os_error_code;
fatal_error_handler((kal_uint8 *)error_param_g.param1, error_param_g.param2, error_param_g.param3);

}
在fatal_error_handler中
{

/* lockout all interrupts */
DisableIRQ();

/* mask all interrupts */
IRQDirectMaskAll();

/*
* NoteXXX: To avoid system hang in the exception handler,
*          watchdog remains active while handling exception (if it is enabled).
*/
WDT_Restart2();

/* increase the coutner */
INT_Exception_Enter++;

/* determine if multi-level exception*/
if (INT_Exception_Enter >= 2) {

tst_sysfatal_trace((kal_uint8 *)"Caution: Possibly Endless Nested Exceptions!");

ex_reboot();
}

//以下开始准备得到reset时的系统状态。
/*
* I. Initialize the exception log.
*/
/* reset hardware */
ex_reset_hw();//dma_recover_all,L1Audio_ResetDevice,L1D_PauseDSP
/* re-start WDT again */
WDT_Restart2();

然后得到当前task,并将其优先级设为0,最高
/* get the current thread id */
current_thread = kal_get_current_thread_ID();

/* determine if the current executed task is a TASK, not a HISR */
if ((current_thread != NULL) && (kal_if_hisr() == KAL_FALSE)) {

/* raise the task priority level to the highest */
kal_change_priority((NU_TASK *)current_thread, 0);
}

/* setup param */
param.ext = KAL_FALSE;
param.e1 = param.e2 = param.e3 = 0;
param.dump_param = NULL;

/* initialize the exception log */

/* determine if ARM pre-defined exceptions */
if (err_code < ASSERT_FAIL_EXCEPTION) {

param.type = (exception_type)err_code;

param.code1 = (kal_uint32 *)&os_err_code;

param.code2 = 0;

ex_init_log(&param);

} else
//在ex_init_log中会取得当前版本信息,当前时间,当前系统堆栈信息,当前task状态,hisr状态

然后
/* output the exception log */
ex_output_log();
最后重启系统
/* reboot silently */
ex_reboot();  //使用watchdog来重启系统。

}

在系统重启后有如下一段代码
;  /* Check if abnormal reset */
LDR   a1,ABN_RST_PTR
BL    INT_SystemReset_Check
在INT_SystemReset_Check中会读取地址为0×80040018 的寄存器的值并且同0×0ffa进行比较不相等就返回否则进入kal_fatal_error_handler

关于0×80040018的这个寄存器,datasheet上如下描述Watchdog Timer Reset Signal Duration Register。This register indicates the reset duration
When Watchdog timer times out

关于这段代码,猜测是因为有可能是系统因为挂起而没有reset watchdog寄存器导致重启,这里就可以进行log的抓取。

Tagged with: .
« Previous Page