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:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user