[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,
                 &current_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