mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-08-05 21:37:15 +02:00
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.
235 lines
8.7 KiB
Diff
235 lines
8.7 KiB
Diff
From 262c098794914079125490d088c7eb2ceb515e41 Mon Sep 17 00:00:00 2001
|
|
From: Luca Weiss <luca.weiss@fairphone.com>
|
|
Date: Fri, 23 Feb 2024 10:12:35 +0100
|
|
Subject: [PATCH 3/5] uim: Add Send APDU command
|
|
|
|
Allow an APDU to be sent to the SIM card, using the logical channel
|
|
opened with Open Logical Channel.
|
|
|
|
QMI format is based on ChromiumOS hermes definition:
|
|
https://chromium.googlesource.com/chromiumos/platform2/+/eab2f7edb247fc11b3f0ec4b886aa7a5b12f24f6/hermes/uim_cmd.qmi#38
|
|
---
|
|
data/qmi-service-uim.json | 37 ++++++
|
|
.../libqmi-glib/libqmi-glib-docs.xml | 1 +
|
|
src/qmicli/qmicli-uim.c | 109 ++++++++++++++++++
|
|
3 files changed, 147 insertions(+)
|
|
|
|
diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json
|
|
index 2a0d21e6..9a562ead 100644
|
|
--- a/data/qmi-service-uim.json
|
|
+++ b/data/qmi-service-uim.json
|
|
@@ -920,6 +920,43 @@
|
|
"format" : "guint8" } ] } } ] },
|
|
"prerequisites" : [ { "common-ref" : "Success" } ] } ] },
|
|
|
|
+ // *********************************************************************************
|
|
+ { "name" : "Send APDU",
|
|
+ "type" : "Message",
|
|
+ "service" : "UIM",
|
|
+ "id" : "0x003B",
|
|
+ "since" : "1.36",
|
|
+ "input" : [ { "name" : "Slot",
|
|
+ "id" : "0x01",
|
|
+ "type" : "TLV",
|
|
+ "since" : "1.36",
|
|
+ "format" : "guint8" },
|
|
+ { "name" : "APDU",
|
|
+ "id" : "0x02",
|
|
+ "type" : "TLV",
|
|
+ "since" : "1.36",
|
|
+ "format" : "array",
|
|
+ "size-prefix-format" : "guint16",
|
|
+ "array-element" : { "format" : "guint8" } },
|
|
+ { "name" : "Channel ID",
|
|
+ "id" : "0x10",
|
|
+ "type" : "TLV",
|
|
+ "since" : "1.36",
|
|
+ "format" : "guint8" },
|
|
+ { "name" : "Procedure bytes",
|
|
+ "id" : "0x11",
|
|
+ "type" : "TLV",
|
|
+ "since" : "1.36",
|
|
+ "format" : "guint8" } ],
|
|
+ "output" : [ { "common-ref" : "Operation Result" },
|
|
+ { "name" : "APDU Response",
|
|
+ "id" : "0x10",
|
|
+ "type" : "TLV",
|
|
+ "since" : "1.36",
|
|
+ "format" : "array",
|
|
+ "size-prefix-format" : "guint16",
|
|
+ "array-element" : { "format" : "guint8" } } ] },
|
|
+
|
|
// *********************************************************************************
|
|
{ "name" : "Open Logical Channel",
|
|
"type" : "Message",
|
|
diff --git a/docs/reference/libqmi-glib/libqmi-glib-docs.xml b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
|
|
index f6cd58b2..72c76fa5 100644
|
|
--- a/docs/reference/libqmi-glib/libqmi-glib-docs.xml
|
|
+++ b/docs/reference/libqmi-glib/libqmi-glib-docs.xml
|
|
@@ -372,6 +372,7 @@
|
|
<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"/>
|
|
+ <xi:include href="xml/qmi-message-uim-send-apdu.xml"/>
|
|
</section>
|
|
</chapter>
|
|
|
|
diff --git a/src/qmicli/qmicli-uim.c b/src/qmicli/qmicli-uim.c
|
|
index 402d74fe..cd91ec99 100644
|
|
--- a/src/qmicli/qmicli-uim.c
|
|
+++ b/src/qmicli/qmicli-uim.c
|
|
@@ -30,6 +30,7 @@
|
|
#include <gio/gio.h>
|
|
|
|
#include <libqmi-glib.h>
|
|
+#include <qmi-common.h>
|
|
|
|
#include "qmicli.h"
|
|
#include "qmicli-helpers.h"
|
|
@@ -66,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 *send_apdu_str;
|
|
static gchar **monitor_refresh_file_array;
|
|
static gboolean get_card_status_flag;
|
|
static gboolean get_supported_messages_flag;
|
|
@@ -211,6 +213,12 @@ static GOptionEntry entries[] = {
|
|
"Open logical channel",
|
|
"[(slot number),(aid)]"
|
|
},
|
|
+#endif
|
|
+#if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU
|
|
+ { "uim-send-apdu", 0, 0, G_OPTION_ARG_STRING, &send_apdu_str,
|
|
+ "Send APDU",
|
|
+ "[(slot number),(channel ID),(apdu)]"
|
|
+ },
|
|
#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'",
|
|
@@ -258,6 +266,7 @@ qmicli_uim_options_enabled (void)
|
|
!!depersonalization_str +
|
|
!!remote_unlock_str +
|
|
!!open_logical_channel_str +
|
|
+ !!send_apdu_str +
|
|
get_card_status_flag +
|
|
get_supported_messages_flag +
|
|
get_slot_status_flag +
|
|
@@ -2736,6 +2745,84 @@ open_logical_channel_ready (QmiClientUim *client,
|
|
|
|
#endif /* HAVE_QMI_MESSAGE_UIM_OPEN_LOGICAL_CHANNEL */
|
|
|
|
+#if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU
|
|
+
|
|
+static QmiMessageUimSendApduInput *
|
|
+send_apdu_input_create (const gchar *str)
|
|
+{
|
|
+ QmiMessageUimSendApduInput *input;
|
|
+ g_auto(GStrv) split = NULL;
|
|
+ guint slot;
|
|
+ guint channel_id;
|
|
+ g_autoptr(GArray) apdu_data = NULL;
|
|
+
|
|
+ /* Prepare inputs.
|
|
+ * Format of the string is:
|
|
+ * "[(slot number),(channel ID),(apdu)]"
|
|
+ */
|
|
+ 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;
|
|
+ }
|
|
+
|
|
+ if (!split[2] || !qmicli_read_raw_data_from_string (split[2], &apdu_data)) {
|
|
+ g_printerr ("error: invalid APDU data\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ input = qmi_message_uim_send_apdu_input_new ();
|
|
+ qmi_message_uim_send_apdu_input_set_slot (input, slot, NULL);
|
|
+ qmi_message_uim_send_apdu_input_set_channel_id (input, channel_id, NULL);
|
|
+ qmi_message_uim_send_apdu_input_set_apdu (input, apdu_data, NULL);
|
|
+
|
|
+ return input;
|
|
+}
|
|
+
|
|
+static void
|
|
+send_apdu_ready (QmiClientUim *client,
|
|
+ GAsyncResult *res)
|
|
+{
|
|
+ g_autoptr(QmiMessageUimSendApduOutput) output = NULL;
|
|
+ g_autoptr(GError) error = NULL;
|
|
+ GArray *apdu_res = NULL;
|
|
+ gchar *apdu_res_hex;
|
|
+
|
|
+ output = qmi_client_uim_send_apdu_finish (client, res, &error);
|
|
+ if (!output) {
|
|
+ g_printerr ("error: operation failed: %s\n", error->message);
|
|
+ operation_shutdown (FALSE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!qmi_message_uim_send_apdu_output_get_result (output, &error)) {
|
|
+ g_printerr ("error: send apdu operation failed: %s\n", error->message);
|
|
+ operation_shutdown (FALSE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!qmi_message_uim_send_apdu_output_get_apdu_response (output, &apdu_res, &error)) {
|
|
+ g_printerr ("error: get apdu response operation failed: %s\n", error->message);
|
|
+ operation_shutdown (FALSE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ g_print ("Send APDU operation successfully completed:");
|
|
+ apdu_res_hex = qmi_common_str_hex (apdu_res->data, apdu_res->len, ':');
|
|
+ g_print (" %s\n", apdu_res_hex);
|
|
+ g_free (apdu_res_hex);
|
|
+
|
|
+ operation_shutdown (TRUE);
|
|
+}
|
|
+
|
|
+#endif /* HAVE_QMI_MESSAGE_UIM_SEND_APDU */
|
|
+
|
|
void
|
|
qmicli_uim_run (QmiDevice *device,
|
|
QmiClientUim *client,
|
|
@@ -3157,6 +3244,28 @@ qmicli_uim_run (QmiDevice *device,
|
|
}
|
|
#endif
|
|
|
|
+#if defined HAVE_QMI_MESSAGE_UIM_SEND_APDU
|
|
+ /* Request to send APDU? */
|
|
+ if (send_apdu_str) {
|
|
+ g_autoptr(QmiMessageUimSendApduInput) input = NULL;
|
|
+
|
|
+ g_debug ("Asynchronously sending APDU...");
|
|
+ input = send_apdu_input_create (send_apdu_str);
|
|
+ if (!input) {
|
|
+ operation_shutdown (FALSE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ qmi_client_uim_send_apdu (ctx->client,
|
|
+ input,
|
|
+ 10,
|
|
+ ctx->cancellable,
|
|
+ (GAsyncReadyCallback)send_apdu_ready,
|
|
+ NULL);
|
|
+ return;
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Just client allocate/release? */
|
|
if (noop_flag) {
|
|
g_idle_add (noop_cb, NULL);
|
|
--
|
|
2.45.1
|
|
|