From 164e5dfd498d2e746014cacbd3cc1a5bbf8528d1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Jun 2010 22:26:20 -0700 Subject: [PATCH 01/15] release: bump version to 0.3.998 (0.4-beta2) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0c66201d..808a9c08 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.52) -AC_INIT(ModemManager, 0.3.997, dcbw@redhat.com, ModemManager) +AC_INIT(ModemManager, 0.3.998, dcbw@redhat.com, ModemManager) AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2]) AM_MAINTAINER_MODE From 962a6b0939cd4b3ea7306492cb25f88b77668ef5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 10 Jun 2010 10:41:10 -0700 Subject: [PATCH 02/15] core: return errors to outstanding requests when serial ports are closed Prevents crashes when the callback info completes when the modem is removed, plus it's the right thing to do anyway... --- src/mm-serial-port.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c index df704af3..ed44167b 100644 --- a/src/mm-serial-port.c +++ b/src/mm-serial-port.c @@ -825,6 +825,25 @@ mm_serial_port_close (MMSerialPort *self) for (i = 0; i < g_queue_get_length (priv->queue); i++) { MMQueueData *item = g_queue_peek_nth (priv->queue, i); + if (item->callback) { + GError *error; + GByteArray *response; + + g_warn_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->handle_response != NULL); + error = g_error_new_literal (MM_SERIAL_ERROR, + MM_SERIAL_ERROR_SEND_FAILED, + "Serial port is now closed"); + response = g_byte_array_sized_new (1); + g_byte_array_append (response, (const guint8 *) "\0", 1); + MM_SERIAL_PORT_GET_CLASS (self)->handle_response (self, + response, + error, + item->callback, + item->user_data); + g_error_free (error); + g_byte_array_free (response, TRUE); + } + g_byte_array_free (item->command, TRUE); g_slice_free (MMQueueData, item); } From ea955f64c5ce562a1a73e05d227113e7383c8f58 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 16 Jun 2010 10:33:09 -0700 Subject: [PATCH 03/15] release: bump version to 0.4 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 808a9c08..b763d7b6 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ(2.52) -AC_INIT(ModemManager, 0.3.998, dcbw@redhat.com, ModemManager) +AC_INIT(ModemManager, 0.4, dcbw@redhat.com, ModemManager) AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2]) AM_MAINTAINER_MODE From 597f691eb8b12450d8f895f7a25d724eeba6c277 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 00:55:47 -0700 Subject: [PATCH 04/15] gsm: fix handling of SMS options --- src/mm-modem-gsm-sms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mm-modem-gsm-sms.c b/src/mm-modem-gsm-sms.c index 083ce8ae..d74c7b39 100644 --- a/src/mm-modem-gsm-sms.c +++ b/src/mm-modem-gsm-sms.c @@ -194,6 +194,7 @@ sms_auth_info_new (guint num1, dst = g_slice_new0 (GValue); g_value_init (dst, G_VALUE_TYPE (src)); + g_value_copy (src, dst); g_hash_table_insert (info->hash, g_strdup (str_key), dst); } } From a60216f5f44d4ead2fd36a129dee789d2941b02e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 01:58:41 -0700 Subject: [PATCH 05/15] huawei: use g_timeout_add_seconds() --- plugins/mm-plugin-huawei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c index b4c97d6e..2993689d 100644 --- a/plugins/mm-plugin-huawei.c +++ b/plugins/mm-plugin-huawei.c @@ -237,7 +237,7 @@ supports_port (MMPluginBase *base, add_regex (info->serial, "\\r\\n\\^BOOT:.+\\r\\n", task); add_regex (info->serial, "\\r\\r\\^BOOT:.+\\r\\r", task); - info->id = g_timeout_add (5000, probe_secondary_timeout, task); + info->id = g_timeout_add_seconds (7, probe_secondary_timeout, task); g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO, info, huawei_supports_info_destroy); From adfe264b67ba28effd3fb8378cbcbe2081f6ed49 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 01:58:54 -0700 Subject: [PATCH 06/15] core: ensure claimed ports don't fall back to Generic (rh #597296) Found by jklimes. If some plugin already supports this port, it's pointless to let Generic figure out if it supports the port since we're just going to hand it to the other plugin anyway. --- src/mm-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mm-manager.c b/src/mm-manager.c index 32b0d2a8..9b4c6d6e 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -626,7 +626,7 @@ supports_callback (MMPlugin *plugin, if (next_plugin) { const char *next_name = mm_plugin_get_name (next_plugin); - if (info->best_plugin && strcmp (next_name, MM_PLUGIN_GENERIC_NAME)) + if (info->best_plugin && !strcmp (next_name, MM_PLUGIN_GENERIC_NAME)) next_plugin = NULL; } From f179a56908f62f59f5e1419d562e5b9219cfbe7d Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Tue, 22 Jun 2010 14:05:09 -0700 Subject: [PATCH 07/15] gsm: add UnlockRetries property Which reports the # of attempts remaining for the current PIN required by the device or SIM. Some modifications/cleanups by dcbw. --- introspection/mm-modem.xml | 7 +++ plugins/mm-modem-mbm.c | 96 +++++++++++++++++++++++++++++++++++++- src/mm-generic-gsm.c | 38 +++++++++++++++ src/mm-modem-base.c | 47 +++++++++++++++++++ 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, 249 insertions(+), 2 deletions(-) diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml index da7635b6..298617d5 100644 --- a/introspection/mm-modem.xml +++ b/introspection/mm-modem.xml @@ -125,6 +125,13 @@ + + + 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 IP configuration method. diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 10be0be8..e1cb6e52 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,91 @@ 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 = 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: unhandled pin type '%s'", __func__, pin_type); + + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type"); + } + + 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; + } + + 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'", __func__, 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, @@ -804,6 +892,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) { diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 8c155e2b..635b7e8c 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -205,6 +205,18 @@ error_for_unlock_required (const char *unlock) "Unknown unlock request '%s'", 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, @@ -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, @@ -1379,6 +1401,21 @@ change_pin (MMModemGsmCard *modem, g_free (command); } +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, @@ -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 0a91d3f6..875ea6c4 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,41 @@ 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 for %s is %d", + dbus_path, priv->unlock_required, priv->unlock_retries); + } + + g_object_notify (G_OBJECT (self), MM_MODEM_UNLOCK_RETRIES); +} + const char * mm_modem_base_get_manf (MMModemBase *self) { @@ -490,6 +526,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 +578,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 +623,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 +701,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 516af2eb..8eec0e48 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 432a4a3f..ca8bdcb0 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -76,6 +76,19 @@ str_call_not_supported (MMModemGsmCard *self, mm_callback_info_schedule (info); } +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) { @@ -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 4d690e65..1d1916d6 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 35e3b07c..b378fffa 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 6eeb4dea..d2863e4a 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; From c95216e575b1740bf8e28005b36d327da578c44d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 14:06:13 -0700 Subject: [PATCH 08/15] huawei: add support for UnlockRetries --- plugins/mm-modem-huawei-gsm.c | 147 +++++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 6637bd02..5123e7f0 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -17,12 +17,14 @@ #include #include #include +#include #define G_UDEV_API_IS_SUBJECT_TO_CHANGE #include #include "mm-modem-huawei-gsm.h" #include "mm-modem-gsm-network.h" +#include "mm-modem-gsm-card.h" #include "mm-errors.h" #include "mm-callback-info.h" #include "mm-at-serial-port.h" @@ -30,10 +32,12 @@ static void modem_init (MMModem *modem_class); static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); +static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); G_DEFINE_TYPE_EXTENDED (MMModemHuaweiGsm, mm_modem_huawei_gsm, 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_GSM_NETWORK, modem_gsm_network_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init)) #define MM_MODEM_HUAWEI_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_HUAWEI_GSM, MMModemHuaweiGsmPrivate)) @@ -447,6 +451,141 @@ get_access_technology (MMGenericGsm *modem, mm_at_serial_port_queue_command (port, "^SYSINFO", 3, get_act_request_done, info); } +/*****************************************************************************/ + +static gboolean +parse_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_huawei_cpin_done (MMAtSerialPort *port, + GString *response, + GError *error, + 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; + + if (error) { + info->error = g_error_copy (error); + 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); + if (!r) { + g_set_error_literal (&info->error, + MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse ^CPIN 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 ^CPIN results (match failed)."); + 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 { + g_debug ("%s: unhandled pin type '%s'", __func__, 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); + } + + 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)."); + } + } + + mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL); + + g_match_info_free (match_info); + +done: + if (r) + g_regex_unref (r); + mm_serial_port_close (MM_SERIAL_PORT (port)); + mm_callback_info_schedule (info); +} + +static void +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'", __func__, 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 ("^CPIN?"); + mm_at_serial_port_queue_command (port, command, 3, send_huawei_cpin_done, info); + g_free (command); +} + /*****************************************************************************/ /* Unsolicited message handlers */ @@ -626,6 +765,12 @@ modem_gsm_network_init (MMModemGsmNetwork *class) class->get_band = get_band; } +static void +modem_gsm_card_init (MMModemGsmCard *class) +{ + class->get_unlock_retries = get_unlock_retries; +} + static void mm_modem_huawei_gsm_init (MMModemHuaweiGsm *self) { From 52929a2c926eee99e401765446c8f7a9168b38db Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Tue, 22 Jun 2010 14:36:49 -0700 Subject: [PATCH 09/15] core: add modem EquipmentIdentity property to report IMEI/ESN/MEID --- introspection/mm-modem.xml | 7 +++++ src/mm-generic-gsm.c | 43 ++++++++++++++++++++++++++++++ src/mm-modem-base.c | 54 ++++++++++++++++++++++++++++++++++++++ src/mm-modem-base.h | 5 ++++ src/mm-modem.c | 8 ++++++ src/mm-modem.h | 4 ++- 6 files changed, 120 insertions(+), 1 deletion(-) diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml index 298617d5..57d2e856 100644 --- a/introspection/mm-modem.xml +++ b/introspection/mm-modem.xml @@ -113,6 +113,13 @@ + + + The EquipmentIdentity of the device. This will be the IMEI number for + GSM devices and the hex-format ESN/MEID for CDMA devices. + + + Empty if the device is usable without an unlock code or has already diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 635b7e8c..ad3ce144 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -290,6 +290,18 @@ check_pin (MMGenericGsm *modem, mm_at_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info); } +static void +get_imei_cb (MMModem *modem, + const char *result, + GError *error, + gpointer user_data) +{ + if (modem) { + mm_modem_base_set_equipment_identity (MM_MODEM_BASE (modem), error ? "" : result); + mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary)); + } +} + /*****************************************************************************/ void @@ -403,6 +415,34 @@ initial_pin_check (MMGenericGsm *self) } } +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 gboolean owns_port (MMModem *modem, const char *subsys, const char *name) { @@ -456,6 +496,9 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, /* Get modem's initial lock/unlock state */ initial_pin_check (self); + /* Get modem's IMEI number */ + initial_imei_check (self); + } else if (ptype == MM_PORT_TYPE_SECONDARY) priv->secondary = MM_AT_SERIAL_PORT (port); } else if (MM_IS_QCDM_SERIAL_PORT (port)) { diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 875ea6c4..ba4339b9 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -42,6 +42,7 @@ typedef struct { char *driver; char *plugin; char *device; + char *equipment_identity; char *unlock_required; guint32 unlock_retries; guint32 ip_method; @@ -192,6 +193,47 @@ mm_modem_base_get_valid (MMModemBase *self) return MM_MODEM_BASE_GET_PRIVATE (self)->valid; } +const char * +mm_modem_base_get_equipment_identity (MMModemBase *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); + + return MM_MODEM_BASE_GET_PRIVATE (self)->equipment_identity; +} + +void +mm_modem_base_set_equipment_identity (MMModemBase *self, const char *equipment_identity) +{ + 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->equipment_identity == equipment_identity) + || ( priv->equipment_identity + && equipment_identity + && !strcmp (priv->equipment_identity, equipment_identity))) + return; + + g_free (priv->equipment_identity); + priv->equipment_identity = g_strdup (equipment_identity); + + dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG); + if (dbus_path) { + if (priv->equipment_identity) + g_message ("Modem %s: EquipmentIdentity set (%s)", dbus_path, priv->equipment_identity); + else + g_message ("Modem %s: EquipmentIdentity not set", dbus_path); + } + + g_object_notify (G_OBJECT (self), MM_MODEM_EQUIPMENT_IDENTITY); +} + const char * mm_modem_base_get_unlock_required (MMModemBase *self) { @@ -523,6 +565,9 @@ mm_modem_base_init (MMModemBase *self) mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_ENABLED, MM_MODEM_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_EQUIPMENT_IDENTITY, + MM_MODEM_DBUS_INTERFACE); mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED, MM_MODEM_DBUS_INTERFACE); @@ -577,6 +622,7 @@ set_property (GObject *object, guint prop_id, case MM_MODEM_PROP_VALID: case MM_MODEM_PROP_TYPE: case MM_MODEM_PROP_ENABLED: + case MM_MODEM_PROP_EQUIPMENT_IDENTITY: case MM_MODEM_PROP_UNLOCK_REQUIRED: case MM_MODEM_PROP_UNLOCK_RETRIES: break; @@ -620,6 +666,9 @@ get_property (GObject *object, guint prop_id, case MM_MODEM_PROP_ENABLED: g_value_set_boolean (value, is_enabled (priv->state)); break; + case MM_MODEM_PROP_EQUIPMENT_IDENTITY: + g_value_set_string (value, priv->equipment_identity); + break; case MM_MODEM_PROP_UNLOCK_REQUIRED: g_value_set_string (value, priv->unlock_required); break; @@ -644,6 +693,7 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->plugin); g_free (priv->device); + g_free (priv->equipment_identity); g_free (priv->unlock_required); G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object); @@ -697,6 +747,10 @@ mm_modem_base_class_init (MMModemBaseClass *klass) MM_MODEM_PROP_ENABLED, MM_MODEM_ENABLED); + g_object_class_override_property (object_class, + MM_MODEM_PROP_EQUIPMENT_IDENTITY, + MM_MODEM_EQUIPMENT_IDENTITY); + g_object_class_override_property (object_class, MM_MODEM_PROP_UNLOCK_REQUIRED, MM_MODEM_UNLOCK_REQUIRED); diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h index 8eec0e48..49daae27 100644 --- a/src/mm-modem-base.h +++ b/src/mm-modem-base.h @@ -62,6 +62,11 @@ void mm_modem_base_set_valid (MMModemBase *self, gboolean mm_modem_base_get_valid (MMModemBase *self); +const char *mm_modem_base_get_equipment_identity (MMModemBase *self); + +void mm_modem_base_set_equipment_identity (MMModemBase *self, + const char *equipment_identity); + const char *mm_modem_base_get_unlock_required (MMModemBase *self); void mm_modem_base_set_unlock_required (MMModemBase *self, diff --git a/src/mm-modem.c b/src/mm-modem.c index b378fffa..8cb7e725 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -803,6 +803,14 @@ mm_modem_init (gpointer g_iface) FALSE, G_PARAM_READABLE)); + g_object_interface_install_property + (g_iface, + g_param_spec_string (MM_MODEM_EQUIPMENT_IDENTITY, + "EquipmentIdentiy", + "The equipment identity of the device", + NULL, + G_PARAM_READABLE)); + g_object_interface_install_property (g_iface, g_param_spec_string (MM_MODEM_UNLOCK_REQUIRED, diff --git a/src/mm-modem.h b/src/mm-modem.h index d2863e4a..a5923b86 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -58,8 +58,9 @@ typedef enum { #define MM_MODEM_TYPE "type" #define MM_MODEM_IP_METHOD "ip-method" #define MM_MODEM_ENABLED "enabled" +#define MM_MODEM_EQUIPMENT_IDENTITY "equipment-identity" #define MM_MODEM_UNLOCK_REQUIRED "unlock-required" -#define MM_MODEM_UNLOCK_RETRIES "unlock-retries" +#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 */ @@ -84,6 +85,7 @@ typedef enum { MM_MODEM_PROP_PLUGIN, /* Not exported */ MM_MODEM_PROP_STATE, /* Not exported */ MM_MODEM_PROP_ENABLED, + MM_MODEM_PROP_EQUIPMENT_IDENTITY, MM_MODEM_PROP_UNLOCK_REQUIRED, MM_MODEM_PROP_UNLOCK_RETRIES } MMModemProp; From e442b3b7f13c7a7277b15f0b0cdf5175f4da22f6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 14:37:20 -0700 Subject: [PATCH 10/15] cdma: implement EquipmentIdentity for CDMA devices --- src/mm-generic-cdma.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 0c185d14..7f34960e 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -124,6 +124,44 @@ check_valid (MMGenericCdma *self) mm_modem_base_set_valid (MM_MODEM_BASE (self), new_valid); } +static void +get_esn_cb (MMModem *modem, + const char *result, + GError *error, + gpointer user_data) +{ + if (modem) { + mm_modem_base_set_equipment_identity (MM_MODEM_BASE (modem), error ? "" : result); + mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_CDMA_GET_PRIVATE (modem)->primary)); + check_valid (MM_GENERIC_CDMA (modem)); + } +} + +static void +initial_esn_check (MMGenericCdma *self) +{ + GError *error = NULL; + MMGenericCdmaPrivate *priv; + + g_return_if_fail (MM_IS_GENERIC_CDMA (self)); + priv = MM_GENERIC_CDMA_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_cdma_get_esn (MM_MODEM_CDMA (self), get_esn_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); + check_valid (self); + } +} + static gboolean owns_port (MMModem *modem, const char *subsys, const char *name) { @@ -176,7 +214,10 @@ mm_generic_cdma_grab_port (MMGenericCdma *self, priv->data = port; g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); } - check_valid (self); + + /* Get modem's ESN number */ + initial_esn_check (self); + } else if (ptype == MM_PORT_TYPE_SECONDARY) priv->secondary = MM_AT_SERIAL_PORT (port); } else if (MM_IS_QCDM_SERIAL_PORT (port)) { From 8873c0a7dc6cd02fa487092aeb889464b4dc752d Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Tue, 22 Jun 2010 16:50:21 -0700 Subject: [PATCH 11/15] gsm: add GetOperatorID method Returns the ID of the operator that issued the SIM card. Cleanups and get_mnc_length_done() by me (dcbw). --- introspection/mm-modem-gsm-card.xml | 14 ++++ src/Makefile.am | 4 +- src/mm-charsets.c | 57 +------------ src/mm-generic-gsm.c | 122 +++++++++++++++++++++++++++- src/mm-modem-gsm-card.c | 54 ++++++++++++ src/mm-modem-gsm-card.h | 8 ++ src/mm-plugin-base.c | 36 ++------ src/mm-utils.c | 78 ++++++++++++++++++ src/mm-utils.h | 24 ++++++ 9 files changed, 309 insertions(+), 88 deletions(-) create mode 100644 src/mm-utils.c create mode 100644 src/mm-utils.h diff --git a/introspection/mm-modem-gsm-card.xml b/introspection/mm-modem-gsm-card.xml index 708d5c9a..9c9fdc19 100644 --- a/introspection/mm-modem-gsm-card.xml +++ b/introspection/mm-modem-gsm-card.xml @@ -28,6 +28,20 @@ + + + Returns the ID of the network operator that issued the SIM card, + formatted as a 5 or 6-digit MCC/MNC code (ex "310410"). + + + + + + The operator ID formatted as an MCC/MNC code. + + + + Send the PUK and a new PIN to unlock the SIM card. diff --git a/src/Makefile.am b/src/Makefile.am index 46046ce5..2061ae8a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,7 +20,9 @@ libmodem_helpers_la_SOURCES = \ mm-modem-helpers.c \ mm-modem-helpers.h \ mm-charsets.c \ - mm-charsets.h + mm-charsets.h \ + mm-utils.c \ + mm-utils.h sbin_PROGRAMS = modem-manager diff --git a/src/mm-charsets.c b/src/mm-charsets.c index abe54a1c..c75c3a97 100644 --- a/src/mm-charsets.c +++ b/src/mm-charsets.c @@ -20,6 +20,7 @@ #include #include "mm-charsets.h" +#include "mm-utils.h" typedef struct { const char *gsm_name; @@ -150,60 +151,6 @@ mm_modem_charset_byte_array_append (GByteArray *array, return TRUE; } -/* From hostap, Copyright (c) 2002-2005, Jouni Malinen */ - -static int hex2num (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - -static int hex2byte (const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - -static char * -hexstr2bin (const char *hex, gsize *out_len) -{ - size_t len = strlen (hex); - size_t i; - int a; - const char * ipos = hex; - char * buf = NULL; - char * opos; - - /* Length must be a multiple of 2 */ - g_return_val_if_fail ((len % 2) == 0, NULL); - - opos = buf = g_malloc0 ((len / 2) + 1); - for (i = 0; i < len; i += 2) { - a = hex2byte (ipos); - if (a < 0) { - g_free (buf); - return NULL; - } - *opos++ = a; - ipos += 2; - } - *out_len = len / 2; - return buf; -} - -/* End from hostap */ - char * mm_modem_charset_hex_to_utf8 (const char *src, MMModemCharset charset) { @@ -217,7 +164,7 @@ mm_modem_charset_hex_to_utf8 (const char *src, MMModemCharset charset) iconv_from = charset_iconv_from (charset); g_return_val_if_fail (iconv_from != NULL, FALSE); - unconverted = hexstr2bin (src, &unconverted_len); + unconverted = utils_hexstr2bin (src, &unconverted_len); g_return_val_if_fail (unconverted != NULL, NULL); if (charset == MM_MODEM_CHARSET_UTF8 || charset == MM_MODEM_CHARSET_IRA) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index ad3ce144..330f67a8 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -12,7 +12,7 @@ * * Copyright (C) 2008 - 2009 Novell, Inc. * Copyright (C) 2009 - 2010 Red Hat, Inc. - * Copyright (C) 2009 Ericsson + * Copyright (C) 2009 - 2010 Ericsson */ #include @@ -20,6 +20,7 @@ #include #include #include + #include "mm-generic-gsm.h" #include "mm-modem-gsm-card.h" #include "mm-modem-gsm-network.h" @@ -33,6 +34,7 @@ #include "mm-modem-helpers.h" #include "mm-options.h" #include "mm-properties-changed-signal.h" +#include "mm-utils.h" static void modem_init (MMModem *modem_class); static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); @@ -1175,6 +1177,110 @@ get_string_done (MMAtSerialPort *port, mm_callback_info_schedule (info); } +static void +get_mnc_length_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + int sw1, sw2; + const char *imsi; + gboolean success = FALSE; + char hex[51]; + char *bin; + + if (error) { + info->error = g_error_copy (error); + goto done; + } + + memset (hex, 0, sizeof (hex)); + if (sscanf (response->str, "+CRSM:%d,%d,\"%50c\"", &sw1, &sw2, (char *) &hex) == 3) + success = TRUE; + else { + /* May not include quotes... */ + if (sscanf (response->str, "+CRSM:%d,%d,%50c", &sw1, &sw2, (char *) &hex) == 3) + success = TRUE; + } + + if (!success) { + info->error = g_error_new_literal (MM_MODEM_ERROR, + MM_MODEM_ERROR_GENERAL, + "Could not parse the CRSM response"); + goto done; + } + + if ((sw1 == 0x90 && sw2 == 0x00) || (sw1 == 0x91) || (sw1 == 0x92) || (sw1 == 0x9f)) { + gsize buflen = 0; + guint32 mnc_len; + + /* Make sure the buffer is only hex characters */ + while (buflen < sizeof (hex) && hex[buflen]) { + if (!isxdigit (hex[buflen])) { + hex[buflen] = 0x0; + break; + } + buflen++; + } + + /* Convert hex string to binary */ + bin = utils_hexstr2bin (hex, &buflen); + if (!bin || buflen < 4) { + info->error = g_error_new (MM_MODEM_ERROR, + MM_MODEM_ERROR_GENERAL, + "SIM returned malformed response '%s'", + hex); + goto done; + } + + /* MNC length is byte 4 of this SIM file */ + mnc_len = bin[3] & 0xFF; + if (mnc_len == 2 || mnc_len == 3) { + imsi = mm_callback_info_get_data (info, "imsi"); + mm_callback_info_set_result (info, g_strndup (imsi, 3 + mnc_len), g_free); + } else { + info->error = g_error_new (MM_MODEM_ERROR, + MM_MODEM_ERROR_GENERAL, + "SIM returned invalid MNC length %d (should be either 2 or 3)", + mnc_len); + } + } 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: + mm_callback_info_schedule (info); +} + +static void +get_operator_id_imsi_done (MMModem *modem, + const char *result, + GError *error, + gpointer user_data) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + + if (error) { + info->error = g_error_copy (error); + mm_callback_info_schedule (info); + return; + } + + mm_callback_info_set_data (info, "imsi", g_strdup (result), g_free); + + /* READ BINARY of EFad (Administrative Data) ETSI 51.011 section 10.3.18 */ + mm_at_serial_port_queue_command_cached (priv->primary, + "+CRSM=176,28589,0,0,4", + 3, + get_mnc_length_done, + info); +} + static void get_imei (MMModemGsmCard *modem, MMModemStringFn callback, @@ -1199,6 +1305,19 @@ get_imsi (MMModemGsmCard *modem, mm_at_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info); } +static void +get_operator_id (MMModemGsmCard *modem, + MMModemStringFn callback, + gpointer user_data) +{ + MMCallbackInfo *info; + + info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); + mm_modem_gsm_card_get_imsi (MM_MODEM_GSM_CARD (modem), + get_operator_id_imsi_done, + info); +} + static void get_card_info (MMModem *modem, MMModemInfoFn callback, @@ -3615,6 +3734,7 @@ modem_gsm_card_init (MMModemGsmCard *class) { class->get_imei = get_imei; class->get_imsi = get_imsi; + class->get_operator_id = get_operator_id; class->send_pin = send_pin; class->send_puk = send_puk; class->enable_pin = enable_pin; diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index ca8bdcb0..e03b964d 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -28,6 +28,9 @@ static void impl_gsm_modem_get_imei (MMModemGsmCard *modem, static void impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context); +static void impl_gsm_modem_get_operator_id (MMModemGsmCard *modem, + DBusGMethodInvocation *context); + static void impl_gsm_modem_send_pin (MMModemGsmCard *modem, const char *pin, DBusGMethodInvocation *context); @@ -158,6 +161,20 @@ void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self, uint_call_not_supported (self, callback, user_data); } +void +mm_modem_gsm_card_get_operator_id (MMModemGsmCard *self, + MMModemStringFn callback, + gpointer user_data) +{ + g_return_if_fail (MM_IS_MODEM_GSM_CARD (self)); + g_return_if_fail (callback != NULL); + + if (MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_operator_id) + MM_MODEM_GSM_CARD_GET_INTERFACE (self)->get_operator_id (self, callback, user_data); + else + str_call_not_supported (self, callback, user_data); +} + void mm_modem_gsm_card_send_puk (MMModemGsmCard *self, const char *puk, @@ -303,6 +320,43 @@ impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context) /*****************************************************************************/ +static void +operator_id_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) +{ + MMModemGsmCard *self = MM_MODEM_GSM_CARD (owner); + GError *error = NULL; + + /* Return any authorization error, otherwise get the operator id */ + if (!mm_modem_auth_finish (MM_MODEM (self), req, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_gsm_card_get_operator_id (self, str_call_done, context); +} + +static void +impl_gsm_modem_get_operator_id (MMModemGsmCard *modem, DBusGMethodInvocation *context) +{ + GError *error = NULL; + + /* Make sure the caller is authorized to get the operator id */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE_INFO, + context, + operator_id_auth_cb, + NULL, + NULL, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/*****************************************************************************/ + typedef struct { char *puk; char *pin; diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h index 1d1916d6..584d7344 100644 --- a/src/mm-modem-gsm-card.h +++ b/src/mm-modem-gsm-card.h @@ -53,6 +53,10 @@ struct _MMModemGsmCard { MMModemUIntFn callback, gpointer user_data); + void (*get_operator_id) (MMModemGsmCard *self, + MMModemStringFn callback, + gpointer user_data); + void (*send_puk) (MMModemGsmCard *self, const char *puk, const char *pin, @@ -92,6 +96,10 @@ void mm_modem_gsm_card_get_unlock_retries (MMModemGsmCard *self, MMModemUIntFn callback, gpointer user_data); +void mm_modem_gsm_card_get_operator_id (MMModemGsmCard *self, + MMModemStringFn callback, + gpointer user_data); + void mm_modem_gsm_card_send_puk (MMModemGsmCard *self, const char *puk, const char *pin, diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c index af91ad88..80d0f904 100644 --- a/src/mm-plugin-base.c +++ b/src/mm-plugin-base.c @@ -31,6 +31,7 @@ #include "mm-serial-parsers.h" #include "mm-errors.h" #include "mm-marshal.h" +#include "mm-utils.h" #include "libqcdm/src/commands.h" #include "libqcdm/src/utils.h" @@ -881,33 +882,6 @@ modem_destroyed (gpointer data, GObject *modem) g_hash_table_remove_all (cached_caps); } -/* From hostap, Copyright (c) 2002-2005, Jouni Malinen */ - -static int hex2num (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - -static int hex2byte (const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - -/* End from hostap */ - gboolean mm_plugin_base_get_device_ids (MMPluginBase *self, const char *subsys, @@ -940,8 +914,8 @@ mm_plugin_base_get_device_ids (MMPluginBase *self, goto out; if (vendor) { - *vendor = (guint16) (hex2byte (vid + 2) & 0xFF); - *vendor |= (guint16) ((hex2byte (vid) & 0xFF) << 8); + *vendor = (guint16) (utils_hex2byte (vid + 2) & 0xFF); + *vendor |= (guint16) ((utils_hex2byte (vid) & 0xFF) << 8); } pid = g_udev_device_get_property (device, "ID_MODEL_ID"); @@ -951,8 +925,8 @@ mm_plugin_base_get_device_ids (MMPluginBase *self, } if (product) { - *product = (guint16) (hex2byte (pid + 2) & 0xFF); - *product |= (guint16) ((hex2byte (pid) & 0xFF) << 8); + *product = (guint16) (utils_hex2byte (pid + 2) & 0xFF); + *product |= (guint16) ((utils_hex2byte (pid) & 0xFF) << 8); } success = TRUE; diff --git a/src/mm-utils.c b/src/mm-utils.c new file mode 100644 index 00000000..56182c0c --- /dev/null +++ b/src/mm-utils.c @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "mm-utils.h" + +/* From hostap, Copyright (c) 2002-2005, Jouni Malinen */ + +static int hex2num (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +int utils_hex2byte (const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +char * +utils_hexstr2bin (const char *hex, gsize *out_len) +{ + size_t len = strlen (hex); + size_t i; + int a; + const char * ipos = hex; + char * buf = NULL; + char * opos; + + /* Length must be a multiple of 2 */ + g_return_val_if_fail ((len % 2) == 0, NULL); + + opos = buf = g_malloc0 ((len / 2) + 1); + for (i = 0; i < len; i += 2) { + a = utils_hex2byte (ipos); + if (a < 0) { + g_free (buf); + return NULL; + } + *opos++ = a; + ipos += 2; + } + *out_len = len / 2; + return buf; +} + +/* End from hostap */ + diff --git a/src/mm-utils.h b/src/mm-utils.h new file mode 100644 index 00000000..79e7827b --- /dev/null +++ b/src/mm-utils.h @@ -0,0 +1,24 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef MM_UTILS_H +#define MM_UTILS_H + +int utils_hex2byte (const char *hex); + +char *utils_hexstr2bin (const char *hex, gsize *out_len); + +#endif /* MM_UTILS_H */ + From 88c538314aab99775c4b496170785d588e60ac6f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Jun 2010 17:14:13 -0700 Subject: [PATCH 12/15] core: EquipmentIdentity -> EquipmentIdentifier --- introspection/mm-modem.xml | 4 ++-- src/mm-generic-cdma.c | 2 +- src/mm-generic-gsm.c | 2 +- src/mm-modem-base.c | 40 ++++++++++++++++++-------------------- src/mm-modem-base.h | 6 +++--- src/mm-modem.c | 6 +++--- src/mm-modem.h | 4 ++-- 7 files changed, 31 insertions(+), 33 deletions(-) diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml index 57d2e856..35b67968 100644 --- a/introspection/mm-modem.xml +++ b/introspection/mm-modem.xml @@ -113,9 +113,9 @@ - + - The EquipmentIdentity of the device. This will be the IMEI number for + The identity of the device. This will be the IMEI number for GSM devices and the hex-format ESN/MEID for CDMA devices. diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 7f34960e..9fe897fa 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -131,7 +131,7 @@ get_esn_cb (MMModem *modem, gpointer user_data) { if (modem) { - mm_modem_base_set_equipment_identity (MM_MODEM_BASE (modem), error ? "" : result); + mm_modem_base_set_equipment_identifier (MM_MODEM_BASE (modem), error ? "" : result); mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_CDMA_GET_PRIVATE (modem)->primary)); check_valid (MM_GENERIC_CDMA (modem)); } diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 330f67a8..06a2e161 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -299,7 +299,7 @@ get_imei_cb (MMModem *modem, gpointer user_data) { if (modem) { - mm_modem_base_set_equipment_identity (MM_MODEM_BASE (modem), error ? "" : result); + mm_modem_base_set_equipment_identifier (MM_MODEM_BASE (modem), error ? "" : result); mm_serial_port_close (MM_SERIAL_PORT (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary)); } } diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index ba4339b9..0c39d2c7 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -42,7 +42,7 @@ typedef struct { char *driver; char *plugin; char *device; - char *equipment_identity; + char *equipment_ident; char *unlock_required; guint32 unlock_retries; guint32 ip_method; @@ -194,16 +194,16 @@ mm_modem_base_get_valid (MMModemBase *self) } const char * -mm_modem_base_get_equipment_identity (MMModemBase *self) +mm_modem_base_get_equipment_identifier (MMModemBase *self) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (MM_IS_MODEM_BASE (self), NULL); - return MM_MODEM_BASE_GET_PRIVATE (self)->equipment_identity; + return MM_MODEM_BASE_GET_PRIVATE (self)->equipment_ident; } void -mm_modem_base_set_equipment_identity (MMModemBase *self, const char *equipment_identity) +mm_modem_base_set_equipment_identifier (MMModemBase *self, const char *ident) { MMModemBasePrivate *priv; const char *dbus_path; @@ -214,24 +214,22 @@ mm_modem_base_set_equipment_identity (MMModemBase *self, const char *equipment_i priv = MM_MODEM_BASE_GET_PRIVATE (self); /* Only do something if the value changes */ - if ( (priv->equipment_identity == equipment_identity) - || ( priv->equipment_identity - && equipment_identity - && !strcmp (priv->equipment_identity, equipment_identity))) + if ( (priv->equipment_ident == ident) + || (priv->equipment_ident && ident && !strcmp (priv->equipment_ident, ident))) return; - g_free (priv->equipment_identity); - priv->equipment_identity = g_strdup (equipment_identity); + g_free (priv->equipment_ident); + priv->equipment_ident = g_strdup (ident); dbus_path = (const char *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG); if (dbus_path) { - if (priv->equipment_identity) - g_message ("Modem %s: EquipmentIdentity set (%s)", dbus_path, priv->equipment_identity); + if (priv->equipment_ident) + g_message ("Modem %s: Equipment identifier set (%s)", dbus_path, priv->equipment_ident); else - g_message ("Modem %s: EquipmentIdentity not set", dbus_path); + g_message ("Modem %s: Equipment identifier not set", dbus_path); } - g_object_notify (G_OBJECT (self), MM_MODEM_EQUIPMENT_IDENTITY); + g_object_notify (G_OBJECT (self), MM_MODEM_EQUIPMENT_IDENTIFIER); } const char * @@ -566,7 +564,7 @@ mm_modem_base_init (MMModemBase *self) MM_MODEM_ENABLED, MM_MODEM_DBUS_INTERFACE); mm_properties_changed_signal_register_property (G_OBJECT (self), - MM_MODEM_EQUIPMENT_IDENTITY, + MM_MODEM_EQUIPMENT_IDENTIFIER, MM_MODEM_DBUS_INTERFACE); mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_UNLOCK_REQUIRED, @@ -622,7 +620,7 @@ set_property (GObject *object, guint prop_id, case MM_MODEM_PROP_VALID: case MM_MODEM_PROP_TYPE: case MM_MODEM_PROP_ENABLED: - case MM_MODEM_PROP_EQUIPMENT_IDENTITY: + case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER: case MM_MODEM_PROP_UNLOCK_REQUIRED: case MM_MODEM_PROP_UNLOCK_RETRIES: break; @@ -666,8 +664,8 @@ get_property (GObject *object, guint prop_id, case MM_MODEM_PROP_ENABLED: g_value_set_boolean (value, is_enabled (priv->state)); break; - case MM_MODEM_PROP_EQUIPMENT_IDENTITY: - g_value_set_string (value, priv->equipment_identity); + case MM_MODEM_PROP_EQUIPMENT_IDENTIFIER: + g_value_set_string (value, priv->equipment_ident); break; case MM_MODEM_PROP_UNLOCK_REQUIRED: g_value_set_string (value, priv->unlock_required); @@ -693,7 +691,7 @@ finalize (GObject *object) g_free (priv->driver); g_free (priv->plugin); g_free (priv->device); - g_free (priv->equipment_identity); + g_free (priv->equipment_ident); g_free (priv->unlock_required); G_OBJECT_CLASS (mm_modem_base_parent_class)->finalize (object); @@ -748,8 +746,8 @@ mm_modem_base_class_init (MMModemBaseClass *klass) MM_MODEM_ENABLED); g_object_class_override_property (object_class, - MM_MODEM_PROP_EQUIPMENT_IDENTITY, - MM_MODEM_EQUIPMENT_IDENTITY); + MM_MODEM_PROP_EQUIPMENT_IDENTIFIER, + MM_MODEM_EQUIPMENT_IDENTIFIER); g_object_class_override_property (object_class, MM_MODEM_PROP_UNLOCK_REQUIRED, diff --git a/src/mm-modem-base.h b/src/mm-modem-base.h index 49daae27..04099577 100644 --- a/src/mm-modem-base.h +++ b/src/mm-modem-base.h @@ -62,10 +62,10 @@ void mm_modem_base_set_valid (MMModemBase *self, gboolean mm_modem_base_get_valid (MMModemBase *self); -const char *mm_modem_base_get_equipment_identity (MMModemBase *self); +const char *mm_modem_base_get_equipment_identifier (MMModemBase *self); -void mm_modem_base_set_equipment_identity (MMModemBase *self, - const char *equipment_identity); +void mm_modem_base_set_equipment_identifier (MMModemBase *self, + const char *ident); const char *mm_modem_base_get_unlock_required (MMModemBase *self); diff --git a/src/mm-modem.c b/src/mm-modem.c index 8cb7e725..8d25e483 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -805,9 +805,9 @@ mm_modem_init (gpointer g_iface) g_object_interface_install_property (g_iface, - g_param_spec_string (MM_MODEM_EQUIPMENT_IDENTITY, - "EquipmentIdentiy", - "The equipment identity of the device", + g_param_spec_string (MM_MODEM_EQUIPMENT_IDENTIFIER, + "EquipmentIdentifier", + "The equipment identifier of the device", NULL, G_PARAM_READABLE)); diff --git a/src/mm-modem.h b/src/mm-modem.h index a5923b86..154de87c 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -58,7 +58,7 @@ typedef enum { #define MM_MODEM_TYPE "type" #define MM_MODEM_IP_METHOD "ip-method" #define MM_MODEM_ENABLED "enabled" -#define MM_MODEM_EQUIPMENT_IDENTITY "equipment-identity" +#define MM_MODEM_EQUIPMENT_IDENTIFIER "equipment-identifier" #define MM_MODEM_UNLOCK_REQUIRED "unlock-required" #define MM_MODEM_UNLOCK_RETRIES "unlock-retries" #define MM_MODEM_VALID "valid" /* not exported */ @@ -85,7 +85,7 @@ typedef enum { MM_MODEM_PROP_PLUGIN, /* Not exported */ MM_MODEM_PROP_STATE, /* Not exported */ MM_MODEM_PROP_ENABLED, - MM_MODEM_PROP_EQUIPMENT_IDENTITY, + MM_MODEM_PROP_EQUIPMENT_IDENTIFIER, MM_MODEM_PROP_UNLOCK_REQUIRED, MM_MODEM_PROP_UNLOCK_RETRIES } MMModemProp; From 89c572e59d736e273576987ccde91f62ce6f4ce5 Mon Sep 17 00:00:00 2001 From: David Rochberg Date: Tue, 22 Jun 2010 17:47:07 -0700 Subject: [PATCH 13/15] core: add FactoryReset method Cleanups and authorization checks by me (dcbw). --- introspection/mm-modem.xml | 11 ++++++++ src/mm-modem.c | 57 ++++++++++++++++++++++++++++++++++++++ src/mm-modem.h | 10 +++++++ 3 files changed, 78 insertions(+) diff --git a/introspection/mm-modem.xml b/introspection/mm-modem.xml index 35b67968..7d54dd30 100644 --- a/introspection/mm-modem.xml +++ b/introspection/mm-modem.xml @@ -81,6 +81,17 @@ + + + Reset the modem to as close to factory state as possible. + + + + + Carrier-supplied code required to reset the modem. Ignored if not required. + + + The modem port to use for IP configuration and traffic. diff --git a/src/mm-modem.c b/src/mm-modem.c index 8d25e483..221c9eab 100644 --- a/src/mm-modem.c +++ b/src/mm-modem.c @@ -28,6 +28,7 @@ static void impl_modem_connect (MMModem *modem, const char *number, DBusGMethodI static void impl_modem_disconnect (MMModem *modem, DBusGMethodInvocation *context); static void impl_modem_get_ip4_config (MMModem *modem, DBusGMethodInvocation *context); static void impl_modem_get_info (MMModem *modem, DBusGMethodInvocation *context); +static void impl_modem_factory_reset (MMModem *modem, const char *code, DBusGMethodInvocation *context); #include "mm-modem-glue.h" @@ -476,6 +477,62 @@ impl_modem_get_info (MMModem *modem, /*****************************************************************************/ +static void +factory_reset_auth_cb (MMAuthRequest *req, + GObject *owner, + DBusGMethodInvocation *context, + gpointer user_data) +{ + MMModem *self = MM_MODEM (owner); + const char *code = user_data; + GError *error = NULL; + + /* Return any authorization error, otherwise try to reset the modem */ + if (!mm_modem_auth_finish (self, req, &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else + mm_modem_factory_reset (self, code, async_call_done, context); +} + +static void +impl_modem_factory_reset (MMModem *modem, + const char *code, + DBusGMethodInvocation *context) +{ + GError *error = NULL; + + /* Make sure the caller is authorized to reset the device */ + if (!mm_modem_auth_request (MM_MODEM (modem), + MM_AUTHORIZATION_DEVICE_CONTROL, + context, + factory_reset_auth_cb, + g_strdup (code), + g_free, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +void +mm_modem_factory_reset (MMModem *self, + const char *code, + MMModemFn callback, + gpointer user_data) +{ + g_return_if_fail (MM_IS_MODEM (self)); + g_return_if_fail (callback != NULL); + g_return_if_fail (code != NULL); + + if (MM_MODEM_GET_INTERFACE (self)->factory_reset) + MM_MODEM_GET_INTERFACE (self)->factory_reset (self, code, callback, user_data); + else + async_op_not_supported (self, callback, user_data); +} + +/*****************************************************************************/ + void mm_modem_get_supported_charsets (MMModem *self, MMModemUIntFn callback, diff --git a/src/mm-modem.h b/src/mm-modem.h index 154de87c..0915180b 100644 --- a/src/mm-modem.h +++ b/src/mm-modem.h @@ -188,6 +188,11 @@ struct _MMModem { MMAuthRequest *req, GError **error); + void (*factory_reset) (MMModem *self, + const char *code, + MMModemFn callback, + gpointer user_data); + /* Signals */ void (*state_changed) (MMModem *self, MMModemState new_state, @@ -246,6 +251,11 @@ void mm_modem_set_charset (MMModem *self, MMModemFn callback, gpointer user_data); +void mm_modem_factory_reset (MMModem *self, + const char *code, + MMModemFn callback, + gpointer user_data); + gboolean mm_modem_get_valid (MMModem *self); char *mm_modem_get_device (MMModem *self); From 48dbece33cb187196e69f4ff058c93a43a071ac4 Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Wed, 23 Jun 2010 16:39:13 -0700 Subject: [PATCH 14/15] mbm: add factory reset support --- plugins/mm-modem-mbm.c | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index e1cb6e52..7f6bc9c8 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -508,6 +508,59 @@ do_disconnect (MMGenericGsm *gsm, MM_GENERIC_GSM_CLASS (mm_modem_mbm_parent_class)->do_disconnect (gsm, cid, callback, user_data); } +static void +factory_reset_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + + mm_serial_port_close (MM_SERIAL_PORT (port)); + mm_callback_info_schedule (info); +} + +static void +factory_reset (MMModem *self, + const char *code, + MMModemFn callback, + gpointer user_data) +{ + MMAtSerialPort *port; + MMCallbackInfo *info; + + info = mm_callback_info_new (self, 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 (self), &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; + } + + mm_at_serial_port_queue_command (port, "&F +CMEE=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+COPS=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CR=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CRC=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CREG=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CMER=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "*EPEE=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CNMI=2, 0, 0, 0, 0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CGREG=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "*EIAD=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CGSMS=3", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CSCA=\"\",129", 3, factory_reset_done, info); +} + /*****************************************************************************/ static void @@ -916,6 +969,7 @@ modem_init (MMModem *modem_class) modem_class->grab_port = grab_port; modem_class->disable = disable; modem_class->connect = do_connect; + modem_class->factory_reset = factory_reset; } static void From 5fc9f259e253fc32510eca8fbd42416706fe0db6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 24 Jun 2010 09:19:55 -0700 Subject: [PATCH 15/15] trivial: print out useful debugging info before asserting --- src/mm-manager.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mm-manager.c b/src/mm-manager.c index 9b4c6d6e..1dd19026 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -614,8 +614,17 @@ supports_callback (MMPlugin *plugin, * supports it. */ next_plugin = existing_plugin; - } else + } else { + g_debug ("(%s/%s): plugin %p (%s) existing %p (%s) info->best %p (%s)", + info->subsys, info->name, + plugin, + plugin ? mm_plugin_get_name (plugin) : "none", + existing_plugin, + existing_plugin ? mm_plugin_get_name (existing_plugin) : "none", + info->best_plugin, + info->best_plugin ? mm_plugin_get_name (info->best_plugin) : "none"); g_assert_not_reached (); + } } else { info->cur_plugin = g_slist_next (info->cur_plugin); if (info->cur_plugin)