[PATCH] add UnlockRetries property to the modem dbus interface



Hi!

This is a new patch that fixes the issues from your comments.

Now only a property containing the UnlockRetries for the currently locked pin type is added and no extra dbus method.

I also removed the change in send_pin_done, but as mentioned in a previously mail that will still have to be addressed somehow as the UnlockRequired 
and UnlockRetries properties do not properly update on failed SendPin attempts.

Regards
Torgny

---

 introspection/mm-modem.xml |    7 +++
 plugins/mm-modem-mbm.c     |   93 +++++++++++++++++++++++++++++++++++++++++++-
 src/mm-generic-gsm.c       |   38 ++++++++++++++++++
 src/mm-modem-base.c        |   46 ++++++++++++++++++++++
 src/mm-modem-base.h        |    6 +++
 src/mm-modem-gsm-card.c    |   28 +++++++++++++
 src/mm-modem-gsm-card.h    |   17 ++++++++
 src/mm-modem.c             |    8 ++++
 src/mm-modem.h             |    4 +-
 9 files changed, 245 insertions(+), 2 deletions(-)

diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml
index da7635b..2810db0 100644
--- a/introspection/mm-modem.xml
+++ b/introspection/mm-modem.xml
@@ -125,6 +125,13 @@
       </tp:docstring>
     </property>
 
+	<property name="UnlockRetries" type="u" access="read">
+      <tp:docstring>
+        The number of unlock retries for the unlock code given by the property UnlockRequired, or 999 if
+		the device does not support reporting unlock retries.
+      </tp:docstring>
+    </property>
+
     <property name="IpMethod" type="u" access="read" tp:type="MM_MODEM_IP_METHOD">
       <tp:docstring>
         The IP configuration method.
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 10be0be..8441d96 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -28,17 +28,20 @@
 
 #include "mm-modem-mbm.h"
 #include "mm-modem-simple.h"
+#include "mm-modem-gsm-card.h"
 #include "mm-errors.h"
 #include "mm-callback-info.h"
 
 static void modem_init (MMModem *modem_class);
 static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class);
 static void modem_simple_init (MMModemSimple *class);
+static void modem_gsm_card_init (MMModemGsmCard *class);
 
 G_DEFINE_TYPE_EXTENDED (MMModemMbm, mm_modem_mbm, MM_TYPE_GENERIC_GSM, 0,
                         G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)
-                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init))
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init))
 
 #define MM_MODEM_MBM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_MBM, MMModemMbmPrivate))
 
