commit f7ce74f57f4ddd712b549a172a6c6d24cd5ed7e6
Author: Norbert <nf2.email@gmail.com>
Date:   Mon Jan 18 02:10:50 2010 +0100

    Initial check if modem requires unlock (PIN or PUK)

diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index ba8422f..a708fef 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -50,6 +50,7 @@ typedef struct {
     char *device;
 
     gboolean valid;
+    gboolean pin_checked;
 
     char *oper_code;
     char *oper_name;
@@ -287,12 +288,79 @@ check_valid (MMGenericGsm *self)
     MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
     gboolean new_valid = FALSE;
 
-    if (priv->primary && priv->data)
+    if (priv->primary && priv->data && priv->pin_checked)
         new_valid = TRUE;
 
     mm_modem_base_set_valid (MM_MODEM_BASE (self), new_valid);
 }
 
+static void
+initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data)
+{
+    MMGenericGsmPrivate *priv;
+    gchar *unlock_required_str = NULL;
+
+    g_return_if_fail (MM_IS_GENERIC_GSM (modem));
+    priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+
+    priv->pin_checked = TRUE;
+
+    if (error) {
+        switch (error->code) {
+            case MM_MOBILE_ERROR_SIM_PIN: unlock_required_str = "sim-pin"; break;
+            case MM_MOBILE_ERROR_SIM_PUK: unlock_required_str = "sim-puk"; break;
+            case MM_MOBILE_ERROR_PH_SIM_PIN: unlock_required_str = "ph-sim-pin"; break;
+            case MM_MOBILE_ERROR_PH_FSIM_PIN: unlock_required_str = "ph-fsim-pin"; break;
+            case MM_MOBILE_ERROR_PH_FSIM_PUK: unlock_required_str = "ph-fsim-puk"; break;
+            case MM_MOBILE_ERROR_SIM_PIN2: unlock_required_str = "sim-pin2"; break;
+            case MM_MOBILE_ERROR_SIM_PUK2: unlock_required_str = "sim-puk2"; break;
+            case MM_MOBILE_ERROR_NETWORK_PIN: unlock_required_str = "ph-net-pin"; break;
+            case MM_MOBILE_ERROR_NETWORK_PUK: unlock_required_str = "ph-net-puk"; break;
+            case MM_MOBILE_ERROR_NETWORK_SUBSET_PIN: unlock_required_str = "ph-netsub-pin"; break;
+            case MM_MOBILE_ERROR_NETWORK_SUBSET_PUK: unlock_required_str = "ph-netsub-puk"; break;
+            case MM_MOBILE_ERROR_SERVICE_PIN: unlock_required_str = "ph-sp-pin"; break;
+            case MM_MOBILE_ERROR_SERVICE_PUK: unlock_required_str = "ph-sp-puk"; break;
+            case MM_MOBILE_ERROR_CORP_PIN: unlock_required_str = "ph-corp-pin"; break;
+            case MM_MOBILE_ERROR_CORP_PUK: unlock_required_str = "ph-corp-puk"; break;
+            case MM_MOBILE_ERROR_PHONE_FAILURE: unlock_required_str = "ph-failure"; break;
+        }
+        /* TODO: should we rather set "unlock_required" in pin_check_done() */
+        /* and reset it to NULL when send_pin/puk was successful? */
+
+        mm_modem_base_set_unlock_required (MM_MODEM_BASE(modem),
+                unlock_required_str);
+    }
+
+    if (mm_serial_port_open (priv->primary, NULL))
+        mm_serial_port_close (priv->primary);
+
+    check_valid (MM_GENERIC_GSM (modem));
+}
+
+static void
+initial_pin_check (MMGenericGsm *self)
+{
+    GError *error = NULL;
+    MMGenericGsmPrivate *priv;
+
+    g_return_if_fail (MM_IS_GENERIC_GSM (self));
+    priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+
+    g_return_if_fail (priv->primary != NULL);
+
+    if (!mm_serial_port_open (priv->primary, &error)) {
+        MMCallbackInfo *info;
+
+        g_assert (error);
+        info = mm_callback_info_new (MM_MODEM(self), initial_pin_check_done, NULL);
+        info->error = error;
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    mm_generic_gsm_check_pin (self, initial_pin_check_done, NULL);
+}
+
 static gboolean
 owns_port (MMModem *modem, const char *subsys, const char *name)
 {
@@ -329,7 +397,11 @@ mm_generic_gsm_grab_port (MMGenericGsm *self,
                 priv->data = port;
                 g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE);
             }
-            check_valid (self);
+
+            /* check if the modem demands a PIN or PUK */
+            /* calls check_valid() afterwards */
+            initial_pin_check(self);
+
         } else if (ptype == MM_PORT_TYPE_SECONDARY)
             priv->secondary = MM_SERIAL_PORT (port);
     } else {
