summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Weiss <luca.weiss@fairphone.com>2024-03-01 09:54:21 +0100
committerAleksander Morgado <aleksander@aleksander.es>2024-05-13 09:35:09 +0000
commit5d5ac16b7f525aa598f4e5b25a711b880bc04fa1 (patch)
treed6dfac3473e5a88d2f4f082adb3ad2c986651de1
parent55f15b0b55e431b12caab349e309bad3fd87a2a3 (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.json59
-rw-r--r--docs/reference/libqmi-glib/libqmi-glib-common.sections4
-rw-r--r--docs/reference/libqmi-glib/libqmi-glib-docs.xml1
-rw-r--r--src/libqmi-glib/qmi-enums-uim.h20
-rw-r--r--src/qmicli/qmicli-uim.c89
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) {