@@ -736,6 +739,88 @@ mbm_modem_authenticate (MMModemMbm *self,
 
 /*****************************************************************************/
 
+static void
+send_epin_done (MMAtSerialPort *port,
+           GString *response,
+           GError *error,
+           gpointer user_data)
+{
+    MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+    const char *pin_type;
+    int attempts_left = 0;
+
+    if (error) {
+        info->error = g_error_copy (error);
+        goto done;
+    }
+
+    pin_type = ((char *)mm_callback_info_get_data (info, "pin_type"));
+
+    if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN))
+        sscanf (response->str, "*EPIN: %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK)) 
+        sscanf (response->str, "*EPIN: %*d, %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2)) 
+        sscanf (response->str, "*EPIN: %*d, %*d, %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2)) 
+        sscanf (response->str, "*EPIN: %*d, %*d, %*d, %d", &attempts_left);
+    else {
+        g_debug ("%s unknown pin type: %s", __FUNCTION__, pin_type);
+        
+        info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unknown PIN type");
+    }
+
+    mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
+
+done:
+    mm_serial_port_close (MM_SERIAL_PORT (port));
+    mm_callback_info_schedule (info);
+}
+
+static void
+mbm_get_unlock_retries (MMModemGsmCard *modem,
+              const char *pin_type,
+              MMModemUIntFn callback,
+              gpointer user_data)
+{
+    MMAtSerialPort *port;
+    char *command;
+    MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+
+    g_debug ("%s pin type: %s", __FUNCTION__, pin_type);
+
+    /* Ensure we have a usable port to use for the command */
+    port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
+    if (!port) {
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    /* Modem may not be enabled yet, which sometimes can't be done until
+     * the device has been unlocked.  In this case we have to open the port
+     * ourselves.
+     */
+    if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) {
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    /* if the modem have not yet been enabled we need to make sure echoing is turned off */
+    command = g_strdup_printf ("E0");
+    mm_at_serial_port_queue_command (port, command, 3, NULL, NULL);
+    g_free (command);
+
+    mm_callback_info_set_data (info, "pin_type", g_strdup (pin_type), g_free);
+
+    command = g_strdup_printf ("*EPIN?");
+
+    mm_at_serial_port_queue_command (port, command, 3, send_epin_done, info);
+
+    g_free (command);
+}
+
+/*****************************************************************************/
+
 static gboolean
 grab_port (MMModem *modem,
            const char *subsys,
@@ -805,6 +890,12 @@ grab_port (MMModem *modem,
 /*****************************************************************************/
 
 static void
+modem_gsm_card_init (MMModemGsmCard *class)
+{
+    class->get_unlock_retries = mbm_get_unlock_retries;
+}
+
+static void
 modem_gsm_network_init (MMModemGsmNetwork *class)
 {
     class->do_register = do_register;
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 8c155e2..141d1ea 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -206,6 +206,18 @@ error_for_unlock_required (const char *unlock)
 }
 
 static void
+get_unlock_retries_cb (MMModem *modem,
+                       guint32 result,
+                       GError *error,
+                       gpointer user_data)
+{
+    if (!error)
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (modem), result);
+    else
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (modem), MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED);
+}
+
+static void
 pin_check_done (MMAtSerialPort *port,
                 GString *response,
                 GError *error,
@@ -221,6 +233,11 @@ pin_check_done (MMAtSerialPort *port,
 
         if (g_str_has_prefix (str, "READY")) {
             mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), NULL);
+            if (MM_MODEM_GSM_CARD_GET_INTERFACE (info->modem)->get_unlock_retries)
+                mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem), 0);
+            else
+                mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem),
+                                                  MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED);
             parsed = TRUE;
         } else {
             CPinResult *iter = &unlock_results[0];
@@ -230,6 +247,10 @@ pin_check_done (MMAtSerialPort *port,
                 if (g_str_has_prefix (str, iter->result)) {
                     info->error = mm_mobile_error_for_code (iter->code);
                     mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), iter->normalized);
+                    mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (info->modem),
+                                                        iter->normalized,
+                                                        get_unlock_retries_cb,
+                                                        NULL);
                     parsed = TRUE;
                     break;
                 }
