diff options
-rw-r--r-- | introspection/org.freedesktop.ModemManager.Modem.xml | 17 | ||||
-rw-r--r-- | plugins/mm-modem-huawei-gsm.c | 65 | ||||
-rw-r--r-- | plugins/mm-modem-mbm.c | 50 | ||||
-rwxr-xr-x | plugins/mm-modem-samsung-gsm.c | 95 | ||||
-rw-r--r-- | src/mm-callback-info.c | 20 | ||||
-rw-r--r-- | src/mm-callback-info.h | 4 | ||||
-rw-r--r-- | src/mm-generic-gsm.c | 62 | ||||
-rw-r--r-- | src/mm-modem-base.c | 98 | ||||
-rw-r--r-- | src/mm-modem-base.h | 11 | ||||
-rw-r--r-- | src/mm-modem-gsm-card.c | 16 | ||||
-rw-r--r-- | src/mm-modem-gsm-card.h | 10 | ||||
-rw-r--r-- | src/mm-modem.c | 10 | ||||
-rw-r--r-- | src/mm-modem.h | 9 |
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; |