You cannot mix in the same async method a code execution path using
> +static GList *
> +scan_networks_finish (MMIfaceModem3gpp *self,
> + GAsyncResult *res,
> + GError **error)
> +{
> + const gchar *result;
> +
> + result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
> + if (!result)
> + return NULL;
> +
> + return mm_3gpp_parse_cops_test_response (result, error);
> +}
> +
> +static void
> +scan_networks (MMIfaceModem3gpp *self,
> + GAsyncReadyCallback callback,
> + gpointer user_data)
> +{
> + MMModemAccessTechnology access_tech;
> +
> + mm_dbg ("scanning for networks (Novatel LTE)...");
> +
> + access_tech = mm_iface_modem_get_access_technologies (MM_IFACE_MODEM (self));
> + /* The Novatel LTE modem does not properly support AT+COPS=? in LTE mode.
> + * Thus, do not try to scan networks when the current access technologies
> + * include LTE.
> + */
> + if (access_tech & MM_MODEM_ACCESS_TECHNOLOGY_LTE) {
> + GSimpleAsyncResult *simple;
> + gchar *access_tech_string;
> +
> + access_tech_string = mm_modem_access_technology_build_string_from_mask (access_tech);
> + mm_warn ("Couldn't scan for networks with access technologies: %s", access_tech_string);
> + simple = g_simple_async_result_new (G_OBJECT (self),
> + callback,
> + user_data,
> + scan_networks);
> + g_simple_async_result_set_error (simple,
> + MM_CORE_ERROR,
> + MM_CORE_ERROR_UNSUPPORTED,
> + "Couldn't scan for networks with access technologies: %s",
> + access_tech_string);
> + g_simple_async_result_complete_in_idle (simple);
> + g_object_unref (simple);
> + g_free (access_tech_string);
> + return;
> + }
> +
> + mm_base_modem_at_command (MM_BASE_MODEM (self),
> + "+COPS=?",
> + 120,
> + FALSE,
> + callback,
> + user_data);
> +}
mm_base_modem_at_command() with another one using GSimpleAsyncResult and
completion in idle. When you use mm_base_modem_at_command(), in
finish() you're expected to use mm_base_modem_at_command_finish(), like
you did. But when you use GSimpleAsyncResult and completion in idle you
should use g_simple_async_result_propagate_error() in finish(). The fact
that it may work as expected is due to how at_command_finish() is
implemented; but you shouldn't rely on that.
So you'll need to use GSimpleAsyncResult for both cases, i.e. provide a
_ready() GAsyncReadyCallback in mm_base_modem_at_command() to which you
pass 'simple' as user_data; and then complete the 'simple' from within
the _ready() method. In this way, you can safely call
g_simple_async_result_propagate_error() in finish().
See for example:
http://cgit.freedesktop.org/ModemManager/ModemManager/tree/plugins/simtech/mm-broadband-modem-simtech.c#n416
And btw, a hint for when you just always need to report an error in idle
in the async method (avoids the need to create a GSimpleAsyncResult
yourself):
http://developer.gnome.org/gio/unstable/GSimpleAsyncResult.html#g-simple-async-report-error-in-idle
--
Aleksander