@@ -241,6 +262,7 @@ pin_check_done (MMAtSerialPort *port,
     if (!parsed) {
         /* Assume unlocked if we don't recognize the pin request result */
         mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), NULL);
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem), 0);
 
         if (!info->error) {
             info->error = g_error_new (MM_MODEM_ERROR,
@@ -1380,6 +1402,21 @@ change_pin (MMModemGsmCard *modem,
 }
 
 static void
+get_unlock_retries (MMModemGsmCard *modem,
+                    const char *pin_type,
+                    MMModemUIntFn callback,
+                    gpointer user_data)
+{
+    MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+
+    mm_callback_info_set_result (info,
+                                 GUINT_TO_POINTER (MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED),
+                                 NULL);
+    
+    mm_callback_info_schedule (info);                             
+}
+
+static void
 reg_info_updated (MMGenericGsm *self,
                   gboolean update_rs,
                   MMModemGsmNetworkRegStatus status,
@@ -3539,6 +3576,7 @@ modem_gsm_card_init (MMModemGsmCard *class)
     class->send_puk = send_puk;
     class->enable_pin = enable_pin;
     class->change_pin = change_pin;
+    class->get_unlock_retries = get_unlock_retries;
 }
 
 static void
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 0a91d3f..611b1a1 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -43,6 +43,7 @@ typedef struct {
     char *plugin;
     char *device;
     char *unlock_required;
+    guint32 unlock_retries;
     guint32 ip_method;
     gboolean valid;
     MMModemState state;
@@ -232,6 +233,40 @@ mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_require
     g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED);
 }
 
+guint32
+mm_modem_base_get_unlock_retries (MMModemBase *self)
+{   
+    g_return_val_if_fail (self != NULL, 0);
+    g_return_val_if_fail (MM_IS_MODEM_BASE (self), 0);
+
+    return MM_MODEM_BASE_GET_PRIVATE (self)->unlock_retries;
+}
+
+void
+mm_modem_base_set_unlock_retries (MMModemBase *self, guint unlock_retries)
+{
+    MMModemBasePrivate *priv;
+    const char *dbus_path;
+
+    g_return_if_fail (self != NULL);
+    g_return_if_fail (MM_IS_MODEM_BASE (self));
+
+    priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+    /* Only do something if the value changes */
+    if (priv->unlock_retries == unlock_retries)
+        return;
+
+    priv->unlock_retries = unlock_retries;
+
+    dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
+    if (dbus_path) {
+        g_message ("Modem %s: unlock retries is %d", dbus_path, priv->unlock_retries);
+    }
+
+    g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES);
+}
+
 const char *
 mm_modem_base_get_manf (MMModemBase *self)
 {
@@ -490,6 +525,9 @@ mm_modem_base_init (MMModemBase *self)
     mm_properties_changed_signal_register_property (G_OBJECT (self),
                                                     MM_MODEM_UNLOCK_REQUIRED,
                                                     MM_MODEM_DBUS_INTERFACE);
+    mm_properties_changed_signal_register_property (G_OBJECT (self),
+                                                    MM_MODEM_UNLOCK_RETRIES,
+                                                    MM_MODEM_DBUS_INTERFACE);
 }
 
 static void
@@ -539,6 +577,7 @@ set_property (GObject *object, guint prop_id,
     case MM_MODEM_PROP_TYPE:
     case MM_MODEM_PROP_ENABLED:
     case MM_MODEM_PROP_UNLOCK_REQUIRED:
+    case MM_MODEM_PROP_UNLOCK_RETRIES:
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -583,6 +622,9 @@ get_property (GObject *object, guint prop_id,
     case MM_MODEM_PROP_UNLOCK_REQUIRED:
         g_value_set_string (value, priv->unlock_required);
         break;
+    case MM_MODEM_PROP_UNLOCK_RETRIES:
+        g_value_set_uint (value, priv->unlock_retries);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -658,6 +700,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
                                       MM_MODEM_PROP_UNLOCK_REQUIRED,
                                       MM_MODEM_UNLOCK_REQUIRED);
 
+    g_object_class_override_property (object_class,
+                                      MM_MODEM_PROP_UNLOCK_RETRIES,
+                                      MM_MODEM_UNLOCK_RETRIES);
+
     mm_properties_changed_signal_new (object_class);
 }
 
diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h
index 516af2e..8eec0e4 100644
--- a/src/mm-modem-base.h
+++ b/src/mm-modem-base.h
@@ -67,6 +67,12 @@ const char *mm_modem_base_get_unlock_required (MMModemBase *self);
 void mm_modem_base_set_unlock_required (MMModemBase *self,
                                         const char *unlock_required);
 
+guint mm_modem_base_get_unlock_retries (MMModemBase *self);
+
+void mm_modem_base_set_unlock_retries (MMModemBase *self,
+                                        guint unlock_retries);
+
+
 const char *mm_modem_base_get_manf (MMModemBase *self);
 void        mm_modem_base_set_manf (MMModemBase *self, const char *manf);
 
diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c
index 432a4a3..1023743 100644
--- a/src/mm-modem-gsm-card.c
+++ b/src/mm-modem-gsm-card.c
@@ -77,6 +77,19 @@ str_call_not_supported (MMModemGsmCard *self,
 }
 
 static void
+uint_call_not_supported (MMModemGsmCard *self,
+                         MMModemUIntFn callback,
+                         gpointer user_data)
+{
+    MMCallbackInfo *info;
+
+    info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+    info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+                                       "Operation not supported");
+    mm_callback_info_schedule (info);
+}
+
+static void
 async_call_done (MMModem *modem, GError *error, gpointer user_data)
 {
     DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
@@ -130,6 +143,21 @@ mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
         str_call_not_supported (self, callback, user_data);
 }
 
