/************************************************************************ | |
(c) Copyright 2019 by 天翼物联科技有限公司. All rights reserved. | |
**************************************************************************/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdarg.h> | |
#include "eSIM.h" | |
#include "LPAd.h" | |
//static uint8_t iccidString[21] = {0}; | |
static uint8_t imeiString[20] = {0}; | |
static uint8_t eSIMStatus = ESIM_UNINIT; | |
static CT_LPAd_session_t myLPAd; | |
static CT_LPAd_sys_hooks_t sysHooks; | |
static eSIM_cb_t myesimCB; | |
/*********************************************************/ | |
#if 0 | |
#define LOG_BUFF_LEN 1024 | |
uint8_t log_buff[LOG_BUFF_LEN]; | |
static void system_log(int level, const char *format, ...) | |
{ | |
va_list ap; | |
if( level == 0 ) | |
return; | |
#if 0 | |
va_start(ap, format); | |
vsnprintf(log_buff, LOG_BUFF_LEN, format, ap); | |
va_end(ap); | |
os_log(log_buff); | |
#else | |
va_start(ap, format); | |
vprintf(format, ap); | |
va_end(ap); | |
#endif | |
} | |
#endif | |
static uint8_t hex2byte(uint8_t *hexstr) | |
{ | |
uint8_t n1,n2; | |
if( hexstr == NULL || hexstr[0] == 0 || hexstr[1] == 0) | |
return -1; | |
n1 = (hexstr[0] <= '9' && hexstr[0] >= '0')? hexstr[0]-'0':hexstr[0]+10-'A'; | |
n2 = (hexstr[1] <= '9' && hexstr[1] >= '0')? hexstr[1]-'0':hexstr[1]+10-'A'; | |
return ((n1<<4)&0xf0) | (n2&0x0f); | |
} | |
static int hexString_to_bytes(uint8_t *hex, uint8_t *bytes) | |
{ | |
if( hex == NULL || bytes == NULL ) | |
return -1; | |
int len = strlen((char *)hex); | |
int i=0; | |
for(i=0; i < len/2; i++ ) | |
{ | |
bytes[i] = hex2byte(hex + i*2); | |
} | |
bytes[len/2] = 0; | |
return len/2; | |
} | |
static void iccid_little_to_big(uint8_t *iccid) | |
{ | |
uint8_t temp; | |
uint8_t *p = iccid; | |
if(p == NULL || strlen((char *)p) != 20 ) | |
return; | |
while(*p) | |
{ | |
temp = p[0]; | |
p[0] = p[1]; | |
p[1] = temp; | |
p += 2; | |
} | |
} | |
int eSIM_get_svn(eSIM_Version_t *svn) | |
{ | |
int ret; | |
LPAd_EUICCInfo1_t EUICCInfo1={0}; | |
if( svn == NULL ) | |
return -1; | |
svn->euiccGSMASGP = 0; | |
svn->Software = 0x00010200; | |
svn->LpaGSMASGP = 0x00020202; | |
ret = CT_LPAd_getEUICCInfo1(&myLPAd, &EUICCInfo1); | |
if( ret == 0 ) | |
{ | |
svn->euiccGSMASGP = EUICCInfo1.svn; | |
} | |
return ret; | |
} | |
int check_eSIM_status(void) | |
{ | |
if( eSIMStatus == ESIM_ERR_BUSY ) | |
return ESIM_ERR_BUSY; | |
if( eSIMStatus == ESIM_ERR_UNINIT ) | |
return ESIM_ERR_UNINIT; | |
return ESIM_OK; | |
} | |
int check_eSIM_callback(eSIM_cb_t *esimCB) | |
{ | |
if( esimCB == NULL ) | |
return -1; | |
if( esimCB->eSIM_trylock == NULL || esimCB->eSIM_unlock == NULL ) | |
return -1; | |
if( esimCB->eSIM_http == NULL || esimCB->eSIM_ccho == NULL || esimCB->eSIM_cchc == NULL || esimCB->eSIM_cgla == NULL ) | |
return -1; | |
if( esimCB->eSIM_malloc == NULL || esimCB->eSIM_free == NULL || esimCB->eSIM_strdup == NULL ) | |
return -1; | |
return 0; | |
} | |
int CT_eSIM_init(eSIM_cb_t *esimCB) | |
{ | |
if( check_eSIM_callback(esimCB) == -1 ) | |
return ESIM_ERR_PARAM; | |
//init PLAd context | |
myLPAd.imei = imeiString; | |
//init lock | |
myesimCB.eSIM_trylock = esimCB->eSIM_trylock; | |
myesimCB.eSIM_unlock = esimCB->eSIM_unlock; | |
//init es9 and es10 | |
myLPAd.LPAd_http = esimCB->eSIM_http; | |
myLPAd.LPAd_ccho = esimCB->eSIM_ccho; | |
myLPAd.LPAd_cchc = esimCB->eSIM_cchc; | |
myLPAd.LPAd_cgla = esimCB->eSIM_cgla; | |
//init system hooks | |
sysHooks.LPAd_malloc = esimCB->eSIM_malloc; | |
sysHooks.LPAd_free = esimCB->eSIM_free; | |
sysHooks.LPAd_strdup = esimCB->eSIM_strdup; | |
sysHooks.LPAd_log = esimCB->eSIM_log; | |
CT_LPAd_set_sys_hooks(&sysHooks); | |
eSIMStatus = ESIM_IDLE; | |
return ESIM_OK; | |
} | |
static int eSIM_lock(void) | |
{ | |
#if CT_ESIM_THREAD_MUTEX == 1 | |
if( myesimCB.eSIM_trylock() != 0 ) | |
{ | |
return -1; | |
} | |
#endif | |
eSIMStatus = ESIM_BUSY; | |
return ESIM_OK; | |
} | |
static void eSIM_unlock(void) | |
{ | |
#if CT_ESIM_THREAD_MUTEX == 1 | |
myesimCB.eSIM_unlock(); | |
#endif | |
eSIMStatus = ESIM_IDLE; | |
} | |
#define ESIM_LOCK() if( eSIM_lock() < 0 ) return ESIM_ERR_BUSY | |
int CT_eSIM_install_profile(uint8_t *smdp_addr, uint8_t *macthingID, uint8_t flag, eSIM_InstallResult_t *installResult) | |
{ | |
int ret; | |
int notify = 0; | |
uint16_t seqNumber = 0; | |
if( smdp_addr == NULL || macthingID == NULL || installResult == NULL ) | |
return ESIM_ERR_PARAM; | |
/* check eSIM status */ | |
ret = check_eSIM_status(); | |
if( ret != ESIM_OK ) | |
return ret; | |
/* lock */ | |
ESIM_LOCK(); | |
myLPAd.DPurl = smdp_addr; | |
myLPAd.macthingID = macthingID; | |
if( flag == 1 ) | |
{ | |
notify = 1; | |
} | |
ret = CT_LPAd_install_profile(&myLPAd, &seqNumber, ¬ify); | |
if( ret == 0 ) | |
{ | |
installResult->result = ESIM_INSTALL_OK; | |
memmove(installResult->iccid, myLPAd.iccid, 20); | |
if( flag == 1 || flag == 2 ) | |
{ | |
ret = CT_LPAd_enable_profile(&myLPAd, myLPAd.iccid, 0); | |
if( ret == 0 ) | |
{ | |
installResult->result = ESIM_INSTALL_ENABILE_OK; | |
} | |
} | |
ret = ESIM_OK; | |
} | |
else | |
{ | |
if( myLPAd.status == AUTHENTICATION_PROCEDURE ) | |
{ | |
installResult->result = ESIM_AUTHENTICATION_FAIL; | |
} | |
else if( myLPAd.status == PROFILE_DOWNLOAD ) | |
{ | |
installResult->result = ESIM_DOWLOAD_FAIL; | |
} | |
else if( myLPAd.status == PROFILE_INSTALLATION ) | |
{ | |
installResult->result = ESIM_INSTALL_FAIL; | |
} | |
else | |
{ | |
installResult->result = ESIM_AUTHENTICATION_FAIL; | |
} | |
//if( myLPAd.errorCode.apdu_sw == -1 || myLPAd.errorCode.apdu_sw == 0 ) | |
//os_log("\r\ninstall profile fail\r\n"); | |
//else | |
//os_log("\r\ninstall profile fail, apdu sw:%X\r\n", myLPAd.errorCode.apdu_sw); | |
ret = ESIM_ERR_OTHER; | |
} | |
/* unlock */ | |
eSIM_unlock(); | |
return ret; | |
} | |
int CT_eSIM_management_profile(uint8_t action, uint8_t *iccid, uint8_t *result) | |
{ | |
int ret; | |
if( iccid == NULL || action > 1 ) | |
return ESIM_ERR_PARAM; | |
/* check eSIM status */ | |
ret = check_eSIM_status(); | |
if( ret != ESIM_OK ) | |
return ret; | |
/* lock */ | |
ESIM_LOCK(); | |
if( action == 1 ) | |
{ | |
ret = CT_LPAd_enable_profile(&myLPAd, iccid, 0); | |
if( ret >= 0 ) | |
{ | |
*result = ret; | |
ret = ESIM_OK; | |
} | |
else | |
{ | |
//if( myLPAd.errorCode.apdu_sw == -1 || myLPAd.errorCode.apdu_sw == 0 ) | |
// os_log("enable profile fail\r\n"); | |
//else | |
// os_log("enable profile fail, apdu sw:%x\r\n", myLPAd.errorCode.apdu_sw); | |
ret = ESIM_ERR_OTHER; | |
} | |
} | |
else if( action == 0 ) | |
{ | |
ret = CT_LPAd_disable_profile(&myLPAd, iccid, 0); | |
if( ret >= 0 ) | |
{ | |
*result = ret; | |
ret = ESIM_OK; | |
} | |
if( ret < 0 ) | |
{ | |
//if( myLPAd.errorCode.apdu_sw == -1 || myLPAd.errorCode.apdu_sw == 0 ) | |
// os_log("enable profile fail\r\n"); | |
//else | |
// os_log("enable profile fail, apdu sw:%x\r\n", myLPAd.errorCode.apdu_sw); | |
ret = ESIM_ERR_OTHER; | |
} | |
} | |
/* unlock */ | |
eSIM_unlock(); | |
return ret; | |
} | |
int CT_eSIM_get_eid(uint8_t *eid) | |
{ | |
int ret; | |
if( eid == NULL ) | |
return ESIM_ERR_PARAM; | |
/* check eSIM status */ | |
ret = check_eSIM_status(); | |
if( ret != ESIM_OK ) | |
return ret; | |
/* lock */ | |
ESIM_LOCK(); | |
ret = CT_LPAd_get_eid(&myLPAd, eid); | |
if( ret == 0 ) | |
{ | |
ret = ESIM_OK; | |
} | |
else | |
{ | |
ret = ESIM_ERR_OTHER; | |
} | |
/* unlock */ | |
eSIM_unlock(); | |
return ret; | |
} | |
int CT_eSIM_getProfileInfo(uint8_t* iccid, eSIM_ProfilesInfoList_t *profilesInfoList) | |
{ | |
int ret; | |
/* check eSIM status */ | |
ret = check_eSIM_status(); | |
if( ret != ESIM_OK ) | |
return ret; | |
/* lock */ | |
ESIM_LOCK(); | |
ret = CT_LPAd_getProfileInfo(&myLPAd, iccid, NULL, (CT_LPAdProfilesInfoList_t *)profilesInfoList); | |
if( ret == 0 ) | |
{ | |
ret = ESIM_OK; | |
} | |
else | |
{ | |
ret = ESIM_ERR_OTHER; | |
} | |
/* unlock */ | |
eSIM_unlock(); | |
return ret; | |
} | |
int CT_eSIM_getProfileIccidList(uint8_t *iccid, eSIM_ProfilesIccidList_t *iccidList) | |
{ | |
int ret; | |
/* check eSIM status */ | |
ret = check_eSIM_status(); | |
if( ret != ESIM_OK ) | |
return ret; | |
/* lock */ | |
ESIM_LOCK(); | |
ret = CT_LPAd_getProfileIccidList(&myLPAd, iccid, (CT_LPAdProfilesIccidList_t *)iccidList); | |
if( ret == 0 ) | |
{ | |
ret = ESIM_OK; | |
} | |
else | |
{ | |
ret = ESIM_ERR_OTHER; | |
} | |
/* unlock */ | |
eSIM_unlock(); | |
return ret; | |
} | |
static int eSIM_get_seqNumber(uint8_t *iccid, LPAd_notificationMetadataList_t *NotificationMetadataList, uint16_t *seqNumber) | |
{ | |
uint8_t *p; | |
int i=0; | |
if(iccid == NULL || NotificationMetadataList == NULL || NotificationMetadataList->validCount == 0 || seqNumber == NULL ) | |
return -1; | |
for(i=0;i<NotificationMetadataList->validCount;i++) | |
{ | |
p = NotificationMetadataList->NotificationMetadata[i].seqNumber; | |
if(strcmp((char *)iccid, (char *)NotificationMetadataList->NotificationMetadata[i].iccid) == 0 && p != NULL ) | |
{ | |
if(strcmp((char *)p, "00") !=0 ) | |
{ | |
*seqNumber = strtol((char *)NotificationMetadataList->NotificationMetadata[i].seqNumber, NULL, 16); | |
if( *seqNumber == 0 ) | |
return -1; | |
return 0; | |
} | |
else | |
{ | |
*seqNumber = 0; | |
return 0; | |
} | |
} | |
} | |
return -1; | |
} | |
static int eSIM_get_notificationAddress(uint8_t *iccid, LPAd_notificationMetadataList_t *NotificationMetadataList, uint8_t **notificationAddress) | |
{ | |
uint8_t *p; | |
int i = 0; | |
if(iccid == NULL || NotificationMetadataList == NULL || NotificationMetadataList->validCount == 0 || notificationAddress == NULL ) | |
return -1; | |
for(i=0;i<NotificationMetadataList->validCount;i++) | |
{ | |
p = NotificationMetadataList->NotificationMetadata[i].notificationAddress; | |
if(strcmp((char *)iccid, (char *)NotificationMetadataList->NotificationMetadata[i].iccid) == 0 && p != NULL ) | |
{ | |
*notificationAddress = (uint8_t *)sysHooks.LPAd_strdup((char *)p); | |
} | |
} | |
return 0; | |
} | |
static void eSIM_show_NotificationMetadataList(LPAd_notificationMetadataList_t *NotificationMetadataList) | |
{ | |
uint8_t *p; | |
int i = 0; | |
if( sysHooks.LPAd_log == NULL ) | |
return; | |
sysHooks.LPAd_log(0, "/***************NotificationMetadataList start*************************/\r\n"); | |
for(i=0;i<NotificationMetadataList->validCount;i++) | |
{ | |
p = NotificationMetadataList->NotificationMetadata[i].seqNumber; | |
if( p != NULL ) | |
sysHooks.LPAd_log(0,"seqNumber: %s\r\n", p); | |
p = NotificationMetadataList->NotificationMetadata[i].profileManagementOperation; | |
if( p != NULL ) | |
{ | |
if(strcmp((char *)p, "0410") == 0 ) | |
{ | |
sysHooks.LPAd_log(0, "profileManagementOperation: notificationInstall\r\n"); | |
} | |
else if(strcmp((char *)p, "0520") == 0 ) | |
{ | |
sysHooks.LPAd_log(0, "profileManagementOperation: notificationEnable\r\n"); | |
} | |
else if(strcmp((char *)p, "0640") == 0 ) | |
{ | |
sysHooks.LPAd_log(0, "profileManagementOperation: notificationDisable\r\n"); | |
} | |
else if(strcmp((char *)p, "0780") == 0 ) | |
{ | |
sysHooks.LPAd_log(0, "profileManagementOperation: notificationDelete\r\n"); | |
} | |
} | |
p = NotificationMetadataList->NotificationMetadata[i].notificationAddress; | |
if( p != NULL ) | |
{ | |
hexString_to_bytes(p,p); | |
sysHooks.LPAd_log(0, "notificationAddress: %s\r\n", p); | |
} | |
p = NotificationMetadataList->NotificationMetadata[i].iccid; | |
iccid_little_to_big(p); | |
if( p != NULL ) | |
sysHooks.LPAd_log(0, "iccid: %s\r\n", p); | |
sysHooks.LPAd_log(0, " \r\n"); | |
} | |
sysHooks.LPAd_log(0, "/***************NotificationMetadataList end *************************/\r\n"); | |
} | |
int CT_eSIM_send_enable_notification(uint8_t *iccid) | |
{ | |
int ret; | |
uint16_t seqNumber = 0; | |
uint16_t delSeqNumber; | |
LPAd_notificationMetadataList_t NotificationMetadataList={0}; | |
ret = CT_LPAd_list_notification(&myLPAd, (uint8_t *)"0520", &NotificationMetadataList); | |
if( ret < 0 ) | |
{ | |
return ESIM_NOTIFY_OTHER_ERR; | |
} | |
eSIM_show_NotificationMetadataList(&NotificationMetadataList); | |
ret = eSIM_get_seqNumber(iccid, &NotificationMetadataList, &seqNumber); | |
if( ret < 0 ) | |
{ | |
return ESIM_NOTIFY_ICCID_NOT_FOUND; | |
} | |
ret = eSIM_get_notificationAddress(iccid, &NotificationMetadataList, &myLPAd.DPurl); | |
if( ret < 0 ) | |
{ | |
return ESIM_NOTIFY_ICCID_NOT_FOUND; | |
} | |
ret = CT_LPAd_process_notification(&myLPAd, seqNumber, 0); | |
if( myLPAd.DPurl != NULL) | |
{ | |
sysHooks.LPAd_free(myLPAd.DPurl); | |
myLPAd.DPurl = NULL; | |
} | |
if( ret < 0 ) | |
{ | |
return ESIM_NOTIFY_OTHER_ERR; | |
} | |
myLPAd.DPurl = NULL; | |
int i =0; | |
//delete all enable notification | |
for(i=0;i<NotificationMetadataList.validCount;i++) | |
{ | |
uint8_t *p = NotificationMetadataList.NotificationMetadata[i].seqNumber; | |
if(strcmp((char *)iccid, (char *)NotificationMetadataList.NotificationMetadata[i].iccid) == 0 && p != NULL ) | |
{ | |
delSeqNumber = strtol((char *)NotificationMetadataList.NotificationMetadata[i].seqNumber, NULL, 16); | |
if( delSeqNumber != seqNumber ) | |
{ | |
CT_LPAd_remove_notification(&myLPAd, seqNumber); | |
} | |
} | |
} | |
return ESIM_NOTIFY_OK; | |
} | |
uint8_t CT_eSIM_get_status(void) | |
{ | |
return eSIMStatus; | |
} | |