broadband-modem: implement support for the +CEMODE command

The +CEMODE command is defined in 3GPP TS 27.007 (e.g. in section
10.1.28 in v11.0.0). This command allows querying or updating the
current UE mode, as well as checking the supported modes.

We implement support for loading the current mode and updating it. It
is assumed that the device does any additional operation needed by the
setting update, e.g. un-registering from CS when selecting an EPS-only
mode.
This commit is contained in:
Aleksander Morgado
2017-12-28 18:41:51 +01:00
parent d4aaa436d9
commit 22ffd3f3aa
3 changed files with 117 additions and 0 deletions

View File

@@ -3935,6 +3935,68 @@ modem_3gpp_load_subscription_state (MMIfaceModem3gpp *self,
g_object_unref (task); g_object_unref (task);
} }
/*****************************************************************************/
/* UE mode of operation for EPS loading (3GPP interface) */
static MMModem3gppEpsUeModeOperation
modem_3gpp_load_eps_ue_mode_operation_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
MMModem3gppEpsUeModeOperation mode;
const gchar *result;
result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
if (!result || !mm_3gpp_parse_cemode_query_response (result, &mode, error))
return MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN;
return mode;
}
static void
modem_3gpp_load_eps_ue_mode_operation (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
mm_dbg ("loading UE mode of operation for EPS...");
mm_base_modem_at_command (MM_BASE_MODEM (self),
"+CEMODE?",
3,
FALSE,
callback,
user_data);
}
/*****************************************************************************/
/* UE mode of operation for EPS settin (3GPP interface) */
static gboolean
modem_3gpp_set_eps_ue_mode_operation_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
}
static void
modem_3gpp_set_eps_ue_mode_operation (MMIfaceModem3gpp *self,
MMModem3gppEpsUeModeOperation mode,
GAsyncReadyCallback callback,
gpointer user_data)
{
gchar *cmd;
mm_dbg ("updating UE mode of operation for EPS...");
cmd = mm_3gpp_build_cemode_set_request (mode);
mm_base_modem_at_command (MM_BASE_MODEM (self),
cmd,
3,
FALSE,
callback,
user_data);
g_free (cmd);
}
/*****************************************************************************/ /*****************************************************************************/
/* Unsolicited registration messages handling (3GPP interface) */ /* Unsolicited registration messages handling (3GPP interface) */
@@ -11038,6 +11100,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
iface->load_imei_finish = modem_3gpp_load_imei_finish; iface->load_imei_finish = modem_3gpp_load_imei_finish;
iface->load_enabled_facility_locks = modem_3gpp_load_enabled_facility_locks; iface->load_enabled_facility_locks = modem_3gpp_load_enabled_facility_locks;
iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish; iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish;
iface->load_eps_ue_mode_operation = modem_3gpp_load_eps_ue_mode_operation;
iface->load_eps_ue_mode_operation_finish = modem_3gpp_load_eps_ue_mode_operation_finish;
/* Enabling steps */ /* Enabling steps */
iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events; iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events;
@@ -11072,6 +11136,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
iface->register_in_network_finish = modem_3gpp_register_in_network_finish; iface->register_in_network_finish = modem_3gpp_register_in_network_finish;
iface->scan_networks = modem_3gpp_scan_networks; iface->scan_networks = modem_3gpp_scan_networks;
iface->scan_networks_finish = modem_3gpp_scan_networks_finish; iface->scan_networks_finish = modem_3gpp_scan_networks_finish;
iface->set_eps_ue_mode_operation = modem_3gpp_set_eps_ue_mode_operation;
iface->set_eps_ue_mode_operation_finish = modem_3gpp_set_eps_ue_mode_operation_finish;
} }
static void static void

View File

@@ -2485,6 +2485,51 @@ mm_3gpp_parse_cfun_query_generic_response (const gchar *response,
} }
} }
static MMModem3gppEpsUeModeOperation cemode_values[] = {
[0] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_2,
[1] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_1,
[2] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_2,
[3] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_1,
};
gchar *
mm_3gpp_build_cemode_set_request (MMModem3gppEpsUeModeOperation mode)
{
guint i;
g_return_val_if_fail (mode != MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN, NULL);
for (i = 0; i < G_N_ELEMENTS (cemode_values); i++) {
if (mode == cemode_values[i])
return g_strdup_printf ("+CEMODE=%u", i);
}
g_assert_not_reached ();
return NULL;
}
gboolean
mm_3gpp_parse_cemode_query_response (const gchar *response,
MMModem3gppEpsUeModeOperation *out_mode,
GError **error)
{
guint value = 0;
response = mm_strip_tag (response, "+CEMODE:");
if (mm_get_uint_from_str (response, &value) && value < G_N_ELEMENTS (cemode_values)) {
if (out_mode)
*out_mode = cemode_values[value];
return TRUE;
}
g_set_error (error,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Couldn't parse UE mode of operation: '%s' (value %u)",
response, value);
return FALSE;
}
/*************************************************************************/ /*************************************************************************/
static MMSmsStorage static MMSmsStorage

View File

@@ -328,6 +328,12 @@ gboolean mm_3gpp_cesq_response_to_signal_info (const gchar *response,
MMSignal **out_lte, MMSignal **out_lte,
GError **error); GError **error);
/* CEMODE? response parser */
gchar *mm_3gpp_build_cemode_set_request (MMModem3gppEpsUeModeOperation mode);
gboolean mm_3gpp_parse_cemode_query_response (const gchar *response,
MMModem3gppEpsUeModeOperation *out_mode,
GError **error);
/* Additional 3GPP-specific helpers */ /* Additional 3GPP-specific helpers */
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str); MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);