diff options
-rw-r--r-- | data/qmi-service-uim.json | 52 | ||||
-rw-r--r-- | docs/reference/libqmi-glib/libqmi-glib-common.sections | 5 | ||||
-rw-r--r-- | docs/reference/libqmi-glib/libqmi-glib-docs.xml | 1 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-enums-uim.h | 21 | ||||
-rw-r--r-- | src/qmicli/qmicli-dms.c | 8 | ||||
-rw-r--r-- | src/qmicli/qmicli-helpers.c | 31 | ||||
-rw-r--r-- | src/qmicli/qmicli-helpers.h | 4 | ||||
-rw-r--r-- | src/qmicli/qmicli-uim.c | 118 |
8 files changed, 232 insertions, 8 deletions
diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json index 6b38f2a..8ad0cd9 100644 --- a/data/qmi-service-uim.json +++ b/data/qmi-service-uim.json @@ -292,6 +292,58 @@ "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, // ********************************************************************************* + { "name" : "Set PIN Protection", + "type" : "Message", + "service" : "UIM", + "id" : "0x0025", + "version" : "1.0", + "input" : [ { "name" : "Session Information", + "id" : "0x01", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Session Type", + "format" : "guint8", + "public-format" : "QmiUimSessionType" }, + { "name" : "Application Identifier", + "format" : "string" } ] }, + { "name" : "Info", + "id" : "0x02", + "mandatory" : "yes", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "PIN ID", + "format" : "guint8", + "public-format" : "QmiUimPinId" }, + { "name" : "PIN enabled", + "format" : "guint8", + "public-format" : "gboolean" }, + { "name" : "PIN Value", + "format" : "string" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x11", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Retries Remaining", + "id" : "0x10", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "Verify Retries Left", + "format" : "guint8" }, + { "name" : "Unblock Retries Left", + "format" : "guint8" } ], + "prerequisites": [ { "common-ref" : "No Success" } ] }, + { "name" : "Response In Indication Token", + "id" : "0x12", + "mandatory" : "no", + "type" : "TLV", + "format" : "guint32", + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* { "name" : "Get Card Status", "type" : "Message", "service" : "UIM", diff --git a/docs/reference/libqmi-glib/libqmi-glib-common.sections b/docs/reference/libqmi-glib/libqmi-glib-common.sections index d45aeb9..1b0ab6d 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-common.sections +++ b/docs/reference/libqmi-glib/libqmi-glib-common.sections @@ -755,6 +755,7 @@ QmiUimCardApplicationType QmiUimCardApplicationState QmiUimCardApplicationPersonalizationState QmiUimCardApplicationPersonalizationFeature +QmiUimPinId <SUBSECTION Methods> qmi_uim_session_type_get_string qmi_uim_file_type_get_string @@ -767,6 +768,7 @@ qmi_uim_card_application_type_get_string qmi_uim_card_application_state_get_string qmi_uim_card_application_personalization_state_get_string qmi_uim_card_application_personalization_feature_get_string +qmi_uim_pin_id_get_string <SUBSECTION Private> qmi_uim_session_type_build_string_from_mask qmi_uim_file_type_build_string_from_mask @@ -779,6 +781,7 @@ qmi_uim_card_application_type_build_string_from_mask qmi_uim_card_error_build_string_from_mask qmi_uim_card_state_build_string_from_mask qmi_uim_pin_state_build_string_from_mask +qmi_uim_pin_id_build_string_from_mask <SUBSECTION Standard> QMI_TYPE_UIM_SESSION_TYPE QMI_TYPE_UIM_FILE_TYPE @@ -791,6 +794,7 @@ QMI_TYPE_UIM_CARD_APPLICATION_TYPE QMI_TYPE_UIM_CARD_ERROR QMI_TYPE_UIM_CARD_STATE QMI_TYPE_UIM_PIN_STATE +QMI_TYPE_UIM_PIN_ID qmi_uim_session_type_get_type qmi_uim_file_type_get_type qmi_uim_security_attribute_logic_get_type @@ -802,6 +806,7 @@ qmi_uim_card_application_type_get_type qmi_uim_card_error_get_type qmi_uim_card_state_get_type qmi_uim_pin_state_get_type +qmi_uim_pin_id_get_type </SECTION> <SECTION> diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml index e753fc2..8159b26 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml +++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml @@ -247,6 +247,7 @@ <section> <title>UIM Requests</title> <xi:include href="xml/qmi-message-uim-reset.xml"/> + <xi:include href="xml/qmi-message-uim-set-pin-protection.xml"/> <xi:include href="xml/qmi-message-uim-read-transparent.xml"/> <xi:include href="xml/qmi-message-uim-read-record.xml"/> <xi:include href="xml/qmi-message-uim-get-file-attributes.xml"/> diff --git a/src/libqmi-glib/qmi-enums-uim.h b/src/libqmi-glib/qmi-enums-uim.h index 35b8f73..58ea549 100644 --- a/src/libqmi-glib/qmi-enums-uim.h +++ b/src/libqmi-glib/qmi-enums-uim.h @@ -122,6 +122,27 @@ typedef enum { } QmiUimSecurityAttribute; /*****************************************************************************/ +/* Helper enums for the 'QMI UIM Set PIN Protection' */ + +/** + * QmiUimPinId: + * @QMI_UIM_PIN_ID_UNKNOWN: Unknown. + * @QMI_UIM_PIN_ID_PIN1: PIN1. + * @QMI_UIM_PIN_ID_PIN2: PIN2. + * @QMI_UIM_PIN_ID_UPIN: UPIN. + * @QMI_UIM_PIN_ID_HIDDEN_KEY: Hidden key. + * + * PIN ID. + */ +typedef enum { + QMI_UIM_PIN_ID_UNKNOWN = 0, + QMI_UIM_PIN_ID_PIN1 = 1, + QMI_UIM_PIN_ID_PIN2 = 2, + QMI_UIM_PIN_ID_UPIN = 3, + QMI_UIM_PIN_ID_HIDDEN_KEY = 4 +} QmiUimPinId; + +/*****************************************************************************/ /* Helper enums for the 'QMI UIM Get Card Status' request/response */ /** diff --git a/src/qmicli/qmicli-dms.c b/src/qmicli/qmicli-dms.c index c53aca5..5d080eb 100644 --- a/src/qmicli/qmicli-dms.c +++ b/src/qmicli/qmicli-dms.c @@ -685,7 +685,7 @@ uim_set_pin_protection_input_create (const gchar *str) * "[(PIN|PIN2),(disable|enable),(current PIN)]" */ split = g_strsplit (str, ",", -1); - if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + if (qmicli_read_dms_uim_pin_id_from_string (split[0], &pin_id) && qmicli_read_enable_disable_from_string (split[1], &enable_disable) && qmicli_read_non_empty_string (split[2], "current PIN", ¤t_pin)) { GError *error = NULL; @@ -769,7 +769,7 @@ uim_verify_pin_input_create (const gchar *str) * "[(PIN|PIN2),(current PIN)]" */ split = g_strsplit (str, ",", -1); - if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + if (qmicli_read_dms_uim_pin_id_from_string (split[0], &pin_id) && qmicli_read_non_empty_string (split[1], "current PIN", ¤t_pin)) { GError *error = NULL; @@ -852,7 +852,7 @@ uim_unblock_pin_input_create (const gchar *str) * "[(PIN|PIN2),(PUK),(new PIN)]" */ split = g_strsplit (str, ",", -1); - if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + if (qmicli_read_dms_uim_pin_id_from_string (split[0], &pin_id) && qmicli_read_non_empty_string (split[1], "PUK", &puk) && qmicli_read_non_empty_string (split[2], "new PIN", &new_pin)) { GError *error = NULL; @@ -937,7 +937,7 @@ uim_change_pin_input_create (const gchar *str) * "[(PIN|PIN2),(old PIN),(new PIN)]" */ split = g_strsplit (str, ",", -1); - if (qmicli_read_pin_id_from_string (split[0], &pin_id) && + if (qmicli_read_dms_uim_pin_id_from_string (split[0], &pin_id) && qmicli_read_non_empty_string (split[1], "old PIN", &old_pin) && qmicli_read_non_empty_string (split[2], "new PIN", &new_pin)) { GError *error = NULL; diff --git a/src/qmicli/qmicli-helpers.c b/src/qmicli/qmicli-helpers.c index 511adf5..205f319 100644 --- a/src/qmicli/qmicli-helpers.c +++ b/src/qmicli/qmicli-helpers.c @@ -105,8 +105,8 @@ qmicli_get_raw_data_printable (const GArray *data, } gboolean -qmicli_read_pin_id_from_string (const gchar *str, - QmiDmsUimPinId *out) +qmicli_read_dms_uim_pin_id_from_string (const gchar *str, + QmiDmsUimPinId *out) { if (!str || str[0] == '\0') { g_printerr ("error: expected 'PIN' or 'PIN2', got: none\n"); @@ -128,6 +128,33 @@ qmicli_read_pin_id_from_string (const gchar *str, } gboolean +qmicli_read_uim_pin_id_from_string (const gchar *str, + QmiUimPinId *out) +{ + if (!str || str[0] == '\0') { + g_printerr ("error: expected 'PIN1', 'PIN2' or 'UPIN', got: none\n"); + return FALSE; + } + + if (g_str_equal (str, "PIN1")) { + *out = QMI_UIM_PIN_ID_PIN1; + return TRUE; + } + + if (g_str_equal (str, "PIN2")) { + *out = QMI_UIM_PIN_ID_PIN2; + return TRUE; + } + if (g_str_equal (str, "UPIN")) { + *out = QMI_UIM_PIN_ID_UPIN; + return TRUE; + } + + g_printerr ("error: expected 'PIN1', 'PIN2' or 'UPIN', got: '%s'\n", str); + return FALSE; +} + +gboolean qmicli_read_operating_mode_from_string (const gchar *str, QmiDmsOperatingMode *out) { diff --git a/src/qmicli/qmicli-helpers.h b/src/qmicli/qmicli-helpers.h index 1dcb95c..1a2a78c 100644 --- a/src/qmicli/qmicli-helpers.h +++ b/src/qmicli/qmicli-helpers.h @@ -30,8 +30,10 @@ gchar *qmicli_get_raw_data_printable (const GArray *data, gsize max_line_length, const gchar *new_line_prefix); -gboolean qmicli_read_pin_id_from_string (const gchar *str, +gboolean qmicli_read_dms_uim_pin_id_from_string (const gchar *str, QmiDmsUimPinId *out); +gboolean qmicli_read_uim_pin_id_from_string (const gchar *str, + QmiUimPinId *out); gboolean qmicli_read_operating_mode_from_string (const gchar *str, QmiDmsOperatingMode *out); gboolean qmicli_read_rat_mode_pref_from_string (const gchar *str, diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c index c350474..e7276eb 100644 --- a/src/qmicli/qmicli-uim.c +++ b/src/qmicli/qmicli-uim.c @@ -43,6 +43,7 @@ static Context *ctx; /* Options */ static gchar *read_transparent_str; +static gchar *set_pin_protection_str; static gchar *get_file_attributes_str; static gboolean get_card_status_flag; static gboolean get_supported_messages_flag; @@ -50,6 +51,10 @@ static gboolean reset_flag; static gboolean noop_flag; static GOptionEntry entries[] = { + { "uim-set-pin-protection", 0, 0, G_OPTION_ARG_STRING, &set_pin_protection_str, + "Set PIN protection", + "[(PIN1|PIN2|UPIN),(disable|enable),(current PIN)]" + }, { "uim-read-transparent", 0, 0, G_OPTION_ARG_STRING, &read_transparent_str, "Read a transparent file given the file path", "[0xNNNN,0xNNNN,...]" @@ -101,7 +106,8 @@ qmicli_uim_options_enabled (void) if (checked) return !!n_actions; - n_actions = (!!read_transparent_str + + n_actions = (!!set_pin_protection_str + + !!read_transparent_str + !!get_file_attributes_str + get_card_status_flag + get_supported_messages_flag + @@ -138,6 +144,96 @@ operation_shutdown (gboolean operation_status) qmicli_async_operation_done (operation_status); } +static QmiMessageUimSetPinProtectionInput * +set_pin_protection_input_create (const gchar *str) +{ + QmiMessageUimSetPinProtectionInput *input = NULL; + gchar **split; + QmiUimPinId pin_id; + gboolean enable_disable; + gchar *current_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN1|PIN2|UPIN),(disable|enable),(current PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_uim_pin_id_from_string (split[0], &pin_id) && + qmicli_read_enable_disable_from_string (split[1], &enable_disable) && + qmicli_read_non_empty_string (split[2], "current PIN", ¤t_pin)) { + GError *error = NULL; + + input = qmi_message_uim_set_pin_protection_input_new (); + if (!qmi_message_uim_set_pin_protection_input_set_info ( + input, + pin_id, + enable_disable, + current_pin, + &error) || + !qmi_message_uim_set_pin_protection_input_set_session_information ( + input, + QMI_UIM_SESSION_TYPE_CARD_SLOT_1, + "", /* ignored */ + &error)) { + g_printerr ("error: couldn't create input data bundle: '%s'\n", + error->message); + g_error_free (error); + qmi_message_uim_set_pin_protection_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +set_pin_protection_ready (QmiClientUim *client, + GAsyncResult *res) +{ + QmiMessageUimSetPinProtectionOutput *output; + GError *error = NULL; + + output = qmi_client_uim_set_pin_protection_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + g_error_free (error); + operation_shutdown (FALSE); + return; + } + + if (!qmi_message_uim_set_pin_protection_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't set PIN protection: %s\n", error->message); + g_error_free (error); + + if (qmi_message_uim_set_pin_protection_output_get_retries_remaining ( + output, + &verify_retries_left, + &unblock_retries_left, + NULL)) { + g_printerr ("[%s] Retries left:\n" + "\tVerify: %u\n" + "\tUnblock: %u\n", + qmi_device_get_path_display (ctx->device), + verify_retries_left, + unblock_retries_left); + } + + qmi_message_uim_set_pin_protection_output_unref (output); + operation_shutdown (FALSE); + return; + } + + g_print ("[%s] PIN protection updated\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_uim_set_pin_protection_output_unref (output); + operation_shutdown (TRUE); +} + static void get_supported_messages_ready (QmiClientUim *client, GAsyncResult *res) @@ -690,6 +786,26 @@ qmicli_uim_run (QmiDevice *device, ctx->client = g_object_ref (client); ctx->cancellable = g_object_ref (cancellable); + /* Set PIN protection */ + if (set_pin_protection_str) { + QmiMessageUimSetPinProtectionInput *input; + + g_debug ("Asynchronously setting PIN protection..."); + input = set_pin_protection_input_create (set_pin_protection_str); + if (!input) { + operation_shutdown (FALSE); + return; + } + qmi_client_uim_set_pin_protection (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)set_pin_protection_ready, + NULL); + qmi_message_uim_set_pin_protection_input_unref (input); + return; + } + /* Request to read a transparent file? */ if (read_transparent_str) { QmiMessageUimReadTransparentInput *input; |