telit-plugin: ignore QSS when SIM-ME interface is locked
With some modems, the lock/unlock of the SIM-ME interface with +CSIM=1/0 command is followed by #QSS unsolicited messages. With the current implementation, this messages are mistaken for SIM swap events and so the modem is first dropped and then re-probed. With this patch, the plugin takes into account the SIM-ME lock state when parsing #QSS unsolicited, so that the QSS handler can correctly elaborate the messages that are not related to SIM swap events.
This commit is contained in:

committed by
Aleksander Morgado

parent
60092ed7ea
commit
b5dba9ad1c
@@ -44,6 +44,8 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemTelit, mm_broadband_modem_telit, MM_TYPE
|
|||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
|
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
|
||||||
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));
|
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));
|
||||||
|
|
||||||
|
#define CSIM_UNLOCK_MAX_TIMEOUT 3
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FEATURE_SUPPORT_UNKNOWN,
|
FEATURE_SUPPORT_UNKNOWN,
|
||||||
FEATURE_NOT_SUPPORTED,
|
FEATURE_NOT_SUPPORTED,
|
||||||
@@ -53,6 +55,9 @@ typedef enum {
|
|||||||
struct _MMBroadbandModemTelitPrivate {
|
struct _MMBroadbandModemTelitPrivate {
|
||||||
FeatureSupport csim_lock_support;
|
FeatureSupport csim_lock_support;
|
||||||
MMTelitQssStatus qss_status;
|
MMTelitQssStatus qss_status;
|
||||||
|
MMTelitCsimLockState csim_lock_state;
|
||||||
|
GTask *csim_lock_task;
|
||||||
|
guint csim_lock_timeout_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -107,6 +112,7 @@ typedef struct {
|
|||||||
} QssSetupContext;
|
} QssSetupContext;
|
||||||
|
|
||||||
static void qss_setup_step (GTask *task);
|
static void qss_setup_step (GTask *task);
|
||||||
|
static void pending_csim_unlock_complete (MMBroadbandModemTelit *self);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
telit_qss_unsolicited_handler (MMPortSerialAt *port,
|
telit_qss_unsolicited_handler (MMPortSerialAt *port,
|
||||||
@@ -122,14 +128,36 @@ telit_qss_unsolicited_handler (MMPortSerialAt *port,
|
|||||||
prev_qss_status = self->priv->qss_status;
|
prev_qss_status = self->priv->qss_status;
|
||||||
self->priv->qss_status = cur_qss_status;
|
self->priv->qss_status = cur_qss_status;
|
||||||
|
|
||||||
|
if (self->priv->csim_lock_state >= CSIM_LOCK_STATE_LOCK_REQUESTED) {
|
||||||
|
|
||||||
|
if (prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED) {
|
||||||
|
mm_dbg ("QSS handler: #QSS=0 after +CSIM=1 -> CSIM locked!");
|
||||||
|
self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) {
|
||||||
|
mm_dbg ("QSS handler: #QSS>=1 after +CSIM=0 -> CSIM unlocked!");
|
||||||
|
self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED;
|
||||||
|
|
||||||
|
if (self->priv->csim_lock_timeout_id) {
|
||||||
|
g_source_remove (self->priv->csim_lock_timeout_id);
|
||||||
|
self->priv->csim_lock_timeout_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending_csim_unlock_complete (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cur_qss_status != prev_qss_status)
|
if (cur_qss_status != prev_qss_status)
|
||||||
mm_dbg ("QSS: status changed '%s -> %s",
|
mm_dbg ("QSS handler: status changed '%s -> %s",
|
||||||
mm_telit_qss_status_get_string (prev_qss_status),
|
mm_telit_qss_status_get_string (prev_qss_status),
|
||||||
mm_telit_qss_status_get_string (cur_qss_status));
|
mm_telit_qss_status_get_string (cur_qss_status));
|
||||||
|
|
||||||
if ((prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) ||
|
if ((prev_qss_status == QSS_STATUS_SIM_REMOVED && cur_qss_status != QSS_STATUS_SIM_REMOVED) ||
|
||||||
(prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED)) {
|
(prev_qss_status > QSS_STATUS_SIM_REMOVED && cur_qss_status == QSS_STATUS_SIM_REMOVED)) {
|
||||||
mm_info ("QSS: SIM swap detected");
|
mm_info ("QSS handler: SIM swap detected");
|
||||||
mm_broadband_modem_update_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
|
mm_broadband_modem_update_sim_hot_swap_detected (MM_BROADBAND_MODEM (self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -610,8 +638,9 @@ csim_unlock_ready (MMBaseModem *_self,
|
|||||||
if (!response) {
|
if (!response) {
|
||||||
if (g_error_matches (error,
|
if (g_error_matches (error,
|
||||||
MM_MOBILE_EQUIPMENT_ERROR,
|
MM_MOBILE_EQUIPMENT_ERROR,
|
||||||
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED))
|
MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED)) {
|
||||||
self->priv->csim_lock_support = FEATURE_NOT_SUPPORTED;
|
self->priv->csim_lock_support = FEATURE_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
mm_warn ("Couldn't unlock SIM card: %s", error->message);
|
mm_warn ("Couldn't unlock SIM card: %s", error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
@@ -703,6 +732,8 @@ csim_lock_ready (MMBaseModem *_self,
|
|||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self->priv->csim_lock_state = CSIM_LOCK_STATE_LOCK_REQUESTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->priv->csim_lock_support != FEATURE_NOT_SUPPORTED) {
|
if (self->priv->csim_lock_support != FEATURE_NOT_SUPPORTED) {
|
||||||
@@ -754,6 +785,37 @@ handle_csim_locking (GTask *task,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_csim_unlock_complete (MMBroadbandModemTelit *self)
|
||||||
|
{
|
||||||
|
LoadUnlockRetriesContext *ctx;
|
||||||
|
|
||||||
|
ctx = g_task_get_task_data (self->priv->csim_lock_task);
|
||||||
|
|
||||||
|
if (ctx->succeded_requests == 0) {
|
||||||
|
g_task_return_new_error (self->priv->csim_lock_task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
|
"Could not get any of the SIM unlock retries values");
|
||||||
|
} else {
|
||||||
|
g_task_return_pointer (self->priv->csim_lock_task, g_object_ref (ctx->retries), g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&self->priv->csim_lock_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
csim_unlock_periodic_check (MMBroadbandModemTelit *self)
|
||||||
|
{
|
||||||
|
if (self->priv->csim_lock_state != CSIM_LOCK_STATE_UNLOCKED) {
|
||||||
|
mm_warn ("CSIM is still locked after %d seconds. Trying to continue anyway", CSIM_UNLOCK_MAX_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->csim_lock_timeout_id = 0;
|
||||||
|
pending_csim_unlock_complete (self);
|
||||||
|
g_object_unref (self);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_unlock_retries_step (GTask *task)
|
load_unlock_retries_step (GTask *task)
|
||||||
{
|
{
|
||||||
@@ -805,12 +867,16 @@ load_unlock_retries_step (GTask *task)
|
|||||||
handle_csim_locking (task, FALSE);
|
handle_csim_locking (task, FALSE);
|
||||||
break;
|
break;
|
||||||
case LOAD_UNLOCK_RETRIES_STEP_LAST:
|
case LOAD_UNLOCK_RETRIES_STEP_LAST:
|
||||||
if (ctx->succeded_requests == 0)
|
self->priv->csim_lock_task = task;
|
||||||
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
if (self->priv->csim_lock_state == CSIM_LOCK_STATE_LOCKED) {
|
||||||
"Could not get any of the SIM unlock retries values");
|
mm_dbg ("CSIM is locked. Waiting for #QSS=1");
|
||||||
else
|
self->priv->csim_lock_timeout_id = g_timeout_add_seconds (CSIM_UNLOCK_MAX_TIMEOUT,
|
||||||
g_task_return_pointer (task, g_object_ref (ctx->retries), g_object_unref);
|
(GSourceFunc) csim_unlock_periodic_check,
|
||||||
g_object_unref (task);
|
g_object_ref(self));
|
||||||
|
} else {
|
||||||
|
self->priv->csim_lock_state = CSIM_LOCK_STATE_UNLOCKED;
|
||||||
|
pending_csim_unlock_complete (self);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1389,6 +1455,7 @@ mm_broadband_modem_telit_init (MMBroadbandModemTelit *self)
|
|||||||
MMBroadbandModemTelitPrivate);
|
MMBroadbandModemTelitPrivate);
|
||||||
|
|
||||||
self->priv->csim_lock_support = FEATURE_SUPPORT_UNKNOWN;
|
self->priv->csim_lock_support = FEATURE_SUPPORT_UNKNOWN;
|
||||||
|
self->priv->csim_lock_state = CSIM_LOCK_STATE_UNKNOWN;
|
||||||
self->priv->qss_status = QSS_STATUS_UNKNOWN;
|
self->priv->qss_status = QSS_STATUS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -110,4 +110,13 @@ typedef enum { /*< underscore_name=mm_telit_qss_status >*/
|
|||||||
|
|
||||||
MMTelitQssStatus mm_telit_parse_qss_query (const gchar *response, GError **error);
|
MMTelitQssStatus mm_telit_parse_qss_query (const gchar *response, GError **error);
|
||||||
|
|
||||||
|
/* CSIM lock state */
|
||||||
|
typedef enum { /*< underscore_name=mm_telit_csim_lock_state >*/
|
||||||
|
CSIM_LOCK_STATE_UNKNOWN,
|
||||||
|
CSIM_LOCK_STATE_UNLOCKED,
|
||||||
|
CSIM_LOCK_STATE_LOCK_REQUESTED,
|
||||||
|
CSIM_LOCK_STATE_LOCKED,
|
||||||
|
} MMTelitCsimLockState;
|
||||||
|
|
||||||
|
|
||||||
#endif /* MM_MODEM_HELPERS_TELIT_H */
|
#endif /* MM_MODEM_HELPERS_TELIT_H */
|
||||||
|
Reference in New Issue
Block a user