blob: 48d55057f4ec399a44f99bd5d6dc485302aedb10 [file] [log] [blame]
/************************************************************************
(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, &notify);
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;
}