cinterion: setup initial LTE parameters

This commit is contained in:
Giacinto Cifelli
2020-08-11 07:17:07 +00:00
committed by Aleksander Morgado
parent 28ad994e37
commit e2ab49db0f
6 changed files with 722 additions and 12 deletions
@@ -197,15 +197,30 @@ parse_auth_type (MMBearerAllowedAuth mm_auth)
}
}
MMBearerAllowedAuth
mm_auth_type_from_cinterion_auth_type (guint cinterion_auth)
{
switch (cinterion_auth) {
case BEARER_CINTERION_AUTH_NONE:
return MM_BEARER_ALLOWED_AUTH_NONE;
case BEARER_CINTERION_AUTH_PAP:
return MM_BEARER_ALLOWED_AUTH_PAP;
case BEARER_CINTERION_AUTH_CHAP:
return MM_BEARER_ALLOWED_AUTH_CHAP;
default:
return MM_BEARER_ALLOWED_AUTH_UNKNOWN;
}
}
/* Cinterion authentication is done with the command AT^SGAUTH,
whose syntax depends on the modem family, as follow:
- AT^SGAUTH=<cid>[, <auth_type>[, <user>, <passwd>]] for the IMT family
- AT^SGAUTH=<cid>[, <auth_type>[, <passwd>, <user>]] for the rest */
static gchar *
build_auth_string (MMBroadbandBearerCinterion *self,
MMCinterionModemFamily modem_family,
MMBearerProperties *config,
guint cid)
gchar *
mm_broadband_bearer_cinterion_build_auth_string (gpointer log_object,
MMCinterionModemFamily modem_family,
MMBearerProperties *config,
guint cid)
{
MMBearerAllowedAuth auth;
BearerCinterionAuthType encoded_auth = BEARER_CINTERION_AUTH_UNKNOWN;
@@ -227,7 +242,7 @@ build_auth_string (MMBroadbandBearerCinterion *self,
/* When 'none' requested, we won't require user/password */
if (encoded_auth == BEARER_CINTERION_AUTH_NONE) {
if (has_user || has_passwd)
mm_obj_warn (self, "APN user/password given but 'none' authentication requested");
mm_obj_warn (log_object, "APN user/password given but 'none' authentication requested");
if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT)
return g_strdup_printf ("^SGAUTH=%u,%d,\"\",\"\"", cid, encoded_auth);
return g_strdup_printf ("^SGAUTH=%u,%d", cid, encoded_auth);
@@ -240,7 +255,7 @@ build_auth_string (MMBroadbandBearerCinterion *self,
return NULL;
/* If user/passwd given, default to CHAP (more common than PAP) */
mm_obj_dbg (self, "APN user/password given but no authentication type explicitly requested: defaulting to 'CHAP'");
mm_obj_dbg (log_object, "APN user/password given but no authentication type explicitly requested: defaulting to 'CHAP'");
encoded_auth = BEARER_CINTERION_AUTH_CHAP;
}
@@ -422,10 +437,10 @@ dial_3gpp_context_step (GTask *task)
case DIAL_3GPP_CONTEXT_STEP_AUTH: {
gchar *command;
command = build_auth_string (self,
mm_broadband_modem_cinterion_get_family (MM_BROADBAND_MODEM_CINTERION (ctx->modem)),
mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)),
ctx->cid);
command = mm_broadband_bearer_cinterion_build_auth_string (self,
mm_broadband_modem_cinterion_get_family (MM_BROADBAND_MODEM_CINTERION (ctx->modem)),
mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)),
ctx->cid);
if (command) {
mm_obj_dbg (self, "dial step %u/%u: authenticating...", ctx->step, DIAL_3GPP_CONTEXT_STEP_LAST);
@@ -51,4 +51,11 @@ void mm_broadband_bearer_cinterion_new (MMBroadbandModemCinterio
MMBaseBearer *mm_broadband_bearer_cinterion_new_finish (GAsyncResult *res,
GError **error);
gchar *mm_broadband_bearer_cinterion_build_auth_string (gpointer log_object,
MMCinterionModemFamily modem_family,
MMBearerProperties *config,
guint cid);
MMBearerAllowedAuth mm_auth_type_from_cinterion_auth_type (guint cinterion_auth);
#endif /* MM_BROADBAND_BEARER_CINTERION_H */
@@ -971,6 +971,559 @@ modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp *self,
task);
}
typedef enum {
INITIAL_EPS_CONTEXT_STEP_FIRST = 0,
INITIAL_EPS_CONTEXT_STEP_CHECK_MODE,
INITIAL_EPS_CONTEXT_STEP_RF_OFF,
INITIAL_EPS_CONTEXT_STEP_PROFILE,
INITIAL_EPS_CONTEXT_STEP_APN,
INITIAL_EPS_CONTEXT_STEP_AUTH,
INITIAL_EPS_CONTEXT_STEP_RF_ON,
INITIAL_EPS_CONTEXT_STEP_LAST,
} InitialEpsStep;
typedef struct {
MMBearerProperties *properties;
InitialEpsStep step;
guint cid;
guint initial_cfun_mode;
GError *error;
void (*step_function) (GTask *task);
gboolean get_current_status;
} InitialEpsContext;
static void
initial_eps_context_free (InitialEpsContext *ctx)
{
g_object_unref (ctx->properties);
g_slice_free (InitialEpsContext, ctx);
}
/*****************************************************************************/
/* Set initial EPS bearer settings */
static gboolean
modem_3gpp_set_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_boolean (G_TASK (res), error);
}
static void
initial_eps_common_cmd_check (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
InitialEpsContext *ctx;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
mm_base_modem_at_command_finish (self, res, &error);
if (error) {
mm_obj_warn (self, "%s", error->message);
/* do not overwrite original error */
if (!ctx->error)
ctx->error = error;
else
g_error_free (error);
}
/* Go to next step */
ctx->step++;
ctx->step_function (task);
}
static void
set_cid_from_mno_profile (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
const gchar *response;
InitialEpsContext *ctx;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (self, res, NULL);
/* in case of error, it means that the MNO profiles are not supported
* and therefore that the default CID=1 is ok. */
if (response != NULL)
mm_cinterion_provcfg_response_to_cid (response,
MM_BROADBAND_MODEM_CINTERION (self)->priv->modem_family,
mm_broadband_modem_get_current_charset (MM_BROADBAND_MODEM (self)),
self,
&ctx->cid);
/* Go to next step */
ctx->step++;
ctx->step_function (task);
}
static void
check_cfun_mode (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
const gchar *response;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
InitialEpsContext *ctx;
guint mode;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (self, res, &error);
/* in case of error, abort - something wrong with the modem */
if (error)
goto error;
r = g_regex_new ("\\+CFUN:\\s*(\\d+)", 0, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL);
if (!g_match_info_matches (match_info)) {
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "unmatched CFUN response: %s", response);
goto error;
}
if (!mm_get_uint_from_match_info (match_info, 1, &mode)) {
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "couldn't retrieve current mode from CFUN? response: %s", response);
goto error;
}
mm_obj_dbg (self, "current cfun mode: %u", mode);
if (mode != 1 && mode != 4) {
error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "cannot setup the default LTE bearer at this time: the SIM must be powered");
goto error;
}
ctx->initial_cfun_mode = mode;
ctx->step++;
ctx->step_function (task);
return;
error:
mm_obj_warn (self, "%s", error->message);
g_task_return_error (task, error);
g_object_unref (task);
}
static void
modem_3gpp_set_initial_eps_bearer_settings_step (GTask *task)
{
MMIfaceModem3gpp *self;
InitialEpsContext *ctx;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
/* in case of error, skip all steps and restore radio if needed */
if (ctx->error && ctx->step < INITIAL_EPS_CONTEXT_STEP_RF_ON)
ctx->step = INITIAL_EPS_CONTEXT_STEP_RF_ON;
switch (ctx->step) {
case INITIAL_EPS_CONTEXT_STEP_FIRST:
/* set defaults */
ctx->cid = 1;
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_CHECK_MODE:
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CFUN?",
5,
FALSE,
(GAsyncReadyCallback)check_cfun_mode,
task);
return;
case INITIAL_EPS_CONTEXT_STEP_RF_OFF:
if (ctx->initial_cfun_mode != 4) {
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CFUN=4",
5,
FALSE,
(GAsyncReadyCallback)initial_eps_common_cmd_check,
task);
return;
}
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_PROFILE:
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"^SCFG=\"MEopMode/Prov/Cfg\"",
20,
FALSE,
(GAsyncReadyCallback)set_cid_from_mno_profile,
task);
return;
case INITIAL_EPS_CONTEXT_STEP_APN: {
const gchar *apn;
g_autofree gchar *quoted_apn = NULL;
g_autofree gchar *apn_cmd = NULL;
const gchar *ip_family_str;
MMBearerIpFamily ip_family;
ip_family = mm_bearer_properties_get_ip_type (ctx->properties);
if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY)
ip_family = MM_BEARER_IP_FAMILY_IPV4;
if (ip_family != MM_BEARER_IP_FAMILY_IPV4) {
/* we must have the same settings as in dial_3gpp_context_step()
* for the case when the CID is re-used for the connection PDN */
mm_obj_dbg (self, "Only IPv4 is supported by this modem");
ip_family = MM_BEARER_IP_FAMILY_IPV4;
}
ip_family_str = mm_3gpp_get_pdp_type_from_ip_family (ip_family);
apn = mm_bearer_properties_get_apn (ctx->properties);
mm_obj_dbg (self, "context CID=%d with APN '%s' and PDP type '%s'", ctx->cid, apn, ip_family_str);
quoted_apn = mm_port_serial_at_quote_string (apn);
apn_cmd = g_strdup_printf ("+CGDCONT=%u,\"%s\",%s", ctx->cid, ip_family_str, quoted_apn);
mm_base_modem_at_command (
MM_BASE_MODEM (self),
apn_cmd,
20,
FALSE,
(GAsyncReadyCallback)initial_eps_common_cmd_check,
task);
return;
}
case INITIAL_EPS_CONTEXT_STEP_AUTH: {
g_autofree gchar *auth_cmd = NULL;
auth_cmd = mm_broadband_bearer_cinterion_build_auth_string (self,
MM_BROADBAND_MODEM_CINTERION (self)->priv->modem_family,
ctx->properties,
ctx->cid);
mm_base_modem_at_command (
MM_BASE_MODEM (self),
auth_cmd,
20,
FALSE,
(GAsyncReadyCallback)initial_eps_common_cmd_check,
task);
return;
}
case INITIAL_EPS_CONTEXT_STEP_RF_ON:
if (ctx->initial_cfun_mode == 1) {
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CFUN=1",
5,
FALSE,
(GAsyncReadyCallback)initial_eps_common_cmd_check,
task);
return;
}
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_LAST:
if (ctx->error)
g_task_return_error (task, ctx->error);
else
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
default:
g_assert_not_reached ();
}
}
static void
modem_3gpp_set_initial_eps_bearer_settings (MMIfaceModem3gpp *self,
MMBearerProperties *properties,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
InitialEpsContext *ctx;
task = g_task_new (self, NULL, callback, user_data);
ctx = g_slice_new0 (InitialEpsContext);
g_task_set_task_data (task, ctx, (GDestroyNotify) initial_eps_context_free);
/* Setup context */
ctx->properties = g_object_ref (properties);
ctx->step = INITIAL_EPS_CONTEXT_STEP_FIRST;
ctx->step_function = modem_3gpp_set_initial_eps_bearer_settings_step;
modem_3gpp_set_initial_eps_bearer_settings_step (task);
}
/*****************************************************************************/
/* Initial EPS bearer info loading -> current dynamic configuration */
static MMBearerProperties *
modem_3gpp_load_initial_eps_bearer_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error));
}
static void
get_apn_from_cgdcont (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
const gchar *response;
InitialEpsContext *ctx;
GList *context_list;
GList *l;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (self, res, NULL);
/* in case of error, skip */
if (!response)
goto end;
context_list = mm_3gpp_parse_cgdcont_read_response (response, NULL);
if (!context_list)
goto end;
for (l = context_list; l; l = g_list_next (l)) {
MM3gppPdpContext *pdp = l->data;
if (pdp->cid == ctx->cid) {
mm_bearer_properties_set_ip_type (ctx->properties, pdp->pdp_type);
mm_bearer_properties_set_apn (ctx->properties, pdp->apn ? pdp->apn : "");
}
}
mm_3gpp_pdp_context_list_free (context_list);
end:
/* Go to next step */
ctx->step++;
ctx->step_function (task);
}
static void
get_apn_from_cgcontrdp (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
const gchar *response;
InitialEpsContext *ctx;
gchar *apn = NULL;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (self, res, NULL);
/* in case of error, skip */
mm_obj_dbg (self, "response: %s", response);
if (response && mm_3gpp_parse_cgcontrdp_response (response, NULL, NULL, &apn, NULL, NULL, NULL, NULL, NULL, NULL)) {
mm_bearer_properties_set_apn (ctx->properties, apn);
g_free (apn);
}
/* Go to next step */
ctx->step++;
ctx->step_function (task);
}
/* at^sgauth?
* ^SGAUTH: 1,2,"vf"
* ^SGAUTH: 3,0,""
* ^SGAUTH: 4,0
*
* OK
*/
static void
get_auth_params (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
const gchar *response;
InitialEpsContext *ctx;
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
ctx = (InitialEpsContext *) g_task_get_task_data (task);
response = mm_base_modem_at_command_finish (self, res, NULL);
/* in case of error, skip */
if (response != NULL)
mm_obj_dbg (self, "response: %s", response);
r = g_regex_new ("\\^SGAUTH:\\s*(\\d+),(\\d+),?\"?([a-zA-Z0-9_-]+)?\"?", 0, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL);
while (g_match_info_matches (match_info)) {
guint cid = 0;
guint cinterion_auth_type = 0;
g_autofree gchar *username = NULL;
mm_get_uint_from_match_info (match_info, 1, &cid);
mm_get_uint_from_match_info (match_info, 2, &cinterion_auth_type);
username = mm_get_string_unquoted_from_match_info (match_info, 3);
if (cid == ctx->cid) {
mm_bearer_properties_set_allowed_auth (ctx->properties, mm_auth_type_from_cinterion_auth_type (cinterion_auth_type));
if (username)
mm_bearer_properties_set_user (ctx->properties, username);
}
g_match_info_next (match_info, NULL);
}
/* Go to next step */
ctx->step++;
ctx->step_function (task);
}
static void
modem_3gpp_load_initial_eps_step (GTask *task)
{
MMIfaceModem3gpp *self;
InitialEpsContext *ctx;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
switch (ctx->step) {
case INITIAL_EPS_CONTEXT_STEP_FIRST:
/* set defaults */
ctx->cid = 1;
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_CHECK_MODE:
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CFUN?",
5,
FALSE,
(GAsyncReadyCallback)check_cfun_mode,
task);
return;
case INITIAL_EPS_CONTEXT_STEP_RF_OFF:
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_PROFILE:
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"^SCFG=\"MEopMode/Prov/Cfg\"",
20,
FALSE,
(GAsyncReadyCallback)set_cid_from_mno_profile,
task);
return;
case INITIAL_EPS_CONTEXT_STEP_APN: {
if (ctx->get_current_status)
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CGDCONT?",
20,
FALSE,
(GAsyncReadyCallback)get_apn_from_cgdcont,
task);
else {
g_autofree gchar *cmd = NULL;
cmd = g_strdup_printf ("+CGCONTRDP=%u", ctx->cid);
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CGCONTRDP",
20,
FALSE,
(GAsyncReadyCallback)get_apn_from_cgcontrdp,
task);
}
return;
}
case INITIAL_EPS_CONTEXT_STEP_AUTH: {
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"^SGAUTH?",
20,
FALSE,
(GAsyncReadyCallback)get_auth_params,
task);
return;
}
case INITIAL_EPS_CONTEXT_STEP_RF_ON:
ctx->step++;
/* fall through */
case INITIAL_EPS_CONTEXT_STEP_LAST:
g_task_return_pointer (task, ctx->properties, g_object_unref);
g_object_unref (task);
return;
default:
g_assert_not_reached ();
}
}
static void
modem_3gpp_load_initial_eps_bearer (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
InitialEpsContext *ctx;
MMBearerProperties *properties;
task = g_task_new (self, NULL, callback, user_data);
ctx = g_slice_new0 (InitialEpsContext);
g_task_set_task_data (task, ctx, (GDestroyNotify) initial_eps_context_free);
properties = mm_bearer_properties_new ();
/* Setup context */
ctx->properties = g_object_ref (properties);
ctx->step = INITIAL_EPS_CONTEXT_STEP_FIRST;
ctx->step_function = modem_3gpp_load_initial_eps_step;
ctx-> get_current_status = TRUE;
modem_3gpp_load_initial_eps_step (task);
}
/*****************************************************************************/
/* Initial EPS bearer settings loading -> set configuration */
static MMBearerProperties *
modem_3gpp_load_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error)
{
return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error));
}
static void
modem_3gpp_load_initial_eps_bearer_settings (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
InitialEpsContext *ctx;
MMBearerProperties *properties;
task = g_task_new (self, NULL, callback, user_data);
ctx = g_slice_new0 (InitialEpsContext);
g_task_set_task_data (task, ctx, (GDestroyNotify) initial_eps_context_free);
properties = mm_bearer_properties_new ();
/* Setup context */
ctx->properties = g_object_ref (properties);
ctx->step = INITIAL_EPS_CONTEXT_STEP_FIRST;
ctx->step_function = modem_3gpp_load_initial_eps_step;
ctx-> get_current_status = FALSE;
modem_3gpp_load_initial_eps_step (task);
}
/*****************************************************************************/
/* Load supported modes (Modem interface) */
@@ -1319,7 +1872,7 @@ scfg_set_ready_sequence (MMBaseModem *_self,
self = g_task_get_source_object (task);
for (i = 0; self->priv->cmds[i].command; i++)
mm_base_modem_at_command_alloc_clear (&self->priv->cmds[i]);
g_free(self->priv->cmds);
g_free (self->priv->cmds);
self->priv->cmds = NULL;
mm_base_modem_at_sequence_finish (_self, res, &ctx, &error);
@@ -2031,6 +2584,14 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
iface->setup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish;
iface->cleanup_unsolicited_events = modem_3gpp_cleanup_unsolicited_events;
iface->cleanup_unsolicited_events_finish = modem_3gpp_setup_cleanup_unsolicited_events_finish;
iface->load_initial_eps_bearer = modem_3gpp_load_initial_eps_bearer;
iface->load_initial_eps_bearer_finish = modem_3gpp_load_initial_eps_bearer_finish;
iface->load_initial_eps_bearer_settings = modem_3gpp_load_initial_eps_bearer_settings;
iface->load_initial_eps_bearer_settings_finish = modem_3gpp_load_initial_eps_bearer_settings_finish;
iface->set_initial_eps_bearer_settings = modem_3gpp_set_initial_eps_bearer_settings;
iface->set_initial_eps_bearer_settings_finish = modem_3gpp_set_initial_eps_bearer_settings_finish;
}
static void
@@ -1398,3 +1398,55 @@ mm_cinterion_smoni_response_to_signal_info (const gchar *response,
return TRUE;
}
/*****************************************************************************/
/* provider cfg information to CID number for EPS initial settings */
/*
* at^scfg="MEopMode/Prov/Cfg"
* ^SCFG: "MEopMode/Prov/Cfg","vdfde"
* ^SCFG: "MEopMode/Prov/Cfg","attus"
* ^SCFG: "MEopMode/Prov/Cfg","2" -> PLS8-X vzw
* ^SCFG: "MEopMode/Prov/Cfg","vzwdcus" -> PLAS9-x vzw
* ^SCFG: "MEopMode/Prov/Cfg","tmode" -> t-mob germany
* OK
*/
void
mm_cinterion_provcfg_response_to_cid (const gchar *response,
MMCinterionModemFamily modem_family,
MMModemCharset charset,
gpointer log_object,
guint *cid)
{
g_autoptr(GRegex) r = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
g_autofree GError *inner_error = NULL;
r = g_regex_new ("\\^SCFG:\\s*\"MEopMode/Prov/Cfg\",\\s*\"([0-9a-zA-Z]*)\"", 0, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
if (inner_error)
return;
if (g_match_info_matches (match_info)) {
g_autofree gchar *mno = NULL;
mno = mm_get_string_unquoted_from_match_info (match_info, 1);
if (mno && modem_family == MM_CINTERION_MODEM_FAMILY_IMT) {
mno = mm_charset_take_and_convert_to_utf8 (mno, charset);
mm_obj_dbg (log_object, "current mno: %s", mno);
}
/* for Cinterion LTE modules, some CID numbers have special meaning.
* This is dictated by the chipset and by the MNO:
* - the chipset uses a special one, CID 1, as a LTE combined attach chipset
* - the MNOs can define the sequence and number of APN to be used for their network.
* This takes priority over the chipset preferences, and therefore for some of them
* the CID for the initial EPS context must be changed.
*/
if (g_strcmp0 (mno, "2") == 0 || g_strcmp0 (mno, "vzwdcus") == 0)
*cid = 3;
else if (g_strcmp0 (mno, "tmode") == 0)
*cid = 2;
/* in all other cases no change to the preset value */
}
}
@@ -163,4 +163,13 @@ gboolean mm_cinterion_smoni_response_to_signal_info (const gchar *response,
MMSignal **out_lte,
GError **error);
/*****************************************************************************/
/* ^SCFG="MEopMode/Prov/Cfg" helper */
void mm_cinterion_provcfg_response_to_cid (const gchar *response,
MMCinterionModemFamily modem_family,
MMModemCharset charset,
gpointer log_object,
guint *cid);
#endif /* MM_MODEM_HELPERS_CINTERION_H */
@@ -1596,6 +1596,71 @@ test_smoni_response_to_signal (void)
}
}
/*****************************************************************************/
/* Test ^SCFG="MEopMode/Prov/Cfg" responses */
typedef struct {
const gchar *str;
MMCinterionModemFamily modem_family;
guint initial_cid;
gdouble expected_cid;
} ProvcfgResponseTest;
static const ProvcfgResponseTest provcfg_response_tests[] = {
{
.str = "^SCFG: \"MEopMode/Prov/Cfg\",\"vdfde\"",
.modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT,
.initial_cid = 1,
.expected_cid = 1,
},
{
.str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"attus\"",
.modem_family = MM_CINTERION_MODEM_FAMILY_IMT,
.initial_cid = 1,
.expected_cid = 1,
},
{
.str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"2\"",
.modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT,
.initial_cid = 1,
.expected_cid = 3,
},
{
.str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"vzwdcus\"",
.modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT,
.initial_cid = 1,
.expected_cid = 3,
},
{
.str = "* ^SCFG: \"MEopMode/Prov/Cfg\",\"tmode\"",
.modem_family = MM_CINTERION_MODEM_FAMILY_DEFAULT,
.initial_cid = 1,
.expected_cid = 2,
}
};
static void
test_provcfg_response (void)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (provcfg_response_tests); i++) {
guint cid = provcfg_response_tests[i].initial_cid;
mm_cinterion_provcfg_response_to_cid (provcfg_response_tests[i].str,
provcfg_response_tests[i].modem_family,
MM_MODEM_CHARSET_GSM,
NULL,
&cid);
g_assert_cmpuint (cid, ==, provcfg_response_tests[i].expected_cid);
}
}
/*****************************************************************************/
@@ -1629,6 +1694,7 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/cinterion/ctzu/urc/full", test_ctzu_urc_full);
g_test_add_func ("/MM/cinterion/smoni/query_response", test_smoni_response);
g_test_add_func ("/MM/cinterion/smoni/query_response_to_signal", test_smoni_response_to_signal);
g_test_add_func ("/MM/cinterion/scfg/provcfg", test_provcfg_response);
return g_test_run ();
}