aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2011-06-22 13:01:17 +0200
committerAleksander Morgado <aleksander@lanedo.com>2011-06-22 13:11:39 +0200
commiteae5d6c41be6652bac384340c47d274164007ebb (patch)
tree0edccb62fd57f02f3626a1a2e1e0b8daea2c9c58
parent56db81890120e63f251b899b0eac66dc8941d411 (diff)
cinterion: enable power-off command to go to sleep/standby mode
AT+CFUN=4 will be used when available to go to standby mode. If not supported, (as in EGS5) AT+CFUN=7 will be used instead, which enables a CYCLIC SLEEP mode. Flow control setup was updated to RCS/CTS so that waking up from sleep mode works properly.
-rw-r--r--plugins/mm-modem-cinterion-gsm.c97
1 files changed, 92 insertions, 5 deletions
diff --git a/plugins/mm-modem-cinterion-gsm.c b/plugins/mm-modem-cinterion-gsm.c
index 56a6b007..34a5d6dc 100644
--- a/plugins/mm-modem-cinterion-gsm.c
+++ b/plugins/mm-modem-cinterion-gsm.c
@@ -66,6 +66,9 @@ typedef struct {
/* Bitmask for currently active bands */
guint32 current_bands;
+
+ /* Command to go into sleep mode */
+ gchar *sleep_mode_cmd;
} MMModemCinterionGsmPrivate;
/* Setup relationship between the band bitmask in the modem and the bitmask
@@ -834,6 +837,55 @@ enable_complete (MMGenericGsm *gsm,
}
static void
+get_supported_functionality_status_cb (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
+{
+ MMCallbackInfo *info = user_data;
+ MMModemCinterionGsmPrivate *priv;
+
+ /* If the modem has already been removed, return without
+ * scheduling callback */
+ if (mm_callback_info_check_modem_removed (info))
+ return;
+
+ if (error) {
+ enable_complete (MM_GENERIC_GSM (info->modem), error, info);
+ return;
+ }
+
+ priv = MM_MODEM_CINTERION_GSM_GET_PRIVATE (info->modem);
+
+ /* We need to get which power-off command to use to put the modem in low
+ * power mode (with serial port open for AT commands, but with RF switched
+ * off). According to the documentation of various Cinterion modems, some
+ * support AT+CFUN=4 (HC25) and those which don't support it can use
+ * AT+CFUN=7 (CYCLIC SLEEP mode with 2s timeout after last character
+ * received in the serial port).
+ *
+ * So, just look for '4' in the reply; if not found, look for '7', and if
+ * not found, report warning and don't use any.
+ */
+
+ g_free (priv->sleep_mode_cmd);
+ if (strstr (response->str, "4") != NULL) {
+ mm_dbg ("Device supports CFUN=4 sleep mode");
+ priv->sleep_mode_cmd = g_strdup ("+CFUN=4");
+ } else if (strstr (response->str, "7") != NULL) {
+ mm_dbg ("Device supports CFUN=7 sleep mode");
+ priv->sleep_mode_cmd = g_strdup ("+CFUN=7");
+ } else {
+ mm_warn ("Unknown functionality mode to go into sleep mode");
+ priv->sleep_mode_cmd = NULL;
+ }
+
+ /* All done without errors! */
+ mm_dbg ("[3/3] All done");
+ enable_complete (MM_GENERIC_GSM (info->modem), NULL, info);
+}
+
+static void
get_supported_networks_cb (MMAtSerialPort *port,
GString *response,
GError *error,
@@ -841,7 +893,6 @@ get_supported_networks_cb (MMAtSerialPort *port,
{
MMCallbackInfo *info = user_data;
MMModemCinterionGsmPrivate *priv;
- GError *inner_error = NULL;
/* If the modem has already been removed, return without
* scheduling callback */
@@ -880,17 +931,22 @@ get_supported_networks_cb (MMAtSerialPort *port,
if (!priv->only_geran &&
!priv->only_utran &&
!priv->both_geran_utran) {
+ GError *inner_error = NULL;
+
mm_warn ("Invalid list of supported networks: '%s'",
response->str);
inner_error = g_error_new (MM_MODEM_ERROR,
MM_MODEM_ERROR_GENERAL,
"Invalid list of supported networks: '%s'",
response->str);
+ enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info);
+ g_error_free (inner_error);
+ return;
}
- enable_complete (MM_GENERIC_GSM (info->modem), inner_error, info);
- if (inner_error)
- g_error_free (inner_error);
+ /* Next, check which supported functionality modes are available */
+ mm_dbg ("[2/3] Getting list of supported functionality status...");
+ mm_at_serial_port_queue_command (port, "+CFUN=?", 3, get_supported_functionality_status_cb, info);
}
static void
@@ -915,7 +971,8 @@ do_enable_power_up_done (MMGenericGsm *gsm,
return;
}
- /* List supported networks */
+ /* First, list supported networks */
+ mm_dbg ("[1/3] Getting list of supported networks...");
mm_at_serial_port_queue_command (port, "+WS46=?", 3, get_supported_networks_cb, info);
}
@@ -934,7 +991,13 @@ get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
+ MMModemCinterionGsmPrivate *priv = MM_MODEM_CINTERION_GSM_GET_PRIVATE (object);
+
switch (prop_id) {
+ case MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD:
+ /* We need to enable RTS/CTS so that CYCLIC SLEEP mode works */
+ g_value_set_string (value, "\\Q3");
+ break;
case MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD:
/* AT+CNMO=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]]
* but <bfr> should be either not set, or equal to 1;
@@ -956,11 +1019,25 @@ get_property (GObject *object,
* */
g_value_set_string (value, "+CMER=3,0,0,2");
break;
+ case MM_GENERIC_GSM_PROP_POWER_DOWN_CMD:
+ /* Use the value computed before, if any. */
+ g_value_set_string (value, priv->sleep_mode_cmd ? priv->sleep_mode_cmd : "");
+ break;
default:
break;
}
}
+static void
+finalize (GObject *object)
+{
+ MMModemCinterionGsmPrivate *priv = MM_MODEM_CINTERION_GSM_GET_PRIVATE (object);
+
+ g_free (priv->sleep_mode_cmd);
+
+ G_OBJECT_CLASS (mm_modem_cinterion_gsm_parent_class)->finalize (object);
+}
+
/*****************************************************************************/
static void
@@ -990,12 +1067,18 @@ mm_modem_cinterion_gsm_class_init (MMModemCinterionGsmClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass);
+ mm_modem_cinterion_gsm_parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (object_class, sizeof (MMModemCinterionGsmPrivate));
+ object_class->finalize = finalize;
object_class->get_property = get_property;
object_class->set_property = set_property;
g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD,
+ MM_GENERIC_GSM_FLOW_CONTROL_CMD);
+
+ g_object_class_override_property (object_class,
MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD,
MM_GENERIC_GSM_SMS_INDICATION_ENABLE_CMD);
@@ -1007,6 +1090,10 @@ mm_modem_cinterion_gsm_class_init (MMModemCinterionGsmClass *klass)
MM_GENERIC_GSM_PROP_CMER_ENABLE_CMD,
MM_GENERIC_GSM_CMER_ENABLE_CMD);
+ g_object_class_override_property (object_class,
+ MM_GENERIC_GSM_PROP_POWER_DOWN_CMD,
+ MM_GENERIC_GSM_POWER_DOWN_CMD);
+
gsm_class->do_enable_power_up_done = do_enable_power_up_done;
gsm_class->set_allowed_mode = set_allowed_mode;
gsm_class->get_allowed_mode = get_allowed_mode;