+void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
+                                         const char *pin_type,
+                                         MMModemUIntFn callback,
+                                         gpointer user_data)
+{
+    g_return_if_fail (MM_IS_MODEM_GSM_CARD (self));
+    g_return_if_fail (pin_type != NULL);
+    g_return_if_fail (callback != NULL);
+
+    if (MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_unlock_retries)
+        MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_unlock_retries (self, pin_type, callback, user_data);
+    else
+        uint_call_not_supported (self, callback, user_data);
+}
+
 void
 mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
                             const char *puk,
diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h
index 4d690e6..71371df 100644
--- a/src/mm-modem-gsm-card.h
+++ b/src/mm-modem-gsm-card.h
@@ -27,6 +27,13 @@
 #define MM_MODEM_GSM_CARD_SUPPORTED_BANDS "supported-bands"
 #define MM_MODEM_GSM_CARD_SUPPORTED_MODES "supported-modes"
 
+#define MM_MODEM_GSM_CARD_SIM_PIN "sim-pin"
+#define MM_MODEM_GSM_CARD_SIM_PIN2 "sim-pin2"
+#define MM_MODEM_GSM_CARD_SIM_PUK "sim-puk"
+#define MM_MODEM_GSM_CARD_SIM_PUK2 "sim-puk2"
+
+#define MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED 999
+
 typedef struct _MMModemGsmCard MMModemGsmCard;
 
 struct _MMModemGsmCard {
@@ -41,6 +48,11 @@ struct _MMModemGsmCard {
                       MMModemStringFn callback,
                       gpointer user_data);
 
+    void (*get_unlock_retries) (MMModemGsmCard *self,
+                              const char *pin_type,
+                              MMModemUIntFn callback,
+                              gpointer user_data);
+
     void (*send_puk) (MMModemGsmCard *self,
                       const char *puk,
                       const char *pin,
@@ -75,6 +87,11 @@ void mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
                                  MMModemStringFn callback,
                                  gpointer user_data);
 
+void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
+                                         const char *pin_type,
+                                         MMModemUIntFn callback,
+                                         gpointer user_data);
+
 void mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
                                  const char *puk,
                                  const char *pin,
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 35e3b07..b378fff 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -812,6 +812,14 @@ mm_modem_init (gpointer g_iface)
                                NULL,
                                G_PARAM_READABLE));
 
