blob: 509d0476f8ad5aabcd55d5e07b6c881413727c6a [file] [log] [blame]
/***************************************************************/
//
//²Î¼û ÖйúÁªÍ¨esimÄ£×éÀ©Õ¹Ö¸Áî¼¼Êõ¹æ·¶
//
/***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <termios.h>
#include <errno.h>
#include "lpa_inner.h"
#define SMDP_PORT 443
#define SMDP_DL_INTERVAL 95//ÏÂÔØ¼ä¸ô>90s
//´¥·¢·þÎñÆ÷httpÇëÇó
static char smdp_https_req[] =
"POST /gsma/rsp2/es9plus/%s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: gsma-rsp-lpad\r\n"
"X-Admin-Protocol: gsma/rsp/v2.2.0\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %d\r\n"
"\r\n%s\r\n";
static https_context_t g_https_ct = {0};
static char g_transid[MAX_TRANSID_LEN] = {0};
char curent_iccid[ICCID_LEN+1] = {0};
extern char g_imei[MAX_IMEI_LEN];
//iccid from bpp install result, if null, failed
//ISD-P AID, tag '4F';ICCID, tag '5A'. if succ, has AID
static int lpa_parse_iccid_apdu(char *apdu, char *iccid, int size)
{
int apdu_len = strlen(apdu);
unsigned char *apdu_byte = malloc(apdu_len/2 + 1);
int apdu_byte_len = 0;
char *tag_hex = NULL;
char has_iccid[ICCID_LEN+1] = {0};
if (apdu_byte == NULL) {
printf("lpa_parse_iccid_apdu no memory\n");
return -1;
}
memset(apdu_byte, 0, apdu_len/2 + 1);
apdu_byte_len = string2bytes(apdu, apdu_byte, apdu_len);
tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x4F);
if (tag_hex == NULL) {
printf("lpa_parse_iccid_apdu not find AID\n");
free(apdu_byte);
return -1;
}
printf("lpa aid:%s\n", tag_hex);
free(tag_hex);
tag_hex = NULL;
tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x5A);
if (tag_hex == NULL) {
printf("lpa_parse_iccid_apdu not find iccid\n");
free(apdu_byte);
return -1;
}
snprintf(iccid, size, "%s", tag_hex);
sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));
if (strcmp(iccid, has_iccid) != 0) {
sc_cfg_set("lpa_bpp_iccid", iccid);
sc_cfg_save();
printf("lpa iccid not same?\n");
}
printf("lpa iccid:%s\n", iccid);
free(apdu_byte);
free(tag_hex);
return 0;
}
static int lpa_connect_smdp(char *host)
{
SSL_library_init();
g_https_ct.port=SMDP_PORT;
g_https_ct.host=host;
g_https_ct.path=NULL;
return https_init(&g_https_ct);
}
static void lpa_disconn_smdp(char *host)
{
https_uninit(&g_https_ct);
}
static char *lpa_smdp_session(char *path, char *req_data, int *res_len)
{
int ret = -1;
int cont_len = 0;
char *https_req = NULL;
char *https_resp = NULL;
int https_req_len = strlen(smdp_https_req)+strlen(path)+strlen(g_https_ct.host)+strlen(req_data)+32;
*res_len = -1;
if (https_req_len > SMDP_HTTP_MAX_LEN)
return NULL;
https_req = malloc(https_req_len);
if (https_req == NULL)
return NULL;
memset(https_req, 0, https_req_len);
g_https_ct.path = path;
ret = snprintf(https_req, https_req_len, smdp_https_req,
g_https_ct.path, g_https_ct.host, strlen(req_data), req_data);
printf("[https_smdp]req[%d]:##%s##\n", strlen(https_req), https_req);
ret = https_write(&g_https_ct, https_req, ret);
if (ret == -1) {
//EAGAIN?
free(https_req);
printf("[https_smdp] https_write err:%d.\n", errno);
return NULL;
}
ret = https_get_status_code(&g_https_ct, &cont_len);
if(ret == 200) {
printf("[https_smdp] https_recv len:%d.\n", cont_len);
if (cont_len == HTTP_CHUNKED_FLAG) {
ret = https_read_chunked_content(&g_https_ct, &https_resp, SMDP_HTTP_MAX_LEN);
if(ret > 0) {
*res_len = ret;
https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
printf("[https_smdp] https_write https_resp_content##%s##\n",https_resp);
}
printf("[https_smdp] https_resp chunk %d!!!\n", ret);
}
else {
if (cont_len >= SMDP_HTTP_MAX_LEN) {
free(https_req);
printf("[https_smdp] https_recv too long = %d.\n", cont_len);
return NULL;
}
https_resp = malloc(cont_len + 1);
if (https_resp == NULL) {
free(https_req);
return NULL;
}
memset(https_resp, 0, cont_len + 1);
ret = https_read_content(&g_https_ct, https_resp, cont_len);
if(ret > 0) {
*res_len = ret;
https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
printf("[https_smdp] https_read_content##%s##\n",https_resp);
}
else {
*res_len = -1;
free(https_req);
free(https_resp);
return NULL;
}
}
}
else if(ret == 204) {
*res_len = 0;
}
else {
printf("[https_smdp] https_resp code = %d.\n", ret);
}
free(https_req);
return https_resp;
}
/***************************************************************/
//
//ÌáÈ¡stringÀàÐÍÊý¾Ý
//
/***************************************************************/
static char *lpa_parse_json_str(char *srcStr, char *key)
{
cJSON *root = NULL;
cJSON *object = NULL;
char *value_str = NULL;
int value_len = 0;
root = cJSON_Parse(srcStr);
if (root == NULL) {
printf("root == NULL\n");
return NULL;
}
object = cJSON_GetObjectItem(root, key);
if (object == NULL) {
printf("key: %s not find\n", key);
cJSON_Delete(root);
return NULL;
}
//printf("key:%s-value:%s\n", key, object->valuestring);
value_len = strlen(object->valuestring);
value_str = malloc(value_len + 1);
if (value_str == NULL) {
cJSON_Delete(root);
return NULL;
}
memset(value_str, 0, value_len + 1);
strncpy(value_str, object->valuestring, value_len);
cJSON_Delete(root);
return value_str;
}
/***************************************************************/
//
//ÌáÈ¡stringÀàÐ͵Äbase64Êý¾Ý->decode->hex string
//
/***************************************************************/
static char *lpa_parse_json_decode(char *srcStr, char *key)
{
cJSON *root = NULL;
cJSON *object = NULL;
char *value_byte = NULL;
char *value_str = NULL;
int value_len = 0;
root = cJSON_Parse(srcStr);
if (root == NULL) {
printf("root == NULL\n");
return NULL;
}
object = cJSON_GetObjectItem(root, key);
if (object == NULL) {
printf("key: %s not find\n", key);
cJSON_Delete(root);
return NULL;
}
//printf("key:%s-value:%s\n", key, object->valuestring);
value_byte = lpa_base64_decode(object->valuestring, strlen(object->valuestring), &value_len);
if (value_byte == NULL) {
printf("lpa_base64_decode fail\n");
cJSON_Delete(root);
return NULL;
}
value_str = malloc(value_len*2 + 1);
if (value_str == NULL) {
free(value_byte);
cJSON_Delete(root);
return NULL;
}
memset(value_str, 0, value_len*2 + 1);
bytes2string(value_byte, value_str, value_len);
*(value_str + value_len*2) = '\0';
//printf("key:%s(%d)-hex:%s\n", key, value_len*2, value_str);
free(value_byte);
cJSON_Delete(root);
return value_str;
}
/***************************************************************/
//
//char srcStr[] =
//"{"
// "\"header\" : {"
// "\"functionExecutionStatus\" : {"
// "\"status\" : \"Executed-Success\""
// "}"
// "},"
// "\"serverSigned1\": \"MEKAEAK3+mF5GUrrl+BlIUcujtSBEFK4u91WT/9GbQX+6pX/aoCDCmVzaW0ud28uY26EEEYRuTYzeka9iSyW+gSFF44=\","
// "\"transactionId\": \"02B7FA6179194AEB97E06521472E8ED4\","
// "\"serverSignature1\": \"XzdA9J6G6txPTOeOjQThaH/u/Wy/LOcZYec9reC65gjva7waj0XFBs0k551ynos1izFUpXbF8vctFw+/Enqu5aDQTA==\","
// "\"serverCertificate\": \"MIIC1jCCAn2gAwIBAgIDAYb6MAoGCCqGSM49BAMCMH4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVKSUxJTjESMBAGA1UEBwwJQ0hBTkdDSFVOMQ0wCwYDVQQLDARDVUNBMQswCQYDVQQKDAJDVTEvMC0GA1UEAwwmQ2hpbmEgVW5pY29tIGVTSU0gUm9vdCBDQSBOSVNUUCBCWlRFU1QwHhcNMTkxMjI1MTUyNzEyWhcNMjAxMjI0MTUyNzEyWjB5MQswCQYDVQQGEwJDTjEnMCUGA1UECwweSW5ub3ZhdGl2ZSBCdXNpbmVzcyBEZXBhcnRtZW50MQ4wDAYDVQQKDAVWc2VuczExMC8GA1UEAwwoVW5pY29tIFZzZW5zIENvbW11bmljYXRpb24gQ28uIEx0ZChUZXN0KTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABC0BAmyq7voWvhezfZnAoQyRb5CgvPjFuGr7c4arFsbBFNYcv7w5C3Tp3wHD03HkIIhPuZrkx9kWNYeBrekfBw6jge4wgeswHwYDVR0jBBgwFoAUfA5UcBQ+qJmO2d8wBXTJLlqayx8wHQYDVR0OBBYEFC2+UJhg5G9/+zlI3mqf7YMrZHPMMA4GA1UdDwEB/wQEAwIHgDAXBgNVHSABAf8EDTALMAkGB2eBEgECAQQwFQYDVR0RBA4wDIgKKwYBBAGC9UYCBDBpBgNVHR8EYjBgMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjEuY3JsMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjIuY3JsMAoGCCqGSM49BAMCA0cAMEQCIBEAZfg9hJIax/xRpVIAjjmENrPr7q97E0Hv2s+8aOPDAiBaURKuxxzZ8/P0DKE7SmW+AhbxBl1TQd09sM6+Plzu9A==\","
// "\"euiccCiPKIdToBeUsed\": \"BBR8DlRwFD6omY7Z3zAFdMkuWprLHw==\""
//"}";
//
/***************************************************************/
static char *lpa_parse_initauth_resp(char *srcStr)
{
char *transid = NULL;
char *signed_hex = NULL;
char *signature_hex = NULL;
char *ciPKId_hex = NULL;
char *certificate_hex = NULL;
char *authser_apdu = NULL;
//1 transid
//2 get sig...
//3 genaner at and send
transid = lpa_parse_json_str(srcStr, "transactionId");
if (transid == NULL)
goto parse_END;
snprintf(g_transid, sizeof(g_transid), "%s", transid);
signed_hex = lpa_parse_json_decode(srcStr, "serverSigned1");
if (signed_hex == NULL)
goto parse_END;
signature_hex = lpa_parse_json_decode(srcStr, "serverSignature1");
if (signature_hex == NULL)
goto parse_END;
ciPKId_hex = lpa_parse_json_decode(srcStr, "euiccCiPKIdToBeUsed");
if (ciPKId_hex == NULL)
goto parse_END;
certificate_hex = lpa_parse_json_decode(srcStr, "serverCertificate");
if (certificate_hex == NULL)
goto parse_END;
//×îºóÒ»¶ÎÊÇɶ£¿ctxparams
//80E29103£¿91±íʾ½öÒ»¶Î»òÕß×îºóÒ»¶Î
//×î×îºóµÄ00²»ËãÔÚ³¤¶ÈÄÚ
// 80E21100FFBF38(00 = i, ff =len)
// ffÖ®ºó×¶àÉÙÏß²»¹Ü
// ÏÈËãbf38ºó×¶àÉÙ£¬½«bf38ºóÊý¾ÝÏÈ×éºÃ£¬ÔÙ¼Ó
// 80E2110iLLÀ´·Ö¸îat
// ²¢ÔÚ×îºóÒ»¶ÎÏ·¢ºó¶ÁÈÏÖ¤·þÎñÆ÷µÄ²ÎÊýat
//matchingId´Ó¼¤»îÂëÖÐÈ¡£¬Ä¿Ç°Ã»ÓÃ
authser_apdu = AuthenticateServer(signed_hex, signature_hex, ciPKId_hex, certificate_hex, "", g_imei);
parse_END:
if (transid != NULL)
free(transid);
if (signed_hex != NULL)
free(signed_hex);
if (signature_hex != NULL)
free(signature_hex);
if (ciPKId_hex != NULL)
free(ciPKId_hex);
if (certificate_hex != NULL)
free(certificate_hex);
return authser_apdu;
}
static char *lpa_parse_authcli_resp(char *srcStr)
{
char *transid = NULL;
char *signed2_hex = NULL;
char *signature2_hex = NULL;
char *certi_hex = NULL;
//char *meta_hex = NULL;
char *predl_apdu = NULL;
transid = lpa_parse_json_str(srcStr, "transactionId");
if (transid == NULL)
goto parse_END;
snprintf(g_transid, sizeof(g_transid), "%s", transid);
signed2_hex = lpa_parse_json_decode(srcStr, "smdpSigned2");
if (signed2_hex == NULL)
goto parse_END;
signature2_hex = lpa_parse_json_decode(srcStr, "smdpSignature2");
if (signature2_hex == NULL)
goto parse_END;
certi_hex = lpa_parse_json_decode(srcStr, "smdpCertificate");
if (certi_hex == NULL)
goto parse_END;
//meta_hex = lpa_parse_json_decode(srcStr, "profileMetadata");
//if (meta_hex == NULL)
// goto parse_END;
predl_apdu = PrepareDownload(transid, signed2_hex, signature2_hex, certi_hex, "");
parse_END:
if (transid != NULL)
free(transid);
if (signed2_hex != NULL)
free(signed2_hex);
if (signature2_hex != NULL)
free(signature2_hex);
if (certi_hex != NULL)
free(certi_hex);
//if (meta_hex != NULL)
// free(meta_hex);
return predl_apdu;
}
static char *lpa_parse_getbpp_resp(char *srcStr)
{
char *transid = NULL;
char *bpp_b64 = NULL;
char *notify_apdu = NULL;
transid = lpa_parse_json_str(srcStr, "transactionId");
if (transid == NULL)
goto parse_END;
snprintf(g_transid, sizeof(g_transid), "%s", transid);
bpp_b64 = lpa_parse_json_str(srcStr, "boundProfilePackage");
if (bpp_b64 == NULL)
goto parse_END;
notify_apdu = LoadBoundProfilePackage(bpp_b64);
parse_END:
if (transid != NULL)
free(transid);
if (bpp_b64 != NULL)
free(bpp_b64);
return notify_apdu;
}
//·µ»ØjsonÊý¾Ý¸øÏÂÒ»²½µ÷ÓÃ
static char *lpa_initauth(void)
{
int ret = -1;
char *euiccChallenge = NULL;
char *euiccInfo1 = NULL;
char *ia_json = NULL;
char *https_resp = NULL;
char *resp_apdu = NULL;
euiccChallenge = GetEUICCChallenge();
if (euiccChallenge == NULL) {
return NULL;
}
euiccInfo1 = GetEUICCInfo(TRUE);
if (euiccInfo1 == NULL) {
free(euiccChallenge);
return NULL;
}
ia_json = InitiateAuthentication(euiccChallenge, euiccInfo1, g_https_ct.host);
if (ia_json == NULL) {
free(euiccChallenge);
free(euiccInfo1);
return NULL;
}
https_resp = lpa_smdp_session("initiateAuthentication", ia_json, &ret);
if (https_resp != NULL) {
resp_apdu = lpa_parse_initauth_resp(https_resp);
free(https_resp);
}
free(euiccChallenge);
free(euiccInfo1);
free(ia_json);
return resp_apdu;
}
static char *lpa_authclient(char *as_apdu)
{
int ret = -1;
char *ac_json = NULL;
char *https_resp = NULL;
char *resp_apdu = NULL;
ac_json = AuthenticateClient(g_transid, as_apdu);
if (ac_json == NULL) {
return NULL;
}
https_resp = lpa_smdp_session("authenticateClient", ac_json, &ret);
if (https_resp != NULL) {
resp_apdu = lpa_parse_authcli_resp(https_resp);
free(https_resp);
}
free(ac_json);
return resp_apdu;
}
static char *lpa_getbpp(char *pdl_apdu)
{
int ret = -1;
char *bpp_json = NULL;
char *https_resp = NULL;
char *resp_apdu = NULL;
bpp_json = GetBoundProfilePackage(g_transid, pdl_apdu);
if (bpp_json == NULL) {
return NULL;
}
https_resp = lpa_smdp_session("getBoundProfilePackage", bpp_json, &ret);
if (ret > 0) {
resp_apdu = lpa_parse_getbpp_resp(https_resp);
free(https_resp);
}
free(bpp_json);
return resp_apdu;
}
static int lpa_notification(char *notify_apdu)
{
int ret = -1;
char *notify_json = NULL;
char *https_resp = NULL;
notify_json = HandleNotification(notify_apdu);
if (notify_json == NULL) {
return ret;
}
https_resp = lpa_smdp_session("handleNotification", notify_json, &ret);
if (https_resp != NULL)
free(https_resp);
//no resp?
free(notify_json);
return ret;
}
/***************************************************************/
//
//"1$esim.wo.cn$$1.3.6.1.4.1.47814.2.4"
//
/***************************************************************/
static char *parse_accode(char *activecode)
{
char *save = NULL;
char *host = NULL;
char *tmp = NULL;
tmp = strtok_r(activecode, "$", &save);
if (tmp == NULL)
return NULL;
tmp = strtok_r(NULL, "$", &save);
if (tmp == NULL)
return NULL;
host = malloc(APDU_RESP_LEN);
if (host == NULL)
return NULL;
memset(host, 0, APDU_RESP_LEN);
strncpy(host, tmp, APDU_RESP_LEN-1);
printf("server:%s\n", host);
return host;
}
static int downloadProfile(char *smdpAddress)
{
int res = -1;
char *authser_apdu = NULL;//auth server apdu
char *predl_apdu = NULL;//prepare download apdu
char *notify_apdu = NULL;//Notification apdu
int notify_res = -1;
int notify_check = -1;
//1 creat https
//2 get auth, send
res = lpa_connect_smdp(smdpAddress);
if (res != 0) {
res = -2;
goto download_END;
}
authser_apdu = lpa_initauth();
if (authser_apdu == NULL || strlen(authser_apdu) == 0) {
res = -2;
goto download_END;
}
predl_apdu = lpa_authclient(authser_apdu);
if (predl_apdu == NULL || strlen(predl_apdu) == 0) {
res = -2;
goto download_END;
}
notify_apdu = lpa_getbpp(predl_apdu);
if (notify_apdu == NULL || strlen(notify_apdu) == 0) {
res = -2;
goto download_END;
}
//dtest
#if 1
notify_res = lpa_notification(notify_apdu);
if (notify_res == -1) {
printf("lpa_notification fail\n");
//goto download_END;//skip, use updata result
}
#endif
notify_check = lpa_parse_iccid_apdu(notify_apdu, curent_iccid, sizeof(curent_iccid));
if (notify_check == -1)
goto download_END;
res = 0;
download_END:
if (authser_apdu != NULL)
free(authser_apdu);
if (predl_apdu != NULL)
free(predl_apdu);
if (notify_apdu != NULL)
free(notify_apdu);
lpa_disconn_smdp(smdpAddress);
return res;
}
/***************************************************************/
//
//ÊäÈ뼤»îÂ뷽ʽÏÂÔØprofile
//È·ÈÏÂëδÓà confirmcode = NULL
//
/***************************************************************/
int downloadProfileByAc(char *activecode, char *confirmcode)
{
int res = -1;
char *smdpAddress = NULL;
char dl_retry[6] = {0};
int count = 0;
int i = 0;
sc_cfg_get("lpa_dl_retry", dl_retry, sizeof(dl_retry));
count = atoi(dl_retry);
printf("lpa_updata_retry:%s,%d\n", dl_retry, count);
if (count <= 0 || count > 10) { //kw 3
count = 1;
}
smdpAddress = parse_accode(activecode);
if (smdpAddress == NULL)
return -1;
for (i = 0; i < count; i++) {
res = downloadProfile(smdpAddress);
if (res == -2 && i < count-1) {
//retry
sleep(SMDP_DL_INTERVAL);
continue;
}
break;
}
free(smdpAddress);
return res;
}
#if 0
int downloadProfileByEid(void)
{
int res = -1;
char *smdpAddress = "esim.wo.cn";//get from default
res = downloadProfile(smdpAddress);
return res;
}
#endif
/***************************************************************/
//
//ÆôÓÃprofile
//in: iccid 20
//
//parse 8001xx return xx:
//0£ºOK
//1£ºiccidOrAidNotFound£»
//2£ºprofileNotInDisabledState£»
//3£ºdisallowedByPolicy£»
//4£ºwrongProfileReenabling£»
//5£ºcatBusy£»
//127£ºundefinedError
//ÆäÓà·µ»ØÖµ²Î¿¼6.10½Ú
//
/***************************************************************/
int enableProfile(char *iccid)
{
char *apdu = NULL;
int res = 127;
apdu = EnableProfile(iccid);
if (apdu == NULL)
return 127;
errno = 0;
res = strtol(apdu, NULL, 16);
if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
{
printf("strtol errno %d: %s\n", errno, strerror(errno));
}
free(apdu);
return res;
}
/***************************************************************/
//
//½ûÓÃprofile
//
/***************************************************************/
int disableProfile(char * iccid)
{
char *apdu = NULL;
int res = 127;
apdu = DisableProfile(iccid);
if (apdu == NULL)
return 127;
errno = 0;
res = strtol(apdu, NULL, 16);
if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
{
printf("strtol errno %d: %s\n", errno, strerror(errno));
}
free(apdu);
return res;
}
/***************************************************************/
//
//ɾ³ýprofile
//
/***************************************************************/
int deleteProfile(char * iccid)
{
char *apdu = NULL;
int res = 127;
apdu = DeleteProfile(iccid);
if (apdu == NULL)
return 127;
errno = 0;
res = strtol(apdu, NULL, 16);
if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
{
printf("strtol errno %d: %s\n", errno, strerror(errno));
}
free(apdu);
return res;
}
int memoryReset(void)
{
char *apdu = NULL;
int res = 127;
apdu = EUICCMemoryReset();
if (apdu == NULL)
return 127;
errno = 0;
res = strtol(apdu, NULL, 16);
if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
{
printf("strtol errno %d: %s\n", errno, strerror(errno));
}
free(apdu);
return res;
}
//limit 10
static char *lap_parse_profile_list(char *pdu, int *list_n)
{
char *js_list = NULL;
char *profile = NULL;
char *iccid = NULL;
char *state = NULL;
int status = 0;
int i = 0;
char *tmp_pdu = pdu;
char *offset = NULL;
js_list = malloc(APDU_RESP_LEN);
if (js_list == NULL)
return NULL;
memset(js_list, 0, APDU_RESP_LEN);
while(i < 10 && strlen(tmp_pdu) > 0) {
profile = lpa_tag_apdu_from_atresp(tmp_pdu, 0xE3);
if (profile == NULL)
break;
iccid = lpa_tag_apdu_from_atresp(tmp_pdu, 0x5A);
if (iccid == NULL) {
free(profile);
break;
}
lpa_trans_iccid(iccid, strlen(iccid));
state = lpa_tag_apdu_from_atresp(tmp_pdu, 0x9F70);
if (state == NULL) {
free(profile);
free(iccid);
break;
}
errno = 0;
status = strtol(state, NULL, 16);
if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
{
printf("strtol errno %d: %s\n", errno, strerror(errno));
}
if (i == 0) {
snprintf(js_list, APDU_RESP_LEN,
"{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
}
else {
snprintf(js_list + strlen(js_list), APDU_RESP_LEN - strlen(js_list),
",{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
}
offset = strstr(tmp_pdu, profile);
if (offset == NULL) {
free(profile);
free(iccid);
free(state);
break;
}
tmp_pdu = offset + strlen(profile);
free(profile);
free(iccid);
free(state);
i++;
}
*list_n = i;
return js_list;
}
/***************************************************************/
//
//·µ»Ø¸öÊý£¬ºÍjson array[iccid, state]
//
/***************************************************************/
int getProfileList(char **info)
{
char *apdu = NULL;
int prof_num = 0;
apdu = GetProfilesInfo(NULL);
if (apdu == NULL)
return prof_num;
*info = lap_parse_profile_list(apdu, &prof_num);
free(apdu);
return prof_num;
}