aports/community/libqmi/0002-uim-Add-Open-Logical-Channel-command.patch
Luca Weiss 6157b11983 community/libqmi: backport patches for Logical Channel & APDU commands
Already merged in libqmi main, will be included with the next release.

Patch Nr.2 got a slight edit to replace qmi_common_str_hex with
qmi_helpers_str_hex since it was only renamed after the 1.34.0 release.
2024-05-24 07:56:02 +00:00

225 lines
9.0 KiB
Diff

From 2ac09dbc9e433290a26c6ace653d28d0aff223d0 Mon Sep 17 00:00:00 2001
From: Luca Weiss <luca.weiss@fairphone.com>
Date: Fri, 23 Feb 2024 08:46:55 +0100
Subject: [PATCH 2/5] uim: Add Open Logical Channel command
Allows the client to open a logical channel to the SIM card which can
then be used to e.g. send APDU requests to the SIM card.
QMI format is based on ChromiumOS hermes definition:
https://chromium.googlesource.com/chromiumos/platform2/+/eab2f7edb247fc11b3f0ec4b886aa7a5b12f24f6/hermes/uim_cmd.qmi#17
---
data/qmi-service-uim.json | 43 ++++++++
.../libqmi-glib/libqmi-glib-docs.xml | 1 +
src/qmicli/qmicli-uim.c | 100 ++++++++++++++++++
3 files changed, 144 insertions(+)
diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json
index 35edd8e1..2a0d21e6 100644
--- a/data/qmi-service-uim.json
+++ b/data/qmi-service-uim.json
@@ -920,6 +920,49 @@
"format" : "guint8" } ] } } ] },
"prerequisites" : [ { "common-ref" : "Success" } ] } ] },
+ // *********************************************************************************
+ { "name" : "Open Logical Channel",
+ "type" : "Message",
+ "service" : "UIM",
+ "id" : "0x0042",
+ "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" } } ],
+ "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" : "Refresh Register All",
"type" : "Message",
diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
index 1374c365..f6cd58b2 100644
--- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml
+++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
@@ -371,6 +371,7 @@
<xi:include href="xml/qmi-message-uim-refresh-register-all.xml"/>
<xi:include href="xml/qmi-message-uim-refresh-complete.xml"/>
<xi:include href="xml/qmi-message-uim-remote-unlock.xml"/>
+ <xi:include href="xml/qmi-message-uim-open-logical-channel.xml"/>
</section>
</chapter>
diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c
index c3d0abad..402d74fe 100644
--- a/src/qmicli/qmicli-uim.c
+++ b/src/qmicli/qmicli-uim.c
@@ -65,6 +65,7 @@ static gchar *change_provisioning_session_str;
static gchar *switch_slot_str;
static gchar *depersonalization_str;
static gchar *remote_unlock_str;
+static gchar *open_logical_channel_str;
static gchar **monitor_refresh_file_array;
static gboolean get_card_status_flag;
static gboolean get_supported_messages_flag;
@@ -204,6 +205,12 @@ static GOptionEntry entries[] = {
"Updates the SimLock configuration data",
"[XX:XX:...]"
},
+#endif
+#if defined HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL
+ { "uim-open-logical-channel", 0, 0, G_OPTION_ARG_STRING, &open_logical_channel_str,
+ "Open logical channel",
+ "[(slot number),(aid)]"
+ },
#endif
{ "uim-noop", 0, 0, G_OPTION_ARG_NONE, &noop_flag,
"Just allocate or release a UIM client. Use with `--client-no-release-cid' and/or `--client-cid'",
@@ -250,6 +257,7 @@ qmicli_uim_options_enabled (void)
!!monitor_refresh_file_array +
!!depersonalization_str +
!!remote_unlock_str +
+ !!open_logical_channel_str +
get_card_status_flag +
get_supported_messages_flag +
get_slot_status_flag +
@@ -2658,6 +2666,76 @@ remote_unlock_ready (QmiClientUim *client,
#endif /* HAVE_QMI_MESSAGE_UIM_REMOTE_UNLOCK */
+#if defined HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL
+
+static QmiMessageUimOpenLogicalChannelInput *
+open_logical_channel_input_create (const gchar *str)
+{
+ QmiMessageUimOpenLogicalChannelInput *input;
+ g_auto(GStrv) split = NULL;
+ guint slot;
+ g_autoptr(GArray) aid_data = NULL;
+
+ /* Prepare inputs.
+ * Format of the string is:
+ * "[(slot number),(aid)]"
+ */
+ 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;
+ }
+
+ /* AID is optional */
+ if (split[1]) {
+ if (!qmicli_read_raw_data_from_string (split[1], &aid_data)) {
+ g_printerr ("error: invalid AID data\n");
+ return NULL;
+ }
+ }
+
+ input = qmi_message_uim_open_logical_channel_input_new ();
+ qmi_message_uim_open_logical_channel_input_set_slot (input, slot, NULL);
+ if (aid_data)
+ qmi_message_uim_open_logical_channel_input_set_aid (input, aid_data, NULL);
+
+ return input;
+}
+
+static void
+open_logical_channel_ready (QmiClientUim *client,
+ GAsyncResult *res)
+{
+ g_autoptr(QmiMessageUimOpenLogicalChannelOutput) output = NULL;
+ g_autoptr(GError) error = NULL;
+ guint8 channel_id;
+
+ output = qmi_client_uim_open_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_open_logical_channel_output_get_result (output, &error)) {
+ g_printerr ("error: open logical channel operation failed: %s\n", error->message);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ if (!qmi_message_uim_open_logical_channel_output_get_channel_id (output, &channel_id, &error)) {
+ g_printerr ("error: get channel id operation failed: %s\n", error->message);
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ g_print ("Open Logical Channel operation successfully completed: %d\n", channel_id);
+ operation_shutdown (TRUE);
+}
+
+#endif /* HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL */
+
void
qmicli_uim_run (QmiDevice *device,
QmiClientUim *client,
@@ -3057,6 +3135,28 @@ qmicli_uim_run (QmiDevice *device,
}
#endif
+#if defined HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL
+ /* Request to open logical channel? */
+ if (open_logical_channel_str) {
+ g_autoptr(QmiMessageUimOpenLogicalChannelInput) input = NULL;
+
+ g_debug ("Asynchronously opening logical channel...");
+ input = open_logical_channel_input_create (open_logical_channel_str);
+ if (!input) {
+ operation_shutdown (FALSE);
+ return;
+ }
+
+ qmi_client_uim_open_logical_channel (ctx->client,
+ input,
+ 10,
+ ctx->cancellable,
+ (GAsyncReadyCallback)open_logical_channel_ready,
+ NULL);
+ return;
+ }
+#endif
+
/* Just client allocate/release? */
if (noop_flag) {
g_idle_add (noop_cb, NULL);
--
2.45.1