+    g_object_interface_install_property
+        (g_iface,
+         g_param_spec_uint (MM_MODEM_UNLOCK_RETRIES,
+                               "UnlockRetries",
+                               "The remaining number of unlock attempts",
+                               0, G_MAXUINT32, 0,
+                               G_PARAM_READABLE));
+
     /* Signals */
     g_signal_new ("state-changed",
                   iface_type,
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 6eeb4de..d2863e4 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -59,6 +59,7 @@ typedef enum {
 #define MM_MODEM_IP_METHOD     "ip-method"
 #define MM_MODEM_ENABLED       "enabled"
 #define MM_MODEM_UNLOCK_REQUIRED  "unlock-required"
+#define MM_MODEM_UNLOCK_RETRIES  "unlock-retries"
 #define MM_MODEM_VALID         "valid"      /* not exported */
 #define MM_MODEM_PLUGIN        "plugin"     /* not exported */
 #define MM_MODEM_STATE         "state"      /* not exported */
@@ -83,7 +84,8 @@ typedef enum {
     MM_MODEM_PROP_PLUGIN,      /* Not exported */
     MM_MODEM_PROP_STATE,       /* Not exported */
     MM_MODEM_PROP_ENABLED,
-    MM_MODEM_PROP_UNLOCK_REQUIRED
+    MM_MODEM_PROP_UNLOCK_REQUIRED,
+    MM_MODEM_PROP_UNLOCK_RETRIES
 } MMModemProp;
 
 typedef struct _MMModem MMModem;
-- 
1.7.0.4

From 0b1d4508e701abcb38105393c9eb54f4496cf75b Mon Sep 17 00:00:00 2001
From: Torgny Johansson <torgny johansson ericsson com>
Date: Thu, 27 May 2010 11:12:18 +0200
Subject: [PATCH 1/2] Added UnlockRetries property to the modem interface.

---
 introspection/mm-modem.xml |    7 +++
 plugins/mm-modem-mbm.c     |   93 +++++++++++++++++++++++++++++++++++++++++++-
 src/mm-generic-gsm.c       |   38 ++++++++++++++++++
 src/mm-modem-base.c        |   46 ++++++++++++++++++++++
 src/mm-modem-base.h        |    6 +++
 src/mm-modem-gsm-card.c    |   28 +++++++++++++
 src/mm-modem-gsm-card.h    |   17 ++++++++
 src/mm-modem.c             |    8 ++++
 src/mm-modem.h             |    4 +-
 9 files changed, 245 insertions(+), 2 deletions(-)

diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml
index da7635b..2810db0 100644
--- a/introspection/mm-modem.xml
+++ b/introspection/mm-modem.xml
@@ -125,6 +125,13 @@
       </tp:docstring>
     </property>
 
+	<property name="UnlockRetries" type="u" access="read">
+      <tp:docstring>
+        The number of unlock retries for the unlock code given by the property UnlockRequired, or 999 if
+		the device does not support reporting unlock retries.
+      </tp:docstring>
+    </property>
+
     <property name="IpMethod" type="u" access="read" tp:type="MM_MODEM_IP_METHOD">
       <tp:docstring>
         The IP configuration method.
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 10be0be..8441d96 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -28,17 +28,20 @@
 
 #include "mm-modem-mbm.h"
 #include "mm-modem-simple.h"
+#include "mm-modem-gsm-card.h"
 #include "mm-errors.h"
 #include "mm-callback-info.h"
 
 static void modem_init (MMModem *modem_class);
 static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class);
 static void modem_simple_init (MMModemSimple *class);
+static void modem_gsm_card_init (MMModemGsmCard *class);
 
 G_DEFINE_TYPE_EXTENDED (MMModemMbm, mm_modem_mbm, MM_TYPE_GENERIC_GSM, 0,
                         G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)
-                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init))
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init))
 
 #define MM_MODEM_MBM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_MBM, MMModemMbmPrivate))
 
