broadband-modem-icera: fix issues checking supported bands

Icera devices include bands that the modem doesn't support in
the %IPBM=? list, so the plugin sets the band to its current
enabled/disabled value to test whether that band is supported.
There were two problems with this approach:

1) Setting an already-enabled band to be enabled apparently
isn't a NOP; it might take more than the 3 seconds given, and
if the response comes after 3 seconds, this greatly confuses
ModemManager because the AT command/reply sequence is now
messed up.  So increase the timeout to 10 seconds.

2) Why bother checking bands that are already enabled anyway?
We already know they are supported, so just don't check those
bands at all.  This requires some parkour because we use the
parsed band array from %IPBM=? to track whether bands are
enabled/disabled by indexing into the array, so instead just
use two separate arrays.  This actually makes the fix for #1
un-needed (because we never enable any bands) but it's good
to have #1 anyway.
This commit is contained in:
Dan Williams
2013-04-24 16:48:29 -05:00
parent 18bfefba2d
commit 2320411113

View File

@@ -1064,7 +1064,8 @@ parse_bands (const gchar *response, guint32 *out_len)
typedef struct { typedef struct {
MMBaseModemAtCommand *cmds; MMBaseModemAtCommand *cmds;
GSList *bands; GSList *check_bands;
GSList *enabled_bands;
guint32 idx; guint32 idx;
} SupportedBandsContext; } SupportedBandsContext;
@@ -1076,7 +1077,8 @@ supported_bands_context_free (SupportedBandsContext *ctx)
for (i = 0; ctx->cmds[i].command; i++) for (i = 0; ctx->cmds[i].command; i++)
g_free (ctx->cmds[i].command); g_free (ctx->cmds[i].command);
g_free (ctx->cmds); g_free (ctx->cmds);
g_slist_free_full (ctx->bands, (GDestroyNotify) band_free); g_slist_free_full (ctx->check_bands, (GDestroyNotify) band_free);
g_slist_free_full (ctx->enabled_bands, (GDestroyNotify) band_free);
g_free (ctx); g_free (ctx);
} }
@@ -1107,12 +1109,21 @@ load_supported_bands_ready (MMBaseModem *self,
g_simple_async_result_take_error (simple, error); g_simple_async_result_take_error (simple, error);
else { else {
bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), ctx->idx); bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), ctx->idx);
for (iter = ctx->bands; iter; iter = g_slist_next (iter)) {
/* Add already enabled bands */
for (iter = ctx->enabled_bands; iter; iter = g_slist_next (iter)) {
Band *b = iter->data;
g_array_prepend_val (bands, b->band);
}
/* Add any checked bands that are supported */
for (iter = ctx->check_bands; iter; iter = g_slist_next (iter)) {
Band *b = iter->data; Band *b = iter->data;
/* 'enabled' here really means supported/unsupported */ /* 'enabled' here really means supported/unsupported */
if (b->enabled) if (b->enabled)
g_array_append_val (bands, b->band); g_array_prepend_val (bands, b->band);
} }
g_simple_async_result_set_op_res_gpointer (simple, g_simple_async_result_set_op_res_gpointer (simple,
@@ -1134,7 +1145,7 @@ load_supported_bands_response_processor (MMBaseModem *self,
GError **result_error) GError **result_error)
{ {
SupportedBandsContext *ctx = context; SupportedBandsContext *ctx = context;
Band *b = g_slist_nth_data (ctx->bands, ctx->idx++); Band *b = g_slist_nth_data (ctx->check_bands, ctx->idx++);
/* If there was no error setting the band, that band is supported. We /* If there was no error setting the band, that band is supported. We
* abuse the 'enabled' item to mean supported/unsupported. * abuse the 'enabled' item to mean supported/unsupported.
@@ -1153,8 +1164,8 @@ load_supported_bands_get_bands_ready (MMIfaceModem *self,
SupportedBandsContext *ctx; SupportedBandsContext *ctx;
const gchar *response; const gchar *response;
GError *error = NULL; GError *error = NULL;
GSList *iter; GSList *iter, *new;
guint32 len = 0, i; guint32 len = 0, i = 0;
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!response) { if (!response) {
@@ -1170,18 +1181,28 @@ load_supported_bands_get_bands_ready (MMIfaceModem *self,
/* For each reported band, build up an AT command to set that band /* For each reported band, build up an AT command to set that band
* to its current enabled/disabled state. * to its current enabled/disabled state.
*/ */
ctx->bands = parse_bands (response, &len); iter = ctx->check_bands = parse_bands (response, &len);
ctx->cmds = g_new0 (MMBaseModemAtCommand, len + 1); ctx->cmds = g_new0 (MMBaseModemAtCommand, len + 1);
for (iter = ctx->bands, i = 0; iter; iter = g_slist_next (iter), i++) { while (iter) {
Band *b = iter->data; Band *b = iter->data;
ctx->cmds[i].command = g_strdup_printf ("%%IPBM=\"%s\",%c", if (b->enabled || b->band == MM_MODEM_BAND_ANY) {
b->name, /* Move known-supported band to the enabled list */
b->enabled ? '1' : '0'); new = g_slist_next (iter);
ctx->cmds[i].timeout = 3; ctx->check_bands = g_slist_remove_link (ctx->check_bands, iter);
ctx->cmds[i].allow_cached = FALSE; ctx->enabled_bands = g_slist_prepend (ctx->enabled_bands, iter->data);
ctx->cmds[i].response_processor = load_supported_bands_response_processor; g_slist_free (iter);
iter = new;
} else {
/* Check support for disabled band */
ctx->cmds[i].command = g_strdup_printf ("%%IPBM=\"%s\",0", b->name);
ctx->cmds[i].timeout = 10;
ctx->cmds[i].allow_cached = FALSE;
ctx->cmds[i].response_processor = load_supported_bands_response_processor;
i++;
iter = g_slist_next (iter);
}
} }
mm_base_modem_at_sequence (MM_BASE_MODEM (self), mm_base_modem_at_sequence (MM_BASE_MODEM (self),