aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-10-25 21:02:43 -0500
committerDan Williams <dcbw@redhat.com>2010-10-25 21:02:43 -0500
commit6f809b589bd8619bf2d0659581389ac3c135d08b (patch)
tree81d42fa1ba6ce026c39c6584f67b5ab1070c0a3d
parentf93e24dda3fa790ca9dd9a0471aa5fc26495a04c (diff)
gsm: request ICCID after checking the PIN status
Checking PIN status makes sure the SIM is initialized, and that has to happen before we try to read the SIM for the ICCID. So move PIN checking before getting the ICCID, and retry the ICCID at least once for odd cards like Gobi 1K that seems to need one more try right after it's done booting up.
-rw-r--r--src/mm-generic-gsm.c309
1 files changed, 166 insertions, 143 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 23d6c551..2ce6add1 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -70,6 +70,8 @@ typedef struct {
guint32 pin_check_tries;
guint pin_check_timeout;
char *simid;
+ gboolean simid_checked;
+ guint32 simid_tries;
MMModemGsmAllowedMode allowed_mode;
@@ -425,137 +427,13 @@ check_valid (MMGenericGsm *self)
MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
gboolean new_valid = FALSE;
- if (priv->primary && priv->data && priv->pin_checked)
+ if (priv->primary && priv->data && priv->pin_checked && priv->simid_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);
-
-static gboolean
-pin_check_again (gpointer user_data)
-{
- MMGenericGsm *self = MM_GENERIC_GSM (user_data);
- MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
-
- priv->pin_check_timeout = 0;
- check_pin (self, initial_pin_check_done, NULL);
- return FALSE;
-}
-
-static void
-initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data)
-{
- MMGenericGsmPrivate *priv;
-
- /* modem could have been removed before we get here, in which case
- * 'modem' will be NULL.
- */
- if (!modem)
- return;
-
- g_return_if_fail (MM_IS_GENERIC_GSM (modem));
- priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
-
- if ( error
- && priv->pin_check_tries++ < 3
- && !mm_modem_base_get_unlock_required (MM_MODEM_BASE (modem))) {
- /* Try it again a few times */
- if (priv->pin_check_timeout)
- g_source_remove (priv->pin_check_timeout);
- priv->pin_check_timeout = g_timeout_add_seconds (2, pin_check_again, modem);
- } else {
- priv->pin_checked = TRUE;
- mm_serial_port_close (MM_SERIAL_PORT (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 (MM_SERIAL_PORT (priv->primary), &error))
- check_pin (self, initial_pin_check_done, NULL);
- else {
- g_warning ("%s: failed to open serial port: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
-
- /* Ensure the modem is still somewhat usable if opening the serial
- * port fails for some reason.
- */
- initial_pin_check_done (MM_MODEM (self), NULL, NULL);
- }
-}
-
-static void
-initial_imei_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 (MM_SERIAL_PORT (priv->primary), &error)) {
- /* Make sure echoing is off */
- mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
-
- /* Get modem's imei number */
- mm_modem_gsm_card_get_imei (MM_MODEM_GSM_CARD (self),
- get_imei_cb,
- NULL);
- } else {
- g_warning ("%s: failed to open serial port: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
- }
-}
-
-static void
-initial_info_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 (MM_SERIAL_PORT (priv->primary), &error)) {
- /* Make sure echoing is off */
- mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
- mm_modem_base_get_card_info (MM_MODEM_BASE (self),
- priv->primary,
- NULL,
- get_info_cb,
- NULL);
- } else {
- g_warning ("%s: failed to open serial port: (%d) %s",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_clear_error (&error);
- }
-}
-
static void
get_iccid_done (MMModem *modem,
const char *response,
@@ -564,10 +442,10 @@ get_iccid_done (MMModem *modem,
{
MMGenericGsmPrivate *priv;
const char *p = response;
- GChecksum *sum;
+ GChecksum *sum = NULL;
if (error || !response || !strlen (response))
- return;
+ goto done;
sum = g_checksum_new (G_CHECKSUM_SHA1);
@@ -575,7 +453,7 @@ get_iccid_done (MMModem *modem,
while (*p) {
if (!isdigit (*p)) {
g_warning ("%s: invalid ICCID format (not a digit)", __func__);
- goto out;
+ goto done;
}
g_checksum_update (sum, (const guchar *) p++, 1);
}
@@ -591,10 +469,18 @@ get_iccid_done (MMModem *modem,
g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_CARD_SIM_IDENTIFIER);
-out:
- g_checksum_free (sum);
+done:
+ if (sum)
+ g_checksum_free (sum);
+
+ if (modem) {
+ MM_GENERIC_GSM_GET_PRIVATE (modem)->simid_checked = TRUE;
+ check_valid (MM_GENERIC_GSM (modem));
+ }
}
+#define ICCID_CMD "+CRSM=176,12258,0,0,10"
+
static void
real_get_iccid_done (MMAtSerialPort *port,
GString *response,
@@ -689,13 +575,27 @@ real_get_iccid_done (MMAtSerialPort *port,
mm_callback_info_set_result (info, g_strdup (swapped), g_free);
} else {
- info->error = g_error_new (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "SIM failed to handle CRSM request (sw1 %d sw2 %d)",
- sw1, sw2);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem);
+
+ if (priv->simid_tries++ < 2) {
+ /* Try one more time... Gobi 1K cards may reply to the first
+ * request with '+CRSM: 106,134,""' which is bogus because
+ * subsequent requests work fine.
+ */
+ mm_at_serial_port_queue_command (port, ICCID_CMD, 20, real_get_iccid_done, info);
+ return;
+ } else {
+ info->error = g_error_new (MM_MODEM_ERROR,
+ MM_MODEM_ERROR_GENERAL,
+ "SIM failed to handle CRSM request (sw1 %d sw2 %d)",
+ sw1, sw2);
+ }
}
done:
+ /* Balance open from real_get_sim_iccid() */
+ mm_serial_port_close (MM_SERIAL_PORT (port));
+
mm_callback_info_schedule (info);
}
@@ -724,11 +624,7 @@ real_get_sim_iccid (MMGenericGsm *self,
info = mm_callback_info_string_new (MM_MODEM (self), callback, callback_data);
/* READ BINARY of EFiccid (ICC Identification) ETSI TS 102.221 section 13.2 */
- mm_at_serial_port_queue_command (port,
- "+CRSM=176,12258,0,0,10",
- 3,
- real_get_iccid_done,
- info);
+ mm_at_serial_port_queue_command (port, ICCID_CMD, 20, real_get_iccid_done, info);
}
static void
@@ -738,6 +634,134 @@ initial_iccid_check (MMGenericGsm *self)
MM_GENERIC_GSM_GET_CLASS (self)->get_sim_iccid (self, get_iccid_done, NULL);
}
+static void initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data);
+
+static gboolean
+pin_check_again (gpointer user_data)
+{
+ MMGenericGsm *self = MM_GENERIC_GSM (user_data);
+ MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self);
+
+ priv->pin_check_timeout = 0;
+ check_pin (self, initial_pin_check_done, NULL);
+ return FALSE;
+}
+
+static void
+initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data)
+{
+ MMGenericGsmPrivate *priv;
+
+ /* modem could have been removed before we get here, in which case
+ * 'modem' will be NULL.
+ */
+ if (!modem)
+ return;
+
+ g_return_if_fail (MM_IS_GENERIC_GSM (modem));
+ priv = MM_GENERIC_GSM_GET_PRIVATE (modem);
+
+ if ( error
+ && priv->pin_check_tries++ < 3
+ && !mm_modem_base_get_unlock_required (MM_MODEM_BASE (modem))) {
+ /* Try it again a few times */
+ if (priv->pin_check_timeout)
+ g_source_remove (priv->pin_check_timeout);
+ priv->pin_check_timeout = g_timeout_add_seconds (2, pin_check_again, modem);
+ } else {
+ /* Try to get the SIM ICCID after we've checked PIN status and the SIM
+ * is ready.
+ */
+ initial_iccid_check (MM_GENERIC_GSM (modem));
+
+ priv->pin_checked = TRUE;
+ mm_serial_port_close (MM_SERIAL_PORT (priv->primary));
+ }
+}
+
+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 (MM_SERIAL_PORT (priv->primary), &error))
+ check_pin (self, initial_pin_check_done, NULL);
+ else {
+ g_warning ("%s: failed to open serial port: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+
+ /* Ensure the modem is still somewhat usable if opening the serial
+ * port fails for some reason.
+ */
+ initial_pin_check_done (MM_MODEM (self), NULL, NULL);
+ }
+}
+
+static void
+initial_imei_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 (MM_SERIAL_PORT (priv->primary), &error)) {
+ /* Make sure echoing is off */
+ mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
+
+ /* Get modem's imei number */
+ mm_modem_gsm_card_get_imei (MM_MODEM_GSM_CARD (self),
+ get_imei_cb,
+ NULL);
+ } else {
+ g_warning ("%s: failed to open serial port: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
+static void
+initial_info_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 (MM_SERIAL_PORT (priv->primary), &error)) {
+ /* Make sure echoing is off */
+ mm_at_serial_port_queue_command (priv->primary, "E0", 3, NULL, NULL);
+ mm_modem_base_get_card_info (MM_MODEM_BASE (self),
+ priv->primary,
+ NULL,
+ get_info_cb,
+ NULL);
+ } else {
+ g_warning ("%s: failed to open serial port: (%d) %s",
+ __func__,
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
static gboolean
owns_port (MMModem *modem, const char *subsys, const char *name)
{
@@ -794,10 +818,9 @@ mm_generic_gsm_grab_port (MMGenericGsm *self,
/* Get modem's IMEI */
initial_imei_check (self);
- /* Try to get the SIM's ICCID */
- initial_iccid_check (self);
-
- /* Get modem's initial lock/unlock state */
+ /* Get modem's initial lock/unlock state; this also ensures the
+ * SIM is ready by waiting if necessary for the SIM to initalize.
+ */
initial_pin_check (self);
} else if (ptype == MM_PORT_TYPE_SECONDARY)