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.
This commit is contained in:
Dan Williams
2009-12-16 15:26:05 -08:00
parent 3ad172d150
commit 8d42094608
3 changed files with 89 additions and 1 deletions

View File

@@ -93,6 +93,15 @@ supports_port (MMPluginBase *base,
} }
/* Otherwise kick off a probe */ /* 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)) if (mm_plugin_base_probe_port (base, task, NULL))
return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS; return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;

View File

@@ -95,6 +95,12 @@ typedef struct {
char *probe_resp; char *probe_resp;
GError *probe_error; 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; MMSupportsPortResultFunc callback;
gpointer callback_data; gpointer callback_data;
} MMPluginBaseSupportsTaskPrivate; } MMPluginBaseSupportsTaskPrivate;
@@ -198,6 +204,27 @@ mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
priv->callback_data = NULL; 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 static void
mm_plugin_base_supports_task_init (MMPluginBaseSupportsTask *self) mm_plugin_base_supports_task_init (MMPluginBaseSupportsTask *self)
{ {
@@ -216,6 +243,7 @@ supports_task_dispose (GObject *object)
g_free (priv->driver); g_free (priv->driver);
g_free (priv->probe_resp); g_free (priv->probe_resp);
g_clear_error (&(priv->probe_error)); g_clear_error (&(priv->probe_error));
g_free (priv->custom_init);
if (priv->open_id) if (priv->open_id)
g_source_remove (priv->open_id); g_source_remove (priv->open_id);
@@ -467,10 +495,56 @@ parse_response (MMSerialPort *port,
task_priv->probe_id = g_idle_add (handle_probe_response, task); task_priv->probe_id = g_idle_add (handle_probe_response, task);
} }
static void flash_done (MMSerialPort *port, GError *error, gpointer user_data);
static void
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 static void
flash_done (MMSerialPort *port, GError *error, gpointer user_data) flash_done (MMSerialPort *port, GError *error, gpointer user_data)
{ {
mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, 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 static gboolean

View File

@@ -68,6 +68,11 @@ guint32 mm_plugin_base_supports_task_get_probed_capabilities (MMPluginBaseSuppor
void mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task, void mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task,
guint32 level); 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_TYPE_PLUGIN_BASE (mm_plugin_base_get_type ())
#define MM_PLUGIN_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BASE, MMPluginBase)) #define MM_PLUGIN_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_BASE, MMPluginBase))