aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--introspection/org.freedesktop.ModemManager.Modem.xml17
-rw-r--r--plugins/mm-modem-huawei-gsm.c65
-rw-r--r--plugins/mm-modem-mbm.c50
-rwxr-xr-xplugins/mm-modem-samsung-gsm.c95
-rw-r--r--src/mm-callback-info.c20
-rw-r--r--src/mm-callback-info.h4
-rw-r--r--src/mm-generic-gsm.c62
-rw-r--r--src/mm-modem-base.c98
-rw-r--r--src/mm-modem-base.h11
-rw-r--r--src/mm-modem-gsm-card.c16
-rw-r--r--src/mm-modem-gsm-card.h10
-rw-r--r--src/mm-modem.c10
-rw-r--r--src/mm-modem.h9
13 files changed, 260 insertions, 207 deletions
diff --git a/introspection/org.freedesktop.ModemManager.Modem.xml b/introspection/org.freedesktop.ModemManager.Modem.xml
index a71a6349..3f80e21f 100644
--- a/introspection/org.freedesktop.ModemManager.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager.Modem.xml
@@ -171,8 +171,21 @@
<property name="UnlockRetries" type="u" access="read">
<tp:docstring>
- The number of unlock retries remaining for the unlock code given by the property UnlockRequired, or 999 if
- the device does not support reporting unlock retries.
+ The number of unlock retries remaining for the unlock code given by the
+ property UnlockRequired, or 999 if the device does not support reporting
+ unlock retries. If UnlockRequired is blank, the value of this property
+ is not meaningful.
+ </tp:docstring>
+ </property>
+
+ <property name="PinRetryCounts" type="a{su}" access="read">
+ <tp:docstring>
+ A dictionary in which the keys are the names of the unlock codes
+ specified for the UnlockRequiredProperty, and the values are integers
+ giving the number of PIN tries remaining before the code becomes
+ blocked (requiring a PUK) or permanently blocked. Dictionary entries
+ exist only for the codes for which the modem is able to report retry
+ counts.
</tp:docstring>
</property>
diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c
index 124c15cb..ad392218 100644
--- a/plugins/mm-modem-huawei-gsm.c
+++ b/plugins/mm-modem-huawei-gsm.c
@@ -511,15 +511,23 @@ get_access_technology (MMGenericGsm *modem,
/*****************************************************************************/
static gboolean
-parse_num (const char *str, guint32 *out_num, guint32 min, guint32 max)
+parse_match_as_num (GMatchInfo *match_info,
+ guint idx,
+ guint32 *out_num,
+ guint32 min,
+ guint32 max)
{
unsigned long int tmp;
+ char *str;
+ str = g_match_info_fetch (match_info, idx);
if (!str || !strlen (str))
return FALSE;
errno = 0;
tmp = strtoul (str, NULL, 10);
+ g_free (str);
+
if (errno != 0 || tmp < min || tmp > max)
return FALSE;
*out_num = (guint32) tmp;
@@ -535,10 +543,12 @@ send_huawei_cpin_done (MMAtSerialPort *port,
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
GRegex *r = NULL;
GMatchInfo *match_info = NULL;
- const char *pin_type;
- guint32 attempts_left = 0;
- char *str = NULL;
- guint32 num = 0;
+ guint32 i = 0;
+ gboolean success = FALSE;
+ GArray *retry_counts;
+ PinRetryCount ur[4] = {
+ {"sim-puk", 0}, {"sim-pin", 0}, {"sim-puk2", 0}, {"sim-pin2", 0}
+ };
/* If the modem has already been removed, return without
* scheduling callback */
@@ -550,9 +560,7 @@ send_huawei_cpin_done (MMAtSerialPort *port,
goto done;
}
- pin_type = mm_callback_info_get_data (info, "pin_type");
-
- r = g_regex_new ("\\^CPIN:\\s*([^,]+),[^,]*,(\\d+),(\\d+),(\\d+),(\\d+)", G_REGEX_UNGREEDY, 0, NULL);
+ r = g_regex_new ("\\^CPIN:\\s*([^,]+),[^,]*,(\\d+),(\\d+),(\\d+),(\\d+)", G_REGEX_UNGREEDY, 0, NULL);
if (!r) {
g_set_error_literal (&info->error,
MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
@@ -567,37 +575,21 @@ send_huawei_cpin_done (MMAtSerialPort *port,
goto done;
}
- if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK))
- num = 2;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN))
- num = 3;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2))
- num = 4;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2))
- num = 5;
- else {
- mm_dbg ("unhandled pin type '%s'", pin_type);
-
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type");
- }
-
- if (num > 0) {
- gboolean success = FALSE;
-
- str = g_match_info_fetch (match_info, num);
- if (str) {
- success = parse_num (str, &attempts_left, 0, 10);
- g_free (str);
- }
-
+ for (i = 0; i <= 3; i++) {
+ success = parse_match_as_num (match_info, i + 2, &ur[i].count, 0, 10);
if (!success) {
info->error = g_error_new_literal (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"Could not parse ^CPIN results (missing or invalid match info).");
+ break;
}
}
- mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
+ if (success) {
+ retry_counts = g_array_sized_new (FALSE, TRUE, sizeof (PinRetryCount), 4);
+ g_array_append_vals (retry_counts, &ur, 4);
+ mm_callback_info_set_result (info, retry_counts, NULL);
+ }
done:
if (match_info)
@@ -610,15 +602,12 @@ done:
static void
get_unlock_retries (MMModemGsmCard *modem,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn callback,
gpointer user_data)
{
MMAtSerialPort *port;
char *command;
- MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- mm_dbg ("pin type '%s'", pin_type);
+ MMCallbackInfo *info = mm_callback_info_array_new (MM_MODEM (modem), callback, user_data);
/* 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);
@@ -641,8 +630,6 @@ get_unlock_retries (MMModemGsmCard *modem,
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 ("^CPIN?");
mm_at_serial_port_queue_command (port, command, 3, send_huawei_cpin_done, info);
g_free (command);
diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c
index 7aa8a019..61499100 100644
--- a/plugins/mm-modem-mbm.c
+++ b/plugins/mm-modem-mbm.c
@@ -867,8 +867,11 @@ send_epin_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- const char *pin_type;
- int attempts_left = 0;
+ int matched;
+ GArray *retry_counts;
+ PinRetryCount ur[4] = {
+ {"sim-pin", 0}, {"sim-puk", 0}, {"sim-pin2", 0}, {"sim-puk2", 0}
+ };
/* If the modem has already been removed, return without
* scheduling callback */
@@ -880,29 +883,23 @@ send_epin_done (MMAtSerialPort *port,
goto done;
}
- pin_type = 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 {
- mm_dbg ("unhandled pin type '%s'", pin_type);
-
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type");
- }
+ matched = sscanf (response->str, "*EPIN: %d, %d, %d, %d",
+ &ur[0].count, &ur[1].count, &ur[2].count, &ur[3].count);
+ if (matched == 4) {
+ if (ur[0].count > 998) {
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Invalid PIN attempts left %d", ur[0].count);
+ ur[0].count = 0;
+ }
- if (attempts_left < 0 || attempts_left > 998) {
- info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid PIN attempts left %d", attempts_left);
- attempts_left = 0;
+ retry_counts = g_array_sized_new (FALSE, TRUE, sizeof (PinRetryCount), 4);
+ g_array_append_vals (retry_counts, &ur, 4);
+ mm_callback_info_set_result (info, retry_counts, NULL);
+ } else {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse PIN retries results");
}
- 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);
@@ -910,15 +907,12 @@ done:
static void
mbm_get_unlock_retries (MMModemGsmCard *modem,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn callback,
gpointer user_data)
{
MMAtSerialPort *port;
char *command;
- MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
-
- mm_dbg ("pin type '%s'", pin_type);
+ MMCallbackInfo *info = mm_callback_info_array_new (MM_MODEM (modem), callback, user_data);
/* 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);
@@ -941,8 +935,6 @@ mbm_get_unlock_retries (MMModemGsmCard *modem,
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);
diff --git a/plugins/mm-modem-samsung-gsm.c b/plugins/mm-modem-samsung-gsm.c
index 2c1de77e..d04c78c9 100755
--- a/plugins/mm-modem-samsung-gsm.c
+++ b/plugins/mm-modem-samsung-gsm.c
@@ -270,22 +270,6 @@ get_band (MMModemGsmNetwork *modem,
mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_band_done, info);
}
-static gboolean
-parse_samsung_num (const char *str, guint32 *out_num, guint32 min, guint32 max)
-{
- unsigned long int tmp;
-
- if (!str || !strlen (str))
- return FALSE;
-
- errno = 0;
- tmp = strtoul (str, NULL, 10);
- if (errno != 0 || tmp < min || tmp > max)
- return FALSE;
- *out_num = (guint32) tmp;
- return TRUE;
-}
-
static void
send_samsung_pinnum_done (MMAtSerialPort *port,
GString *response,
@@ -293,12 +277,11 @@ send_samsung_pinnum_done (MMAtSerialPort *port,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- GRegex *r = NULL;
- GMatchInfo *match_info = NULL;
- const char *pin_type;
- guint32 attempts_left = 0;
- char *str = NULL;
- guint32 num = 0;
+ int matched;
+ GArray *retry_counts;
+ PinRetryCount ur[4] = {
+ {"sim-pin", 0}, {"sim-puk", 0}, {"sim-pin2", 0}, {"sim-puk2", 0}
+ };
/* If the modem has already been removed, return without
* scheduling callback */
@@ -310,58 +293,24 @@ send_samsung_pinnum_done (MMAtSerialPort *port,
goto done;
}
- pin_type = mm_callback_info_get_data (info, "pin_type");
-
- r = g_regex_new ("\\%PINNUM:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)", G_REGEX_UNGREEDY, 0, NULL);
- if (!r) {
- g_set_error_literal (&info->error,
- MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse %PINNUM results (error creating regex).");
- goto done;
- }
-
- if (!g_regex_match_full (r, response->str, response->len, 0, 0, &match_info, &info->error)) {
- g_set_error_literal (&info->error,
- MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse %PINNUM results (match failed).");
- goto done;
- }
-
- if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN))
- num = 1;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK))
- num = 2;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2))
- num = 3;
- else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2))
- num = 4;
- else {
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type");
- }
-
- if (num > 0) {
- gboolean success = FALSE;
-
- str = g_match_info_fetch (match_info, num);
- if (str) {
- success = parse_samsung_num (str, &attempts_left, 0, 10);
- g_free (str);
+ matched = sscanf (response->str, "%%PINNUM: %d, %d, %d, %d",
+ &ur[0].count, &ur[1].count, &ur[2].count, &ur[3].count);
+ if (matched == 4) {
+ if (ur[0].count > 998) {
+ info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Invalid PIN attempts left %d", ur[0].count);
+ ur[0].count = 0;
}
- if (!success) {
- info->error = g_error_new_literal (MM_MODEM_ERROR,
- MM_MODEM_ERROR_GENERAL,
- "Could not parse %PINNUM results (missing or invalid match info).");
- }
+ retry_counts = g_array_sized_new (FALSE, TRUE, sizeof (PinRetryCount), 4);
+ g_array_append_vals (retry_counts, &ur, 4);
+ mm_callback_info_set_result (info, retry_counts, NULL);
+ } else {
+ info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse PIN retries results");
}
- mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL);
-
done:
- if (match_info)
- g_match_info_free (match_info);
- if (r)
- g_regex_unref (r);
mm_serial_port_close (MM_SERIAL_PORT (port));
mm_callback_info_schedule (info);
}
@@ -385,14 +334,13 @@ reset (MMModem *modem,
static void
get_unlock_retries (MMModemGsmCard *modem,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn callback,
gpointer user_data)
{
MMAtSerialPort *port;
- MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+ MMCallbackInfo *info = mm_callback_info_array_new (MM_MODEM (modem), callback, user_data);
- mm_dbg ("pin type '%s'", pin_type);
+ mm_dbg ("get_unlock_retries");
/* 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);
@@ -412,7 +360,6 @@ get_unlock_retries (MMModemGsmCard *modem,
/* if the modem have not yet been enabled we need to make sure echoing is turned off */
mm_at_serial_port_queue_command (port, "E0", 3, NULL, NULL);
- mm_callback_info_set_data (info, "pin_type", g_strdup (pin_type), g_free);
mm_at_serial_port_queue_command (port, "%PINNUM?", 3, send_samsung_pinnum_done, info);
}
diff --git a/src/mm-callback-info.c b/src/mm-callback-info.c
index 302a8160..c738b704 100644
--- a/src/mm-callback-info.c
+++ b/src/mm-callback-info.c
@@ -48,6 +48,16 @@ invoke_mm_modem_string_fn (MMCallbackInfo *info)
}
static void
+invoke_mm_modem_array_fn (MMCallbackInfo *info)
+{
+ MMModemArrayFn callback = (MMModemArrayFn) info->callback;
+
+ callback (info->modem,
+ (GArray *) mm_callback_info_get_data (info, CALLBACK_INFO_RESULT),
+ info->error, info->user_data);
+}
+
+static void
modem_destroyed_cb (gpointer data, GObject *destroyed)
{
MMCallbackInfo *info = data;
@@ -151,6 +161,16 @@ mm_callback_info_string_new (MMModem *modem,
return mm_callback_info_new_full (modem, invoke_mm_modem_string_fn, (GCallback) callback, user_data);
}
+MMCallbackInfo *
+mm_callback_info_array_new (MMModem *modem,
+ MMModemArrayFn callback,
+ gpointer user_data)
+{
+ g_return_val_if_fail (modem != NULL, NULL);
+
+ return mm_callback_info_new_full (modem, invoke_mm_modem_array_fn, (GCallback) callback, user_data);
+}
+
gpointer
mm_callback_info_get_result (MMCallbackInfo *info)
{
diff --git a/src/mm-callback-info.h b/src/mm-callback-info.h
index a00181c1..67fea8d5 100644
--- a/src/mm-callback-info.h
+++ b/src/mm-callback-info.h
@@ -57,6 +57,10 @@ MMCallbackInfo *mm_callback_info_string_new (MMModem *modem,
MMModemStringFn callback,
gpointer user_data);
+MMCallbackInfo *mm_callback_info_array_new (MMModem *modem,
+ MMModemArrayFn callback,
+ gpointer user_data);
+
void mm_callback_info_schedule (MMCallbackInfo *info);
gpointer mm_callback_info_get_result (MMCallbackInfo *info);
void mm_callback_info_set_result (MMCallbackInfo *info,
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index 436c07c0..da0bf5cb 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -265,17 +265,24 @@ error_for_unlock_required (const char *unlock)
MM_MOBILE_ERROR_UNKNOWN,
"Unknown unlock request '%s'", unlock);
}
+typedef void (*MMModemArrayFn) (MMModem *modem,
+ GArray *items,
+ GError *error,
+ gpointer user_data);
static void
get_unlock_retries_cb (MMModem *modem,
- guint32 result,
+ GArray *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);
+ mm_modem_base_set_pin_retry_counts (MM_MODEM_BASE (modem), result);
+ else {
+ if (result)
+ g_array_unref (result);
+ mm_modem_base_set_pin_retry_counts (MM_MODEM_BASE (modem), NULL);
+ }
}
static void
@@ -303,11 +310,9 @@ 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);
+ mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (info->modem),
+ get_unlock_retries_cb,
+ NULL);
parsed = TRUE;
} else {
CPinResult *iter = &unlock_results[0];
@@ -318,7 +323,6 @@ pin_check_done (MMAtSerialPort *port,
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;
@@ -332,8 +336,8 @@ 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);
-
+ mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (info->modem),
+ get_unlock_retries_cb, NULL);
if (!info->error) {
info->error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
@@ -2490,6 +2494,28 @@ pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data)
mm_callback_info_schedule (info);
}
+/* Following an operation other than unlock that requires
+ * a pin, refetch the retry count, which may have changed
+ * if an incorrect PIN was supplied. Check also for a SIM_PUK
+ * error, which occurs if PIN retries has reached zero. */
+static void
+update_pin_puk_status (MMModem *modem, GError *error)
+{
+ if (error) {
+ if (error->domain != MM_MOBILE_ERROR)
+ return;
+ if (error->code == MM_MOBILE_ERROR_SIM_PUK) {
+ mm_modem_base_set_unlock_required (MM_MODEM_BASE (modem),
+ "sim-puk");
+ } else if (error->code != MM_MOBILE_ERROR_WRONG_PASSWORD) {
+ return;
+ }
+ }
+ mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (modem),
+ get_unlock_retries_cb,
+ NULL);
+}
+
static void
send_puk_done (MMAtSerialPort *port,
GString *response,
@@ -2640,6 +2666,7 @@ enable_pin_done (MMAtSerialPort *port,
if (mm_callback_info_check_modem_removed (info))
return;
+ update_pin_puk_status (info->modem, error);
if (error)
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
@@ -2675,6 +2702,7 @@ change_pin_done (MMAtSerialPort *port,
if (mm_callback_info_check_modem_removed (info))
return;
+ update_pin_puk_status (info->modem, error);
if (error)
info->error = g_error_copy (error);
mm_callback_info_schedule (info);
@@ -2699,16 +2727,12 @@ change_pin (MMModemGsmCard *modem,
static void
get_unlock_retries (MMModemGsmCard *modem,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn 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);
+ MMCallbackInfo *info = mm_callback_info_array_new (MM_MODEM (modem), callback, user_data);
+ mm_callback_info_set_result (info, NULL, NULL);
mm_callback_info_schedule (info);
}
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index a065681e..526eb51e 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -55,6 +55,7 @@ typedef struct {
char *device_ident;
char *unlock_required;
guint32 unlock_retries;
+ GArray *pin_retry_counts;
guint32 ip_method;
gboolean valid;
MMModemState state;
@@ -354,44 +355,64 @@ 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)
+mm_modem_base_set_pin_retry_counts (MMModemBase *self, GArray *pin_retries)
{
MMModemBasePrivate *priv;
- const char *dbus_path;
+ GArray *old_retries;
+ gboolean same;
+ PinRetryCount *active = NULL;
+ guint i, j;
+ guint old_unlock_retries;
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)
+ if (!pin_retries) {
+ priv->unlock_retries = MM_MODEM_UNLOCK_RETRIES_NOT_SUPPORTED;
return;
+ }
- priv->unlock_retries = unlock_retries;
+ old_retries = priv->pin_retry_counts;
+ old_unlock_retries = priv->unlock_retries;
- dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
- if (dbus_path) {
- if (priv->unlock_required) {
- mm_info ("Modem %s: # unlock retries for %s is %d",
- dbus_path, priv->unlock_required, priv->unlock_retries);
- } else {
- mm_info ("Modem %s: # unlock retries is %d",
- dbus_path, priv->unlock_retries);
+ /* Only do something if one of the values changes */
+ same = (old_retries != NULL) && (pin_retries->len == old_retries->len);
+ for (i = 0; i < pin_retries->len; ++i) {
+ PinRetryCount *newur = &g_array_index (pin_retries, PinRetryCount, i);
+
+ if (!g_strcmp0 (newur->name, priv->unlock_required))
+ active = newur;
+
+ if (old_retries) {
+ for (j = 0; j < old_retries->len; ++j) {
+ PinRetryCount *oldur = &g_array_index (old_retries, PinRetryCount, i);
+
+ if (!g_strcmp0 (oldur->name, newur->name)) {
+ if (oldur->count != newur->count)
+ same = FALSE;
+ break;
+ }
+ }
}
}
- g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES);
+ if (priv->pin_retry_counts)
+ g_array_unref (priv->pin_retry_counts);
+
+ priv->pin_retry_counts = pin_retries;
+
+ if (priv->unlock_required) {
+ g_assert (active);
+ priv->unlock_retries = active->count;
+ } else
+ priv->unlock_retries = 0;
+
+ if (old_unlock_retries != priv->unlock_retries)
+ g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES);
+ if (!same)
+ g_object_notify (G_OBJECT (self), MM_MODEM_PIN_RETRY_COUNTS);
}
const char *
@@ -700,6 +721,10 @@ mm_modem_base_init (MMModemBase *self)
NULL,
MM_DBUS_INTERFACE_MODEM);
mm_properties_changed_signal_register_property (G_OBJECT (self),
+ MM_MODEM_PIN_RETRY_COUNTS,
+ NULL,
+ MM_DBUS_INTERFACE_MODEM);
+ mm_properties_changed_signal_register_property (G_OBJECT (self),
MM_MODEM_IP_METHOD,
NULL,
MM_DBUS_INTERFACE_MODEM);
@@ -760,6 +785,7 @@ set_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_DEVICE_IDENTIFIER:
case MM_MODEM_PROP_UNLOCK_REQUIRED:
case MM_MODEM_PROP_UNLOCK_RETRIES:
+ case MM_MODEM_PROP_PIN_RETRY_COUNTS:
break;
case MM_MODEM_PROP_HW_VID:
/* Construct only */
@@ -778,6 +804,23 @@ set_property (GObject *object, guint prop_id,
}
}
+static GHashTable *
+get_retry_counts (GArray *counts)
+{
+ GHashTable *map;
+ int i;
+
+ map = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (counts) {
+ for (i = 0; i < counts->len; ++i) {
+ PinRetryCount *ur = (PinRetryCount *) &g_array_index (counts, PinRetryCount, i);
+ g_hash_table_insert (map, (char *) ur->name, GUINT_TO_POINTER (ur->count));
+ }
+ }
+ return map;
+}
+
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -824,6 +867,9 @@ get_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_UNLOCK_RETRIES:
g_value_set_uint (value, priv->unlock_retries);
break;
+ case MM_MODEM_PROP_PIN_RETRY_COUNTS:
+ g_value_set_boxed (value, get_retry_counts (priv->pin_retry_counts));
+ break;
case MM_MODEM_PROP_HW_VID:
g_value_set_uint (value, priv->vid);
break;
@@ -929,6 +975,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
MM_MODEM_UNLOCK_RETRIES);
g_object_class_override_property (object_class,
+ MM_MODEM_PROP_PIN_RETRY_COUNTS,
+ MM_MODEM_PIN_RETRY_COUNTS);
+
+ g_object_class_override_property (object_class,
MM_MODEM_PROP_HW_VID,
MM_MODEM_HW_VID);
diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h
index be11af64..33bba397 100644
--- a/src/mm-modem-base.h
+++ b/src/mm-modem-base.h
@@ -73,10 +73,8 @@ 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);
+void mm_modem_base_set_pin_retry_counts (MMModemBase *self,
+ GArray *pin_retries);
const char *mm_modem_base_get_manf (MMModemBase *self);
@@ -94,5 +92,10 @@ void mm_modem_base_get_card_info (MMModemBase *self,
MMModemInfoFn callback,
gpointer user_data);
+typedef struct {
+ const char *name;
+ guint count;
+} PinRetryCount;
+
#endif /* MM_MODEM_BASE_H */
diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c
index 9b1fd77d..35360db5 100644
--- a/src/mm-modem-gsm-card.c
+++ b/src/mm-modem-gsm-card.c
@@ -84,13 +84,13 @@ str_call_not_supported (MMModemGsmCard *self,
}
static void
-uint_call_not_supported (MMModemGsmCard *self,
- MMModemUIntFn callback,
- gpointer user_data)
+array_call_not_supported (MMModemGsmCard *self,
+ MMModemArrayFn callback,
+ gpointer user_data)
{
MMCallbackInfo *info;
- info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
+ info = mm_callback_info_array_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);
@@ -151,18 +151,16 @@ mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
}
void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn 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);
+ MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_unlock_retries (self, callback, user_data);
else
- uint_call_not_supported (self, callback, user_data);
+ array_call_not_supported (self, callback, user_data);
}
void
diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h
index 9716bf73..34a5d5b7 100644
--- a/src/mm-modem-gsm-card.h
+++ b/src/mm-modem-gsm-card.h
@@ -33,8 +33,6 @@
#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 {
@@ -50,9 +48,8 @@ struct _MMModemGsmCard {
gpointer user_data);
void (*get_unlock_retries) (MMModemGsmCard *self,
- const char *pin_type,
- MMModemUIntFn callback,
- gpointer user_data);
+ MMModemArrayFn callback,
+ gpointer user_data);
void (*get_operator_id) (MMModemGsmCard *self,
MMModemStringFn callback,
@@ -97,8 +94,7 @@ void mm_modem_gsm_card_get_imsi (MMModemGsmCard *self,
gpointer user_data);
void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self,
- const char *pin_type,
- MMModemUIntFn callback,
+ MMModemArrayFn callback,
gpointer user_data);
void mm_modem_gsm_card_get_operator_id (MMModemGsmCard *self,
diff --git a/src/mm-modem.c b/src/mm-modem.c
index 4447a360..0b31108b 100644
--- a/src/mm-modem.c
+++ b/src/mm-modem.c
@@ -33,6 +33,8 @@ static void impl_modem_factory_reset (MMModem *modem, const char *code, DBusGMet
#include "mm-modem-glue.h"
+#define MM_MODEM_PIN_RETRY_COUNTS_PROP_TYPE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_UINT))
+
static void
async_op_not_supported (MMModem *self,
MMModemFn callback,
@@ -915,6 +917,14 @@ mm_modem_init (gpointer g_iface)
g_object_interface_install_property
(g_iface,
+ g_param_spec_boxed (MM_MODEM_PIN_RETRY_COUNTS,
+ "PinRetryCounts",
+ "The remaining number of attempts for each PIN type",
+ MM_MODEM_PIN_RETRY_COUNTS_PROP_TYPE,
+ G_PARAM_READABLE));
+
+ g_object_interface_install_property
+ (g_iface,
g_param_spec_uint (MM_MODEM_HW_VID,
"Hardware vendor ID",
"Hardware vendor ID",
diff --git a/src/mm-modem.h b/src/mm-modem.h
index da39ff5d..8fb662b7 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -43,12 +43,15 @@
#define MM_MODEM_DEVICE_IDENTIFIER "device-identifier"
#define MM_MODEM_UNLOCK_REQUIRED "unlock-required"
#define MM_MODEM_UNLOCK_RETRIES "unlock-retries"
+#define MM_MODEM_PIN_RETRY_COUNTS "pin-retry-counts"
#define MM_MODEM_VALID "valid" /* not exported */
#define MM_MODEM_PLUGIN "plugin" /* not exported */
#define MM_MODEM_STATE "state" /* not exported */
#define MM_MODEM_HW_VID "hw-vid" /* not exported */
#define MM_MODEM_HW_PID "hw-pid" /* not exported */
+#define MM_MODEM_UNLOCK_RETRIES_NOT_SUPPORTED 999
+
typedef enum {
MM_MODEM_PROP_FIRST = 0x1000,
@@ -64,6 +67,7 @@ typedef enum {
MM_MODEM_PROP_EQUIPMENT_IDENTIFIER,
MM_MODEM_PROP_UNLOCK_REQUIRED,
MM_MODEM_PROP_UNLOCK_RETRIES,
+ MM_MODEM_PROP_PIN_RETRY_COUNTS,
MM_MODEM_PROP_DEVICE_IDENTIFIER,
MM_MODEM_PROP_HW_VID, /* Not exported */
MM_MODEM_PROP_HW_PID /* Not exported */
@@ -98,6 +102,11 @@ typedef void (*MMModemInfoFn) (MMModem *modem,
GError *error,
gpointer user_data);
+typedef void (*MMModemArrayFn) (MMModem *modem,
+ GArray *items,
+ GError *error,
+ gpointer user_data);
+
struct _MMModem {
GTypeInterface g_iface;