@@ -736,6 +739,88 @@ mbm_modem_authenticate (MMModemMbm *self,
 
 /*****************************************************************************/
 
+static void
+send_epin_done (MMAtSerialPort *port,
+           GString *response,
+           GError *error,
+           gpointer user_data)
+{
+    MMCallbackInfo *info = (MMCallbackInfo *) user_data;
+    const char *pin_type;
+    int attempts_left = 0;
+
+    if (error) {
+        info->error = g_error_copy (error);
+        goto done;
+    }
+
+    pin_type = ((char *)mm_callback_info_get_data (info, "pin_type"));
+
+    if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN))
+        sscanf (response->str, "*EPIN: %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK)) 
+        sscanf (response->str, "*EPIN: %*d, %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2)) 
+        sscanf (response->str, "*EPIN: %*d, %*d, %d", &attempts_left);
+    else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2)) 
+        sscanf (response->str, "*EPIN: %*d, %*d, %*d, %d", &attempts_left);
+    else {
+        g_debug ("%s unknown pin type: %s", __FUNCTION__, pin_type);
+        
+        info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unknown PIN type");
+    }
+
+    mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
+
+done:
+    mm_serial_port_close (MM_SERIAL_PORT (port));
+    mm_callback_info_schedule (info);
+}
+
+static void
+mbm_get_unlock_retries (MMModemGsmCard *modem,
+              const char *pin_type,
+              MMModemUIntFn callback,
+              gpointer user_data)
+{
+    MMAtSerialPort *port;
+    char *command;
+    MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+
+    g_debug ("%s pin type: %s", __FUNCTION__, pin_type);
+
+    /* Ensure we have a usable port to use for the command */
+    port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error);
+    if (!port) {
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    /* Modem may not be enabled yet, which sometimes can't be done until
+     * the device has been unlocked.  In this case we have to open the port
+     * ourselves.
+     */
+    if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) {
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    /* if the modem have not yet been enabled we need to make sure echoing is turned off */
+    command = g_strdup_printf ("E0");
+    mm_at_serial_port_queue_command (port, command, 3, NULL, NULL);
+    g_free (command);
+
+    mm_callback_info_set_data (info, "pin_type", g_strdup (pin_type), g_free);
+
+    command = g_strdup_printf ("*EPIN?");
+
+    mm_at_serial_port_queue_command (port, command, 3, send_epin_done, info);
+
+    g_free (command);
+}
+
+/*****************************************************************************/
+
 static gboolean
 grab_port (MMModem *modem,
            const char *subsys,
@@ -805,6 +890,12 @@ grab_port (MMModem *modem,
 /*****************************************************************************/
 
 static void
+modem_gsm_card_init (MMModemGsmCard *class)
+{
+    class->get_unlock_retries = mbm_get_unlock_retries;
+}
+
+static void
 modem_gsm_network_init (MMModemGsmNetwork *class)
 {
     class->do_register = do_register;
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 8c155e2..141d1ea 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -206,6 +206,18 @@ error_for_unlock_required (const char *unlock)
 }
 
 static void
+get_unlock_retries_cb (MMModem *modem,
+                       guint32 result,
+                       GError *error,
+                       gpointer user_data)
+{
+    if (!error)
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (modem), result);
+    else
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (modem), MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED);
+}
+
+static void
 pin_check_done (MMAtSerialPort *port,
                 GString *response,
                 GError *error,
@@ -221,6 +233,11 @@ pin_check_done (MMAtSerialPort *port,
 
         if (g_str_has_prefix (str, "READY")) {
             mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), NULL);
+            if (MM_MODEM_GSM_CARD_GET_INTERFACE (info->modem)->get_unlock_retries)
+                mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem), 0);
+            else
+                mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem),
+                                                  MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED);
             parsed = TRUE;
         } else {
             CPinResult *iter = &unlock_results[0];
@@ -230,6 +247,10 @@ pin_check_done (MMAtSerialPort *port,
                 if (g_str_has_prefix (str, iter->result)) {
                     info->error = mm_mobile_error_for_code (iter->code);
                     mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), iter->normalized);
+                    mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (info->modem),
+                                                        iter->normalized,
+                                                        get_unlock_retries_cb,
+                                                        NULL);
                     parsed = TRUE;
                     break;
                 }
@@ -241,6 +262,7 @@ pin_check_done (MMAtSerialPort *port,
     if (!parsed) {
         /* Assume unlocked if we don't recognize the pin request result */
         mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), NULL);
