diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json index ab9d9b7..e3f88d4 100644 --- a/data/qmi-service-uim.json +++ b/data/qmi-service-uim.json @@ -461,6 +461,66 @@ { "name" : "SW2", "format" : "guint8" } ] } ] }, + // ********************************************************************************* + { "name" : "Change PIN", + "type" : "Message", + "service" : "UIM", + "id" : "0x0028", + "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" : "Old PIN", + "format" : "string" }, + { "name" : "New PIN", + "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" : "Card Result", + "id" : "0x13", + "mandatory" : "no", + "type" : "TLV", + "format" : "sequence", + "contents" : [ { "name" : "SW1", + "format" : "guint8" }, + { "name" : "SW2", + "format" : "guint8" } ] } ] }, + // ********************************************************************************* { "name" : "Get Card Status", "type" : "Message", diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml index 417ad4e..515c4d8 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml +++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml @@ -250,6 +250,7 @@ + diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c index 9ab1be5..abf8047 100644 --- a/src/qmicli/qmicli-uim.c +++ b/src/qmicli/qmicli-uim.c @@ -46,6 +46,7 @@ static gchar *read_transparent_str; static gchar *set_pin_protection_str; static gchar *verify_pin_str; static gchar *unblock_pin_str; +static gchar *change_pin_str; static gchar *get_file_attributes_str; static gboolean get_card_status_flag; static gboolean get_supported_messages_flag; @@ -65,6 +66,10 @@ static GOptionEntry entries[] = { "Unblock PIN", "[(PIN1|PIN2|UPIN),(PUK),(new PIN)]", }, + { "uim-change-pin", 0, 0, G_OPTION_ARG_STRING, &change_pin_str, + "Change PIN", + "[(PIN1|PIN2|UPIN),(old PIN),(new PIN)]", + }, { "uim-read-transparent", 0, 0, G_OPTION_ARG_STRING, &read_transparent_str, "Read a transparent file given the file path", "[0xNNNN,0xNNNN,...]" @@ -119,6 +124,7 @@ qmicli_uim_options_enabled (void) n_actions = (!!set_pin_protection_str + !!verify_pin_str + !!unblock_pin_str + + !!change_pin_str + !!read_transparent_str + !!get_file_attributes_str + get_card_status_flag + @@ -423,6 +429,96 @@ unblock_pin_ready (QmiClientUim *client, operation_shutdown (TRUE); } +static QmiMessageUimChangePinInput * +change_pin_input_create (const gchar *str) +{ + QmiMessageUimChangePinInput *input = NULL; + gchar **split; + QmiUimPinId pin_id; + gchar *old_pin; + gchar *new_pin; + + /* Prepare inputs. + * Format of the string is: + * "[(PIN1|PIN2),(old PIN),(new PIN)]" + */ + split = g_strsplit (str, ",", -1); + if (qmicli_read_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; + + input = qmi_message_uim_change_pin_input_new (); + if (!qmi_message_uim_change_pin_input_set_info ( + input, + pin_id, + old_pin, + new_pin, + &error) || + !qmi_message_uim_change_pin_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_change_pin_input_unref (input); + input = NULL; + } + } + g_strfreev (split); + + return input; +} + +static void +change_pin_ready (QmiClientUim *client, + GAsyncResult *res) +{ + QmiMessageUimChangePinOutput *output; + GError *error = NULL; + + output = qmi_client_uim_change_pin_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_change_pin_output_get_result (output, &error)) { + guint8 verify_retries_left; + guint8 unblock_retries_left; + + g_printerr ("error: couldn't change PIN: %s\n", error->message); + g_error_free (error); + + if (qmi_message_uim_change_pin_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_change_pin_output_unref (output); + operation_shutdown (FALSE); + return; + } + + g_print ("[%s] PIN changed successfully\n", + qmi_device_get_path_display (ctx->device)); + + qmi_message_uim_change_pin_output_unref (output); + operation_shutdown (TRUE); +} + static void get_supported_messages_ready (QmiClientUim *client, GAsyncResult *res) @@ -1035,6 +1131,26 @@ qmicli_uim_run (QmiDevice *device, return; } + /* Request to change the PIN? */ + if (change_pin_str) { + QmiMessageUimChangePinInput *input; + + g_debug ("Asynchronously changing PIN..."); + input = change_pin_input_create (change_pin_str); + if (!input) { + operation_shutdown (FALSE); + return; + } + qmi_client_uim_change_pin (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)change_pin_ready, + NULL); + qmi_message_uim_change_pin_input_unref (input); + return; + } + /* Request to read a transparent file? */ if (read_transparent_str) { QmiMessageUimReadTransparentInput *input;