diff options
author | Dan Williams <dcbw@redhat.com> | 2012-09-07 15:34:31 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2012-09-07 15:34:50 -0500 |
commit | 716f1338639eda7c2ce1760ce6595eb88834b316 (patch) | |
tree | adce098ba828495b4593ecdd57568f52a8d36598 | |
parent | 8ba968d59172eb55b5e187db420f6833322608fe (diff) | |
download | ModemManager-716f1338639eda7c2ce1760ce6595eb88834b316.tar.gz |
sierra: add support for new !SELRAT values in newer Sierra LTE modems
This is a backport of:
author Marius B. Kotsbak <marius@kotsbak.com> 2012-09-03 16:26:59 (GMT)
commit 9c2a6320a82aa301b2415227741a8bff5a33ea1b
-rw-r--r-- | plugins/mm-modem-sierra-gsm.c | 106 | ||||
-rw-r--r-- | plugins/mm-modem-sierra-gsm.h | 3 | ||||
-rw-r--r-- | plugins/mm-plugin-sierra.c | 3 |
3 files changed, 101 insertions, 11 deletions
diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c index 665b7c529..23ed02970 100644 --- a/plugins/mm-modem-sierra-gsm.c +++ b/plugins/mm-modem-sierra-gsm.c @@ -44,6 +44,7 @@ G_DEFINE_TYPE_EXTENDED (MMModemSierraGsm, mm_modem_sierra_gsm, MM_TYPE_GENERIC_G typedef struct { guint enable_wait_id; gboolean has_net; + gboolean has_lte; char *username; char *password; gboolean is_icera; @@ -55,7 +56,8 @@ mm_modem_sierra_gsm_new (const char *device, const char *driver, const char *plugin, guint32 vendor, - guint32 product) + guint32 product, + gboolean has_lte) { MMModem *modem; @@ -70,8 +72,10 @@ mm_modem_sierra_gsm_new (const char *device, MM_MODEM_HW_VID, vendor, MM_MODEM_HW_PID, product, NULL); - if (modem) + if (modem) { MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->icera = mm_modem_icera_init_private (); + MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem)->has_lte = has_lte; + } return modem; } @@ -85,6 +89,7 @@ get_allowed_mode_done (MMAtSerialPort *port, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMModemSierraGsmPrivate *priv; GRegex *r = NULL; GMatchInfo *match_info = NULL; @@ -107,6 +112,7 @@ get_allowed_mode_done (MMAtSerialPort *port, goto done; } + priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (info->modem); if (g_regex_match_full (r, response->str, response->len, 0, 0, &match_info, &info->error)) { MMModemGsmAllowedMode mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; char *str; @@ -123,10 +129,28 @@ get_allowed_mode_done (MMAtSerialPort *port, mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; break; case 3: - mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; + /* in Sierra LTE devices, mode 3 is automatic, including LTE, no preference */ + if (priv->has_lte) + mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; + else + mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; break; case 4: - mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; + /* in Sierra LTE devices, mode 4 is automatic, including LTE, no preference */ + if (priv->has_lte) + mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; + else + mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; + break; + case 5: + /* 2G and 3G only; but we can't represent that */ + mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; + break; + case 6: + mode = MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY; + break; + case 7: + mode = MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED; break; default: info->error = g_error_new (MM_MODEM_ERROR, @@ -223,6 +247,15 @@ set_allowed_mode (MMGenericGsm *gsm, return; } + if ( MM_MODEM_SIERRA_GSM_GET_PRIVATE (self)->has_lte == FALSE + && ( mode == MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY + || mode == MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED)) { + g_set_error_literal (&info->error, MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, + "4G allowed modes requested, but modem does not support 4G"); + mm_callback_info_schedule (info); + return; + } + switch (mode) { case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: idx = 2; @@ -230,12 +263,18 @@ set_allowed_mode (MMGenericGsm *gsm, case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: idx = 1; break; + case MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY: + idx = 6; + break; case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: idx = 4; break; case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: idx = 3; break; + case MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED: + idx = 7; + break; case MM_MODEM_GSM_ALLOWED_MODE_ANY: default: break; @@ -460,6 +499,31 @@ icera_check_cb (MMModem *modem, MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_enable_power_up_done (MM_GENERIC_GSM (info->modem), NULL, NULL, info); } +static void +ws46_done_cb (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return; + + /* Ignore errors */ + if (!error && response) { + if (strstr (response->str, "28") || /* 4G only */ + strstr (response->str, "30") || /* 2G/4G */ + strstr (response->str, "31")) { /* 3G/4G */ + MM_MODEM_SIERRA_GSM_GET_PRIVATE (info->modem)->has_lte = TRUE; + } + } + + mm_modem_icera_is_icera (MM_MODEM_ICERA (info->modem), icera_check_cb, info); +} + static gboolean sierra_enabled (gpointer user_data) { @@ -467,13 +531,37 @@ sierra_enabled (gpointer user_data) MMGenericGsm *modem; MMModemSierraGsmPrivate *priv; - /* Make sure we don't use an invalid modem that may have been removed */ - if (info->modem) { - modem = MM_GENERIC_GSM (info->modem); - priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem); - priv->enable_wait_id = 0; + /* If the modem has already been removed, return without + * scheduling callback */ + if (mm_callback_info_check_modem_removed (info)) + return FALSE; + + modem = MM_GENERIC_GSM (info->modem); + priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem); + priv->enable_wait_id = 0; + + if (priv->has_lte) mm_modem_icera_is_icera (MM_MODEM_ICERA (modem), icera_check_cb, info); + else { + MMAtSerialPort *primary; + + /* Some modems (e.g. Sierra Wireless MC7710 or ZTE MF820D) won't report LTE + * capabilities even if they have them. So just run AT+WS46=? as well to see + * if the current supported modes includes any LTE-specific mode. + * This is not a big deal, as the AT+WS46=? command is a test command with a + * cache-able result. + * + * E.g.: + * AT+WS46=? + * +WS46: (12,22,25,28,29) + * OK + * + */ + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (info->modem), MM_AT_PORT_FLAG_PRIMARY); + g_assert (primary); + mm_at_serial_port_queue_command (primary, "+WS46=?", 3, ws46_done_cb, info); } + return FALSE; } diff --git a/plugins/mm-modem-sierra-gsm.h b/plugins/mm-modem-sierra-gsm.h index 8f2391d97..7a376a275 100644 --- a/plugins/mm-modem-sierra-gsm.h +++ b/plugins/mm-modem-sierra-gsm.h @@ -40,6 +40,7 @@ MMModem *mm_modem_sierra_gsm_new (const char *device, const char *driver, const char *plugin_name, guint32 vendor, - guint32 product); + guint32 product, + gboolean has_lte); #endif /* MM_MODEM_SIERRA_GSM_H */ diff --git a/plugins/mm-plugin-sierra.c b/plugins/mm-plugin-sierra.c index 51ad17417..d05fad0e1 100644 --- a/plugins/mm-plugin-sierra.c +++ b/plugins/mm-plugin-sierra.c @@ -201,7 +201,8 @@ grab_port (MMPluginBase *base, mm_plugin_base_supports_task_get_driver (task), mm_plugin_get_name (MM_PLUGIN (base)), vendor, - product); + product, + (caps & MM_PLUGIN_BASE_PORT_CAP_LTE)); } else if (caps & CAP_CDMA) { modem = mm_modem_sierra_cdma_new (sysfs_path, mm_plugin_base_supports_task_get_driver (task), |