| /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @file ql_sim_test.h  | 
 |   @brief SIM service API  | 
 | */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 |  | 
 | /*------------------------------------------------------------------------------------------------- | 
 |   Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved. | 
 |   mobiletek Wireless Solution Proprietary and Confidential. | 
 | -------------------------------------------------------------------------------------------------*/ | 
 |  | 
 | /*------------------------------------------------------------------------------------------------- | 
 |   EDIT HISTORY | 
 |   This section contains comments describing changes made to the file. | 
 |   Notice that changes are listed in reverse chronological order. | 
 |   $Header: $ | 
 |   when       who          what, where, why | 
 |   --------   ---------    ----------------------------------------------------------------- | 
 |   20241022    yq.wang      Created . | 
 | -------------------------------------------------------------------------------------------------*/ | 
 |  | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <stdlib.h> | 
 | #include <stdint.h> | 
 | #include "ql_type.h" | 
 | #include "ql_sim.h" | 
 | #include "ql_test_utils.h" | 
 |  | 
 |  | 
 | static void item_ql_sim_init(void) | 
 | { | 
 |     int ret = 0; | 
 |      | 
 |     printf("test ql_sim_init: "); | 
 |     ret = ql_sim_init(); | 
 |     if(ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_deinit(void) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     printf("test ql_sim_deinit: "); | 
 |     ret = ql_sim_deinit(); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_get_imsi(void) | 
 | { | 
 |     int ret = 0; | 
 |     char imsi[QL_SIM_IMSI_LENGTH+1] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |  | 
 |     printf("test ql_sim_get_imsi: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_get_imsi(slot, app_type, imsi, sizeof(imsi)); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("IMSI: %s\n", imsi); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_get_iccid(void) | 
 | { | 
 |     int ret = 0; | 
 |     char iccid[QL_SIM_ICCID_LENGTH+1] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |  | 
 |     printf("test ql_sim_get_iccid: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_get_iccid(slot, iccid, sizeof(iccid)); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ICCID: %s\n", iccid); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | static void item_ql_sim_get_phone_num(void) | 
 | { | 
 |     int ret = 0; | 
 |     char num[QL_SIM_PHONE_NUMBER_MAX+1] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |  | 
 |     printf("test ql_sim_get_phone_num: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     ret = ql_sim_get_phone_num(slot, app_type, num, sizeof(num)); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("Phone number: %s\n", num); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void print_ascii(char *prefix, char *postfix, char *ascii, int len) | 
 | { | 
 |     int i = 0; | 
 |     printf("%s", prefix); | 
 |     for (i = 0; i < len; i++) | 
 |     { | 
 |         putchar(ascii[i]); | 
 |     } | 
 |     printf("%s",  postfix); | 
 | } | 
 |  | 
 | static void item_ql_sim_get_operators(void) | 
 | { | 
 |     int ret = 0; | 
 |     ql_sim_operator_list_t list = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |  | 
 |     printf("test ql_sim_get_operators: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_get_operators(slot, &list); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         if (0 == list.len) | 
 |         { | 
 |             printf("No operators found\n"); | 
 |         } | 
 |         else | 
 |         { | 
 |             int i = 0; | 
 |             printf("found %d opertators:\n", list.len); | 
 |             for (i = 0; i < list.len; i++) | 
 |             { | 
 |                 printf(" #%02d: ", i + 1); | 
 |                 print_ascii("MCC: ", "", list.operators[i].mcc, (int)sizeof(list.operators[i].mcc)); | 
 |                 print_ascii(", MNC: ", "\n",list.operators[i].mnc, list.operators[i].mnc_len); | 
 |             } | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_enable_pin(void) | 
 | { | 
 |     int ret = 0; | 
 |     int len = 0; | 
 |     char c; | 
 |     char pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     QL_SIM_PIN_E pin; | 
 |  | 
 |     printf("test ql_sim_enable_pin: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter pin(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad pin: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter pin value(at most %d digit): ", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(pin_value, sizeof(pin_value), stdin)) | 
 |     { | 
 |         printf("can not read pin value\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(pin_value); | 
 |     if ('\n' == pin_value[len-1]) | 
 |     { | 
 |         pin_value[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     printf("pin value: %s\n", pin_value); | 
 |      | 
 |     printf("proceed? [y/n]: "); | 
 |     c = getchar(); | 
 |     if ('\n' != c) | 
 |     { | 
 |         getchar(); | 
 |     } | 
 |     if ('Y' != c && 'y' != c) | 
 |     { | 
 |         printf("abort\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_enable_pin(slot, app_type, pin, pin_value); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_disable_pin(void) | 
 | { | 
 |     int ret = 0; | 
 |     int len = 0; | 
 |     char c; | 
 |     char pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     QL_SIM_PIN_E pin; | 
 |  | 
 |     printf("test ql_sim_disable_pin: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter pin(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad pin: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter pin value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(pin_value, sizeof(pin_value), stdin)) | 
 |     { | 
 |         printf("can not read pin value\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(pin_value); | 
 |     if ('\n' == pin_value[len-1]) | 
 |     { | 
 |         pin_value[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     printf("pin value: %s\n", pin_value); | 
 |      | 
 |     printf("proceed? [y/n]: \n"); | 
 |     c = getchar(); | 
 |     if ('\n' != c) | 
 |     { | 
 |         getchar(); | 
 |     } | 
 |     if ('Y' != c && 'y' != c) | 
 |     { | 
 |         printf("abort\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_disable_pin(slot, app_type, pin, pin_value); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_verify_pin(void) | 
 | { | 
 |     int ret = 0; | 
 |     int len = 0; | 
 |     char c; | 
 |     char pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     QL_SIM_PIN_E pin; | 
 |  | 
 |     printf("test ql_sim_verify_pin: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter pin(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad pin: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter pin value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(pin_value, sizeof(pin_value), stdin)) | 
 |     { | 
 |         printf("can not read pin value\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(pin_value); | 
 |     if ('\n' == pin_value[len-1]) | 
 |     { | 
 |         pin_value[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     printf("pin value: %s\n", pin_value); | 
 |      | 
 |     printf("proceed? [y/n]: \n"); | 
 |     c = getchar(); | 
 |     if ('\n' != c) | 
 |     { | 
 |         getchar(); | 
 |     } | 
 |     if ('Y' != c && 'y' != c) | 
 |     { | 
 |         printf("abort\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_verify_pin(slot, app_type, pin, pin_value); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_change_pin(void) | 
 | { | 
 |     int ret = 0; | 
 |     int old_len = 0; | 
 |     int new_len = 0; | 
 |     char c; | 
 |     char old_pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     char new_pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     QL_SIM_PIN_E pin; | 
 |  | 
 |     printf("test ql_sim_change_pin: \n"); | 
 |     printf("please enter slot(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter pin(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad pin: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter old pin value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(old_pin_value, sizeof(old_pin_value), stdin)) | 
 |     { | 
 |         printf("can not read old pin value\n"); | 
 |         return; | 
 |     } | 
 |     old_len = strlen(old_pin_value); | 
 |     if ('\n' == old_pin_value[old_len-1]) | 
 |     { | 
 |         old_pin_value[old_len-1] = 0; | 
 |         old_len--; | 
 |     } | 
 |  | 
 |     printf("please enter new pin value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(new_pin_value, sizeof(new_pin_value), stdin)) | 
 |     { | 
 |         printf("can not read new pin value\n"); | 
 |         return; | 
 |     } | 
 |     new_len = strlen(new_pin_value); | 
 |     if ('\n' == new_pin_value[new_len-1]) | 
 |     { | 
 |         new_pin_value[new_len-1] = 0; | 
 |         new_len--; | 
 |     } | 
 |     printf("old pin value: %s\n", old_pin_value); | 
 |     printf("new pin value: %s\n", new_pin_value); | 
 |      | 
 |     printf("proceed? [y/n]: "); | 
 |     c = getchar(); | 
 |     if ('\n' != c) | 
 |     { | 
 |         getchar(); | 
 |     } | 
 |     if ('Y' != c && 'y' != c) | 
 |     { | 
 |         printf("abort\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_change_pin(slot, app_type, pin, old_pin_value, new_pin_value); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_unblock_pin(void) | 
 | { | 
 |     int ret = 0; | 
 |     int len = 0; | 
 |     int new_len = 0; | 
 |     char c; | 
 |     char puk_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     char new_pin_value[QL_SIM_PIN_MAX*2] = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     QL_SIM_PIN_E pin; | 
 |  | 
 |     printf("test ql_sim_unblock_pin: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter pin(1 or 2): \n"); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         pin = QL_SIM_PIN_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad pin: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter puk value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(puk_value, sizeof(puk_value), stdin)) | 
 |     { | 
 |         printf("can not read old pin value\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(puk_value); | 
 |     if ('\n' == puk_value[len-1]) | 
 |     { | 
 |         puk_value[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |  | 
 |     printf("please enter new pin value(at most %d digit): \n", QL_SIM_PIN_MAX); | 
 |     if (NULL == fgets(new_pin_value, sizeof(new_pin_value), stdin)) | 
 |     { | 
 |         printf("can not read new pin value\n"); | 
 |         return; | 
 |     } | 
 |     new_len = strlen(new_pin_value); | 
 |     if ('\n' == new_pin_value[new_len-1]) | 
 |     { | 
 |         new_pin_value[new_len-1] = 0; | 
 |         new_len--; | 
 |     } | 
 |     printf("    puk value: %s\n", puk_value); | 
 |     printf("new pin value: %s\n", new_pin_value); | 
 |      | 
 |     printf("proceed? [y/n]: "); | 
 |     c = getchar(); | 
 |     if ('\n' != c) | 
 |     { | 
 |         getchar(); | 
 |     } | 
 |     if ('Y' != c && 'y' != c) | 
 |     { | 
 |         printf("abort\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_unblock_pin(slot, app_type, pin, puk_value, new_pin_value); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static char *card_state_desc(QL_SIM_CARD_STATE_E state) | 
 | { | 
 |     switch (state) | 
 |     { | 
 |         case QL_SIM_CARD_STATE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_CARD_STATE_ABSENT: | 
 |             return "absent"; | 
 |         case QL_SIM_CARD_STATE_PRESENT: | 
 |             return "present"; | 
 |         case QL_SIM_CARD_STATE_ERROR_UNKNOWN: | 
 |             return "unknown error"; | 
 |         case QL_SIM_CARD_STATE_ERROR_POWER_DOWN: | 
 |             return "power down"; | 
 |         case QL_SIM_CARD_STATE_ERROR_POLL_ERROR: | 
 |             return "poll error"; | 
 |         case QL_SIM_CARD_STATE_ERROR_NO_ATR_RECEIVED: | 
 |             return "failed to receive an answer to reset"; | 
 |         case QL_SIM_CARD_STATE_ERROR_VOLT_MISMATCH: | 
 |             return "voltage mismatch"; | 
 |         case QL_SIM_CARD_STATE_ERROR_PARITY_ERROR: | 
 |             return "parity error"; | 
 |         case QL_SIM_CARD_STATE_ERROR_SIM_TECHNICAL_PROBLEMS: | 
 |             return "technical problems"; | 
 |         default: | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static char *card_type_desc(QL_SIM_CARD_TYPE_E type) | 
 | { | 
 |     switch (type) | 
 |     { | 
 |         case QL_SIM_CARD_TYPE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_CARD_TYPE_ICC: | 
 |             return "ICC"; | 
 |         case QL_SIM_CARD_TYPE_UICC: | 
 |             return "UICC"; | 
 |         default:  | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static char *card_subscription_desc(QL_SIM_SUBSCRIPTION_E subscription) | 
 | { | 
 |     switch (subscription) | 
 |     { | 
 |         case QL_SIM_SUBSCRIPTION_NONE: | 
 |             return "nonprovisioning"; | 
 |         case QL_SIM_SUBSCRIPTION_PRI: | 
 |             return "primary provisioning subscription"; | 
 |         case QL_SIM_SUBSCRIPTION_SEC: | 
 |             return "secondary provisioning subscription"; | 
 |         default: | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static char *card_app_state_desc(QL_SIM_APP_STATE_E state) | 
 | { | 
 |     switch (state) | 
 |     { | 
 |         case QL_SIM_APP_STATE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_APP_STATE_DETECTED: | 
 |             return "detected"; | 
 |         case QL_SIM_APP_STATE_PIN1_REQ: | 
 |             return "PIN1 required"; | 
 |         case QL_SIM_APP_STATE_PUK1_REQ: | 
 |             return "PUK1 required"; | 
 |         case QL_SIM_APP_STATE_INITALIZATING: | 
 |             return "initializing"; | 
 |         case QL_SIM_APP_STATE_PERSO_CK_REQ: | 
 |             return "personalization control key required"; | 
 |         case QL_SIM_APP_STATE_PERSO_PUK_REQ: | 
 |             return "personalization unblock key required"; | 
 |         case QL_SIM_APP_STATE_PERSO_PERMANENTLY_BLOCKED: | 
 |             return "personalization is permanently blocked"; | 
 |         case QL_SIM_APP_STATE_PIN1_PERM_BLOCKED: | 
 |             return "PIN1 is permanently blocked"; | 
 |         case QL_SIM_APP_STATE_ILLEGAL: | 
 |             return "illegal"; | 
 |         case QL_SIM_APP_STATE_READY: | 
 |             return "ready"; | 
 |         default: | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static char *card_perso_feature_desc(QL_SIM_PERSO_FEATURE_E feature) | 
 | { | 
 |     switch (feature) | 
 |     { | 
 |         case QL_SIM_PERSO_FEATURE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP_NETWORK: | 
 |             return "featurization based on 3GPP MCC and MNC"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP_NETWORK_SUBSET: | 
 |             return "featurization based on 3GPP MCC, MNC, and IMSI digits 6 and 7"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP_SERVICE_PROVIDER: | 
 |             return "featurization based on 3GPP MCC, MNC, and GID1"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP_CORPORATE: | 
 |             return "featurization based on 3GPP MCC, MNC, GID1, and GID2"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP_SIM: | 
 |             return "featurization based on the 3GPP IMSI"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP2_NETWORK_TYPE_1: | 
 |             return "featurization based on 3GPP2 MCC and MNC"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP2_NETWORK_TYPE_2: | 
 |             return "featurization based on 3GPP2 IRM code"; | 
 |         case QL_SIM_PERSO_FEATURE_3GPP2_RUIM: | 
 |             return "featurization based on 3GPP2 IMSI_M"; | 
 |         default: | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static char *card_pin_state_desc(QL_SIM_PIN_STATE_E state) | 
 | { | 
 |     switch (state) | 
 |     { | 
 |         case QL_SIM_PIN_STATE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_PIN_STATE_ENABLED_NOT_VERIFIED: | 
 |             return "PIN required, but has not been verified"; | 
 |         case QL_SIM_PIN_STATE_ENABLED_VERIFIED: | 
 |             return "PIN required and has been verified"; | 
 |         case QL_SIM_PIN_STATE_DISABLED: | 
 |             return "PIN not required"; | 
 |         case QL_SIM_PIN_STATE_BLOCKED: | 
 |             return "PIN verification has failed too many times and is blocked. " | 
 |                    "Recoverable through PUK verification"; | 
 |         case QL_SIM_PIN_STATE_PERMANENTLY_BLOCKED: | 
 |             return "PUK verification has failed too many times and is not recoverable"; | 
 |         default: | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | static void item_ql_sim_get_card_info(void) | 
 | { | 
 |     int ret = 0; | 
 |     ql_sim_card_info_t info = {0}; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |  | 
 |     printf("test ql_sim_get_card_info: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_get_card_info(slot, &info); | 
 |     if (ret != QL_ERR_OK) | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |         return; | 
 |     } | 
 |     printf("========= CARD INFO =========\n"); | 
 |     printf("state: %s\n", card_state_desc(info.state)); | 
 |     printf("type: %s\n", card_type_desc(info.type)); | 
 |     printf("3gpp:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(info.app_3gpp.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", info.app_3gpp.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", info.app_3gpp.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", info.app_3gpp.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", info.app_3gpp.puk2_num_retries); | 
 |     printf("3gpp2:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(info.app_3gpp2.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", info.app_3gpp2.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", info.app_3gpp2.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", info.app_3gpp2.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", info.app_3gpp2.puk2_num_retries); | 
 |     printf("isim:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(info.app_isim.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", info.app_isim.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", info.app_isim.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", info.app_isim.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", info.app_isim.puk2_num_retries); | 
 | } | 
 |  | 
 | #if 0 | 
 | static void item_ql_sim_read_file(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     int len = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     ql_sim_file_t file = {0}; | 
 |  | 
 |     printf("test ql_sim_read_file: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX); | 
 |     if (NULL == fgets(file.path, QL_SIM_PATH_MAX, stdin)) | 
 |     { | 
 |         printf("can not read file path\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(file.path); | 
 |     if ('\n' == file.path[len-1]) | 
 |     { | 
 |         file.path[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     file.path_len = (uint32_t)len; | 
 |  | 
 |     printf("please enter record index(0 for transparent access): "); | 
 |     scanf("%hhu", (uint8_t *)&file.record_idx); | 
 |     getchar(); | 
 |      | 
 |     ret = ql_sim_read_file(slot, app_type, &file); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("data length: %u\n", file.data_len); | 
 |         uint32_t i = 0; | 
 |         printf("data: "); | 
 |         for (i = 0; i < file.data_len; i++) | 
 |         { | 
 |             printf("%02x ", file.data[i]); | 
 |         } | 
 |         printf("\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_write_file(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     int len = 0; | 
 |     uint8_t v; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     ql_sim_file_t file = {0}; | 
 |  | 
 |     printf("test ql_sim_write_file: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX); | 
 |     if (NULL == fgets(file.path, QL_SIM_PATH_MAX, stdin)) | 
 |     { | 
 |         printf("can not read file path\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(file.path); | 
 |     if ('\n' == file.path[len-1]) | 
 |     { | 
 |         file.path[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     file.path_len = (uint32_t)len; | 
 |  | 
 |     printf("please enter record index(0 for transparent access): "); | 
 |     scanf("%hhu", (uint8_t *)&file.record_idx); | 
 |     getchar(); | 
 |  | 
 |     printf("please enter data(hex, end with `q'): "); | 
 |     while (1 == scanf("%hhx", &v)) | 
 |     { | 
 |         file.data[file.data_len++] = v; | 
 |     } | 
 |     getchar();  // read `q' | 
 |     getchar();  // read '\n' | 
 |      | 
 |     printf("please enter data offset: "); | 
 |     scanf("%hu", &file.offset); | 
 |     getchar(); | 
 |      | 
 |     ret = ql_sim_write_file(slot, app_type, &file); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static char *file_type_desc(QL_SIM_FILE_TYPE_E type) | 
 | { | 
 |     switch (type) | 
 |     { | 
 |         case QL_SIM_FILE_TYPE_UNKNOWN: | 
 |             return "unknown"; | 
 |         case QL_SIM_FILE_TYPE_TRANSPARENT: | 
 |             return "transparent"; | 
 |         case QL_SIM_FILE_TYPE_CYCLIC: | 
 |             return "cyclic"; | 
 |         case QL_SIM_FILE_TYPE_LINEAR_FIXED: | 
 |             return "linear fixed"; | 
 |         default:  | 
 |             return "N/A"; | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_get_file_info(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     int len = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     ql_sim_file_info_t info = {0}; | 
 |  | 
 |     printf("test ql_sim_get_file_info: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX); | 
 |     if (NULL == fgets(info.path, QL_SIM_PATH_MAX, stdin)) | 
 |     { | 
 |         printf("can not read file path\n"); | 
 |         return; | 
 |     } | 
 |     len = strlen(info.path); | 
 |     if ('\n' == info.path[len-1]) | 
 |     { | 
 |         info.path[len-1] = 0; | 
 |         len--; | 
 |     } | 
 |     info.path_len = (uint32_t)len; | 
 |      | 
 |     ret = ql_sim_get_file_info(slot, app_type, &info); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("========= FILE INFO =========\n"); | 
 |         printf("path: %s\n", info.path); | 
 |         printf("type: %s\n", file_type_desc(info.file_type)); | 
 |         printf("file size: %hu\n", info.file_size); | 
 |         printf("record size: %hu\n", info.record_size); | 
 |         printf("record count: %hu\n", info.record_count); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_read_phone_book(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     uint8_t record_idx = 0; | 
 |     ql_sim_phone_book_record_t record; | 
 |  | 
 |     memset(&record,0,sizeof(ql_sim_phone_book_record_t)); | 
 |     printf("test ql_sim_read_phone_book: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter record index: "); | 
 |     scanf("%hhu", &record_idx); | 
 |     getchar(); | 
 |      | 
 |      | 
 |     ret = ql_sim_read_phone_book(slot, app_type, QL_SIM_PB_DEFAULT_PATH, record_idx, &record); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("Name: %s\n", record.name); | 
 |         printf("Number: %s\n", record.number); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_write_phone_book(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     int len = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     QL_SIM_APP_TYPE_E app_type; | 
 |     uint8_t record_idx = 0; | 
 |     ql_sim_phone_book_record_t record; | 
 |  | 
 |     memset(&record,0,sizeof(ql_sim_phone_book_record_t)); | 
 |     printf("test ql_sim_write_phone_book: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     switch (input) | 
 |     { | 
 |         case 0: | 
 |             app_type = QL_SIM_APP_TYPE_UNKNOWN; | 
 |             break; | 
 |         case 1: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP; | 
 |             break; | 
 |         case 2: | 
 |             app_type = QL_SIM_APP_TYPE_3GPP2; | 
 |             break; | 
 |         case 3: | 
 |             app_type = QL_SIM_APP_TYPE_ISIM; | 
 |             break; | 
 |         default: | 
 |             printf("bad app type: %d\n", input); | 
 |             return; | 
 |     } | 
 |  | 
 |     printf("please enter record index: "); | 
 |     scanf("%hhu", &record_idx); | 
 |     getchar(); | 
 |  | 
 |     printf("please enter name(at most %d chars): ", QL_SIM_PHONE_BOOK_NAME_MAX - 1); | 
 |     if (NULL == fgets(record.name, QL_SIM_PHONE_BOOK_NAME_MAX, stdin)) | 
 |     { | 
 |         printf("\nname will be set to 0\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         len = strlen(record.name); | 
 |         if ('\n' == record.name[len-1]) | 
 |         { | 
 |             record.name[len-1] = 0; | 
 |         } | 
 |     } | 
 |      | 
 |  | 
 |     printf("please enter number(at most %d digits): ", QL_SIM_PHONE_BOOK_NUMBER_MAX - 1); | 
 |     if (NULL == fgets(record.number, QL_SIM_PHONE_BOOK_NUMBER_MAX, stdin)) | 
 |     { | 
 |         printf("\nnumber will be set to 0\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         len = strlen(record.number); | 
 |         if ('\n' == record.number[len-1]) | 
 |         { | 
 |             record.number[len-1] = 0; | 
 |         } | 
 |     } | 
 |      | 
 |     ret = ql_sim_write_phone_book(slot, app_type, QL_SIM_PB_DEFAULT_PATH, record_idx, &record); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_open_logical_channel(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     uint8_t channel_id = 0; | 
 |  | 
 |     printf("test ql_sim_open_logical_channel: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |      | 
 |     ret = ql_sim_open_logical_channel(slot, &channel_id); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("channel id: %hhu\n", channel_id); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_close_logical_channel(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     uint8_t channel_id = 0; | 
 |  | 
 |     printf("test ql_sim_close_logical_channel: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter channel id: "); | 
 |     scanf("%hhu", &channel_id); | 
 |     getchar(); | 
 |      | 
 |     ret = ql_sim_close_logical_channel(slot, channel_id); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | static void item_ql_sim_send_apdu(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     uint8_t v = 0; | 
 |     QL_SIM_SLOT_E slot; | 
 |     ql_sim_apdu_t *p_apdu = NULL; | 
 |     uint8_t channel_id = 0; | 
 |  | 
 |     printf("test ql_sim_send_apdu: \n"); | 
 |  | 
 |     p_apdu = calloc(1, sizeof(*p_apdu)); | 
 |     if (NULL == p_apdu) | 
 |     { | 
 |         printf("run out of memory\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         slot = QL_SIM_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         free(p_apdu); | 
 |         p_apdu = NULL; | 
 |         return; | 
 |     } | 
 |  | 
 |     printf("please enter channel id: "); | 
 |     scanf("%hhu", &channel_id); | 
 |     getchar(); | 
 |  | 
 |     printf("please enter apdu data(hex, end with `q'): "); | 
 |     while (1 == scanf("%hhx", &v)) | 
 |     { | 
 |         p_apdu->req_apdu[p_apdu->req_apdu_len++] = v; | 
 |     } | 
 |     getchar();  // read `q' | 
 |     getchar();  // read '\n' | 
 |      | 
 |     ret = ql_sim_send_apdu(slot, channel_id, p_apdu); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         uint32_t i = 0; | 
 |         printf("repsonse apdu: "); | 
 |         for (i = 0; i < p_apdu->resp_apdu_len; i++) | 
 |         { | 
 |             printf("%c", p_apdu->resp_apdu[i]); | 
 |         } | 
 |         printf("\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 |     free(p_apdu); | 
 |     p_apdu = NULL; | 
 | } | 
 | #endif | 
 |  | 
 | static void sim_card_status_cb(int slot, ql_sim_card_info_t *p_info) | 
 | { | 
 |     printf("========= CARD STATUS =========\n"); | 
 |     switch (slot) | 
 |     { | 
 |         case 0: | 
 |             printf("slot: invalid\n"); | 
 |             break; | 
 |         case 1: | 
 |             printf("slot: 1\n"); | 
 |             break; | 
 |         case 2: | 
 |             printf("slot: 2\n"); | 
 |             break; | 
 |     } | 
 |      | 
 |     if (NULL == p_info) | 
 |     { | 
 |         printf("status: unavailable\n"); | 
 |         return; | 
 |     } | 
 |      | 
 |     printf("state: %s\n", card_state_desc(p_info->state)); | 
 |     printf("type: %s\n", card_type_desc(p_info->type)); | 
 |     printf("3gpp:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(p_info->app_3gpp.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", p_info->app_3gpp.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", p_info->app_3gpp.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", p_info->app_3gpp.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", p_info->app_3gpp.puk2_num_retries); | 
 |     printf("3gpp2:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(p_info->app_3gpp2.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", p_info->app_3gpp2.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", p_info->app_3gpp2.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", p_info->app_3gpp2.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", p_info->app_3gpp2.puk2_num_retries); | 
 |     printf("isim:\n"); | 
 |     printf(" app state: %s\n", card_app_state_desc(p_info->app_isim.app_state)); | 
 |     printf(" PIN 1 retries: %hhu\n", p_info->app_isim.pin1_num_retries); | 
 |     printf(" PUK 1 retries: %hhu\n", p_info->app_isim.puk1_num_retries); | 
 |     printf(" PIN 2 retries: %hhu\n", p_info->app_isim.pin2_num_retries); | 
 |     printf(" PUK 2 retries: %hhu\n", p_info->app_isim.puk2_num_retries); | 
 | } | 
 |  | 
 | static void item_ql_sim_set_card_status_cb(void) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     printf("test ql_sim_set_card_status_cb: "); | 
 |     ret = ql_sim_set_card_status_cb((ql_sim_card_status_cb_f)sim_card_status_cb); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | void sim_servicie_error_cb(int error) | 
 | { | 
 |     printf("===== SIM Service Abort =====\n"); | 
 | } | 
 |  | 
 | void item_ql_sim_set_service_error_cb(void) | 
 | { | 
 |     int ret = 0; | 
 |     printf("test ql_sim_set_service_error_cb: \n"); | 
 |  | 
 |     ret = ql_sim_set_service_error_cb(sim_servicie_error_cb); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | #if 0 | 
 | void item_ql_sim_switch_slot(void) | 
 | { | 
 |     int ret = 0; | 
 |     int input = 0; | 
 |     QL_SIM_PHY_SLOT_E phy_slot = 0; | 
 |     printf("test item_ql_sim_switch_slot: \n"); | 
 |     printf("please enter slot(1 or 2): "); | 
 |     scanf("%d", &input); | 
 |     getchar(); | 
 |     if (1 == input) | 
 |     { | 
 |         phy_slot = QL_SIM_PHY_SLOT_1; | 
 |     } | 
 |     else if (2 == input) | 
 |     { | 
 |         phy_slot = QL_SIM_PHY_SLOT_2; | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("bad slot: %d\n", input); | 
 |         return; | 
 |     } | 
 |     ret = ql_sim_switch_slot(QL_SIM_SLOT_1, phy_slot); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 | } | 
 |  | 
 | void item_ql_sim_get_active_slots(void) | 
 | { | 
 |     int ret = 0; | 
 |     ql_sim_active_slots_t *p_active_slots = (ql_sim_active_slots_t *)malloc(sizeof(ql_sim_active_slots_t)); | 
 |     if (p_active_slots == NULL) {   | 
 |         printf("Memory allocation failed.\n");   | 
 |         return -1;   | 
 |     } | 
 |     p_active_slots->active_slots_len = 0; | 
 |     p_active_slots->active_slots[0] = 0; | 
 |     printf("test item_ql_sim_get_active_slots: \n"); | 
 |     ret = ql_sim_get_active_slots(p_active_slots); | 
 |     if (ret == QL_ERR_OK) | 
 |     { | 
 |         printf("ok\n"); | 
 | 	printf("p_active_slots(QL_SIM_PHY_SLOT_1/2 = B01/B02) = %X \n",p_active_slots->active_slots[0]); | 
 |     } | 
 |     else | 
 |     { | 
 |         printf("failed, ret = %d\n", ret); | 
 |     } | 
 |     free(p_active_slots); | 
 | } | 
 | #endif | 
 |  | 
 | static t_item_t ql_sim_items[] = | 
 | { | 
 |     {"ql_sim_init", item_ql_sim_init}, | 
 |     {"ql_sim_get_imsi", item_ql_sim_get_imsi}, | 
 |     {"ql_sim_get_iccid", item_ql_sim_get_iccid}, | 
 |     {"ql_sim_get_phone_num", item_ql_sim_get_phone_num}, | 
 |     {"ql_sim_get_operators", item_ql_sim_get_operators}, | 
 |     {"ql_sim_enable_pin", item_ql_sim_enable_pin}, | 
 |     {"ql_sim_disable_pin", item_ql_sim_disable_pin}, | 
 |     {"ql_sim_verify_pin", item_ql_sim_verify_pin}, | 
 |     {"ql_sim_change_pin", item_ql_sim_change_pin}, | 
 |     {"ql_sim_unblock_pin", item_ql_sim_unblock_pin}, | 
 |     {"ql_sim_get_card_info", item_ql_sim_get_card_info}, | 
 | //    {"ql_sim_read_file", item_ql_sim_read_file}, | 
 | //    {"ql_sim_write_file", item_ql_sim_write_file}, | 
 | //    {"ql_sim_get_file_info", item_ql_sim_get_file_info}, | 
 | //    {"ql_sim_read_phone_book", item_ql_sim_read_phone_book}, | 
 | //   {"ql_sim_write_phone_book", item_ql_sim_write_phone_book}, | 
 | //    {"ql_sim_open_logical_channel", item_ql_sim_open_logical_channel}, | 
 | //    {"ql_sim_close_logical_channel", item_ql_sim_close_logical_channel}, | 
 | //    {"ql_sim_send_apdu", item_ql_sim_send_apdu}, | 
 |     {"ql_sim_set_card_status_cb", item_ql_sim_set_card_status_cb}, | 
 |     {"ql_sim_set_service_error_cb", item_ql_sim_set_service_error_cb}, | 
 | //    {"ql_sim_switch_slot", item_ql_sim_switch_slot}, | 
 | //    {"ql_sim_get_active_slots", item_ql_sim_get_active_slots}, | 
 |     {"ql_sim_deinit", item_ql_sim_deinit}, | 
 | }; | 
 |  | 
 | t_module_t ql_sim_module = | 
 | { | 
 |     "sim", | 
 |     T_ARRAY_SIZE(ql_sim_items), | 
 |     ql_sim_items | 
 | }; | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /**  | 
 |   @brief Read a int value from stdin  | 
 |   @param[out] val, Return read data | 
 |   @return  | 
 |   0 - successful | 
 |   1 - read an enter  | 
 |   -1 - invalid input | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int t_get_int(int *val) | 
 | { | 
 |     int dat; | 
 |     char *ptr_end = NULL; | 
 |     char buf[256] = {0}; | 
 |  | 
 |     if(NULL == fgets(buf, sizeof(buf)-1, stdin)) | 
 |     { | 
 |         return -1; | 
 |     } | 
 | #if 0     | 
 |     if(0 == buf[0]) | 
 |     { | 
 |         return -1; | 
 |     } | 
 | #endif | 
 |     if(buf[0] == '\n') | 
 |     { | 
 |         return 1; | 
 |     } | 
 |  | 
 |     dat = strtol(buf, &ptr_end, 10); | 
 |     if(ptr_end!=NULL && ptr_end[0]!='\n') | 
 |     { | 
 |         return -1; | 
 |     } | 
 |  | 
 |     if(val) | 
 |     { | 
 |         val[0] = dat; | 
 |     } | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 | void dump_items() | 
 | { | 
 |     int i; | 
 |  | 
 |     printf("\n"); | 
 |     printf("The current module is: \n"); | 
 |  | 
 |     for(i=0; i< ql_sim_module.item_len; i++) | 
 |     { | 
 |         printf("%d\t%s\n", i, ql_sim_module.item_list[i].name); | 
 |     } | 
 |     printf("-1\texit\n"); | 
 | } | 
 |  | 
 | int main(int argc, char *argv[]) | 
 | { | 
 |     int ret; | 
 |     int idx; | 
 |  | 
 |     dump_items(); | 
 |  | 
 |     while(1) | 
 |     { | 
 |         printf("Please enter your choice: "); | 
 |         ret = t_get_int(&idx); | 
 |         printf("\n"); | 
 |         if(ret < 0) | 
 |         { | 
 |             printf("Invalid input\n"); | 
 |             continue; | 
 |         } | 
 |         else if(ret == 1) | 
 |         { | 
 |             dump_items(); | 
 |             continue; | 
 |         } | 
 |  | 
 |         if(idx == -1) | 
 |         { | 
 |             break; | 
 |         } | 
 |  | 
 |         if(idx<0 || idx>=ql_sim_module.item_len) | 
 |         { | 
 |             printf("Not support idx: %d\n", idx); | 
 |             continue; | 
 |         } | 
 |  | 
 |         printf("->Item : %s\n", ql_sim_module.item_list[idx].name); | 
 |         ql_sim_module.item_list[idx].handle(); | 
 |     } | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 |  | 
 |  |