aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-12-16 15:26:05 -0800
committerDan Williams <dcbw@redhat.com>2009-12-16 15:26:05 -0800
commit8d42094608e68eccbcf5838d87fd59aa605a18be (patch)
tree47f35c6595db0cb4be0edb3dac8ae84aa8982e14
parent3ad172d1504b20949049cf47783e1fe7287c9b95 (diff)
zte: handle unsolicited messages during probe
This implements the same fixes that NetworkManager's 0.7 branch implemented in commits f38ad328acfdc6ce29dd1380602c546b064161ae and 1235f71b20c92cded4abd976ccc5010649aae1a0. Many ZTE devices will spam the port with messages about waiting voicemail/SMS which buffer up and cause the device to eventually crash if not suppressed.
-rw-r--r--plugins/mm-plugin-zte.c9
-rw-r--r--src/mm-plugin-base.c76
-rw-r--r--src/mm-plugin-base.h5
3 files changed, 89 insertions, 1 deletions
diff --git a/plugins/mm-plugin-zte.c b/plugins/mm-plugin-zte.c
index 60a40a97..101fb468 100644
--- a/plugins/mm-plugin-zte.c
+++ b/plugins/mm-plugin-zte.c
@@ -93,6 +93,15 @@ supports_port (MMPluginBase *base,
}
/* Otherwise kick off a probe */
+
+ /* Many ZTE devices will flood the port with "Message waiting" indications
+ * and eventually fill up the serial buffer and crash. We need to turn off
+ * that indicator. See NetworkManager commits
+ * 1235f71b20c92cded4abd976ccc5010649aae1a0 and
+ * f38ad328acfdc6ce29dd1380602c546b064161ae for more details.
+ */
+ mm_plugin_base_supports_task_set_custom_init_command (task, "ATE0+CPMS?", 3, 4, TRUE);
+
if (mm_plugin_base_probe_port (base, task, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c
index ad849218..e6dc6cba 100644
--- a/src/mm-plugin-base.c
+++ b/src/mm-plugin-base.c
@@ -95,6 +95,12 @@ typedef struct {
char *probe_resp;
GError *probe_error;
+ char *custom_init;
+ guint32 custom_init_max_tries;
+ guint32 custom_init_tries;
+ guint32 custom_init_delay_seconds;
+ gboolean custom_init_fail_if_timeout;
+
MMSupportsPortResultFunc callback;
gpointer callback_data;
} MMPluginBaseSupportsTaskPrivate;
@@ -198,6 +204,27 @@ mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
priv->callback_data = NULL;
}
+void
+mm_plugin_base_supports_task_set_custom_init_command (MMPluginBaseSupportsTask *task,
+ const char *cmd,
+ guint32 delay_seconds,
+ guint32 max_tries,
+ gboolean fail_if_timeout)
+{
+ MMPluginBaseSupportsTaskPrivate *priv;
+
+ g_return_if_fail (task != NULL);
+ g_return_if_fail (MM_IS_PLUGIN_BASE_SUPPORTS_TASK (task));
+
+ priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+
+ g_free (priv->custom_init);
+ priv->custom_init = g_strdup (cmd);
+ priv->custom_init_max_tries = max_tries;
+ priv->custom_init_delay_seconds = delay_seconds;
+ priv->custom_init_fail_if_timeout = fail_if_timeout;
+}
+
static void
mm_plugin_base_supports_task_init (MMPluginBaseSupportsTask *self)
{
@@ -216,6 +243,7 @@ supports_task_dispose (GObject *object)
g_free (priv->driver);
g_free (priv->probe_resp);
g_clear_error (&(priv->probe_error));
+ g_free (priv->custom_init);
if (priv->open_id)
g_source_remove (priv->open_id);
@@ -467,12 +495,58 @@ parse_response (MMSerialPort *port,
task_priv->probe_id = g_idle_add (handle_probe_response, task);
}
+static void flash_done (MMSerialPort *port, GError *error, gpointer user_data);
+
static void
-flash_done (MMSerialPort *port, GError *error, gpointer user_data)
+custom_init_response (MMSerialPort *port,
+ GString *response,
+ GError *error,
+ gpointer user_data)
{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+
+ if (error) {
+ task_priv->custom_init_tries++;
+ if (task_priv->custom_init_tries < task_priv->custom_init_max_tries) {
+ /* Try the custom command again */
+ flash_done (port, NULL, user_data);
+ return;
+ } else if (task_priv->custom_init_fail_if_timeout) {
+ /* Fail the probe if the plugin wanted it and the command timed out */
+ if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_RESPONSE_TIMEOUT)) {
+ probe_complete (task);
+ return;
+ }
+ }
+ }
+
+ /* Otherwise proceed to probing */
mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data);
}
+static void
+flash_done (MMSerialPort *port, GError *error, gpointer user_data)
+{
+ MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data);
+ MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task);
+ guint32 delay_secs = task_priv->custom_init_delay_seconds;
+
+ /* Send the custom init command if any */
+ if (task_priv->custom_init) {
+ if (!delay_secs)
+ delay_secs = 3;
+ mm_serial_port_queue_command (port,
+ task_priv->custom_init,
+ delay_secs,
+ custom_init_response,
+ user_data);
+ } else {
+ /* Otherwise start normal probing */
+ custom_init_response (port, NULL, NULL, user_data);
+ }
+}
+
static gboolean
try_open (gpointer user_data)
{
diff --git a/src/mm-plugin-base.h b/src/mm-plugin-base.h
index 91d3ddba..49e68d47 100644
--- a/src/mm-plugin-base.h
+++ b/src/mm-plugin-base.h
@@ -68,6 +68,11 @@ guint32 mm_plugin_base_supports_task_get_probed_capabilities (MMPluginBaseSuppor
void mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
guint32 level);
+void mm_plugin_base_supports_task_set_custom_init_command (MMPluginBaseSupportsTask *task,
+ const char *cmd,
+ guint32 delay_seconds,
+ guint32 max_tries,
+ gboolean fail_if_timeout);
#define MM_TYPE_PLUGIN_BASE (mm_plugin_base_get_type ())
#define MM_PLUGIN_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BASE, MMPluginBase))