Files
banban/ql-kernel/threadx/quec/ql_sim.c

1038 lines
31 KiB
C

/*================================================================
Copyright (c) 2021, Quectel Wireless Solutions Co., Ltd. All rights reserved.
Quectel Wireless Solutions Proprietary and Confidential.
=================================================================*/
#include "ql_atcmd.h"
#include "ql_sim.h"
#include "ci_sim.h"
#include "connect_management.h"
//#include "quec_atcmd_sim.h"
#include "string_utils.h"
#include "usim_config.h"
#include "quec_cust_feature.h"
#if QUEC_MEMORY_OPTIMIZE
#define sim_log(msg, ...) custom_log("SIM_LOG", "[SIM_LOG]"##msg, ##__VA_ARGS__)
#else
#define sim_log(msg, ...) custom_log("SIM_LOG", msg, ##__VA_ARGS__)
#endif
#define AT_CMD_PREFFIX "AT"
#define AT_CMD_NAME_CNUM "+CNUM"
#define AT_CMD_NAME_QCCID "+QCCID"
#define AT_CMD_NAME_CIMI "+CIMI"
#define AT_CMD_NAME_CPOL "+CPOL"
#define AT_CMD_NAME_CPIN "+CPIN"
#define AT_CMD_NAME_CPWD "+CPWD"
#define AT_CMD_NAME_CLCK "+CLCK"
#define AT_CMD_NAME_EUICC "*EUICC"
#define AT_CMD_NAME_EPIN "+EPIN"
#define AT_CMD_NAME_CPBS "+CPBS"
#define AT_CMD_NAME_CPBR "+CPBR"
#define AT_CMD_NAME_CPBW "+CPBW"
#define AT_CMD_NAME_CRSM "+CRSM"
#define AT_CMD_NAME_CCHO "+CCHO"
#define AT_CMD_NAME_CCHC "+CCHC"
#define AT_CMD_NAME_CGLA "+CGLA"
#define AT_CMD_SUFFIX "\r\n"
#define QUEC_NV_DUAL_SIM_SINGLE_IMEI_SUPPORT "quec_nv_dual_sim_single_imei.dat"
static unsigned char ql_dsss_imei_flag = 0; //0-Not support dual sim single IMEI; 1-Support
static uint8_t *QL_SIM_PHONE_BOOK_STORAGE_STR[]={
"DC",
"EN",
"FD",
"LD",
"MC",
"ME",
"MT",
"ON",
"RC",
"SM",
"AP",
"MBDN",
"MN",
"ICI",
"SDN",
"OCI",
};
extern char IMSI[QL_SIM_IMSI_LEN];
extern UINT8 ICCID[QL_SIM_ICCID_LEN];
extern CiSimPinState gSimPinState;
extern CiSimStatus gSimStatus;
#if defined(QUEC_DUAL_SIM_SUPPORT) || defined(QUEC_PS_SINGLE_PHYSICAL_DUAL_SIM_SUPPORT) || defined(QUEC_DUAL_SINGLE_PS_SUPPORT)
#if defined(QUEC_DUAL_SIM_SUPPORT) || defined(QUEC_PS_SINGLE_PHYSICAL_DUAL_SIM_SUPPORT)
extern char IMSI_1[QL_SIM_IMSI_LEN];
extern UINT8 ICCID_1[QL_SIM_ICCID_LEN];
extern CiSimPinState gSimPinState_1;
extern CiSimStatus gSimStatus_1;
extern UINT32 read_usim_swap_flag(void);
static QL_SIM_ERROR_CODE ql_sim_get_card_status_ex(CiSimStatus *card_status, CMSimID_ex sim_id);
//Added by Freddy @220201022 清除SIM卡状态信息
void ql_sim_info_clear(void)
{
//mia.zhong @20210209 更改初始状态,避免识别成锁PIN
gSimPinState = CI_SIM_PIN_NUM_STATES;
gSimPinState_1 = CI_SIM_PIN_NUM_STATES;
gSimStatus = CI_SIM_ST_NOT_READY;
gSimStatus_1 = CI_SIM_ST_NOT_READY;
}
//add switchsim callback
QL_SIM_ERROR_CODE ql_sim_switch_card_ex(CMSimID_ex simID, SwitchSimDoneCb cb)
{
int ret = 0;
#if !defined(NO_DIALER) || defined(QUEC_PS_SINGLE_PHYSICAL_DUAL_SIM_SUPPORT)
#ifndef SINGLE_SIM
ret = CM_SetMasterSimID(simID, cb);
#else
ret = CM_SetSingleSimID((CMSimID)simID, cb);
#endif
if (ret == 0)
{
#if defined(CRANE_DSS) || defined(SINGLE_SIM)
//Add by Freddy @20200905 切卡之后需要清掉上一次的网络信息
extern void ql_nw_info_clear(void);
ql_nw_info_clear();
#endif
return QL_SIM_SUCCESS;
}
else
#endif
return QL_SIM_GENERIC_FAILURE;
}
//mia.zhong @20201130 新增获取卡信息接口
QL_SIM_ERROR_CODE ql_sim_get_simcard_info(QL_SIMCARD_INFO *pt_info, CMSimID_ex sim_id)
{
QL_SIM_STATUS card_status = QL_SIM_STATUS_NOT_INSERTED;
QL_SIM_ERROR_CODE ret = QL_SIM_SUCCESS;
int i=0;
char resp[64]={0};
UINT8 low_nibble, high_nibble;
if(pt_info==NULL)
{
return QL_SIM_GENERIC_FAILURE;
}
memset(pt_info,0,sizeof(QL_SIMCARD_INFO));
//get card status
ret = ql_sim_get_card_status_ex(&card_status, sim_id);
if (ret != QL_SIM_SUCCESS)
{
sim_log("get card status failed!\n");
return QL_SIM_GENERIC_FAILURE;
}
else if (card_status != QL_SIM_STATUS_READY)
{
sim_log("current card status is not QL_SIM_STATUS_READY! card_status=%d\n", card_status);
return QL_SIM_GENERIC_FAILURE;
}
pt_info->card_status = card_status;
//printf("pt_info->card_status = %d %x\n", pt_info->card_status, &(pt_info->card_status));
//get imsi
if((sim_id == QL_SIM_0) && strlen(IMSI))
{
strncpy(pt_info->imsi,IMSI,strlen(IMSI));
}
else if((sim_id == QL_SIM_1) && strlen(IMSI_1))
{
strncpy(pt_info->imsi,IMSI_1,strlen(IMSI_1));
}
else
{
sim_log("get imsi failed!\n");
return QL_SIM_GENERIC_FAILURE;
}
//get iccid
for (i = 0; i < QL_SIM_ICCID_LEN; i++)
{
#ifdef QUEC_DUAL_SIM_SUPPORT
low_nibble = (((sim_id == QL_SIM_0) ? ICCID : ICCID_1))[i] & 0x0f;
high_nibble = ((((sim_id == QL_SIM_0) ? ICCID : ICCID_1))[i] & 0xf0) >> 4;
#else
low_nibble = (ICCID[i] & 0x0f);
high_nibble = (ICCID[i] & 0xf0) >> 4;
#endif
sprintf(resp, "%s%X%X", resp, low_nibble, high_nibble);
}
if(strlen(resp))
{
strncpy((char *)(pt_info->iccid),resp,QL_SIM_ICCID_LEN*2+1);
}
else
{
sim_log("get iccid failed!\n");
return QL_SIM_GENERIC_FAILURE;
}
//get phonenum
return QL_SIM_SUCCESS;
}
static QL_SIM_ERROR_CODE ql_sim_get_card_status_ex(QL_SIM_STATUS *card_status, CMSimID_ex sim_id)
{
#if defined(QUEC_DUAL_SIM_SUPPORT) && !defined(NO_DIALER)
extern SimSwitchCtx gCmSimSwitchCtx;
SimSwitchCtx *ctx = &gCmSimSwitchCtx;
if (ctx->state != CM_SIM_SWITCH_INIT)
{
*card_status=QL_SIM_STATUS_UNKNOWN;
return QL_SIM_SUCCESS;
}
switch ( (sim_id == QL_SIM_0) ? gSimPinState : gSimPinState_1)
#else
switch ( gSimPinState )
#endif
{
case CI_SIM_PIN_ST_READY:
#ifdef QUEC_DUAL_SIM_SUPPORT
if (( (sim_id == QL_SIM_0) ? gSimStatus : gSimStatus_1) == CI_SIM_ST_READY)
#else
if (gSimStatus == CI_SIM_ST_READY)
#endif
{
*card_status=QL_SIM_STATUS_READY;
}
break;
case CI_SIM_PIN_ST_UNIVERSALPIN_REQUIRED:
case CI_SIM_PIN_ST_CHV1_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PIN;
break;
case CI_SIM_PIN_ST_CHV2_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PIN2;
break;
case CI_SIM_PIN_ST_UNBLOCK_UNIVERSALPIN_REQUIRED:
case CI_SIM_PIN_ST_UNBLOCK_CHV1_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_CHV2_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PUK2;
break;
case CI_SIM_PIN_ST_HIDDENKEY_REQUIRED:
*card_status=QL_SIM_STATUS_PH_FSIM_PIN;
break;
case CI_SIM_PIN_ST_UNBLOCK_HIDDENKEY_REQUIRED:
*card_status=QL_SIM_STATUS_PH_FSIM_PUK;
break;
case CI_SIM_PIN_ST_PCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SIM_LOCK_PIN;
break;
case CI_SIM_PIN_ST_NCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_PIN;
break;
case CI_SIM_PIN_ST_NSCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_SUB_PIN;
break;
case CI_SIM_PIN_ST_SPCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SP_PIN;
break;
case CI_SIM_PIN_ST_CCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_CORP_PIN;
break;
case CI_SIM_PIN_ST_UNBLOCK_PCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SIM_LOCK_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_NCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_NSCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_SUB_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_SPCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SP_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_CCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_CORP_PUK;
break;
case CI_SIM_PIN_ST_CHV1_BLOCKED:
case CI_SIM_PIN_ST_CHV2_BLOCKED:
case CI_SIM_PIN_ST_UNIVERSALPIN_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_CHV1_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_CHV2_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_UNIVERSALPIN_BLOCKED:
*card_status=QL_SIM_STATUS_BLOCKED;
break;
case CI_SIM_PIN_ST_REMOVED:
*card_status=QL_SIM_STATUS_NOT_INSERTED;
break;
case CI_SIM_PIN_ST_WAIT_INITIALISATION:
*card_status=QL_SIM_STATUS_BUSY;
break;
case CI_SIM_PIN_ST_NETWORK_REJECTED:
#ifdef QUEC_DUAL_SIM_SUPPORT
if (( (sim_id == QL_SIM_0) ? gSimStatus : gSimStatus_1) == CI_SIM_ST_READY)
#else
if (gSimStatus == CI_SIM_ST_READY)
#endif
{
*card_status=QL_SIM_STATUS_READY;
}
else
{
*card_status=QL_SIM_STATUS_UNKNOWN;
}
break;
case CI_SIM_PIN_ST_MEP_ERROR:
case CI_SIM_PIN_ST_UDP_ERROR:
case CI_SIM_PIN_ST_CPHS_ERROR:
case CI_SIM_PIN_ST_INIT_FAILED:
case CI_SIM_PIN_ST_GENERAL_ERROR:
default:
*card_status=QL_SIM_STATUS_UNKNOWN;
break;
}
return QL_SIM_SUCCESS;
}
#endif
int ql_sim_get_cur_SimId(void)
{
if(CHIP_IS_CRANELRH || CHIP_IS_CRANELG)
{
int ret = 0;
char at_cmd_str[32]={0};
char resp[32]={0};
char para[32]={0};
CMSimID gSimID = NUM_OF_CM_SIM;
snprintf(at_cmd_str,sizeof(at_cmd_str)-1,"AT+QDSIM?%s",AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,resp,sizeof(resp),NULL,10);
if(ret==QL_AT_RESP_OK)
{
ql_atcmd_get_para_value_str(resp,0,0,para,sizeof(para));
gSimID=(CMSimID)atoi(para);
}
return (ret==QL_AT_RESP_OK)?gSimID:-1;
}
else
{
#if !defined(NO_DIALER) || defined(QUEC_PS_SINGLE_PHYSICAL_DUAL_SIM_SUPPORT)
#ifndef SINGLE_SIM
return (isMasterSim0() ? SIM1: SIM2);
#else
CMSimID gSimID = NUM_OF_CM_SIM;
gSimID = (CMSimID)read_usim_swap_flag();
return gSimID;
#endif
#else
return -1;
#endif
}
}
int ql_sim_switch_card(int simID)
{
int ret = 0;
if(CHIP_IS_CRANELRH || CHIP_IS_CRANELG)
{
char at_cmd_str[32]={0};
char resp[32]={0};
snprintf(at_cmd_str,sizeof(at_cmd_str)-1,"AT+QDSIM=%d%s",simID,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,10);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
else
{
#if !defined(NO_DIALER) || defined(QUEC_PS_SINGLE_PHYSICAL_DUAL_SIM_SUPPORT)
#ifndef SINGLE_SIM
ret = CM_SetMasterSimID(simID, NULL);
#else
ret = CM_SetSingleSimID((CMSimID)simID, NULL);
#endif
if (ret == 0)
{
#ifdef CRANE_DSS
//Add by Freddy @20200905 切卡之后需要清掉上一次的网络信息
extern void ql_nw_info_clear(void);
ql_nw_info_clear();
#endif
//changed by mia.zhong @20201201 切卡之后不再清掉card status
//ql_sim_info_clear();
}
#endif
return ret;
}
}
#endif
QL_SIM_ERROR_CODE ql_sim_get_imsi(char *imsi,size_t imsi_len)// NOT SUPPORTED
{
int card_status;
ql_sim_get_card_status(&card_status);
if(card_status!=QL_SIM_STATUS_READY)
return QL_SIM_GENERIC_FAILURE;
memset(imsi,0,imsi_len);
//changed by mia.zhong @20201201
if (isMasterSim0() && strlen(IMSI))
{
strncpy(imsi,IMSI,imsi_len);
return QL_SIM_SUCCESS;
}
#ifdef QUEC_DUAL_SIM_SUPPORT
else if (!isMasterSim0() && strlen(IMSI_1))
{
strncpy(imsi,IMSI_1,imsi_len);
return QL_SIM_SUCCESS;
}
#endif
else
return QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_get_iccid(char *iccid,size_t iccid_len)
{
int i=0;
char resp[64]={0};
UINT8 low_nibble, high_nibble;
int card_status;
ql_sim_get_card_status(&card_status);
if(card_status!=QL_SIM_STATUS_READY)
return QL_SIM_GENERIC_FAILURE;
memset(iccid,0,iccid_len);
for (i = 0; i < 10; i++)
{
//add by freddy @20201019 双卡时ICCID需要分开处理
#ifdef QUEC_DUAL_SIM_SUPPORT
low_nibble = ((isMasterSim0() ? ICCID : ICCID_1))[i] & 0x0f;
high_nibble = (((isMasterSim0() ? ICCID : ICCID_1))[i] & 0xf0) >> 4;
#else
low_nibble = (ICCID[i] & 0x0f);
high_nibble = (ICCID[i] & 0xf0) >> 4;
#endif
sprintf(resp, "%s%X%X", resp, low_nibble, high_nibble);
}
if(strlen(resp))
{
strncpy(iccid,resp,iccid_len);
return QL_SIM_SUCCESS;
}
else
return QL_SIM_GENERIC_FAILURE;
}
#define QL_SIM_READ_RECORD 0xB2
#define QL_SIM_EF_MSISDN 0x6f40
#define QL_SIM_READ_P1 1
#define QL_SIM_READ_P2 4
#define QL_SIM_READ_LEN 28
typedef struct
{
char l_byte;
char h_byte;
}ql_sim_ef_praser_t;
typedef struct
{
char bcd_len_l;
char bcd_len_h;
char ton_npi_l;
char ton_npi_h;
}ql_sim_ef_header_t;
QL_SIM_ERROR_CODE ql_sim_get_phonenumber(char *phonenumber,size_t phonenumber_len)
{
int ret = 0;
char temp[2] = {0};
char atcmd[64]={0};
char resp[128] ={0};
char para[128]={0};
uint32_t len = 0;
int i = 0;
ql_sim_ef_praser_t *praser = NULL; //praser ptr
ql_sim_ef_header_t *header = NULL; //EF MSISDN vaild data hear area ptr
if(phonenumber == NULL ){
return QL_SIM_GENERIC_FAILURE;
}
memset(phonenumber, 0 , phonenumber_len);
// EF_MSISDN read by crsm command -TS 27.007 [8.18]
snprintf(atcmd, sizeof(atcmd), "AT+CRSM=%d,%d,%d,%d,%d\r\n", QL_SIM_READ_RECORD, QL_SIM_EF_MSISDN, QL_SIM_READ_P1, QL_SIM_READ_P2, QL_SIM_READ_LEN);
ret = ql_atcmd_send_sync(atcmd, resp, sizeof(resp), NULL,5);
if(ret==QL_AT_RESP_OK)
{
//sim_log("%s at resp : %s\r\n", __func__, resp);
len = ql_atcmd_get_para_value_str(resp, 0, 2, para, sizeof(para));
//find data area -TS 31.102 [4.2.26]
/*
EFMSISDN(6F40)
1 to X Alpha Identifier
X+1 Length of BCD number/SSC contents
X+2 TON and NPI
X+3 to X+12 Dialling Number/SSC String
X+13 Capability/Configuration2 Record Identifier
X+14 Extension5 Record Identifier
Example:
4D79204E756D626572FFFFFFFFFF07918123108845F8FFFFFFFFFFFF
*/
if((len % 2) || len < (14 * 2) || len >= sizeof(para))
{
return QL_SIM_GENERIC_FAILURE;
}
praser = (ql_sim_ef_praser_t *)&(para[len]);
praser -= 14;
header = (ql_sim_ef_header_t *)praser;
sim_log("%c,%c,%c,%c",header->bcd_len_l,header->bcd_len_h,header->ton_npi_l,header->ton_npi_h);
/* BCD lengh. Max:11 = 14 - 2 - 1. */
len = ((((header->bcd_len_l - '0') & 0x0F) << 4)|((header->bcd_len_h - '0') & 0x0F)) << 1;
sim_log("%s EF_MSISDN: %s/%d/%d\r\n", __func__, para,len,phonenumber_len);
/* Check if buffer is overflow. */
if(len > (11 * 2) || len > phonenumber_len)
{
return QL_SIM_GENERIC_FAILURE;
}
if(header->ton_npi_l == '9' && header->ton_npi_h == '1'){
strcat(phonenumber, "+");
}
praser += 2; //Jump length of BCD number/SSC contents/ & TON and NPI;
len -= 2;
do
{
memset(temp, 0, sizeof(temp));
if(praser->h_byte >= '0' && praser->h_byte <= '9'){
temp[0] = praser->h_byte;
}
if(praser->l_byte >= '0' && praser->l_byte <= '9'){
temp[1] = praser->l_byte;
}
strcat(phonenumber, temp);
praser ++;
i += 2;
}while(i < len);
sim_log("%s resp phonenumber: %s\r\n", __func__, phonenumber);
}
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_verify_pin(QL_SIM_VERIFY_PIN_INFO *pt_info) // NOT SUPPORT
{
int ret = 0;
char at_cmd_str[64]={0};
sprintf(at_cmd_str,"%s%s=%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CPIN,pt_info->pin_value,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_change_pin(QL_SIM_CHANGE_PIN_INFO *pt_info ) // [IN] PIN
{
int ret = 0;
char at_cmd_str[64]={0};
sprintf(at_cmd_str,"%s%s=SC,%s,%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CPWD,pt_info->old_pin_value,pt_info->new_pin_value,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_unblock_pin(QL_SIM_UNBLOCK_PIN_INFO *pt_info)// [IN] input PUK/PUK2 and new PIN/PIN2
{
int ret = 0;
char at_cmd_str[64]={0};
sprintf(at_cmd_str,"%s%s=%s,%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CPIN,pt_info->puk_value,pt_info->new_pin_value,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_enable_pin(QL_SIM_VERIFY_PIN_INFO *pt_info)// [IN] PIN
{
int ret = 0;
char at_cmd_str[64]={0};
char get_pin_value_temp[64]={0};
sprintf(at_cmd_str,"%s%s=SC,1,%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CLCK,pt_info->pin_value, AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_disable_pin(QL_SIM_VERIFY_PIN_INFO *pt_info ) // [IN] PIN
{
int ret = 0;
char at_cmd_str[64]={0};
sprintf(at_cmd_str,"%s%s=SC,0,%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CLCK,pt_info->pin_value, AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
//获取当前主卡的状态
QL_SIM_ERROR_CODE ql_sim_get_card_status(int *card_status)
{
//Modified by freddy@20200907 双卡时需要根据当前卡号来获取状态
#if defined(QUEC_DUAL_SIM_SUPPORT) && !defined(NO_DIALER)
//Added by freddy @20201022 切卡中卡状态直接返回unknown
extern SimSwitchCtx gCmSimSwitchCtx;
SimSwitchCtx *ctx = &gCmSimSwitchCtx;
if (ctx->state != CM_SIM_SWITCH_INIT)
{
*card_status=QL_SIM_STATUS_UNKNOWN;
return QL_SIM_SUCCESS;
}
switch ( isMasterSim0() ? gSimPinState : gSimPinState_1)
#else
switch ( gSimPinState )
#endif
{
case CI_SIM_PIN_ST_READY:
//Modified by freddy@20200907 双卡时需要根据当前卡号来获取状态
#ifdef QUEC_DUAL_SIM_SUPPORT
if (( isMasterSim0() ? gSimStatus : gSimStatus_1) == CI_SIM_ST_READY)
#else
if (gSimStatus == CI_SIM_ST_READY)
#endif
{
*card_status=QL_SIM_STATUS_READY;
}
break;
case CI_SIM_PIN_ST_UNIVERSALPIN_REQUIRED:
case CI_SIM_PIN_ST_CHV1_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PIN;
break;
case CI_SIM_PIN_ST_CHV2_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PIN2;
break;
case CI_SIM_PIN_ST_UNBLOCK_UNIVERSALPIN_REQUIRED:
case CI_SIM_PIN_ST_UNBLOCK_CHV1_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_CHV2_REQUIRED:
*card_status=QL_SIM_STATUS_SIM_PUK2;
break;
case CI_SIM_PIN_ST_HIDDENKEY_REQUIRED:
*card_status=QL_SIM_STATUS_PH_FSIM_PIN;
break;
case CI_SIM_PIN_ST_UNBLOCK_HIDDENKEY_REQUIRED:
*card_status=QL_SIM_STATUS_PH_FSIM_PUK;
break;
case CI_SIM_PIN_ST_PCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SIM_LOCK_PIN;
break;
case CI_SIM_PIN_ST_NCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_PIN;
break;
case CI_SIM_PIN_ST_NSCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_SUB_PIN;
break;
case CI_SIM_PIN_ST_SPCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SP_PIN;
break;
case CI_SIM_PIN_ST_CCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_CORP_PIN;
break;
case CI_SIM_PIN_ST_UNBLOCK_PCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SIM_LOCK_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_NCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_NSCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_NET_SUB_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_SPCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_SP_PUK;
break;
case CI_SIM_PIN_ST_UNBLOCK_CCK_REQUIRED:
*card_status=QL_SIM_STATUS_PH_CORP_PUK;
break;
case CI_SIM_PIN_ST_CHV1_BLOCKED:
case CI_SIM_PIN_ST_CHV2_BLOCKED:
case CI_SIM_PIN_ST_UNIVERSALPIN_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_CHV1_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_CHV2_BLOCKED:
case CI_SIM_PIN_ST_UNBLOCK_UNIVERSALPIN_BLOCKED:
*card_status=QL_SIM_STATUS_BLOCKED;
break;
case CI_SIM_PIN_ST_REMOVED:
*card_status=QL_SIM_STATUS_NOT_INSERTED;
break;
case CI_SIM_PIN_ST_WAIT_INITIALISATION:
*card_status=QL_SIM_STATUS_BUSY;
break;
case CI_SIM_PIN_ST_NETWORK_REJECTED:
//Modified by freddy@20200907 双卡时需要根据当前卡号来获取状态
#ifdef QUEC_DUAL_SIM_SUPPORT
if (( isMasterSim0() ? gSimStatus : gSimStatus_1) == CI_SIM_ST_READY)
#else
if (gSimStatus == CI_SIM_ST_READY)
#endif
{
*card_status=QL_SIM_STATUS_READY;
}
else
{
*card_status=QL_SIM_STATUS_UNKNOWN;
}
break;
case CI_SIM_PIN_ST_MEP_ERROR:
case CI_SIM_PIN_ST_UDP_ERROR:
case CI_SIM_PIN_ST_CPHS_ERROR:
case CI_SIM_PIN_ST_INIT_FAILED:
case CI_SIM_PIN_ST_GENERAL_ERROR:
default:
*card_status=QL_SIM_STATUS_UNKNOWN;
break;
}
return QL_SIM_SUCCESS;
}
QL_SIM_ERROR_CODE ql_sim_get_file_info
(
unsigned int fileid,
QL_SIM_FILE_INFO *file_info, // [OUT] output file info
QL_SIM_FILE_OPERATION_RET *operation_ret // [OUT] return the operation status code
)
{
return QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_read_file
(
unsigned int fileid, // EF file id
unsigned int index, // the index of record for a record EF file, the offest of date for a transparent EF file.
unsigned int data_max_len, // the max length of output data.
QL_SIM_CARD_FILE_DATA *file_data, // [OUT] File data
QL_SIM_FILE_OPERATION_RET *operation_ret // [OUT] return the operation status code
)
{
return QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_write_file
(
unsigned int fileid, // EF file id
int index, // the index of record for a record EF file, the offest of date for a transparent EF file.
QL_SIM_CARD_FILE_DATA *file_data, ///< [IN] File data of the specified one by pt_info
QL_SIM_FILE_OPERATION_RET *operation_ret // [OUT] return the operation status code
)
{
return QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_read_phonebook_record
(
QL_SIM_PHONE_BOOK_STORAGE storage, //IN the storage position of the phone book
int start_index,
int end_index,
char *username,
QL_SIM_PHONE_BOOK_RECORDS_INFO *records // the list of records
)
{
int ret = 0,j=0;
char resp[1024]={0};
char para[64]={0};
char encode[16]={0};
char at_cmd_str[64]={0};
memset(records,0,sizeof(QL_SIM_PHONE_BOOK_RECORDS_INFO));
ret = ql_atcmd_send_sync("AT+CSCS?\r\n",resp,sizeof(resp),NULL,5);
if(ret==QL_AT_RESP_OK)
{
ql_atcmd_get_para_value_str(resp,0,0,encode,sizeof(encode));
if(strcmp(encode,"UCS2"))
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CSCS=UCS2;+CPBS=%s\r\n",QL_SIM_PHONE_BOOK_STORAGE_STR[storage]);
else
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBS=%s\r\n",QL_SIM_PHONE_BOOK_STORAGE_STR[storage]);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
if(ret==QL_AT_RESP_OK)
{
if((start_index!=0)&&(end_index>=start_index)&&((end_index-start_index)<QL_SIM_PHONE_BOOK_RECORDS_MAX_COUNT))
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBR=%d,%d\r\n",start_index,end_index);
else if(username&&strlen(username))
{
int i=0;
int num=quec_utf8_to_usc2((unsigned char *)username,strlen(username),NULL);
unsigned int *username_usc2=(unsigned int *)calloc(num,sizeof(unsigned int));
if(username_usc2)
{
quec_utf8_to_usc2((unsigned char *)username,strlen(username),username_usc2);
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBF=");
for(i=0;i<num;i++)
snprintf(at_cmd_str,sizeof(at_cmd_str),"%s%04x",at_cmd_str,username_usc2[i]);
snprintf(at_cmd_str,sizeof(at_cmd_str),"%s\r\n",at_cmd_str);
free(username_usc2);
}
}
ret = ql_atcmd_send_sync(at_cmd_str,resp,sizeof(resp),NULL,10);
if(ret==QL_AT_RESP_OK)
{
int line_num=ql_atcmd_get_line_num(resp);
while(line_num>0)
{
line_num--;
ql_atcmd_get_para_value_str(resp,line_num,0, para,sizeof(para));
records->record[line_num].index=atoi(para);
ql_atcmd_get_para_value_str(resp,line_num,2, para,sizeof(para));
strncpy((char *)(records->record[line_num].phonenum),para,24);
ql_atcmd_get_para_value_str(resp,line_num,4, para,sizeof(para));
unsigned int *usc2_data=(unsigned int *)calloc(strlen(para)/4,sizeof(unsigned int));
if(usc2_data)
{
for(j=0;j<(strlen(para)/4);j++)
{
char tmp[5]={0};
strncpy(tmp,para+j*4,4);
sscanf(tmp,"%x",&usc2_data[j]);
}
quec_usc2_to_utf8(usc2_data,j,records->record[line_num].username);
free(usc2_data);
}
records->record_count++;
}
}
}
}
if(strcmp(encode,"UCS2"))
{
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CSCS=%s\r\n",encode);
ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
}
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_write_phonebook_record
(
QL_SIM_PHONE_BOOK_STORAGE storage, //IN the storage position of the phone book
QL_SIM_PHONE_BOOK_RECORD_INFO *record //IN a record
)
{
int ret = 0;
char resp[64]={0};
char para[64]={0};
char encode[16]={0};
char at_cmd_str[1024]={0};
ret = ql_atcmd_send_sync("AT+CSCS?\r\n",resp,sizeof(resp),NULL,5);
if(ret==QL_AT_RESP_OK)
{
ql_atcmd_get_para_value_str(resp,0,0,encode,sizeof(encode));
if(strcmp(encode,"UCS2"))
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CSCS=UCS2;+CPBS=%s\r\n",QL_SIM_PHONE_BOOK_STORAGE_STR[storage]);
else
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBS=%s\r\n",QL_SIM_PHONE_BOOK_STORAGE_STR[storage]);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
if(ret==QL_AT_RESP_OK)
{
if(strlen((char *)(record->phonenum))>0)
{
if(record->index!=0)
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBW=%d,%s,129,",record->index,record->phonenum);
else
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBW=,%s,129,",record->phonenum);
int i=0;
int num=quec_utf8_to_usc2(record->username,strlen((char *)(record->username)),NULL);
unsigned int *username_usc2=(unsigned int *)calloc(num,sizeof(unsigned int));
if(username_usc2)
{
quec_utf8_to_usc2(record->username,strlen((char *)(record->username)),username_usc2);
for(i=0;i<num;i++)
snprintf(at_cmd_str,sizeof(at_cmd_str),"%s%04x",at_cmd_str,username_usc2[i]);
snprintf(at_cmd_str,sizeof(at_cmd_str),"%s\r\n",at_cmd_str);
free(username_usc2);
}
}
else if(record->index!=0)
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CPBW=%d\r\n",record->index);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
}
}
if(strcmp(encode,"UCS2"))
{
snprintf(at_cmd_str,sizeof(at_cmd_str),"AT+CSCS=%s\r\n",encode);
ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,5);
}
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
/* 2023 03 16 ql sim detect support */
extern UINT32 usim_1_detect_gpio;
extern UINT32 usim_1_detect_gpio_insert_level;
extern void usim_init_hook(USIM_Card card);
#if defined (__QUECTEL_PROJECT_EC600KCN_CC__) || defined (__QUECTEL_PROJECT_EC600KCN_LC__) || defined (__QUECTEL_PROJECT_EC600KCN_LK__) || defined (__QUECTEL_PROJECT_EC600KCN_CK__)
#define QUEC_USIM1_DET_PIN GPIO_PIN_NO_85 //this consider you project
#else
#define QUEC_USIM1_DET_PIN GPIO_PIN_49 //this consider you project
#endif
typedef struct
{
unsigned char init;
unsigned char detenable;
PIN_LEVEL_E insertlevel;
sim_detect_calback callback;
unsigned int detect_gpio;
}ql_sim_detect_s,*ql_sim_detect_p;
ql_sim_detect_s g_sim_detect = {0};
unsigned char ql_sim1_detect_is_enable(void)
{
ql_sim_detect_p sim_detect_p = &g_sim_detect;
return (sim_detect_p->detenable)?(true):(false);
}
void ql_sim1_detect_ind_cust_callback(unsigned int insert_status)
{
ql_sim_detect_p sim_detect_p = &g_sim_detect;
PIN_LEVEL_E pin_level = PIN_LEVEL_LOW;
if(insert_status){
pin_level = sim_detect_p->insertlevel;
}else{
pin_level = (PIN_LEVEL_E)(!sim_detect_p->insertlevel);
}
if(sim_detect_p->callback){
sim_detect_p->callback(pin_level);
}
}
QL_SIM_ERROR_CODE ql_sim1_detect_gpio_config(unsigned int detect_gpio)
{
ql_sim_detect_p sim_detect_p = &g_sim_detect;
//CPUartLogPrint("ql_sim1_detect_gpio_config",1);
sim_log("%s detect_gpio=%d \r\n", __func__, detect_gpio);
sim_detect_p->detect_gpio = detect_gpio;
usim_1_detect_gpio = sim_detect_p->detect_gpio;
return QL_SIM_SUCCESS;
}
QL_SIM_ERROR_CODE ql_sim_config_hot_plug_detect(unsigned char detenable, PIN_LEVEL_E insertlevel,sim_detect_calback detectcallback)
{
ql_sim_detect_p sim_detect_p = &g_sim_detect;
if(detectcallback == NULL){
sim_log("%s ptr error!\r\n",__func__);
return QL_SIM_GENERIC_FAILURE;
}
//CPUartLogPrint("ql_sim_config_hot_plug_detect",1);
sim_log("%s enable=%d, insert_level=%d, callback=0x%x detect_gpio=%d\r\n", __func__, detenable, insertlevel, detectcallback, sim_detect_p->detect_gpio);
sim_detect_p->callback = detectcallback;
sim_detect_p->detenable = detenable;
sim_detect_p->insertlevel = insertlevel;
// sim1 config for low level init.
if(sim_detect_p->detect_gpio != 0){
usim_1_detect_gpio = sim_detect_p->detect_gpio;//user config sim detect pin
}else{
usim_1_detect_gpio = QUEC_USIM1_DET_PIN;
}
usim_1_detect_gpio_insert_level = insertlevel;
if(true != sim_detect_p->init){
usim_init_hook(USIM_COM_CARD);
sim_detect_p->init = true;
}
return QL_SIM_SUCCESS;
}
QL_SIM_ERROR_CODE ql_sim_open_logical_channel(char *dfName, UINT16* sessionId)
{
int ret = 0;
char at_cmd_str[128]={0};
char resp[64]={0};
char para[64]={0};
if((dfName == NULL) || (sessionId == NULL))
{
return QL_SIM_GENERIC_FAILURE;
}
snprintf(at_cmd_str,sizeof(at_cmd_str)-1,"%s%s=%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CCHO,dfName,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,resp,sizeof(resp),NULL,10);
if(ret==QL_AT_RESP_OK)
{
ql_atcmd_get_para_value_str(resp,0,0,para,sizeof(para));
*sessionId=atoi(para);
}
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_close_logical_channel(UINT16 sessionId)
{
int ret = 0;
char at_cmd_str[64]={0};
char resp[64]={0};
char para[64]={0};
snprintf(at_cmd_str,sizeof(at_cmd_str)-1,"%s%s=%d%s",AT_CMD_PREFFIX,AT_CMD_NAME_CCHC,sessionId,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,NULL,0,NULL,10);
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}
QL_SIM_ERROR_CODE ql_sim_access_logical_channel(UINT16 sessionId, UINT16 commandlength, char *command, UINT16* resplength, char *response)
{
int ret = 0;
char at_cmd_str[1024]={0};
char resp[512]={0};
char para[512]={0};
if((resplength == NULL) || (response == NULL))
{
return QL_SIM_GENERIC_FAILURE;
}
snprintf(at_cmd_str,sizeof(at_cmd_str)-1,"%s%s=%d,%d,%s%s",AT_CMD_PREFFIX,AT_CMD_NAME_CGLA,sessionId,commandlength,command,AT_CMD_SUFFIX);
ret = ql_atcmd_send_sync(at_cmd_str,resp,sizeof(resp),NULL,10);
if(ret==QL_AT_RESP_OK)
{
ql_atcmd_get_para_value_str(resp,0,0,para,sizeof(para));
*resplength=atoi(para);
memset(para,0,sizeof(para));
ql_atcmd_get_para_value_str(resp,0,1,para,sizeof(para));
memcpy(response,para,strlen(para));
}
return (ret==QL_AT_RESP_OK)?QL_SIM_SUCCESS:QL_SIM_GENERIC_FAILURE;
}