[PATCH 1/2] Provide mechansim to disable PIN2 on QMI modems
David McCullough
david.mccullough at accelecon.com
Mon Sep 15 04:10:04 PDT 2014
Some modems report PIN2 support via QMI even though they do not actually
support PIN2. Here is a snippet of debug on the Sierra Wireless MC7354
sghowing this. mmcli would incorrectly report PIN unlocking errors.
<debug> [1410404595.230075] [mm-broadband-modem-qmi.c:1535] modem_load_unlock_required(): loading unlock required...
[/dev/cdc-wdm0] Sent message...
<<<<<< RAW:
<<<<<< length = 13
<<<<<< data = 01:0C:00:00:02:02:00:09:00:2B:00:00:00
[/dev/cdc-wdm0] Sent message (translated)...
<<<<<< QMUX:
<<<<<< length = 12
<<<<<< flags = 0x00
<<<<<< service = "dms"
<<<<<< client = 2
<<<<<< QMI:
<<<<<< flags = "none"
<<<<<< transaction = 9
<<<<<< tlv_length = 0
<<<<<< message = "UIM Get PIN Status" (0x002B)
[/dev/cdc-wdm0] Received message...
>>>>>> RAW:
>>>>>> length = 32
>>>>>> data = 01:1F:00:80:02:02:02:09:00:2B:00:13:00:02:04:00:00:00:00:00:12:03:00:01:03:0A:11:03:00:03:03:0A
[/dev/cdc-wdm0] Received message (translated)...
>>>>>> QMUX:
>>>>>> length = 31
>>>>>> flags = 0x80
>>>>>> service = "dms"
>>>>>> client = 2
>>>>>> QMI:
>>>>>> flags = "response"
>>>>>> transaction = 9
>>>>>> tlv_length = 19
>>>>>> message = "UIM Get PIN Status" (0x002B)
>>>>>> TLV:
>>>>>> type = "Result" (0x02)
>>>>>> length = 4
>>>>>> value = 00:00:00:00
>>>>>> translated = SUCCESS
>>>>>> TLV:
>>>>>> type = "PIN2 Status" (0x12)
>>>>>> length = 3
>>>>>> value = 01:03:0A
>>>>>> translated = [ current_status = 'enabled-not-verified' verify_retries_left = '3' unblock_retries_left = '10' ]
>>>>>> TLV:
>>>>>> type = "PIN1 Status" (0x11)
>>>>>> length = 3
>>>>>> value = 03:03:0A
>>>>>> translated = [ current_status = 'disabled' verify_retries_left = '3' unblock_retries_left = '10' ]
# mmcli -m 0 --command="+cpin2?"
error: command failed: 'GDBus.Error:org.freedesktop.ModemManager1.Error.MobileEquipment.Unknown: Unknown error'
# mmcli -m 0 --command="+cpinc?"
response: '+CPINC: NOT IMPLEMENTED'
# mmcli -m 0 --command="+cpin?"
response: '+CPIN: READY'
This patch adds a UDEV enviroment setting to prevent the recognition of PIN2:
ID_MM_IGNORE_PIN2
Signed-off-by: David McCullough <david.mccullough at accelecon.com>
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index f4b6c55..e0f2f04 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <ctype.h>
#include <arpa/inet.h>
+#include <gudev/gudev.h>
#include "mm-broadband-modem-qmi.h"
@@ -1417,6 +1418,24 @@ modem_load_own_numbers (MMIfaceModem *self,
}
/*****************************************************************************/
+/* context to help pass info to pin operations */
+
+typedef struct {
+ MMIfaceModem *self;
+ GSimpleAsyncResult *result;
+ gboolean ignore_pin2;
+} PinContext;
+
+static void
+pin_context_complete_and_free (PinContext *ctx)
+{
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->self);
+ g_slice_free (PinContext, ctx);
+}
+
+/*****************************************************************************/
/* Check if unlock required (Modem interface) */
static MMModemLock
@@ -1434,7 +1453,7 @@ modem_load_unlock_required_finish (MMIfaceModem *self,
static void
dms_uim_get_pin_status_ready (QmiClientDms *client,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ PinContext *ctx)
{
QmiMessageDmsUimGetPinStatusOutput *output;
GError *error = NULL;
@@ -1442,14 +1461,14 @@ dms_uim_get_pin_status_ready (QmiClientDms *client,
output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
} else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
/* Fatal, so that we mark the modem unusable.*/
if (g_error_matches (error,
QMI_PROTOCOL_ERROR,
QMI_PROTOCOL_ERROR_UIM_UNINITIALIZED)) {
/* This error won't force a pin check retry */
- g_simple_async_result_set_error (simple,
+ g_simple_async_result_set_error (ctx->result,
MM_MOBILE_EQUIPMENT_ERROR,
MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE,
"SIM failure: %s",
@@ -1460,7 +1479,7 @@ dms_uim_get_pin_status_ready (QmiClientDms *client,
else if (g_error_matches (error,
QMI_PROTOCOL_ERROR,
QMI_PROTOCOL_ERROR_INTERNAL)) {
- g_simple_async_result_set_error (simple,
+ g_simple_async_result_set_error (ctx->result,
MM_CORE_ERROR,
MM_CORE_ERROR_RETRY,
"Couldn't get PIN status (retry): %s",
@@ -1470,7 +1489,7 @@ dms_uim_get_pin_status_ready (QmiClientDms *client,
/* Other errors, just propagate them */
else {
g_prefix_error (&error, "Couldn't get PIN status: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
}
} else {
MMModemLock lock = MM_MODEM_LOCK_UNKNOWN;
@@ -1484,7 +1503,7 @@ dms_uim_get_pin_status_ready (QmiClientDms *client,
NULL))
lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, TRUE);
- if (lock == MM_MODEM_LOCK_NONE &&
+ if (lock == MM_MODEM_LOCK_NONE && !ctx->ignore_pin2 &&
qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
output,
¤t_status,
@@ -1493,14 +1512,13 @@ dms_uim_get_pin_status_ready (QmiClientDms *client,
NULL))
lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, FALSE);
- g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (lock), NULL);
+ g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (lock), NULL);
}
if (output)
qmi_message_dms_uim_get_pin_status_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ pin_context_complete_and_free (ctx);
}
static void
@@ -1509,7 +1527,11 @@ modem_load_unlock_required (MMIfaceModem *self,
gpointer user_data)
{
GSimpleAsyncResult *result;
+ PinContext *ctx;
QmiClient *client = NULL;
+ GUdevDevice *gudev = NULL;
+ GUdevClient *gclient = NULL;
+ MMPort *qmi = NULL;
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
QMI_SERVICE_DMS, &client,
@@ -1532,13 +1554,34 @@ modem_load_unlock_required (MMIfaceModem *self,
return;
}
+ ctx = g_slice_new0 (PinContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = result;
+
+ gclient = g_udev_client_new (NULL);
+ qmi = MM_PORT (mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)));
+ if (qmi)
+ gudev = g_udev_client_query_by_subsystem_and_name (gclient,
+ "usb",
+ mm_port_get_device (qmi));
+ if (qmi && !gudev)
+ gudev = g_udev_client_query_by_subsystem_and_name (gclient,
+ "usbmisc",
+ mm_port_get_device (qmi));
+ if (gudev && g_udev_device_get_property_as_boolean(gudev, "ID_MM_IGNORE_PIN2"))
+ ctx->ignore_pin2 = TRUE;
+ if (gudev)
+ g_object_unref (gudev);
+ if (gclient)
+ g_object_unref (gclient);
+
mm_dbg ("loading unlock required...");
qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client),
NULL,
5,
NULL,
(GAsyncReadyCallback)dms_uim_get_pin_status_ready,
- result);
+ ctx);
}
/*****************************************************************************/
@@ -1558,7 +1601,7 @@ modem_load_unlock_retries_finish (MMIfaceModem *self,
static void
retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ PinContext *ctx)
{
QmiMessageDmsUimGetPinStatusOutput *output;
GError *error = NULL;
@@ -1566,10 +1609,10 @@ retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
} else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't get unlock retries: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
} else {
MMUnlockRetries *retries;
guint8 verify_retries_left;
@@ -1587,7 +1630,7 @@ retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, unblock_retries_left);
}
- if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
+ if (!ctx->ignore_pin2 && qmi_message_dms_uim_get_pin_status_output_get_pin2_status (
output,
NULL, /* current_status */
&verify_retries_left,
@@ -1597,14 +1640,12 @@ retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client,
mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, unblock_retries_left);
}
- g_simple_async_result_set_op_res_gpointer (simple, retries, g_object_unref);
+ g_simple_async_result_set_op_res_gpointer (ctx->result, retries, g_object_unref);
}
if (output)
qmi_message_dms_uim_get_pin_status_output_unref (output);
-
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ pin_context_complete_and_free (ctx);
}
static void
@@ -1612,18 +1653,40 @@ modem_load_unlock_retries (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *result;
QmiClient *client = NULL;
+ PinContext *ctx;
+ GUdevDevice *gudev = NULL;
+ GUdevClient *gclient = NULL;
+ MMPort *qmi = NULL;
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
QMI_SERVICE_DMS, &client,
callback, user_data))
return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_unlock_retries);
+ ctx = g_slice_new0 (PinContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_load_unlock_retries);
+
+ gclient = g_udev_client_new (NULL);
+ qmi = MM_PORT (mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)));
+ if (qmi)
+ gudev = g_udev_client_query_by_subsystem_and_name (gclient,
+ "usb",
+ mm_port_get_device (qmi));
+ if (qmi && !gudev)
+ gudev = g_udev_client_query_by_subsystem_and_name (gclient,
+ "usbmisc",
+ mm_port_get_device (qmi));
+ if (gudev && g_udev_device_get_property_as_boolean(gudev, "ID_MM_IGNORE_PIN2"))
+ ctx->ignore_pin2 = TRUE;
+ if (gudev)
+ g_object_unref (gudev);
+ if (gclient)
+ g_object_unref (gclient);
mm_dbg ("loading unlock retries...");
qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client),
@@ -1631,7 +1694,7 @@ modem_load_unlock_retries (MMIfaceModem *self,
5,
NULL,
(GAsyncReadyCallback)retry_count_dms_uim_get_pin_status_ready,
- result);
+ ctx);
}
/*****************************************************************************/
More information about the ModemManager-devel
mailing list