diff options
author | Luca Weiss <luca.weiss@fairphone.com> | 2024-03-01 09:54:21 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2024-05-13 09:35:09 +0000 |
commit | 5d5ac16b7f525aa598f4e5b25a711b880bc04fa1 (patch) | |
tree | d6dfac3473e5a88d2f4f082adb3ad2c986651de1 | |
parent | 55f15b0b55e431b12caab349e309bad3fd87a2a3 (diff) |
uim: Add Logical Channel command
While the "Logical Channel" command can do more things, it can be used
for closing a logical channel that has been opened previously.
QMI format is based on gobi-api definition:
https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/blob/main/gobi-api/GobiAPI_2013-07-31-1347/GobiConnectionMgmt/GobiConnectionMgmtAPIStructs.h#L24531-24584
-rw-r--r-- | data/qmi-service-uim.json | 59 | ||||
-rw-r--r-- | docs/reference/libqmi-glib/libqmi-glib-common.sections | 4 | ||||
-rw-r--r-- | docs/reference/libqmi-glib/libqmi-glib-docs.xml | 1 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-enums-uim.h | 20 | ||||
-rw-r--r-- | src/qmicli/qmicli-uim.c | 89 |
5 files changed, 173 insertions, 0 deletions
diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json index 9a562ea..181f041 100644 --- a/data/qmi-service-uim.json +++ b/data/qmi-service-uim.json @@ -958,6 +958,65 @@ "array-element" : { "format" : "guint8" } } ] }, // ********************************************************************************* + { "name" : "Logical Channel", + "type" : "Message", + "service" : "UIM", + "id" : "0x003F", + "since" : "1.36", + "input" : [ { "name" : "Slot", + "id" : "0x01", + "type" : "TLV", + "since" : "1.36", + "format" : "guint8" }, + { "name" : "AID", + "id" : "0x10", + "type" : "TLV", + "since" : "1.36", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" } }, + { "name" : "Channel ID", + "id" : "0x11", + "type" : "TLV", + "since" : "1.36", + "format" : "guint8" }, + { "name" : "File Control Information", + "id" : "0x12", + "type" : "TLV", + "since" : "1.36", + "format" : "guint8", + "public-format" : "QmiUimFileControlInformation" }, + { "name" : "Terminate Application", + "id" : "0x13", + "type" : "TLV", + "since" : "1.36", + "format" : "guint8" } ], + "output" : [ { "common-ref" : "Operation Result" }, + { "name" : "Channel ID", + "id" : "0x10", + "type" : "TLV", + "since" : "1.36", + "format" : "guint8", + "prerequisites" : [ { "common-ref" : "Success" } ] }, + { "name" : "Card result", + "id" : "0x11", + "type" : "TLV", + "since" : "1.36", + "format" : "sequence", + "contents" : [ { "name" : "SW1", + "format" : "guint8" }, + { "name" : "SW2", + "format" : "guint8" } ] }, + { "name" : "Select Response", + "id" : "0x12", + "type" : "TLV", + "since" : "1.36", + "format" : "array", + "size-prefix-format" : "guint8", + "array-element" : { "format" : "guint8" }, + "prerequisites" : [ { "common-ref" : "Success" } ] } ] }, + + // ********************************************************************************* { "name" : "Open Logical Channel", "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 89473ed..3709dff 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-common.sections +++ b/docs/reference/libqmi-glib/libqmi-glib-common.sections @@ -961,6 +961,7 @@ QmiUimRefreshMode QmiUimRefreshStage QmiUimConfiguration QmiUimDepersonalizationOperation +QmiUimFileControlInformation <SUBSECTION Methods> qmi_uim_event_registration_flag_build_string_from_mask qmi_uim_session_type_get_string @@ -983,6 +984,7 @@ qmi_uim_refresh_mode_get_string qmi_uim_refresh_stage_get_string qmi_uim_configuration_build_string_from_mask qmi_uim_depersonalization_operation_get_string +qmi_uim_file_control_information_get_string <SUBSECTION Standard> QMI_TYPE_UIM_EVENT_REGISTRATION_FLAG QMI_TYPE_UIM_SESSION_TYPE @@ -1005,6 +1007,7 @@ QMI_TYPE_UIM_REFRESH_MODE QMI_TYPE_UIM_REFRESH_STAGE QMI_TYPE_UIM_CONFIGURATION QMI_TYPE_UIM_DEPERSONALIZATION_OPERATION +QMI_TYPE_UIM_FILE_CONTROL_INFORMATION qmi_uim_event_registration_flag_get_type qmi_uim_session_type_get_type qmi_uim_file_type_get_type @@ -1026,6 +1029,7 @@ qmi_uim_refresh_mode_get_type qmi_uim_refresh_stage_get_type qmi_uim_configuration_get_type qmi_uim_depersonalization_operation_get_type +qmi_uim_file_control_information_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 6e3f98f..8941055 100644 --- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml +++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml @@ -373,6 +373,7 @@ <xi:include href="xml/qmi-message-uim-remote-unlock.xml"/> <xi:include href="xml/qmi-message-uim-open-logical-channel.xml"/> <xi:include href="xml/qmi-message-uim-send-apdu.xml"/> + <xi:include href="xml/qmi-message-uim-logical-channel.xml"/> </section> </chapter> diff --git a/src/libqmi-glib/qmi-enums-uim.h b/src/libqmi-glib/qmi-enums-uim.h index 76ede04..6481444 100644 --- a/src/libqmi-glib/qmi-enums-uim.h +++ b/src/libqmi-glib/qmi-enums-uim.h @@ -558,4 +558,24 @@ typedef enum { /*< since=1.30 >*/ QMI_UIM_DEPERSONALIZATION_OPERATION_UNBLOCK = 1, } QmiUimDepersonalizationOperation; +/** + * QmiUimFileControlInformation: + * @QMI_UIM_FILE_CONTROL_INFORMATION_NO_DATA: No data. + * @QMI_UIM_FILE_CONTROL_INFORMATION_FCP: File control parameters + * @QMI_UIM_FILE_CONTROL_INFORMATION_FCI: File control information + * @QMI_UIM_FILE_CONTROL_INFORMATION_FCI_WITH_INTERFACES: FCI with interfaces + * @QMI_UIM_FILE_CONTROL_INFORMATION_FMD: File management data + * + * File Control Information. + * + * Since: 1.36 + */ +typedef enum { /*< since=1.36 >*/ + QMI_UIM_FILE_CONTROL_INFORMATION_NO_DATA = 0, + QMI_UIM_FILE_CONTROL_INFORMATION_FCP = 1, + QMI_UIM_FILE_CONTROL_INFORMATION_FCI = 2, + QMI_UIM_FILE_CONTROL_INFORMATION_FCI_WITH_INTERFACES = 3, + QMI_UIM_FILE_CONTROL_INFORMATION_FMD = 4, +} QmiUimFileControlInformation; + #endif /* _LIBQMI_GLIB_QMI_ENUMS_UIM_H_ */ diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c index 53c8770..e344a68 100644 --- a/src/qmicli/qmicli-uim.c +++ b/src/qmicli/qmicli-uim.c @@ -67,6 +67,7 @@ static gchar *switch_slot_str; static gchar *depersonalization_str; static gchar *remote_unlock_str; static gchar *open_logical_channel_str; +static gchar *close_logical_channel_str; static gchar *send_apdu_str; static gchar **monitor_refresh_file_array; static gboolean get_card_status_flag; @@ -214,6 +215,12 @@ static GOptionEntry entries[] = { "[(slot number),(aid)]" }, #endif +#if defined HAVE_QMI_MESSAGE_UIM_LOGICAL_CHANNEL + { "uim-close-logical-channel", 0, 0, G_OPTION_ARG_STRING, &close_logical_channel_str, + "Close logical channel", + "[(slot number),(channel ID)]" + }, +#endif #if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU { "uim-send-apdu", 0, 0, G_OPTION_ARG_STRING, &send_apdu_str, "Send APDU", @@ -266,6 +273,7 @@ qmicli_uim_options_enabled (void) !!depersonalization_str + !!remote_unlock_str + !!open_logical_channel_str + + !!close_logical_channel_str + !!send_apdu_str + get_card_status_flag + get_supported_messages_flag + @@ -2830,6 +2838,65 @@ open_logical_channel_ready (QmiClientUim *client, #endif /* HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL */ +#if defined HAVE_QMI_MESSAGE_UIM_LOGICAL_CHANNEL + +static QmiMessageUimLogicalChannelInput * +close_logical_channel_input_create (const gchar *str) +{ + QmiMessageUimLogicalChannelInput *input; + g_auto(GStrv) split = NULL; + guint slot; + guint channel_id; + + /* Prepare inputs. + * Format of the string is: + * "[(slot number),(channel ID)]" + */ + split = g_strsplit (str, ",", -1); + + if (!split[0] || !qmicli_read_uint_from_string (split[0], &slot) || (slot > G_MAXUINT8)) { + g_printerr ("error: invalid slot number\n"); + return NULL; + } + + if (!split[1] || !qmicli_read_uint_from_string (split[1], &channel_id) || (channel_id > G_MAXUINT8)) { + g_printerr ("error: invalid channel ID\n"); + return NULL; + } + + input = qmi_message_uim_logical_channel_input_new (); + qmi_message_uim_logical_channel_input_set_slot (input, slot, NULL); + qmi_message_uim_logical_channel_input_set_channel_id (input, channel_id, NULL); + + return input; +} + +static void +close_logical_channel_ready (QmiClientUim *client, + GAsyncResult *res) +{ + g_autoptr(QmiMessageUimLogicalChannelOutput) output = NULL; + g_autoptr(GError) error = NULL; + + output = qmi_client_uim_logical_channel_finish (client, res, &error); + if (!output) { + g_printerr ("error: operation failed: %s\n", error->message); + operation_shutdown (FALSE); + return; + } + + if (!qmi_message_uim_logical_channel_output_get_result (output, &error)) { + g_printerr ("error: close logical channel operation failed: %s\n", error->message); + operation_shutdown (FALSE); + return; + } + + g_print ("Close Logical Channel operation successfully completed\n"); + operation_shutdown (TRUE); +} + +#endif /* HAVE_QMI_MESSAGE_UIM_LOGICAL_CHANNEL */ + #if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU static QmiMessageUimSendApduInput * @@ -3329,6 +3396,28 @@ qmicli_uim_run (QmiDevice *device, } #endif +#if defined HAVE_QMI_MESSAGE_UIM_LOGICAL_CHANNEL + /* Request to close logical channel? */ + if (close_logical_channel_str) { + g_autoptr(QmiMessageUimLogicalChannelInput) input = NULL; + + g_debug ("Asynchronously closing logical channel..."); + input = close_logical_channel_input_create (close_logical_channel_str); + if (!input) { + operation_shutdown (FALSE); + return; + } + + qmi_client_uim_logical_channel (ctx->client, + input, + 10, + ctx->cancellable, + (GAsyncReadyCallback)close_logical_channel_ready, + NULL); + return; + } +#endif + #if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU /* Request to send APDU? */ if (send_apdu_str) { |