+        mm_modem_base_set_unlock_retries (MM_MODEM_BASE (info->modem), 0);
 
         if (!info->error) {
             info->error = g_error_new (MM_MODEM_ERROR,
@@ -1380,6 +1402,21 @@ change_pin (MMModemGsmCard *modem,
 }
 
 static void
+get_unlock_retries (MMModemGsmCard *modem,
+                    const char *pin_type,
+                    MMModemUIntFn callback,
+                    gpointer user_data)
+{
+    MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+
+    mm_callback_info_set_result (info,
+                                 GUINT_TO_POINTER (MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED),
+                                 NULL);
+    
+    mm_callback_info_schedule (info);                             
+}
+
+static void
 reg_info_updated (MMGenericGsm *self,
                   gboolean update_rs,
                   MMModemGsmNetworkRegStatus status,
@@ -3539,6 +3576,7 @@ modem_gsm_card_init (MMModemGsmCard *class)
     class->send_puk = send_puk;
     class->enable_pin = enable_pin;
     class->change_pin = change_pin;
+    class->get_unlock_retries = get_unlock_retries;
 }
 
 static void
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 0a91d3f..611b1a1 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -43,6 +43,7 @@ typedef struct {
     char *plugin;
     char *device;
     char *unlock_required;
+    guint32 unlock_retries;
     guint32 ip_method;
     gboolean valid;
     MMModemState state;
@@ -232,6 +233,40 @@ mm_modem_base_set_unlock_required (MMModemBase *self, const char *unlock_require
     g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED);
 }
 
+guint32
+mm_modem_base_get_unlock_retries (MMModemBase *self)
+{   
+    g_return_val_if_fail (self != NULL, 0);
+    g_return_val_if_fail (MM_IS_MODEM_BASE (self), 0);
+
+    return MM_MODEM_BASE_GET_PRIVATE (self)->unlock_retries;
+}
+
+void
+mm_modem_base_set_unlock_retries (MMModemBase *self, guint unlock_retries)
+{
+    MMModemBasePrivate *priv;
+    const char *dbus_path;
+
+    g_return_if_fail (self != NULL);
+    g_return_if_fail (MM_IS_MODEM_BASE (self));
+
+    priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+    /* Only do something if the value changes */
+    if (priv->unlock_retries == unlock_retries)
+        return;
+
+    priv->unlock_retries = unlock_retries;
+
+    dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
+    if (dbus_path) {
+        g_message ("Modem %s: unlock retries is %d", dbus_path, priv->unlock_retries);
+    }
+
+    g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES);
+}
+
 const char *
 mm_modem_base_get_manf (MMModemBase *self)
 {
@@ -490,6 +525,9 @@ mm_modem_base_init (MMModemBase *self)
     mm_properties_changed_signal_register_property (G_OBJECT (self),
                                                     MM_MODEM_UNLOCK_REQUIRED,
                                                     MM_MODEM_DBUS_INTERFACE);
+    mm_properties_changed_signal_register_property (G_OBJECT (self),
+                                                    MM_MODEM_UNLOCK_RETRIES,
+                                                    MM_MODEM_DBUS_INTERFACE);
 }
 
 static void
@@ -539,6 +577,7 @@ set_property (GObject *object, guint prop_id,
     case MM_MODEM_PROP_TYPE:
     case MM_MODEM_PROP_ENABLED:
     case MM_MODEM_PROP_UNLOCK_REQUIRED:
+    case MM_MODEM_PROP_UNLOCK_RETRIES:
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -583,6 +622,9 @@ get_property (GObject *object, guint prop_id,
     case MM_MODEM_PROP_UNLOCK_REQUIRED:
         g_value_set_string (value, priv->unlock_required);
         break;
+    case MM_MODEM_PROP_UNLOCK_RETRIES:
+        g_value_set_uint (value, priv->unlock_retries);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -658,6 +700,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
                                       MM_MODEM_PROP_UNLOCK_REQUIRED,
                                       MM_MODEM_UNLOCK_REQUIRED);
 
+    g_object_class_override_property (object_class,
+                                      MM_MODEM_PROP_UNLOCK_RETRIES,
+                                      MM_MODEM_UNLOCK_RETRIES);
+
     mm_properties_changed_signal_new (object_class);
 }
 
diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h
index 516af2e..8eec0e4 100644
--- a/src/mm-modem-base.h
+++ b/src/mm-modem-base.h
@@ -67,6 +67,12 @@ const char *mm_modem_base_get_unlock_required (MMModemBase *self);
 void mm_modem_base_set_unlock_required (MMModemBase *self,
                                         const char *unlock_required);
 
+guint mm_modem_base_get_unlock_retries (MMModemBase *self);
+
+void mm_modem_base_set_unlock_retries (MMModemBase *self,
+                                        guint unlock_retries);
+
+
 const char *mm_modem_base_get_manf (MMModemBase *self);
 void        mm_modem_base_set_manf (MMModemBase *self, const char *manf);
 
diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c
index 432a4a3..1023743 100644
--- a/src/mm-modem-gsm-card.c
+++ b/src/mm-modem-gsm-card.c
@@ -77,6 +77,19 @@ str_call_not_supported (MMModemGsmCard *self,
 }
 
 static void
+uint_call_not_supported (MMModemGsmCard *self,
+                         MMModemUIntFn callback,
+                         gpointer user_data)
+{
+    MMCallbackInfo *info;
+
+    info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+    info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED,
+                                       "Operation not supported");
+    mm_callback_info_schedule (info);
+}
+
+static void
 async_call_done (MMModem *modem, GError *error, gpointer user_data)
 {
     DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data;
@@ -130,6 +143,21 @@ mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
         str_call_not_supported (self, callback, user_data);
 }
 
