/***************************************************************/ | |
// | |
//²Î¼û ÖйúÁªÍ¨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); | |
cfg_get_item("lpa_bpp_iccid", has_iccid, sizeof(has_iccid)); | |
if (strcmp(iccid, has_iccid) != 0) { | |
cfg_set("lpa_bpp_iccid", iccid); | |
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; | |
cfg_get_item("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; | |
} | |