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.
This commit is contained in:
@@ -66,6 +66,9 @@ typedef struct {
|
|||||||
|
|
||||||
/* Bitmask for currently active bands */
|
/* Bitmask for currently active bands */
|
||||||
guint32 current_bands;
|
guint32 current_bands;
|
||||||
|
|
||||||
|
/* Command to go into sleep mode */
|
||||||
|
gchar *sleep_mode_cmd;
|
||||||
} MMModemCinterionGsmPrivate;
|
} MMModemCinterionGsmPrivate;
|
||||||
|
|
||||||
/* Setup relationship between the band bitmask in the modem and the bitmask
|
/* Setup relationship between the band bitmask in the modem and the bitmask
|
||||||
@@ -833,6 +836,55 @@ enable_complete (MMGenericGsm *gsm,
|
|||||||
mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
|
mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
get_supported_networks_cb (MMAtSerialPort *port,
|
get_supported_networks_cb (MMAtSerialPort *port,
|
||||||
GString *response,
|
GString *response,
|
||||||
@@ -841,7 +893,6 @@ get_supported_networks_cb (MMAtSerialPort *port,
|
|||||||
{
|
{
|
||||||
MMCallbackInfo *info = user_data;
|
MMCallbackInfo *info = user_data;
|
||||||
MMModemCinterionGsmPrivate *priv;
|
MMModemCinterionGsmPrivate *priv;
|
||||||
GError *inner_error = NULL;
|
|
||||||
|
|
||||||
/* If the modem has already been removed, return without
|
/* If the modem has already been removed, return without
|
||||||
* scheduling callback */
|
* scheduling callback */
|
||||||
@@ -880,17 +931,22 @@ get_supported_networks_cb (MMAtSerialPort *port,
|
|||||||
if (!priv->only_geran &&
|
if (!priv->only_geran &&
|
||||||
!priv->only_utran &&
|
!priv->only_utran &&
|
||||||
!priv->both_geran_utran) {
|
!priv->both_geran_utran) {
|
||||||
|
GError *inner_error = NULL;
|
||||||
|
|
||||||
mm_warn ("Invalid list of supported networks: '%s'",
|
mm_warn ("Invalid list of supported networks: '%s'",
|
||||||
response->str);
|
response->str);
|
||||||
inner_error = g_error_new (MM_MODEM_ERROR,
|
inner_error = g_error_new (MM_MODEM_ERROR,
|
||||||
MM_MODEM_ERROR_GENERAL,
|
MM_MODEM_ERROR_GENERAL,
|
||||||
"Invalid list of supported networks: '%s'",
|
"Invalid list of supported networks: '%s'",
|
||||||
response->str);
|
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);
|
/* Next, check which supported functionality modes are available */
|
||||||
if (inner_error)
|
mm_dbg ("[2/3] Getting list of supported functionality status...");
|
||||||
g_error_free (inner_error);
|
mm_at_serial_port_queue_command (port, "+CFUN=?", 3, get_supported_functionality_status_cb, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -915,7 +971,8 @@ do_enable_power_up_done (MMGenericGsm *gsm,
|
|||||||
return;
|
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);
|
mm_at_serial_port_queue_command (port, "+WS46=?", 3, get_supported_networks_cb, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,7 +991,13 @@ get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
|
MMModemCinterionGsmPrivate *priv = MM_MODEM_CINTERION_GSM_GET_PRIVATE (object);
|
||||||
|
|
||||||
switch (prop_id) {
|
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:
|
case MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD:
|
||||||
/* AT+CNMO=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]]
|
/* AT+CNMO=<mode>,[<mt>[,<bm>[,<ds>[,<bfr>]]]]
|
||||||
* but <bfr> should be either not set, or equal to 1;
|
* 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");
|
g_value_set_string (value, "+CMER=3,0,0,2");
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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
|
static void
|
||||||
@@ -990,11 +1067,17 @@ mm_modem_cinterion_gsm_class_init (MMModemCinterionGsmClass *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_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));
|
g_type_class_add_private (object_class, sizeof (MMModemCinterionGsmPrivate));
|
||||||
|
|
||||||
|
object_class->finalize = finalize;
|
||||||
object_class->get_property = get_property;
|
object_class->get_property = get_property;
|
||||||
object_class->set_property = set_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,
|
g_object_class_override_property (object_class,
|
||||||
MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD,
|
MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD,
|
||||||
MM_GENERIC_GSM_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_PROP_CMER_ENABLE_CMD,
|
||||||
MM_GENERIC_GSM_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->do_enable_power_up_done = do_enable_power_up_done;
|
||||||
gsm_class->set_allowed_mode = set_allowed_mode;
|
gsm_class->set_allowed_mode = set_allowed_mode;
|
||||||
gsm_class->get_allowed_mode = get_allowed_mode;
|
gsm_class->get_allowed_mode = get_allowed_mode;
|
||||||
|
Reference in New Issue
Block a user