From b45c9b5ddb4fb456f41c29e9aabc460db9525366 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 15:58:58 +0200 Subject: [PATCH 1/8] driver: pass EUICC APDU or HTTP struct to driver fini OP Currently, the .fini driver OP can only be used with global variables, but that will be an issue when we cant use global variables. This will be used with direct QMI in order to free the memory used by the driver private structure instead of global variables. Signed-off-by: Robert Marko --- driver/apdu/at.c | 4 ++-- driver/apdu/gbinder_hidl.c | 2 +- driver/apdu/pcsc.c | 4 ++-- driver/apdu/qmi_qrtr.c | 4 ++-- driver/apdu/stdio.c | 4 ++-- driver/driver.c | 4 ++-- driver/driver.private.h | 2 +- driver/http/curl.c | 4 ++-- driver/http/stdio.c | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/driver/apdu/at.c b/driver/apdu/at.c index d2c9cb7..1f0de0d 100644 --- a/driver/apdu/at.c +++ b/driver/apdu/at.c @@ -218,7 +218,7 @@ static int libapduinterface_main(int argc, char **argv) return 0; } -static void libapduinterface_fini(void) +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { } @@ -227,5 +227,5 @@ const struct euicc_driver driver_apdu_at = { .name = "at", .init = (int (*)(void *))libapduinterface_init, .main = libapduinterface_main, - .fini = libapduinterface_fini, + .fini = (void (*)(void *))libapduinterface_fini, }; diff --git a/driver/apdu/gbinder_hidl.c b/driver/apdu/gbinder_hidl.c index 27cd6e5..6c0bde5 100644 --- a/driver/apdu/gbinder_hidl.c +++ b/driver/apdu/gbinder_hidl.c @@ -314,7 +314,7 @@ static int libapduinterface_main(int argc, char **argv) return 0; } -static void libapduinterface_fini(void) +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { } diff --git a/driver/apdu/pcsc.c b/driver/apdu/pcsc.c index ee7feed..7fae2c1 100644 --- a/driver/apdu/pcsc.c +++ b/driver/apdu/pcsc.c @@ -453,7 +453,7 @@ static int libapduinterface_main(int argc, char **argv) return 0; } -static void libapduinterface_fini(void) +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { } @@ -462,5 +462,5 @@ const struct euicc_driver driver_apdu_pcsc = { .name = "pcsc", .init = (int (*)(void *))libapduinterface_init, .main = libapduinterface_main, - .fini = libapduinterface_fini, + .fini = (void (*)(void *))libapduinterface_fini, }; diff --git a/driver/apdu/qmi_qrtr.c b/driver/apdu/qmi_qrtr.c index 0925245..8227ed4 100644 --- a/driver/apdu/qmi_qrtr.c +++ b/driver/apdu/qmi_qrtr.c @@ -272,7 +272,7 @@ static int libapduinterface_main(int argc, char **argv) return 0; } -static void libapduinterface_fini(void) +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { } @@ -281,5 +281,5 @@ const struct euicc_driver driver_apdu_qmi_qrtr = { .name = "qmi_qrtr", .init = (int (*)(void *))libapduinterface_init, .main = libapduinterface_main, - .fini = libapduinterface_fini, + .fini = (void (*)(void *))libapduinterface_fini, }; diff --git a/driver/apdu/stdio.c b/driver/apdu/stdio.c index 9c513aa..dfabc46 100644 --- a/driver/apdu/stdio.c +++ b/driver/apdu/stdio.c @@ -340,7 +340,7 @@ static int libapduinterface_main(int argc, char **argv) return 0; } -static void libapduinterface_fini(void) +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { } @@ -349,5 +349,5 @@ const struct euicc_driver driver_apdu_stdio = { .name = "stdio", .init = (int (*)(void *))libapduinterface_init, .main = libapduinterface_main, - .fini = libapduinterface_fini, + .fini = (void (*)(void *))libapduinterface_fini, }; diff --git a/driver/driver.c b/driver/driver.c index 1ee8c0c..e976fc8 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -112,10 +112,10 @@ void euicc_driver_fini() { if (_driver_apdu != NULL) { - _driver_apdu->fini(); + _driver_apdu->fini(&euicc_driver_interface_apdu); } if (_driver_http != NULL) { - _driver_http->fini(); + _driver_http->fini(&euicc_driver_interface_http); } } diff --git a/driver/driver.private.h b/driver/driver.private.h index d1686d3..c882789 100644 --- a/driver/driver.private.h +++ b/driver/driver.private.h @@ -12,5 +12,5 @@ struct euicc_driver const char *name; int (*init)(void *interface); int (*main)(int argc, char **argv); - void (*fini)(void); + void (*fini)(void *interface); }; diff --git a/driver/http/curl.c b/driver/http/curl.c index c237485..a243ada 100644 --- a/driver/http/curl.c +++ b/driver/http/curl.c @@ -192,7 +192,7 @@ static int libhttpinterface_main(int argc, char **argv) return 0; } -static void libhttpinterface_fini(void) +static void libhttpinterface_fini(struct euicc_http_interface *ifstruct) { } @@ -201,5 +201,5 @@ const struct euicc_driver driver_http_curl = { .name = "curl", .init = (int (*)(void *))libhttpinterface_init, .main = libhttpinterface_main, - .fini = libhttpinterface_fini, + .fini = (void (*)(void *))libhttpinterface_fini, }; diff --git a/driver/http/stdio.c b/driver/http/stdio.c index f0ca865..c035495 100644 --- a/driver/http/stdio.c +++ b/driver/http/stdio.c @@ -272,7 +272,7 @@ static int libhttpinterface_main(int argc, char **argv) return 0; } -static void libhttpinterface_fini(void) +static void libhttpinterface_fini(struct euicc_http_interface *ifstruct) { } @@ -281,5 +281,5 @@ const struct euicc_driver driver_http_stdio = { .name = "stdio", .init = (int (*)(void *))libhttpinterface_init, .main = libhttpinterface_main, - .fini = libhttpinterface_fini, + .fini = (void (*)(void *))libhttpinterface_fini, }; From 435a185c815a84174fd9656177cd80e5f557c850 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 12:31:13 +0200 Subject: [PATCH 2/8] driver: apdu: rename QRTR QMI helpers to QMI helpers Almost all of the QRTR QMI helpers will be reused for direct QMI so, lets rename the sources to indicate that. Signed-off-by: Robert Marko --- driver/CMakeLists.txt | 4 +++- driver/apdu/{qmi_qrtr_helpers.c => qmi_helpers.c} | 2 +- driver/apdu/{qmi_qrtr_helpers.h => qmi_helpers.h} | 0 3 files changed, 4 insertions(+), 2 deletions(-) rename driver/apdu/{qmi_qrtr_helpers.c => qmi_helpers.c} (99%) rename driver/apdu/{qmi_qrtr_helpers.h => qmi_helpers.h} (100%) diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index 4745291..6939631 100644 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -61,7 +61,9 @@ endif() if(LPAC_WITH_APDU_QMI_QRTR) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLPAC_WITH_APDU_QMI_QRTR") - target_sources(euicc-drivers PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_qrtr.c ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_qrtr_helpers.c) + target_sources(euicc-drivers PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_qrtr.c + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_helpers.c) find_package(PkgConfig REQUIRED) pkg_check_modules(QRTR_GLIB REQUIRED IMPORTED_TARGET qrtr-glib) pkg_check_modules(QMI_GLIB REQUIRED IMPORTED_TARGET qmi-glib) diff --git a/driver/apdu/qmi_qrtr_helpers.c b/driver/apdu/qmi_helpers.c similarity index 99% rename from driver/apdu/qmi_qrtr_helpers.c rename to driver/apdu/qmi_helpers.c index c18504b..3d7757e 100644 --- a/driver/apdu/qmi_qrtr_helpers.c +++ b/driver/apdu/qmi_helpers.c @@ -3,7 +3,7 @@ * Copyright (c) 2024, Luca Weiss */ -#include "qmi_qrtr_helpers.h" +#include "qmi_helpers.h" static void async_result_ready(GObject *source_object, diff --git a/driver/apdu/qmi_qrtr_helpers.h b/driver/apdu/qmi_helpers.h similarity index 100% rename from driver/apdu/qmi_qrtr_helpers.h rename to driver/apdu/qmi_helpers.h From f69434e7f054d37e8478172d48e325c3e0392ec4 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 12:26:30 +0200 Subject: [PATCH 3/8] driver: apdu: extract common QMI code Support for using QMI directly and not over QRTR would use a lot of the same code as QMI over QRTR, so in order to prevent code duplication lets extract that common code so it can be reused. Signed-off-by: Robert Marko --- driver/CMakeLists.txt | 3 +- driver/apdu/qmi_common.c | 170 +++++++++++++++++++++++++++++++++++++ driver/apdu/qmi_common.h | 14 +++ driver/apdu/qmi_qrtr.c | 179 +++------------------------------------ 4 files changed, 197 insertions(+), 169 deletions(-) create mode 100644 driver/apdu/qmi_common.c create mode 100644 driver/apdu/qmi_common.h diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index 6939631..2df30fa 100644 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -63,7 +63,8 @@ if(LPAC_WITH_APDU_QMI_QRTR) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLPAC_WITH_APDU_QMI_QRTR") target_sources(euicc-drivers PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_qrtr.c - ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_helpers.c) + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_helpers.c + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_common.c) find_package(PkgConfig REQUIRED) pkg_check_modules(QRTR_GLIB REQUIRED IMPORTED_TARGET qrtr-glib) pkg_check_modules(QMI_GLIB REQUIRED IMPORTED_TARGET qmi-glib) diff --git a/driver/apdu/qmi_common.c b/driver/apdu/qmi_common.c new file mode 100644 index 0000000..439f482 --- /dev/null +++ b/driver/apdu/qmi_common.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024, Luca Weiss + */ + +#include + +#include "qmi_common.h" + +extern int lastChannelId; +extern int uimSlot; +extern GMainContext *context; +extern QmiClientUim *uimClient; + +int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GArray) apdu_data = NULL; + + /* Convert tx into request GArray */ + apdu_data = g_array_new(FALSE, FALSE, sizeof(guint8)); + for (uint32_t i = 0; i < tx_len; i++) + g_array_append_val(apdu_data, tx[i]); + + QmiMessageUimSendApduInput *input; + input = qmi_message_uim_send_apdu_input_new(); + qmi_message_uim_send_apdu_input_set_slot(input, uimSlot, NULL); + qmi_message_uim_send_apdu_input_set_channel_id(input, lastChannelId, NULL); + qmi_message_uim_send_apdu_input_set_apdu(input, apdu_data, NULL); + + QmiMessageUimSendApduOutput *output; + output = qmi_client_uim_send_apdu_sync(uimClient, input, context, &error); + + qmi_message_uim_send_apdu_input_unref(input); + + if (!qmi_message_uim_send_apdu_output_get_result(output, &error)) + { + fprintf(stderr, "error: send apdu operation failed: %s\n", error->message); + return -1; + } + + GArray *apdu_res = NULL; + if (!qmi_message_uim_send_apdu_output_get_apdu_response(output, &apdu_res, &error)) + { + fprintf(stderr, "error: get apdu response operation failed: %s\n", error->message); + return -1; + } + + /* Convert response GArray into rx */ + *rx_len = apdu_res->len; + *rx = malloc(*rx_len); + if (!*rx) + return -1; + for (guint i = 0; i < apdu_res->len; i++) + (*rx)[i] = apdu_res->data[i]; + + qmi_message_uim_send_apdu_output_unref(output); + + return 0; +} + +int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len) +{ + g_autoptr(GError) error = NULL; + guint8 channel_id; + + GArray *aid_data = g_array_new(FALSE, FALSE, sizeof(guint8)); + for (int i = 0; i < aid_len; i++) + g_array_append_val(aid_data, aid[i]); + + QmiMessageUimOpenLogicalChannelInput *input; + input = qmi_message_uim_open_logical_channel_input_new(); + qmi_message_uim_open_logical_channel_input_set_slot(input, uimSlot, NULL); + qmi_message_uim_open_logical_channel_input_set_aid(input, aid_data, NULL); + + QmiMessageUimOpenLogicalChannelOutput *output; + output = qmi_client_uim_open_logical_channel_sync(uimClient, input, context, &error); + + qmi_message_uim_open_logical_channel_input_unref(input); + g_array_unref(aid_data); + + if (!output) + { + fprintf(stderr, "error: send Open Logical Channel command failed: %s\n", error->message); + return -1; + } + + if (!qmi_message_uim_open_logical_channel_output_get_result(output, &error)) + { + fprintf(stderr, "error: open logical channel operation failed: %s\n", error->message); + return -1; + } + + if (!qmi_message_uim_open_logical_channel_output_get_channel_id(output, &channel_id, &error)) + { + fprintf(stderr, "error: get channel id operation failed: %s\n", error->message); + return -1; + } + lastChannelId = channel_id; + + g_debug("Opened logical channel with id %d", channel_id); + + qmi_message_uim_open_logical_channel_output_unref(output); + + return channel_id; +} + +void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t channel) +{ + g_autoptr(GError) error = NULL; + + QmiMessageUimLogicalChannelInput *input; + input = qmi_message_uim_logical_channel_input_new(); + qmi_message_uim_logical_channel_input_set_slot(input, uimSlot, NULL); + qmi_message_uim_logical_channel_input_set_channel_id(input, channel, NULL); + + QmiMessageUimLogicalChannelOutput *output; + output = qmi_client_uim_logical_channel_sync(uimClient, input, context, &error); + + qmi_message_uim_logical_channel_input_unref(input); + + if (error) + { + fprintf(stderr, "error: send Close Logical Channel command failed: %s\n", error->message); + return; + } + + if (!qmi_message_uim_logical_channel_output_get_result(output, &error)) + { + fprintf(stderr, "error: logical channel operation failed: %s\n", error->message); + return; + } + + /* Mark channel as having been cleaned up */ + if (channel == lastChannelId) + lastChannelId = -1; + + g_debug("Closed logical channel with id %d", channel); + + qmi_message_uim_logical_channel_output_unref(output); +} + +void qmi_apdu_interface_disconnect(struct euicc_ctx *ctx) +{ + g_autoptr(GError) error = NULL; + QmiClient *client = QMI_CLIENT(uimClient); + QmiDevice *device = QMI_DEVICE(qmi_client_get_device(client)); + + qmi_device_release_client_sync(device, client, context, &error); + uimClient = NULL; + + g_main_context_unref(context); + context = NULL; +} + +void qmi_cleanup(void) +{ + if (lastChannelId != -1) + { + fprintf(stderr, "Cleaning up leaked APDU channel %d\n", lastChannelId); + qmi_apdu_interface_logic_channel_close(NULL, lastChannelId); + lastChannelId = -1; + } +} + +void qmi_sighandler(int sig) +{ + // This triggers atexit() hooks and therefore call cleanup() + exit(0); +} diff --git a/driver/apdu/qmi_common.h b/driver/apdu/qmi_common.h new file mode 100644 index 0000000..8a5de0a --- /dev/null +++ b/driver/apdu/qmi_common.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024, Luca Weiss + */ + +#include +#include "qmi_helpers.h" + +int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len); +int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len); +void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t channel); +void qmi_apdu_interface_disconnect(struct euicc_ctx *ctx); +void qmi_cleanup(void); +void qmi_sighandler(int sig); diff --git a/driver/apdu/qmi_qrtr.c b/driver/apdu/qmi_qrtr.c index 8227ed4..1169ad7 100644 --- a/driver/apdu/qmi_qrtr.c +++ b/driver/apdu/qmi_qrtr.c @@ -11,13 +11,13 @@ #include #include #include -#include "qmi_qrtr_helpers.h" +#include "qmi_common.h" -static int lastChannelId = -1; -static int uimSlot = -1; -static GMainContext *context = NULL; +int lastChannelId = -1; +int uimSlot = -1; +GMainContext *context = NULL; static QrtrBus *bus = NULL; -static QmiClientUim *uimClient = NULL; +QmiClientUim *uimClient = NULL; static int apdu_interface_connect(struct euicc_ctx *ctx) { @@ -80,176 +80,19 @@ static int apdu_interface_connect(struct euicc_ctx *ctx) return 0; } -static void apdu_interface_disconnect(struct euicc_ctx *ctx) -{ - g_autoptr(GError) error = NULL; - QmiClient *client = QMI_CLIENT(uimClient); - QmiDevice *device = QMI_DEVICE(qmi_client_get_device(client)); - - qmi_device_release_client_sync(device, client, context, &error); - uimClient = NULL; - - g_main_context_unref(context); - context = NULL; -} - -static int apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) -{ - g_autoptr(GError) error = NULL; - g_autoptr(GArray) apdu_data = NULL; - - /* Convert tx into request GArray */ - apdu_data = g_array_new(FALSE, FALSE, sizeof(guint8)); - for (uint32_t i = 0; i < tx_len; i++) - g_array_append_val(apdu_data, tx[i]); - - QmiMessageUimSendApduInput *input; - input = qmi_message_uim_send_apdu_input_new(); - qmi_message_uim_send_apdu_input_set_slot(input, uimSlot, NULL); - qmi_message_uim_send_apdu_input_set_channel_id(input, lastChannelId, NULL); - qmi_message_uim_send_apdu_input_set_apdu(input, apdu_data, NULL); - - QmiMessageUimSendApduOutput *output; - output = qmi_client_uim_send_apdu_sync(uimClient, input, context, &error); - - qmi_message_uim_send_apdu_input_unref(input); - - if (!qmi_message_uim_send_apdu_output_get_result(output, &error)) - { - fprintf(stderr, "error: send apdu operation failed: %s\n", error->message); - return -1; - } - - GArray *apdu_res = NULL; - if (!qmi_message_uim_send_apdu_output_get_apdu_response(output, &apdu_res, &error)) - { - fprintf(stderr, "error: get apdu response operation failed: %s\n", error->message); - return -1; - } - - /* Convert response GArray into rx */ - *rx_len = apdu_res->len; - *rx = malloc(*rx_len); - if (!*rx) - return -1; - for (guint i = 0; i < apdu_res->len; i++) - (*rx)[i] = apdu_res->data[i]; - - qmi_message_uim_send_apdu_output_unref(output); - - return 0; -} - -static int apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len) -{ - g_autoptr(GError) error = NULL; - guint8 channel_id; - - GArray *aid_data = g_array_new(FALSE, FALSE, sizeof(guint8)); - for (int i = 0; i < aid_len; i++) - g_array_append_val(aid_data, aid[i]); - - QmiMessageUimOpenLogicalChannelInput *input; - input = qmi_message_uim_open_logical_channel_input_new(); - qmi_message_uim_open_logical_channel_input_set_slot(input, uimSlot, NULL); - qmi_message_uim_open_logical_channel_input_set_aid(input, aid_data, NULL); - - QmiMessageUimOpenLogicalChannelOutput *output; - output = qmi_client_uim_open_logical_channel_sync(uimClient, input, context, &error); - - qmi_message_uim_open_logical_channel_input_unref(input); - g_array_unref(aid_data); - - if (!output) - { - fprintf(stderr, "error: send Open Logical Channel command failed: %s\n", error->message); - return -1; - } - - if (!qmi_message_uim_open_logical_channel_output_get_result(output, &error)) - { - fprintf(stderr, "error: open logical channel operation failed: %s\n", error->message); - return -1; - } - - if (!qmi_message_uim_open_logical_channel_output_get_channel_id(output, &channel_id, &error)) - { - fprintf(stderr, "error: get channel id operation failed: %s\n", error->message); - return -1; - } - lastChannelId = channel_id; - - g_debug("Opened logical channel with id %d", channel_id); - - qmi_message_uim_open_logical_channel_output_unref(output); - - return channel_id; -} - -static void apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t channel) -{ - g_autoptr(GError) error = NULL; - - QmiMessageUimLogicalChannelInput *input; - input = qmi_message_uim_logical_channel_input_new(); - qmi_message_uim_logical_channel_input_set_slot(input, uimSlot, NULL); - qmi_message_uim_logical_channel_input_set_channel_id(input, channel, NULL); - - QmiMessageUimLogicalChannelOutput *output; - output = qmi_client_uim_logical_channel_sync(uimClient, input, context, &error); - - qmi_message_uim_logical_channel_input_unref(input); - - if (error) - { - fprintf(stderr, "error: send Close Logical Channel command failed: %s\n", error->message); - return; - } - - if (!qmi_message_uim_logical_channel_output_get_result(output, &error)) - { - fprintf(stderr, "error: logical channel operation failed: %s\n", error->message); - return; - } - - /* Mark channel as having been cleaned up */ - if (channel == lastChannelId) - lastChannelId = -1; - - g_debug("Closed logical channel with id %d", channel); - - qmi_message_uim_logical_channel_output_unref(output); -} - -static void cleanup(void) -{ - if (lastChannelId != -1) - { - fprintf(stderr, "Cleaning up leaked APDU channel %d\n", lastChannelId); - apdu_interface_logic_channel_close(NULL, lastChannelId); - lastChannelId = -1; - } -} - -static void sighandler(int sig) -{ - // This triggers atexit() hooks and therefore call cleanup() - exit(0); -} - static int libapduinterface_init(struct euicc_apdu_interface *ifstruct) { memset(ifstruct, 0, sizeof(struct euicc_apdu_interface)); ifstruct->connect = apdu_interface_connect; - ifstruct->disconnect = apdu_interface_disconnect; - ifstruct->logic_channel_open = apdu_interface_logic_channel_open; - ifstruct->logic_channel_close = apdu_interface_logic_channel_close; - ifstruct->transmit = apdu_interface_transmit; + ifstruct->disconnect = qmi_apdu_interface_disconnect; + ifstruct->logic_channel_open = qmi_apdu_interface_logic_channel_open; + ifstruct->logic_channel_close = qmi_apdu_interface_logic_channel_close; + ifstruct->transmit = qmi_apdu_interface_transmit; // Install cleanup routine - atexit(cleanup); - signal(SIGINT, sighandler); + atexit(qmi_cleanup); + signal(SIGINT, qmi_sighandler); /* * Allow the user to select the SIM card slot via environment variable. From faa0a1426d0ec0baba32e4eec6464da8b4a457cb Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 13:08:59 +0200 Subject: [PATCH 4/8] driver: apdu: qmi-helpers: allow compiling without libqrtr Direct QMI backend wont use any of the libqmi QRTR functionality so it wont depend on libqrtr and thus we need to make sure QMI helpers still compile without libqrtr in the system. Signed-off-by: Robert Marko --- driver/apdu/qmi_helpers.c | 2 ++ driver/apdu/qmi_helpers.h | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/driver/apdu/qmi_helpers.c b/driver/apdu/qmi_helpers.c index 3d7757e..63a8c39 100644 --- a/driver/apdu/qmi_helpers.c +++ b/driver/apdu/qmi_helpers.c @@ -16,6 +16,7 @@ async_result_ready(GObject *source_object, *result_out = g_object_ref(res); } +#ifdef LPAC_WITH_APDU_QMI_QRTR QrtrBus * qrtr_bus_new_sync(GMainContext *context, GError **error) @@ -56,6 +57,7 @@ qmi_device_new_from_node_sync(QrtrNode *node, return qmi_device_new_from_node_finish(result, error); } +#endif gboolean qmi_device_open_sync(QmiDevice *device, diff --git a/driver/apdu/qmi_helpers.h b/driver/apdu/qmi_helpers.h index 5a910f5..de98d3c 100644 --- a/driver/apdu/qmi_helpers.h +++ b/driver/apdu/qmi_helpers.h @@ -3,9 +3,11 @@ * Copyright (c) 2024, Luca Weiss */ -#include #include +#ifdef LPAC_WITH_APDU_QMI_QRTR +#include + QrtrBus *qrtr_bus_new_sync( GMainContext *context, GError **error); @@ -15,6 +17,7 @@ qmi_device_new_from_node_sync( QrtrNode *node, GMainContext *context, GError **error); +#endif gboolean qmi_device_open_sync( From e02321fa52236fe9af3b7ae2e1be86c67f2f47ee Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 19:53:45 +0200 Subject: [PATCH 5/8] driver: apdu: dont use global variables for QMI Since we split out the common QMI code then we cannot be using global variables since existing QRTR and the coming QMI drivers will clash by trying to use the same global variable names with the common code. So, lets move to passing a structure which is driver specific instead. Since we are not using global variables anymore, we cannot be using atexit anymore, so lets move that cleanup step to driver finish OP instead. Signed-off-by: Robert Marko --- driver/apdu/qmi_common.c | 55 ++++++++++++++++++---------------------- driver/apdu/qmi_common.h | 11 ++++++-- driver/apdu/qmi_qrtr.c | 40 +++++++++++++++++------------ 3 files changed, 57 insertions(+), 49 deletions(-) diff --git a/driver/apdu/qmi_common.c b/driver/apdu/qmi_common.c index 439f482..6f73646 100644 --- a/driver/apdu/qmi_common.c +++ b/driver/apdu/qmi_common.c @@ -7,13 +7,9 @@ #include "qmi_common.h" -extern int lastChannelId; -extern int uimSlot; -extern GMainContext *context; -extern QmiClientUim *uimClient; - int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len) { + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; g_autoptr(GError) error = NULL; g_autoptr(GArray) apdu_data = NULL; @@ -24,12 +20,12 @@ int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *r QmiMessageUimSendApduInput *input; input = qmi_message_uim_send_apdu_input_new(); - qmi_message_uim_send_apdu_input_set_slot(input, uimSlot, NULL); - qmi_message_uim_send_apdu_input_set_channel_id(input, lastChannelId, NULL); + qmi_message_uim_send_apdu_input_set_slot(input, qmi_priv->uimSlot, NULL); + qmi_message_uim_send_apdu_input_set_channel_id(input, qmi_priv->lastChannelId, NULL); qmi_message_uim_send_apdu_input_set_apdu(input, apdu_data, NULL); QmiMessageUimSendApduOutput *output; - output = qmi_client_uim_send_apdu_sync(uimClient, input, context, &error); + output = qmi_client_uim_send_apdu_sync(qmi_priv->uimClient, input, qmi_priv->context, &error); qmi_message_uim_send_apdu_input_unref(input); @@ -61,6 +57,7 @@ int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *r int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len) { + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; g_autoptr(GError) error = NULL; guint8 channel_id; @@ -70,11 +67,11 @@ int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t * QmiMessageUimOpenLogicalChannelInput *input; input = qmi_message_uim_open_logical_channel_input_new(); - qmi_message_uim_open_logical_channel_input_set_slot(input, uimSlot, NULL); + qmi_message_uim_open_logical_channel_input_set_slot(input, qmi_priv->uimSlot, NULL); qmi_message_uim_open_logical_channel_input_set_aid(input, aid_data, NULL); QmiMessageUimOpenLogicalChannelOutput *output; - output = qmi_client_uim_open_logical_channel_sync(uimClient, input, context, &error); + output = qmi_client_uim_open_logical_channel_sync(qmi_priv->uimClient, input, qmi_priv->context, &error); qmi_message_uim_open_logical_channel_input_unref(input); g_array_unref(aid_data); @@ -96,7 +93,7 @@ int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t * fprintf(stderr, "error: get channel id operation failed: %s\n", error->message); return -1; } - lastChannelId = channel_id; + qmi_priv->lastChannelId = channel_id; g_debug("Opened logical channel with id %d", channel_id); @@ -107,15 +104,16 @@ int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t * void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t channel) { + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; g_autoptr(GError) error = NULL; QmiMessageUimLogicalChannelInput *input; input = qmi_message_uim_logical_channel_input_new(); - qmi_message_uim_logical_channel_input_set_slot(input, uimSlot, NULL); + qmi_message_uim_logical_channel_input_set_slot(input, qmi_priv->uimSlot, NULL); qmi_message_uim_logical_channel_input_set_channel_id(input, channel, NULL); QmiMessageUimLogicalChannelOutput *output; - output = qmi_client_uim_logical_channel_sync(uimClient, input, context, &error); + output = qmi_client_uim_logical_channel_sync(qmi_priv->uimClient, input, qmi_priv->context, &error); qmi_message_uim_logical_channel_input_unref(input); @@ -132,8 +130,8 @@ void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t chann } /* Mark channel as having been cleaned up */ - if (channel == lastChannelId) - lastChannelId = -1; + if (channel == qmi_priv->lastChannelId) + qmi_priv->lastChannelId = -1; g_debug("Closed logical channel with id %d", channel); @@ -142,29 +140,24 @@ void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t chann void qmi_apdu_interface_disconnect(struct euicc_ctx *ctx) { + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; g_autoptr(GError) error = NULL; - QmiClient *client = QMI_CLIENT(uimClient); + QmiClient *client = QMI_CLIENT(qmi_priv->uimClient); QmiDevice *device = QMI_DEVICE(qmi_client_get_device(client)); - qmi_device_release_client_sync(device, client, context, &error); - uimClient = NULL; + qmi_device_release_client_sync(device, client, qmi_priv->context, &error); + qmi_priv->uimClient = NULL; - g_main_context_unref(context); - context = NULL; + g_main_context_unref(qmi_priv->context); + qmi_priv->context = NULL; } -void qmi_cleanup(void) +void qmi_cleanup(struct qmi_data *qmi_priv) { - if (lastChannelId != -1) + if (qmi_priv->lastChannelId != -1) { - fprintf(stderr, "Cleaning up leaked APDU channel %d\n", lastChannelId); - qmi_apdu_interface_logic_channel_close(NULL, lastChannelId); - lastChannelId = -1; + fprintf(stderr, "Cleaning up leaked APDU channel %d\n", qmi_priv->lastChannelId); + qmi_apdu_interface_logic_channel_close(NULL, qmi_priv->lastChannelId); + qmi_priv->lastChannelId = -1; } } - -void qmi_sighandler(int sig) -{ - // This triggers atexit() hooks and therefore call cleanup() - exit(0); -} diff --git a/driver/apdu/qmi_common.h b/driver/apdu/qmi_common.h index 8a5de0a..2ddb692 100644 --- a/driver/apdu/qmi_common.h +++ b/driver/apdu/qmi_common.h @@ -4,11 +4,18 @@ */ #include +#include #include "qmi_helpers.h" +struct qmi_data { + int lastChannelId; + int uimSlot; + GMainContext *context; + QmiClientUim *uimClient; +}; + int qmi_apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len); int qmi_apdu_interface_logic_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, uint8_t aid_len); void qmi_apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t channel); void qmi_apdu_interface_disconnect(struct euicc_ctx *ctx); -void qmi_cleanup(void); -void qmi_sighandler(int sig); +void qmi_cleanup(struct qmi_data *qmi_priv); diff --git a/driver/apdu/qmi_qrtr.c b/driver/apdu/qmi_qrtr.c index 1169ad7..cb395c9 100644 --- a/driver/apdu/qmi_qrtr.c +++ b/driver/apdu/qmi_qrtr.c @@ -13,23 +13,20 @@ #include #include "qmi_common.h" -int lastChannelId = -1; -int uimSlot = -1; -GMainContext *context = NULL; static QrtrBus *bus = NULL; -QmiClientUim *uimClient = NULL; static int apdu_interface_connect(struct euicc_ctx *ctx) { + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; g_autoptr(GError) error = NULL; QrtrNode *node = NULL; QmiDevice *device = NULL; QmiClient *client = NULL; bool found = false; - context = g_main_context_new(); + qmi_priv->context = g_main_context_new(); - bus = qrtr_bus_new_sync(context, &error); + bus = qrtr_bus_new_sync(qmi_priv->context, &error); if (bus == NULL) { fprintf(stderr, "error: connect to QRTR bus failed: %s\n", error->message); @@ -54,34 +51,42 @@ static int apdu_interface_connect(struct euicc_ctx *ctx) return -1; } - device = qmi_device_new_from_node_sync(node, context, &error); + device = qmi_device_new_from_node_sync(node, qmi_priv->context, &error); if (!device) { fprintf(stderr, "error: create QMI device from QRTR node failed: %s\n", error->message); return -1; } - qmi_device_open_sync(device, context, &error); + qmi_device_open_sync(device, qmi_priv->context, &error); if (error) { fprintf(stderr, "error: open QMI device failed: %s\n", error->message); return -1; } - client = qmi_device_allocate_client_sync(device, context, &error); + client = qmi_device_allocate_client_sync(device, qmi_priv->context, &error); if (!client) { fprintf(stderr, "error: allocate QMI client failed: %s\n", error->message); return -1; } - uimClient = QMI_CLIENT_UIM(client); + qmi_priv->uimClient = QMI_CLIENT_UIM(client); return 0; } static int libapduinterface_init(struct euicc_apdu_interface *ifstruct) { + struct qmi_data *qmi_priv; + + qmi_priv = malloc(sizeof(struct qmi_data)); + if(!qmi_priv) { + fprintf(stderr, "Failed allocating memory\n"); + return -1; + } + memset(ifstruct, 0, sizeof(struct euicc_apdu_interface)); ifstruct->connect = apdu_interface_connect; @@ -90,23 +95,21 @@ static int libapduinterface_init(struct euicc_apdu_interface *ifstruct) ifstruct->logic_channel_close = qmi_apdu_interface_logic_channel_close; ifstruct->transmit = qmi_apdu_interface_transmit; - // Install cleanup routine - atexit(qmi_cleanup); - signal(SIGINT, qmi_sighandler); - /* * Allow the user to select the SIM card slot via environment variable. * Use the primary SIM slot if not set. */ if (getenv("UIM_SLOT")) { - uimSlot = atoi(getenv("UIM_SLOT")); + qmi_priv->uimSlot = atoi(getenv("UIM_SLOT")); } else { - uimSlot = 1; + qmi_priv->uimSlot = 1; } + ifstruct->userdata = qmi_priv; + return 0; } @@ -117,6 +120,11 @@ static int libapduinterface_main(int argc, char **argv) static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) { + struct qmi_data *qmi_priv = ifstruct->userdata; + + qmi_cleanup(qmi_priv); + + free(qmi_priv); } const struct euicc_driver driver_apdu_qmi_qrtr = { From 94914df9eb19380e07346f7204c1bf96b91d6fca Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 12:44:13 +0200 Subject: [PATCH 6/8] driver: apdu: add QMI backend Previously QMI over QRTR support was added, however that is only present in modern Qualcomm modems and only when running in PCIe mode and its quite common to still only use even the latest modems via USB. In that case, they are all still controllable via QMI but it is directly exposed as a character device in Linux so we can reuse most of the code from QMI over QRTR support but drop the support for libqrtr to talk to the modems. We require the QMI device path to be passed via QMI_DEVICE env variable for the backend to operate. Signed-off-by: Robert Marko --- driver/CMakeLists.txt | 15 ++++++ driver/apdu/qmi.c | 101 ++++++++++++++++++++++++++++++++++++++ driver/apdu/qmi.h | 8 +++ driver/apdu/qmi_helpers.c | 26 ++++++++++ driver/apdu/qmi_helpers.h | 8 +++ driver/driver.c | 7 +++ 6 files changed, 165 insertions(+) create mode 100644 driver/apdu/qmi.c create mode 100644 driver/apdu/qmi.h diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index 2df30fa..4b72258 100644 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -4,6 +4,7 @@ cmake_dependent_option(LPAC_DYNAMIC_DRIVERS "Build lpac/libeuicc driver backends option(LPAC_WITH_APDU_PCSC "Build APDU PCSC Backend (requires PCSC libraries)" ON) option(LPAC_WITH_APDU_AT "Build APDU AT Backend" ON) option(LPAC_WITH_APDU_GBINDER "Build APDU Gbinder backend for libhybris devices (requires gbinder headers)" OFF) +option(LPAC_WITH_APDU_QMI "Build QMI backend for Qualcomm devices (requires libqmi)" OFF) option(LPAC_WITH_APDU_QMI_QRTR "Build QMI-over-QRTR backend for Qualcomm devices (requires libqrtr and libqmi headers)" OFF) option(LPAC_WITH_HTTP_CURL "Build HTTP Curl interface" ON) @@ -59,6 +60,20 @@ if(LPAC_WITH_APDU_GBINDER) endif() endif() +if(LPAC_WITH_APDU_QMI) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLPAC_WITH_APDU_QMI") + target_sources(euicc-drivers PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi.c + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_helpers.c + ${CMAKE_CURRENT_SOURCE_DIR}/apdu/qmi_common.c) + find_package(PkgConfig REQUIRED) + pkg_check_modules(QMI_GLIB REQUIRED IMPORTED_TARGET qmi-glib) + target_link_libraries(euicc-drivers PkgConfig::QMI_GLIB) + if(LPAC_DYNAMIC_DRIVERS) + list(APPEND LIBEUICC_DRIVERS_REQUIRES "qmi-glib") + endif() +endif() + if(LPAC_WITH_APDU_QMI_QRTR) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLPAC_WITH_APDU_QMI_QRTR") target_sources(euicc-drivers PRIVATE diff --git a/driver/apdu/qmi.c b/driver/apdu/qmi.c new file mode 100644 index 0000000..43dff80 --- /dev/null +++ b/driver/apdu/qmi.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024, Robert Marko + */ +#include "qmi.h" + +#include +#include "qmi_common.h" + +static int apdu_interface_connect(struct euicc_ctx *ctx) +{ + struct qmi_data *qmi_priv = ctx->apdu.interface->userdata; + g_autoptr(GError) error = NULL; + QmiDevice *device = NULL; + QmiClient *client = NULL; + const char *device_path; + GFile *file; + + if (!(device_path = getenv("QMI_DEVICE"))) { + fprintf(stderr, "No QMI device path specified!\n"); + return -1; + } + file = g_file_new_for_path(device_path); + + qmi_priv->context = g_main_context_new(); + + device = qmi_device_new_from_path(file, qmi_priv->context, &error); + if (!device) { + fprintf(stderr, "error: create QMI device from path failed: %s\n", error->message); + return -1; + } + + qmi_device_open_sync(device, qmi_priv->context, &error); + if (error) { + fprintf(stderr, "error: open QMI device failed: %s\n", error->message); + return -1; + } + + client = qmi_device_allocate_client_sync(device, qmi_priv->context, &error); + if (!client) { + fprintf(stderr, "error: allocate QMI client failed: %s\n", error->message); + return -1; + } + + qmi_priv->uimClient = QMI_CLIENT_UIM(client); + + return 0; +} + +static int libapduinterface_init(struct euicc_apdu_interface *ifstruct) +{ + struct qmi_data *qmi_priv; + + qmi_priv = malloc(sizeof(struct qmi_data)); + if(!qmi_priv) { + fprintf(stderr, "Failed allocating memory\n"); + return -1; + } + + memset(ifstruct, 0, sizeof(struct euicc_apdu_interface)); + ifstruct->connect = apdu_interface_connect; + ifstruct->disconnect = qmi_apdu_interface_disconnect; + ifstruct->logic_channel_open = qmi_apdu_interface_logic_channel_open; + ifstruct->logic_channel_close = qmi_apdu_interface_logic_channel_close; + ifstruct->transmit = qmi_apdu_interface_transmit; + + /* + * Allow the user to select the SIM card slot via environment variable. + * Use the primary SIM slot if not set. + */ + if (getenv("UIM_SLOT")) + qmi_priv->uimSlot = atoi(getenv("UIM_SLOT")); + else + qmi_priv->uimSlot = 1; + + ifstruct->userdata = qmi_priv; + + return 0; +} + +static int libapduinterface_main(int argc, char **argv) +{ + return 0; +} + +static void libapduinterface_fini(struct euicc_apdu_interface *ifstruct) +{ + struct qmi_data *qmi_priv = ifstruct->userdata; + + qmi_cleanup(qmi_priv); + + free(qmi_priv); +} + +const struct euicc_driver driver_apdu_qmi = { + .type = DRIVER_APDU, + .name = "qmi", + .init = (int (*)(void *))libapduinterface_init, + .main = libapduinterface_main, + .fini = (void (*)(void *))libapduinterface_fini, +}; diff --git a/driver/apdu/qmi.h b/driver/apdu/qmi.h new file mode 100644 index 0000000..7c007f7 --- /dev/null +++ b/driver/apdu/qmi.h @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2024, Robert Marko + */ +#pragma once +#include + +extern const struct euicc_driver driver_apdu_qmi; diff --git a/driver/apdu/qmi_helpers.c b/driver/apdu/qmi_helpers.c index 63a8c39..26726ca 100644 --- a/driver/apdu/qmi_helpers.c +++ b/driver/apdu/qmi_helpers.c @@ -59,6 +59,32 @@ qmi_device_new_from_node_sync(QrtrNode *node, } #endif +#ifdef LPAC_WITH_APDU_QMI +QmiDevice * +qmi_device_new_from_path(GFile *file, + GMainContext *context, + GError **error) +{ + g_autoptr(GMainContextPusher) pusher = NULL; + g_autoptr(GAsyncResult) result = NULL; + g_autofree gchar *id = NULL; + + pusher = g_main_context_pusher_new(context); + + id = g_file_get_path (file); + if (id) + qmi_device_new(file, + NULL, + async_result_ready, + &result); + + while (result == NULL) + g_main_context_iteration(context, TRUE); + + return qmi_device_new_finish(result, error); +} +#endif + gboolean qmi_device_open_sync(QmiDevice *device, GMainContext *context, diff --git a/driver/apdu/qmi_helpers.h b/driver/apdu/qmi_helpers.h index de98d3c..0184b88 100644 --- a/driver/apdu/qmi_helpers.h +++ b/driver/apdu/qmi_helpers.h @@ -19,6 +19,14 @@ qmi_device_new_from_node_sync( GError **error); #endif +#ifdef LPAC_WITH_APDU_QMI +QmiDevice * +qmi_device_new_from_path( + GFile *file, + GMainContext *context, + GError **error); +#endif + gboolean qmi_device_open_sync( QmiDevice *device, diff --git a/driver/driver.c b/driver/driver.c index e976fc8..1fd07cf 100644 --- a/driver/driver.c +++ b/driver/driver.c @@ -8,6 +8,10 @@ #include "driver/apdu/gbinder_hidl.h" #endif +#ifdef LPAC_WITH_APDU_QMI +#include "driver/apdu/qmi.h" +#endif + #ifdef LPAC_WITH_APDU_QMI_QRTR #include "driver/apdu/qmi_qrtr.h" #endif @@ -28,6 +32,9 @@ static const struct euicc_driver *drivers[] = { #ifdef LPAC_WITH_APDU_GBINDER &driver_apdu_gbinder_hidl, #endif +#ifdef LPAC_WITH_APDU_QMI + &driver_apdu_qmi, +#endif #ifdef LPAC_WITH_APDU_QMI_QRTR &driver_apdu_qmi_qrtr, #endif From 7b7772dc4672bd2431fd21d80e15c65d26fed396 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Wed, 3 Jul 2024 20:25:33 +0200 Subject: [PATCH 7/8] docs: ENVVARS: document QMI backend Document the new direct QMI backend ENV variables as well as make it clear that UIM_SLOT is not a QMI QRTR only variable. Signed-off-by: Robert Marko --- docs/ENVVARS.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/ENVVARS.md b/docs/ENVVARS.md index 5a5a5fa..e99e804 100644 --- a/docs/ENVVARS.md +++ b/docs/ENVVARS.md @@ -6,6 +6,7 @@ - `at`: use AT commands interface used by LTE module - `pcsc`: use PC/SC Smart Card API - `stdio`: use standard input/output + - `qmi`: use QMI - `qmi_qrtr`: use QMI over QRTR - GBinder-based backends for `libhybris` (Halium) distributions: - `gbinder_hidl`: use HIDL IRadio (SoC launched before Android 13) @@ -13,7 +14,8 @@ - `curl`: use libcurl - `stdio`: use standard input/ouput * `AT_DEVICE`: specify which serial port device will be used by AT APDU backend. -* `UIM_SLOT`: specify which UIM slot will be used by QMI QRTR APDU backend. (default: 1) +* `QMI_DEVICE`: specify which QMI device will be used by QMI APDU backend. +* `UIM_SLOT`: specify which UIM slot will be used by QMI APDU backends. (default: 1) * `DRIVER_IFID`: specify which PC/SC interface will be used by PC/SC APDU backend. ## Debug From 75204f3f57069521c0e6944e3b956b30c5faa523 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 8 Jul 2024 10:56:00 +0200 Subject: [PATCH 8/8] driver: apdu: qmi-helpers: support opening QMI device in proxy mode Currently, we are using QMI_DEVICE_OPEN_FLAGS_NONE to open the QMI device and thus we are requesting exclusive access to the device while we need to talk to it. This will work fine as long as we are the only thing trying to use that QMI device at the same time or the device was not already opened in proxy mode. This is an issue since ModemManager will open the device in proxy mode so that qmicli or other applications can still talk to the same QMI device but it will break lpac from trying to use QMI. So, lets try and open the device in proxy mode, libqmi will the start the qmi-proxy service automatically as its built and installed as part of it. Signed-off-by: Robert Marko --- driver/apdu/qmi_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/apdu/qmi_helpers.c b/driver/apdu/qmi_helpers.c index 26726ca..bc3e2d0 100644 --- a/driver/apdu/qmi_helpers.c +++ b/driver/apdu/qmi_helpers.c @@ -96,7 +96,7 @@ qmi_device_open_sync(QmiDevice *device, pusher = g_main_context_pusher_new(context); qmi_device_open(device, - QMI_DEVICE_OPEN_FLAGS_NONE, + QMI_DEVICE_OPEN_FLAGS_PROXY, 15, NULL, async_result_ready,