diff --git a/community/libqmi/0001-qmi-common-turn-qmi_helpers_str_hex-into-qmi_common_.patch b/community/libqmi/0001-qmi-common-turn-qmi_helpers_str_hex-into-qmi_common_.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8e097cbe07cfc938d12a6b238cbf2bf262a42b24
--- /dev/null
+++ b/community/libqmi/0001-qmi-common-turn-qmi_helpers_str_hex-into-qmi_common_.patch
@@ -0,0 +1,347 @@
+From ff9d55551a5ec381ccfc04a773b82d98b5b95028 Mon Sep 17 00:00:00 2001
+From: Fabio Porcedda <fabio.porcedda@gmail.com>
+Date: Tue, 12 Dec 2023 10:09:47 +0100
+Subject: [PATCH 1/5] qmi-common: turn qmi_helpers_str_hex into
+ qmi_common_str_hex
+
+Rename qmi_helpers_str_hex() to qmi_common_str_hex() and move it to
+the new library libqmi-common that will be shared between libqmi-glib
+and qmicli.
+---
+ build-aux/qmi-codegen/Message.py      |  2 +-
+ build-aux/qmi-codegen/utils.py        |  1 +
+ src/common/meson.build                | 15 +++++++++
+ src/common/qmi-common.c               | 45 +++++++++++++++++++++++++++
+ src/common/qmi-common.h               | 16 ++++++++++
+ src/libqmi-glib/generated/meson.build |  5 ++-
+ src/libqmi-glib/meson.build           |  1 +
+ src/libqmi-glib/qmi-compat.c          |  5 +--
+ src/libqmi-glib/qmi-device.c          |  5 +--
+ src/libqmi-glib/qmi-endpoint.c        |  4 +--
+ src/libqmi-glib/qmi-helpers.c         | 36 ---------------------
+ src/libqmi-glib/qmi-helpers.h         |  4 ---
+ src/libqmi-glib/qmi-message.c         |  3 +-
+ src/meson.build                       |  1 +
+ 14 files changed, 94 insertions(+), 49 deletions(-)
+ create mode 100644 src/common/meson.build
+ create mode 100644 src/common/qmi-common.c
+ create mode 100644 src/common/qmi-common.h
+
+diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py
+index b522fd4d..eb56358f 100644
+--- a/build-aux/qmi-codegen/Message.py
++++ b/build-aux/qmi-codegen/Message.py
+@@ -381,7 +381,7 @@ class Message:
+                 '        g_autofree gchar *value_hex = NULL;\n'
+                 '\n'
+                 '        if (qmi_utils_get_show_personal_info () || !value_has_personal_info)\n'
+-                '            value_hex = qmi_helpers_str_hex (value, length, \':\');\n'
++                '            value_hex = qmi_common_str_hex (value, length, \':\');\n'
+                 '        else\n'
+                 '            value_hex = g_strdup ("###...");\n'
+                 '\n'
+diff --git a/build-aux/qmi-codegen/utils.py b/build-aux/qmi-codegen/utils.py
+index b4313a58..00d98c33 100644
+--- a/build-aux/qmi-codegen/utils.py
++++ b/build-aux/qmi-codegen/utils.py
+@@ -114,6 +114,7 @@ def add_source_start(f, output_name):
+         "#include <string.h>\n"
+         "\n"
+         "#include \"${name}.h\"\n"
++        "#include \"qmi-common.h\"\n"
+         "#include \"qmi-enum-types.h\"\n"
+         "#include \"qmi-flag-types.h\"\n"
+         "#include \"qmi-enum-types-private.h\"\n"
+diff --git a/src/common/meson.build b/src/common/meson.build
+new file mode 100644
+index 00000000..06fcdc31
+--- /dev/null
++++ b/src/common/meson.build
+@@ -0,0 +1,15 @@
++# SPDX-License-Identifier: LGPL-2.1-or-later
++# Copyright (C) 2023 Fabio Porcedda <fabio.porcedda@gmail.com>
++
++libqmi_common = static_library(
++  'qmi-common',
++  sources: 'qmi-common.c',
++  include_directories: top_inc,
++  dependencies: glib_dep,
++)
++
++libqmi_common_dep = declare_dependency(
++  include_directories: '.',
++  dependencies: glib_dep,
++  link_with: libqmi_common,
++)
+diff --git a/src/common/qmi-common.c b/src/common/qmi-common.c
+new file mode 100644
+index 00000000..a65e346b
+--- /dev/null
++++ b/src/common/qmi-common.c
+@@ -0,0 +1,45 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* SPDX-License-Identifier: LGPL-2.1-or-later */
++/*
++ * Copyright (C) 2023 Fabio Porcedda <fabio.porcedda@gmail.com>
++ */
++
++#include "qmi-common.h"
++
++#include <stdio.h>
++
++/*****************************************************************************/
++
++gchar *
++qmi_common_str_hex (gconstpointer mem,
++                    gsize         size,
++                    gchar         delimiter)
++{
++    const guint8 *data = mem;
++    gsize         i;
++    gsize         j;
++    gsize         new_str_length;
++    gchar        *new_str;
++
++    /* Get new string length. If input string has N bytes, we need:
++     * - 1 byte for last NUL char
++     * - 2N bytes for hexadecimal char representation of each byte...
++     * - N-1 bytes for the separator ':'
++     * So... a total of (1+2N+N-1) = 3N bytes are needed... */
++    new_str_length =  3 * size;
++
++    /* Allocate memory for new array and initialize contents to NUL */
++    new_str = g_malloc0 (new_str_length);
++
++    /* Print hexadecimal representation of each byte... */
++    for (i = 0, j = 0; i < size; i++, j += 3) {
++        /* Print character in output string... */
++        snprintf (&new_str[j], 3, "%02X", data[i]);
++        /* And if needed, add separator */
++        if (i != (size - 1) )
++            new_str[j + 2] = delimiter;
++    }
++
++    /* Set output string */
++    return new_str;
++}
+diff --git a/src/common/qmi-common.h b/src/common/qmi-common.h
+new file mode 100644
+index 00000000..d59e5e7b
+--- /dev/null
++++ b/src/common/qmi-common.h
+@@ -0,0 +1,16 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * Copyright (C) 2023 Fabio Porcedda <fabio.porcedda@gmail.com>
++ */
++
++#ifndef _COMMON_QMI_COMMON_H_
++#define _COMMON_QMI_COMMON_H_
++
++#include <glib.h>
++
++gchar *qmi_common_str_hex (gconstpointer mem,
++                           gsize         size,
++                           gchar         delimiter);
++
++#endif /* _COMMON_QMI_COMMON_H_ */
+diff --git a/src/libqmi-glib/generated/meson.build b/src/libqmi-glib/generated/meson.build
+index 19eeeb69..9c07c881 100644
+--- a/src/libqmi-glib/generated/meson.build
++++ b/src/libqmi-glib/generated/meson.build
+@@ -305,7 +305,10 @@ c_flags = [
+   '-Wno-unused-function',
+ ]
+ 
+-deps = [glib_deps]
++deps = [
++  glib_deps,
++  libqmi_common_dep,
++]
+ 
+ if enable_qrtr
+   deps += qrtr_glib_dep
+diff --git a/src/libqmi-glib/meson.build b/src/libqmi-glib/meson.build
+index f3113747..854234ff 100644
+--- a/src/libqmi-glib/meson.build
++++ b/src/libqmi-glib/meson.build
+@@ -99,6 +99,7 @@ sources = files(
+ deps = [
+   generated_dep,
+   gio_unix_dep,
++  libqmi_common_dep,
+ ]
+ 
+ if enable_mbim_qmux
+diff --git a/src/libqmi-glib/qmi-compat.c b/src/libqmi-glib/qmi-compat.c
+index 636a9631..d65d2e75 100644
+--- a/src/libqmi-glib/qmi-compat.c
++++ b/src/libqmi-glib/qmi-compat.c
+@@ -21,6 +21,7 @@
+ 
+ #include <string.h>
+ 
++#include "qmi-common.h"
+ #include "qmi-compat.h"
+ #include "qmi-helpers.h"
+ #include "qmi-enum-types.h"
+@@ -40,8 +41,8 @@ print_read_bytes_trace (const gchar *type,
+     gchar *str1;
+     gchar *str2;
+ 
+-    str1 = qmi_helpers_str_hex (buffer, n_bytes, ':');
+-    str2 = qmi_helpers_str_hex (out, n_bytes, ':');
++    str1 = qmi_common_str_hex (buffer, n_bytes, ':');
++    str2 = qmi_common_str_hex (out, n_bytes, ':');
+ 
+     g_debug ("Read %s (%s) --> (%s)", type, str1, str2);
+     g_warn_if_fail (g_str_equal (str1, str2));
+diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
+index 55ec075a..b901a62a 100644
+--- a/src/libqmi-glib/qmi-device.c
++++ b/src/libqmi-glib/qmi-device.c
+@@ -31,6 +31,7 @@
+ #include <termios.h>
+ #include <unistd.h>
+ 
++#include "qmi-common.h"
+ #include "qmi-device.h"
+ #include "qmi-message.h"
+ #include "qmi-file.h"
+@@ -1744,13 +1745,13 @@ trace_message (QmiDevice         *self,
+     }
+ 
+     if (qmi_utils_get_show_personal_info () || (((GByteArray *)message)->len < MAX_PRINTED_BYTES)) {
+-        printable = qmi_helpers_str_hex (((GByteArray *)message)->data,
++        printable = qmi_common_str_hex (((GByteArray *)message)->data,
+                                          ((GByteArray *)message)->len,
+                                          ':');
+     } else {
+         g_autofree gchar *tmp = NULL;
+ 
+-        tmp = qmi_helpers_str_hex (((GByteArray *)message)->data, MAX_PRINTED_BYTES, ':');
++        tmp = qmi_common_str_hex (((GByteArray *)message)->data, MAX_PRINTED_BYTES, ':');
+         printable = g_strdup_printf ("%s...", tmp);
+     }
+ 
+diff --git a/src/libqmi-glib/qmi-endpoint.c b/src/libqmi-glib/qmi-endpoint.c
+index 362311cc..f5c5aae1 100644
+--- a/src/libqmi-glib/qmi-endpoint.c
++++ b/src/libqmi-glib/qmi-endpoint.c
+@@ -24,7 +24,7 @@
+ 
+ #include "qmi-endpoint.h"
+ 
+-#include "qmi-helpers.h"
++#include "qmi-common.h"
+ #include "qmi-error-types.h"
+ #include "qmi-errors.h"
+ 
+@@ -93,7 +93,7 @@ qmi_endpoint_parse_buffer (QmiEndpoint        *self,
+                 gchar *printable;
+                 guint len = MIN (self->priv->buffer->len, 2048);
+ 
+-                printable = qmi_helpers_str_hex (self->priv->buffer->data, len, ':');
++                printable = qmi_common_str_hex (self->priv->buffer->data, len, ':');
+                 g_debug ("<<<<<< RAW INVALID MESSAGE:\n"
+                          "<<<<<<   length = %u\n"
+                          "<<<<<<   data   = %s\n",
+diff --git a/src/libqmi-glib/qmi-helpers.c b/src/libqmi-glib/qmi-helpers.c
+index 2cd433fb..d5626105 100644
+--- a/src/libqmi-glib/qmi-helpers.c
++++ b/src/libqmi-glib/qmi-helpers.c
+@@ -37,42 +37,6 @@
+ 
+ /*****************************************************************************/
+ 
+-gchar *
+-qmi_helpers_str_hex (gconstpointer mem,
+-                     gsize         size,
+-                     gchar         delimiter)
+-{
+-    const guint8 *data = mem;
+-    gsize         i;
+-    gsize         j;
+-    gsize         new_str_length;
+-    gchar        *new_str;
+-
+-    /* Get new string length. If input string has N bytes, we need:
+-     * - 1 byte for last NUL char
+-     * - 2N bytes for hexadecimal char representation of each byte...
+-     * - N-1 bytes for the separator ':'
+-     * So... a total of (1+2N+N-1) = 3N bytes are needed... */
+-    new_str_length =  3 * size;
+-
+-    /* Allocate memory for new array and initialize contents to NUL */
+-    new_str = g_malloc0 (new_str_length);
+-
+-    /* Print hexadecimal representation of each byte... */
+-    for (i = 0, j = 0; i < size; i++, j += 3) {
+-        /* Print character in output string... */
+-        snprintf (&new_str[j], 3, "%02X", data[i]);
+-        /* And if needed, add separator */
+-        if (i != (size - 1) )
+-            new_str[j + 2] = delimiter;
+-    }
+-
+-    /* Set output string */
+-    return new_str;
+-}
+-
+-/*****************************************************************************/
+-
+ gboolean
+ qmi_helpers_check_user_allowed (uid_t    uid,
+                                 GError **error)
+diff --git a/src/libqmi-glib/qmi-helpers.h b/src/libqmi-glib/qmi-helpers.h
+index 48b9f6df..5be5c09a 100644
+--- a/src/libqmi-glib/qmi-helpers.h
++++ b/src/libqmi-glib/qmi-helpers.h
+@@ -34,10 +34,6 @@
+ 
+ G_BEGIN_DECLS
+ 
+-G_GNUC_INTERNAL
+-gchar *qmi_helpers_str_hex (gconstpointer mem,
+-                            gsize         size,
+-                            gchar         delimiter);
+ G_GNUC_INTERNAL
+ gboolean qmi_helpers_check_user_allowed  (uid_t    uid,
+                                           GError **error);
+diff --git a/src/libqmi-glib/qmi-message.c b/src/libqmi-glib/qmi-message.c
+index 3e31b4b4..ab928a15 100644
+--- a/src/libqmi-glib/qmi-message.c
++++ b/src/libqmi-glib/qmi-message.c
+@@ -34,6 +34,7 @@
+ #include <string.h>
+ #include <endian.h>
+ 
++#include "qmi-common.h"
+ #include "qmi-message.h"
+ #include "qmi-helpers.h"
+ #include "qmi-enums-private.h"
+@@ -1623,7 +1624,7 @@ qmi_message_get_tlv_printable (QmiMessage *self,
+     g_return_val_if_fail (line_prefix != NULL, NULL);
+     g_return_val_if_fail (raw != NULL, NULL);
+ 
+-    value_hex = qmi_helpers_str_hex (raw, raw_length, ':');
++    value_hex = qmi_common_str_hex (raw, raw_length, ':');
+     printable = g_strdup_printf ("%sTLV:\n"
+                                  "%s  type   = 0x%02x\n"
+                                  "%s  length = %" G_GSIZE_FORMAT "\n"
+diff --git a/src/meson.build b/src/meson.build
+index 10550ab7..33f642f6 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+ # Copyright (C) 2019 - 2021 Iñigo Martinez <inigomartinez@gmail.com>
+ 
++subdir('common')
+ subdir('libqmi-glib')
+ subdir('qmicli')
+ subdir('qmi-proxy')
+-- 
+2.45.1
+
diff --git a/community/libqmi/0002-uim-Add-Open-Logical-Channel-command.patch b/community/libqmi/0002-uim-Add-Open-Logical-Channel-command.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fa0351594b695f762ad59506cd43c9bdfb9264a1
--- /dev/null
+++ b/community/libqmi/0002-uim-Add-Open-Logical-Channel-command.patch
@@ -0,0 +1,224 @@
+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
+
diff --git a/community/libqmi/0003-uim-Add-Send-APDU-command.patch b/community/libqmi/0003-uim-Add-Send-APDU-command.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6825e07da7d185db5e0e4922c9dfc8506847fa53
--- /dev/null
+++ b/community/libqmi/0003-uim-Add-Send-APDU-command.patch
@@ -0,0 +1,234 @@
+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
+
diff --git a/community/libqmi/0004-uim-Add-Logical-Channel-command.patch b/community/libqmi/0004-uim-Add-Logical-Channel-command.patch
new file mode 100644
index 0000000000000000000000000000000000000000..cecbc9ac3271bf7e518612340d2548608ea430dd
--- /dev/null
+++ b/community/libqmi/0004-uim-Add-Logical-Channel-command.patch
@@ -0,0 +1,296 @@
+From a8bd657cafc5d9265b1e3ee63a143d5c43e925cb Mon Sep 17 00:00:00 2001
+From: Luca Weiss <luca.weiss@fairphone.com>
+Date: Fri, 1 Mar 2024 09:54:21 +0100
+Subject: [PATCH 4/5] 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
+---
+ data/qmi-service-uim.json                     | 59 ++++++++++++
+ .../libqmi-glib/libqmi-glib-common.sections   |  4 +
+ .../libqmi-glib/libqmi-glib-docs.xml          |  1 +
+ src/libqmi-glib/qmi-enums-uim.h               | 20 +++++
+ src/qmicli/qmicli-uim.c                       | 89 +++++++++++++++++++
+ 5 files changed, 173 insertions(+)
+
+diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json
+index 9a562ead..181f0418 100644
+--- a/data/qmi-service-uim.json
++++ b/data/qmi-service-uim.json
+@@ -957,6 +957,65 @@
+                      "size-prefix-format" : "guint16",
+                      "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",
+diff --git a/docs/reference/libqmi-glib/libqmi-glib-common.sections b/docs/reference/libqmi-glib/libqmi-glib-common.sections
+index 89473ed8..3709dff5 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 72c76fa5..c59f1fad 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 76ede04a..64814441 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 cd91ec99..83b0c8fa 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 +
+@@ -2745,6 +2753,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 *
+@@ -3244,6 +3311,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) {
+-- 
+2.45.1
+
diff --git a/community/libqmi/0005-uim-Add-File-Control-Information-to-Open-Logical-Cha.patch b/community/libqmi/0005-uim-Add-File-Control-Information-to-Open-Logical-Cha.patch
new file mode 100644
index 0000000000000000000000000000000000000000..bd2a2fc042a67c8680f1df21f6e68f475c69b3d2
--- /dev/null
+++ b/community/libqmi/0005-uim-Add-File-Control-Information-to-Open-Logical-Cha.patch
@@ -0,0 +1,34 @@
+From 1fcfda5f1dc5675afe54846ca0d01e32b39fbac2 Mon Sep 17 00:00:00 2001
+From: Luca Weiss <luca.weiss@fairphone.com>
+Date: Fri, 1 Mar 2024 10:33:23 +0100
+Subject: [PATCH 5/5] uim: Add "File Control Information" to Open Logical
+ Channel request
+
+According to gobi-api sources this TLV exists:
+https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/blob/main/gobi-api/GobiAPI_2013-07-31-1347/GobiConnectionMgmt/GobiConnectionMgmtAPIStructs.h#L24641-24645
+---
+ data/qmi-service-uim.json | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/data/qmi-service-uim.json b/data/qmi-service-uim.json
+index 181f0418..cd7ca237 100644
+--- a/data/qmi-service-uim.json
++++ b/data/qmi-service-uim.json
+@@ -1033,7 +1033,13 @@
+                      "since"              : "1.36",
+                      "format"             : "array",
+                      "size-prefix-format" : "guint8",
+-                     "array-element"      : { "format" : "guint8" } } ],
++                     "array-element"      : { "format" : "guint8" } },
++                   { "name"          : "File Control Information",
++                     "id"            : "0x11",
++                     "type"          : "TLV",
++                     "since"         : "1.36",
++                     "format"        : "guint8",
++                     "public-format" : "QmiUimFileControlInformation" } ],
+      "output"  : [ { "common-ref" : "Operation Result" },
+                    { "name"          : "Channel ID",
+                      "id"            : "0x10",
+-- 
+2.45.1
+
diff --git a/community/libqmi/APKBUILD b/community/libqmi/APKBUILD
index 21d52a77d2e07c3998f37bf8ba031b4dcc5dfb48..4087983b707afe1edcb2777e0713009823f6b88f 100644
--- a/community/libqmi/APKBUILD
+++ b/community/libqmi/APKBUILD
@@ -2,7 +2,7 @@
 # Maintainer: Stuart Cardall <developer@it-offshore.co.uk>
 pkgname=libqmi
 pkgver=1.34.0
-pkgrel=0
+pkgrel=1
 pkgdesc="QMI modem protocol helper library"
 url="https://www.freedesktop.org/wiki/Software/libqmi"
 arch="all"
@@ -25,7 +25,13 @@ subpackages="
 	$pkgname-bash-completion
 	qmi-utils
 	"
-source="https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/archive/$pkgver/libqmi-$pkgver.tar.gz"
+source="https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/archive/$pkgver/libqmi-$pkgver.tar.gz
+	0001-qmi-common-turn-qmi_helpers_str_hex-into-qmi_common_.patch
+	0002-uim-Add-Open-Logical-Channel-command.patch
+	0003-uim-Add-Send-APDU-command.patch
+	0004-uim-Add-Logical-Channel-command.patch
+	0005-uim-Add-File-Control-Information-to-Open-Logical-Cha.patch
+	"
 
 build() {
 	abuild-meson \
@@ -54,4 +60,9 @@ utils() {
 
 sha512sums="
 4be50814c846e986d2f792af1d488e76f9e3d5457741c1e49187232150b4e14fd26538d0850f2c014be0144b61781827787ca466cd94f1032019ec69e3ab3f3b  libqmi-1.34.0.tar.gz
+9fd2e5a4b3b5b148c01e9b713385623b1c9c20b491b8d99760cb42fcf0a1d7d1f3bcb35044119bb57c8577bc19dd3d7a20098dc2447b397612aee01bc52d9974  0001-qmi-common-turn-qmi_helpers_str_hex-into-qmi_common_.patch
+503c0f8ac3869b5fc0486708d10ec9095148d900914187a00e3c0a90d47657672e6dffddbf1cf59a66601272e9b598f710ea14c2eacf7dc49b05838506878d58  0002-uim-Add-Open-Logical-Channel-command.patch
+c66418eaba0ce6d6a878685a2e80a86cd8cf5c47ecb2842fbf15439f5335e6b19e69e9838579eee156e53938e05570327b82e2e22349eb30e3a92c10e82b7ec9  0003-uim-Add-Send-APDU-command.patch
+0bc0568f5bde4bd12f7a73875a9c178af3d2fb2151dd119084501e33156e21062964e7bdbd6137d0b66011048150fb12c8194ffa2d50b1e114e9361836456478  0004-uim-Add-Logical-Channel-command.patch
+548b795681ed8bafad2e34a3c7f8857fa8c09e6814afd94569b9254d3865fffb21c28d9056552866defee7af43ea735c9f767895a61cf158da99bc416c0f0079  0005-uim-Add-File-Control-Information-to-Open-Logical-Cha.patch
 "