aboutsummaryrefslogtreecommitdiff
path: root/src/mm-modem-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-modem-base.c')
-rw-r--r--src/mm-modem-base.c69
1 files changed, 68 insertions, 1 deletions
diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c
index 451e2ebe..788020fe 100644
--- a/src/mm-modem-base.c
+++ b/src/mm-modem-base.c
@@ -41,6 +41,12 @@ G_DEFINE_TYPE_EXTENDED (MMModemBase, mm_modem_base,
#define MM_MODEM_BASE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_BASE, MMModemBasePrivate))
+enum {
+ PROP_0,
+ PROP_MAX_TIMEOUTS,
+ LAST_PROP
+};
+
typedef struct {
char *driver;
char *plugin;
@@ -62,6 +68,9 @@ typedef struct {
char *ati1;
char *gsn;
+ guint max_timeouts;
+ guint set_invalid_unresponsive_modem_id;
+
MMAuthProvider *authp;
GHashTable *ports;
@@ -105,6 +114,42 @@ find_primary (gpointer key, gpointer data, gpointer user_data)
*found = port;
}
+static gboolean
+set_invalid_unresponsive_modem_cb (MMModemBase *self)
+{
+ MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+ mm_modem_base_set_valid (self, FALSE);
+ priv->set_invalid_unresponsive_modem_id = 0;
+ return FALSE;
+}
+
+static void
+serial_port_timed_out_cb (MMSerialPort *port,
+ guint n_consecutive_timeouts,
+ gpointer user_data)
+{
+ MMModemBase *self = (MM_MODEM_BASE (user_data));
+ MMModemBasePrivate *priv = MM_MODEM_BASE_GET_PRIVATE (self);
+
+ if (priv->max_timeouts > 0 &&
+ n_consecutive_timeouts >= priv->max_timeouts) {
+ const gchar *dbus_path;
+
+ dbus_path = (const gchar *) g_object_get_data (G_OBJECT (self), DBUS_PATH_TAG);
+ mm_warn ("Modem %s: Port (%s/%s) timed out %u times, marking modem as disabled",
+ dbus_path,
+ mm_port_type_to_name (mm_port_get_port_type (MM_PORT (port))),
+ mm_port_get_device (MM_PORT (port)),
+ n_consecutive_timeouts);
+
+ /* Only set action to invalidate modem if not already done */
+ if (!priv->set_invalid_unresponsive_modem_id)
+ priv->set_invalid_unresponsive_modem_id =
+ g_idle_add ((GSourceFunc)set_invalid_unresponsive_modem_cb, self);
+ }
+}
+
MMPort *
mm_modem_base_add_port (MMModemBase *self,
const char *subsys,
@@ -137,6 +182,13 @@ mm_modem_base_add_port (MMModemBase *self,
port = MM_PORT (mm_qcdm_serial_port_new (name, ptype));
else
port = MM_PORT (mm_at_serial_port_new (name, ptype));
+
+ /* For serial ports, enable port timeout checks */
+ if (port)
+ g_signal_connect (port,
+ "timed-out",
+ G_CALLBACK (serial_port_timed_out_cb),
+ self);
} else if (!strcmp (subsys, "net")) {
port = MM_PORT (g_object_new (MM_TYPE_PORT,
MM_PORT_DEVICE, name,
@@ -538,7 +590,7 @@ mm_modem_base_get_card_info (MMModemBase *self,
priv = MM_MODEM_BASE_GET_PRIVATE (self);
- /* Cached info and errors schedule the callback immediately and do
+ /* Cached info and errors schedule the callback immediately and do
* not hit up the card for it's model information.
*/
if (priv->manf || priv->model || priv->revision)
@@ -717,6 +769,9 @@ set_property (GObject *object, guint prop_id,
/* Construct only */
priv->pid = g_value_get_uint (value);
break;
+ case PROP_MAX_TIMEOUTS:
+ priv->max_timeouts = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -775,6 +830,9 @@ get_property (GObject *object, guint prop_id,
case MM_MODEM_PROP_HW_PID:
g_value_set_uint (value, priv->pid);
break;
+ case PROP_MAX_TIMEOUTS:
+ g_value_set_uint (value, priv->max_timeouts);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -878,6 +936,15 @@ mm_modem_base_class_init (MMModemBaseClass *klass)
MM_MODEM_PROP_HW_PID,
MM_MODEM_HW_PID);
+ g_object_class_install_property
+ (object_class, PROP_MAX_TIMEOUTS,
+ g_param_spec_uint (MM_MODEM_BASE_MAX_TIMEOUTS,
+ "Max timeouts",
+ "Maximum number of consecutive timed out commands sent to "
+ "the modem before disabling it. If 0, this feature is disabled.",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE));
+
mm_properties_changed_signal_enable (object_class);
}