+void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
+                                         const char *pin_type,
+                                         MMModemUIntFn callback,
+                                         gpointer user_data)
+{
+    g_return_if_fail (MM_IS_MODEM_GSM_CARD (self));
+    g_return_if_fail (pin_type != NULL);
+    g_return_if_fail (callback != NULL);
+
+    if (MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_unlock_retries)
+        MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_unlock_retries (self, pin_type, callback, user_data);
+    else
+        uint_call_not_supported (self, callback, user_data);
+}
+
 void
 mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
                             const char *puk,
diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h
index 4d690e6..71371df 100644
--- a/src/mm-modem-gsm-card.h
+++ b/src/mm-modem-gsm-card.h
@@ -27,6 +27,13 @@
 #define MM_MODEM_GSM_CARD_SUPPORTED_BANDS "supported-bands"
 #define MM_MODEM_GSM_CARD_SUPPORTED_MODES "supported-modes"
 
+#define MM_MODEM_GSM_CARD_SIM_PIN "sim-pin"
+#define MM_MODEM_GSM_CARD_SIM_PIN2 "sim-pin2"
+#define MM_MODEM_GSM_CARD_SIM_PUK "sim-puk"
+#define MM_MODEM_GSM_CARD_SIM_PUK2 "sim-puk2"
+
+#define MM_MODEM_GSM_CARD_UNLOCK_RETRIES_NOT_SUPPORTED 999
+
 typedef struct _MMModemGsmCard MMModemGsmCard;
 
 struct _MMModemGsmCard {
@@ -41,6 +48,11 @@ struct _MMModemGsmCard {
                       MMModemStringFn callback,
                       gpointer user_data);
 
+    void (*get_unlock_retries) (MMModemGsmCard *self,
+                              const char *pin_type,
+                              MMModemUIntFn callback,
+                              gpointer user_data);
+
     void (*send_puk) (MMModemGsmCard *self,
                       const char *puk,
                       const char *pin,
@@ -75,6 +87,11 @@ void mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
                                  MMModemStringFn callback,
                                  gpointer user_data);
 
+void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
+                                         const char *pin_type,
+                                         MMModemUIntFn callback,
+                                         gpointer user_data);
+
 void mm_modem_gsm_card_send_puk (MMModemGsmCard *self,
                                  const char *puk,
                                  const char *pin,
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 35e3b07..b378fff 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -812,6 +812,14 @@ mm_modem_init (gpointer g_iface)
                                NULL,
                                G_PARAM_READABLE));
 
+    g_object_interface_install_property
+        (g_iface,
+         g_param_spec_uint (MM_MODEM_UNLOCK_RETRIES,
+                               "UnlockRetries",
+                               "The remaining number of unlock attempts",
+                               0, G_MAXUINT32, 0,
+                               G_PARAM_READABLE));
+
     /* Signals */
     g_signal_new ("state-changed",
                   iface_type,
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 6eeb4de..d2863e4 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -59,6 +59,7 @@ typedef enum {
 #define MM_MODEM_IP_METHOD     "ip-method"
 #define MM_MODEM_ENABLED       "enabled"
 #define MM_MODEM_UNLOCK_REQUIRED  "unlock-required"
+#define MM_MODEM_UNLOCK_RETRIES  "unlock-retries"
 #define MM_MODEM_VALID         "valid"      /* not exported */
 #define MM_MODEM_PLUGIN        "plugin"     /* not exported */
 #define MM_MODEM_STATE         "state"      /* not exported */
@@ -83,7 +84,8 @@ typedef enum {
     MM_MODEM_PROP_PLUGIN,      /* Not exported */
     MM_MODEM_PROP_STATE,       /* Not exported */
     MM_MODEM_PROP_ENABLED,
-    MM_MODEM_PROP_UNLOCK_REQUIRED
+    MM_MODEM_PROP_UNLOCK_REQUIRED,
+    MM_MODEM_PROP_UNLOCK_RETRIES
 } MMModemProp;
 
 typedef struct _MMModem MMModem;
-- 
1.7.0.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]