[PATCH 1/5] cinterion, location: refactor enable/disable and capabilities checks

Aleksander Morgado aleksander at aleksander.es
Wed May 17 13:24:00 UTC 2017


When checking for location capabilities, we will make sure AT^SGPSS is
supported and if it isn't we won't report GPS capabilities.

The location enable and disable paths are refactored to make it easier
to add possible new GPS commands to use instead of AT^SGPSS, if this
isn't supported (e.g. in the PLS8 devices).
---
 plugins/cinterion/mm-common-cinterion.c | 534 +++++++++++++++++++++-----------
 1 file changed, 350 insertions(+), 184 deletions(-)

diff --git a/plugins/cinterion/mm-common-cinterion.c b/plugins/cinterion/mm-common-cinterion.c
index 6e4da70c..91af530f 100644
--- a/plugins/cinterion/mm-common-cinterion.c
+++ b/plugins/cinterion/mm-common-cinterion.c
@@ -26,8 +26,15 @@ static GQuark cinterion_location_context_quark;
 
 /*****************************************************************************/
 
+typedef enum {
+    FEATURE_SUPPORT_UNKNOWN,
+    FEATURE_NOT_SUPPORTED,
+    FEATURE_SUPPORTED,
+} FeatureSupport;
+
 typedef struct {
     MMModemLocationSource enabled_sources;
+    FeatureSupport        sgpss_support;
 } LocationContext;
 
 static void
@@ -50,6 +57,7 @@ get_location_context (MMBaseModem *self)
         /* Create context and keep it as object data */
         ctx = g_slice_new (LocationContext);
         ctx->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE;
+        ctx->sgpss_support = FEATURE_SUPPORT_UNKNOWN;
 
         g_object_set_qdata_full (
             G_OBJECT (self),
@@ -61,133 +69,234 @@ get_location_context (MMBaseModem *self)
     return ctx;
 }
 
-
 /*****************************************************************************/
 /* Location capabilities loading (Location interface) */
 
+typedef struct {
+    MMModemLocationSource sources;
+} LoadCapabilitiesContext;
+
+static void
+load_capabilities_context_free (LoadCapabilitiesContext *ctx)
+{
+    g_slice_free (LoadCapabilitiesContext, ctx);
+}
+
 MMModemLocationSource
-mm_common_cinterion_location_load_capabilities_finish (MMIfaceModemLocation *self,
-                                                       GAsyncResult *res,
-                                                       GError **error)
+mm_common_cinterion_location_load_capabilities_finish (MMIfaceModemLocation  *self,
+                                                       GAsyncResult          *res,
+                                                       GError               **error)
 {
-    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+    gssize aux;
+
+    if ((aux = g_task_propagate_int (G_TASK (res), error)) < 0)
         return MM_MODEM_LOCATION_SOURCE_NONE;
 
-    return (MMModemLocationSource) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
-                                                         G_SIMPLE_ASYNC_RESULT (res)));
+    return (MMModemLocationSource) aux;
+}
+
+static void probe_gps_features (GTask *task);
+
+static void
+sgpss_test_ready (MMBaseModem  *self,
+                  GAsyncResult *res,
+                  GTask        *task)
+{
+    LocationContext *location_ctx;
+
+    location_ctx = get_location_context (self);
+    if (!mm_base_modem_at_command_finish (self, res, NULL))
+        location_ctx->sgpss_support = FEATURE_NOT_SUPPORTED;
+    else
+        location_ctx->sgpss_support = FEATURE_SUPPORTED;
+    probe_gps_features (task);
+}
+
+static void
+probe_gps_features (GTask *task)
+{
+    LoadCapabilitiesContext *ctx;
+    MMBaseModem             *self;
+    LocationContext         *location_ctx;
+
+    ctx = (LoadCapabilitiesContext *) g_task_get_task_data (task);
+    self = MM_BASE_MODEM (g_task_get_source_object (task));
+    location_ctx = get_location_context (self);
+
+    /* Need to check if SGPSS supported... */
+    if (location_ctx->sgpss_support == FEATURE_SUPPORT_UNKNOWN) {
+        mm_base_modem_at_command (self, "AT^SGPSS=?", 3, TRUE, (GAsyncReadyCallback) sgpss_test_ready, task);
+        return;
+    }
+
+    /* All GPS features probed, check if GPS supported */
+    if (location_ctx->sgpss_support == FEATURE_SUPPORTED) {
+        mm_dbg ("GPS commands supported: GPS capabilities enabled");
+        ctx->sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
+                         MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
+                         MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED);
+    } else
+        mm_dbg ("No GPS command supported: no GPS capabilities");
+
+    g_task_return_int (task, (gssize) ctx->sources);
+    g_object_unref (task);
 }
 
 static void
 parent_load_capabilities_ready (MMIfaceModemLocation *self,
-                                GAsyncResult *res,
-                                GSimpleAsyncResult *simple)
+                                GAsyncResult         *res,
+                                GTask                *task)
 {
-    MMModemLocationSource sources;
-    GError *error = NULL;
+    LoadCapabilitiesContext *ctx;
+    GError                  *error = NULL;
+
+    ctx = (LoadCapabilitiesContext *) g_task_get_task_data (task);
 
-    sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error);
+    ctx->sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error);
     if (error) {
-        g_simple_async_result_take_error (simple, error);
-        g_simple_async_result_complete (simple);
-        g_object_unref (simple);
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    /* Now our own check. If we don't have any GPS port, we're done */
+    if (!mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) {
+        mm_dbg ("No GPS data port found: no GPS capabilities");
+        g_task_return_boolean (task, TRUE);
+        g_object_unref (task);
         return;
     }
 
-    /* Now our own check. */
-    if (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)))
-        sources |= (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
-                    MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
-                    MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED);
-
-    /* So we're done, complete */
-    g_simple_async_result_set_op_res_gpointer (simple,
-                                               GUINT_TO_POINTER (sources),
-                                               NULL);
-    g_simple_async_result_complete (simple);
-    g_object_unref (simple);
+    /* Probe all GPS features */
+    probe_gps_features (task);
 }
 
 void
 mm_common_cinterion_location_load_capabilities (MMIfaceModemLocation *self,
-                                                GAsyncReadyCallback callback,
-                                                gpointer user_data)
+                                                GAsyncReadyCallback   callback,
+                                                gpointer              user_data)
 {
-    GSimpleAsyncResult *result;
+    GTask                   *task;
+    LoadCapabilitiesContext *ctx;
+
+    task = g_task_new (self, NULL, callback, user_data);
 
-    result = g_simple_async_result_new (G_OBJECT (self),
-                                        callback,
-                                        user_data,
-                                        mm_common_cinterion_location_load_capabilities);
+    ctx = g_slice_new0 (LoadCapabilitiesContext);
+    ctx->sources = MM_MODEM_LOCATION_SOURCE_NONE;
+    g_task_set_task_data (task, ctx, (GDestroyNotify) load_capabilities_context_free);
 
     /* Chain up parent's setup */
     iface_modem_location_parent->load_capabilities (
         self,
         (GAsyncReadyCallback)parent_load_capabilities_ready,
-        result);
+        task);
 }
 
 /*****************************************************************************/
-/* Enable/Disable location gathering (Location interface) */
+/* Disable location gathering (Location interface) */
+
+typedef enum {
+    DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST,
+    DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSS,
+    DISABLE_LOCATION_GATHERING_GPS_STEP_LAST,
+} DisableLocationGatheringGpsStep;
 
 typedef struct {
-    MMBaseModem *self;
-    GSimpleAsyncResult *result;
-    MMModemLocationSource source;
-} LocationGatheringContext;
+    MMModemLocationSource            source;
+    DisableLocationGatheringGpsStep  gps_step;
+    GError                          *sgpss_error;
+} DisableLocationGatheringContext;
 
 static void
-location_gathering_context_complete_and_free (LocationGatheringContext *ctx)
+disable_location_gathering_context_free (DisableLocationGatheringContext *ctx)
 {
-    g_simple_async_result_complete_in_idle (ctx->result);
-    g_object_unref (ctx->result);
-    g_object_unref (ctx->self);
-    g_slice_free (LocationGatheringContext, ctx);
+    if (ctx->sgpss_error)
+        g_error_free (ctx->sgpss_error);
+    g_slice_free (DisableLocationGatheringContext, ctx);
 }
 
-/******************************/
-/* Disable location gathering */
-
 gboolean
-mm_common_cinterion_disable_location_gathering_finish (MMIfaceModemLocation *self,
-                                                       GAsyncResult *res,
-                                                       GError **error)
+mm_common_cinterion_disable_location_gathering_finish (MMIfaceModemLocation  *self,
+                                                       GAsyncResult          *res,
+                                                       GError               **error)
 {
-    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+    return g_task_propagate_boolean (G_TASK (res), error);
 }
 
+static void disable_location_gathering_context_gps_step (GTask *task);
+
 static void
-gps_disabled_ready (MMBaseModem *self,
-                    GAsyncResult *res,
-                    LocationGatheringContext *ctx)
+disable_sgpss_ready (MMBaseModem  *self,
+                     GAsyncResult *res,
+                     GTask        *task)
 {
-    GError *error = NULL;
+    DisableLocationGatheringContext *ctx;
 
-    if (!mm_base_modem_at_command_full_finish (self, res, &error))
-        g_simple_async_result_take_error (ctx->result, error);
-    else
-        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+    ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task);
 
-    /* Only use the GPS port in NMEA/RAW setups */
-    if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
-                       MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
-        MMPortSerialGps *gps_port;
+    /* Store error, if any, and continue */
+    g_assert (!ctx->sgpss_error);
+    mm_base_modem_at_command_finish (self, res, &ctx->sgpss_error);
 
-        /* Even if we get an error here, we try to close the GPS port */
-        gps_port = mm_base_modem_peek_port_gps (self);
-        if (gps_port)
-            mm_port_serial_close (MM_PORT_SERIAL (gps_port));
-    }
+    ctx->gps_step++;
+    disable_location_gathering_context_gps_step (task);
+}
 
-    location_gathering_context_complete_and_free (ctx);
+static void
+disable_location_gathering_context_gps_step (GTask *task)
+{
+    DisableLocationGatheringContext *ctx;
+    MMBaseModem                     *self;
+    LocationContext                 *location_ctx;
+
+    self = MM_BASE_MODEM (g_task_get_source_object (task));
+    ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task);
+    location_ctx = get_location_context (MM_BASE_MODEM (self));
+
+    switch (ctx->gps_step) {
+    case DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST:
+        ctx->gps_step++;
+        /* Fall down to next step */
+
+    case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSS:
+        g_assert (location_ctx->sgpss_support == FEATURE_SUPPORTED);
+        mm_base_modem_at_command (MM_BASE_MODEM (self),
+                                  "AT^SGPSS=0",
+                                  3, FALSE, (GAsyncReadyCallback) disable_sgpss_ready, task);
+        return;
+
+    case DISABLE_LOCATION_GATHERING_GPS_STEP_LAST:
+        /* Only use the GPS port in NMEA/RAW setups */
+        if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
+                           MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
+            MMPortSerialGps *gps_port;
+
+            /* Even if we get an error here, we try to close the GPS port */
+            gps_port = mm_base_modem_peek_port_gps (self);
+            if (gps_port)
+                mm_port_serial_close (MM_PORT_SERIAL (gps_port));
+        }
+
+        if (ctx->sgpss_error) {
+            g_task_return_error (task, ctx->sgpss_error);
+            g_clear_error (&ctx->sgpss_error);
+        } else
+            g_task_return_boolean (task, TRUE);
+        g_object_unref (task);
+        return;
+    }
 }
 
 static void
-internal_disable_location_gathering (LocationGatheringContext *ctx)
+internal_disable_location_gathering (GTask *task)
 {
-    LocationContext *location_ctx;
-    gboolean stop_gps = FALSE;
+    DisableLocationGatheringContext *ctx;
+    LocationContext                 *location_ctx;
+    gboolean                         stop_gps = FALSE;
+
+    ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task);
 
-    location_ctx = get_location_context (MM_BASE_MODEM (ctx->self));
+    location_ctx = get_location_context (MM_BASE_MODEM (g_task_get_source_object (task)));
 
     /* Only stop GPS engine if no GPS-related sources enabled */
     if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
@@ -201,64 +310,59 @@ internal_disable_location_gathering (LocationGatheringContext *ctx)
             stop_gps = TRUE;
     }
 
+    /* Run GPS stop sequence only if required to do so */
     if (stop_gps) {
-        /* We disable continuous GPS fixes */
-        mm_base_modem_at_command_full (MM_BASE_MODEM (ctx->self),
-                                       mm_base_modem_peek_best_at_port (MM_BASE_MODEM (ctx->self), NULL),
-                                       "AT^SGPSS=0",
-                                       3,
-                                       FALSE,
-                                       FALSE, /* raw */
-                                       NULL, /* cancellable */
-                                       (GAsyncReadyCallback)gps_disabled_ready,
-                                       ctx);
+        disable_location_gathering_context_gps_step (task);
         return;
     }
 
     /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */
-    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
-    location_gathering_context_complete_and_free (ctx);
+    g_task_return_boolean (task, TRUE);
+    g_object_unref (task);
 }
 
 static void
 parent_disable_location_gathering_ready (MMIfaceModemLocation *self,
-                                         GAsyncResult *res,
-                                         LocationGatheringContext *ctx)
+                                         GAsyncResult         *res,
+                                         GTask                *task)
 {
-    GError *error = NULL;
+    DisableLocationGatheringContext *ctx;
+    GError                          *error = NULL;
+
+    ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task);
 
     if (!iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) {
-        if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
-                           MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
-                           MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) {
-            /* Ignore errors when disabling GPS, we can try with AT commands */
-            g_error_free (error);
-        } else {
-            /* Fatal */
-            g_simple_async_result_take_error (ctx->result, error);
-            location_gathering_context_complete_and_free (ctx);
+        /* Errors when disabling non-GPS sources are fatal */
+        if (!(ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
+                             MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
+                             MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) {
+            g_task_return_error (task, error);
+            g_object_unref (task);
             return;
         }
+
+        /* Ignore errors when disabling GPS, we can try with AT commands */
+        g_error_free (error);
     }
 
-    internal_disable_location_gathering (ctx);
+    internal_disable_location_gathering (task);
 }
 
 void
-mm_common_cinterion_disable_location_gathering (MMIfaceModemLocation *self,
-                                                MMModemLocationSource source,
-                                                GAsyncReadyCallback callback,
-                                                gpointer user_data)
+mm_common_cinterion_disable_location_gathering (MMIfaceModemLocation  *self,
+                                                MMModemLocationSource  source,
+                                                GAsyncReadyCallback    callback,
+                                                gpointer               user_data)
 {
-    LocationGatheringContext *ctx;
-
-    ctx = g_slice_new (LocationGatheringContext);
-    ctx->self = g_object_ref (self);
-    ctx->result = g_simple_async_result_new (G_OBJECT (self),
-                                             callback,
-                                             user_data,
-                                             mm_common_cinterion_disable_location_gathering);
+    GTask                           *task;
+    DisableLocationGatheringContext *ctx;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    ctx = g_slice_new0 (DisableLocationGatheringContext);
     ctx->source = source;
+    ctx->gps_step = DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST;
+    g_task_set_task_data (task, ctx, (GDestroyNotify) disable_location_gathering_context_free);
 
     /* Chain up parent's gathering enable */
     if (iface_modem_location_parent->disable_location_gathering) {
@@ -266,86 +370,129 @@ mm_common_cinterion_disable_location_gathering (MMIfaceModemLocation *self,
             self,
             source,
             (GAsyncReadyCallback)parent_disable_location_gathering_ready,
-            ctx);
+            task);
         return;
     }
 
-    internal_disable_location_gathering (ctx);
+    internal_disable_location_gathering (task);
 }
 
 /*****************************************************************************/
 /* Enable location gathering (Location interface) */
 
+typedef enum {
+    ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST,
+    ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSS,
+    ENABLE_LOCATION_GATHERING_GPS_STEP_LAST,
+} EnableLocationGatheringGpsStep;
+
+typedef struct {
+    MMModemLocationSource          source;
+    EnableLocationGatheringGpsStep gps_step;
+    gboolean                       sgpss_success;
+} EnableLocationGatheringContext;
+
+static void
+enable_location_gathering_context_free (EnableLocationGatheringContext *ctx)
+{
+    g_slice_free (EnableLocationGatheringContext, ctx);
+}
+
 gboolean
-mm_common_cinterion_enable_location_gathering_finish (MMIfaceModemLocation *self,
-                                                      GAsyncResult *res,
-                                                      GError **error)
+mm_common_cinterion_enable_location_gathering_finish (MMIfaceModemLocation  *self,
+                                                      GAsyncResult          *res,
+                                                      GError               **error)
 {
-    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+    return g_task_propagate_boolean (G_TASK (res), error);
 }
 
+static void enable_location_gathering_context_gps_step (GTask *task);
+
 static void
-gps_enabled_ready (MMBaseModem *self,
-                   GAsyncResult *res,
-                   LocationGatheringContext *ctx)
+enable_sgpss_ready (MMBaseModem  *self,
+                    GAsyncResult *res,
+                    GTask        *task)
 {
-    GError *error = NULL;
+    EnableLocationGatheringContext *ctx;
+    GError                         *error = NULL;
 
-    if (!mm_base_modem_at_command_full_finish (self, res, &error)) {
-        g_simple_async_result_take_error (ctx->result, error);
-        location_gathering_context_complete_and_free (ctx);
+    ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task);
+
+    if (!mm_base_modem_at_command_finish (self, res, &error)) {
+        g_task_return_error (task, error);
+        g_object_unref (task);
         return;
     }
 
-    /* Only use the GPS port in NMEA/RAW setups */
-    if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
-                       MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
-        MMPortSerialGps *gps_port;
-
-        gps_port = mm_base_modem_peek_port_gps (self);
-        if (!gps_port ||
-            !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) {
-            if (error)
-                g_simple_async_result_take_error (ctx->result, error);
-            else
-                g_simple_async_result_set_error (ctx->result,
-                                                 MM_CORE_ERROR,
-                                                 MM_CORE_ERROR_FAILED,
-                                                 "Couldn't open raw GPS serial port");
-        } else
-            g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
-    } else
-        g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+    /* Flag as success with this method */
+    ctx->sgpss_success = TRUE;
 
-    location_gathering_context_complete_and_free (ctx);
+    /* And jump to last step */
+    ctx->gps_step = ENABLE_LOCATION_GATHERING_GPS_STEP_LAST;
+    enable_location_gathering_context_gps_step (task);
 }
 
 static void
-parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
-                                        GAsyncResult *res,
-                                        LocationGatheringContext *ctx)
+enable_location_gathering_context_gps_step (GTask *task)
 {
-    gboolean start_gps = FALSE;
-    GError *error = NULL;
-    LocationContext *location_ctx;
+    EnableLocationGatheringContext *ctx;
+    MMBaseModem                    *self;
+    LocationContext                *location_ctx;
 
-    if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) {
+    self = MM_BASE_MODEM (g_task_get_source_object (task));
+    ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task);
+    location_ctx = get_location_context (MM_BASE_MODEM (self));
+
+    switch (ctx->gps_step) {
+    case ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST:
+        ctx->gps_step++;
+        /* Fall down to next step */
+
+    case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSS:
+        g_assert (location_ctx->sgpss_support == FEATURE_SUPPORTED);
+        mm_base_modem_at_command (MM_BASE_MODEM (self),
+                                  "AT^SGPSS=4",
+                                  3, FALSE, (GAsyncReadyCallback) enable_sgpss_ready, task);
+        return;
+
+    case ENABLE_LOCATION_GATHERING_GPS_STEP_LAST:
+        g_assert (ctx->sgpss_success);
+
+        /* Only use the GPS port in NMEA/RAW setups */
         if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
-                           MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
-                           MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) {
-            /* Ignore errors when enabling GPS, we can try with AT commands */
-            g_error_free (error);
-        } else {
-            /* Fatal */
-            g_simple_async_result_take_error (ctx->result, error);
-            location_gathering_context_complete_and_free (ctx);
-            return;
+                           MM_MODEM_LOCATION_SOURCE_GPS_RAW)) {
+            MMPortSerialGps *gps_port;
+            GError          *error = NULL;
+
+            gps_port = mm_base_modem_peek_port_gps (self);
+            if (!gps_port || !mm_port_serial_open (MM_PORT_SERIAL (gps_port), &error)) {
+                if (error)
+                    g_task_return_error (task, error);
+                else
+                    g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                             "Couldn't open raw GPS serial port");
+                g_object_unref (task);
+                return;
+            }
         }
+
+        /* Success */
+        g_task_return_boolean (task, TRUE);
+        g_object_unref (task);
+        return;
     }
+}
 
-    /* Now our own enabling */
+static void
+internal_enable_location_gathering (GTask *task)
+{
+    EnableLocationGatheringContext *ctx;
+    LocationContext                *location_ctx;
+    gboolean                        start_gps = FALSE;
 
-    location_ctx = get_location_context (MM_BASE_MODEM (self));
+    ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task);
+
+    location_ctx = get_location_context (MM_BASE_MODEM (g_task_get_source_object (task)));
 
     /* NMEA and RAW are both enabled in the same way */
     if (ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
@@ -360,22 +507,41 @@ parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
     }
 
     if (start_gps) {
-        /* We enable continuous GPS fixes */
-        mm_base_modem_at_command_full (MM_BASE_MODEM (self),
-                                       mm_base_modem_peek_best_at_port (MM_BASE_MODEM (self), NULL),
-                                       "AT^SGPSS=4",
-                                       3,
-                                       FALSE,
-                                       FALSE, /* raw */
-                                       NULL, /* cancellable */
-                                       (GAsyncReadyCallback)gps_enabled_ready,
-                                       ctx);
+        enable_location_gathering_context_gps_step (task);
         return;
     }
 
     /* For any other location (e.g. 3GPP), or if GPS already running just return */
-    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
-    location_gathering_context_complete_and_free (ctx);
+    g_task_return_boolean (task, TRUE);
+    g_object_unref (task);
+}
+
+static void
+parent_enable_location_gathering_ready (MMIfaceModemLocation *self,
+                                        GAsyncResult         *res,
+                                        GTask                *task)
+{
+    EnableLocationGatheringContext *ctx;
+    GError                         *error = NULL;
+
+    ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task);
+
+    if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) {
+        /* Errors when enabling non-GPS sources are fatal */
+        if (!(ctx->source & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA |
+                             MM_MODEM_LOCATION_SOURCE_GPS_RAW  |
+                             MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) {
+            g_task_return_error (task, error);
+            g_object_unref (task);
+            return;
+        }
+
+        /* Ignore errors when enabling GPS, we can try with AT commands */
+        g_error_free (error);
+    }
+
+    /* Now our own enabling */
+    internal_enable_location_gathering (task);
 }
 
 void
@@ -384,22 +550,22 @@ mm_common_cinterion_enable_location_gathering (MMIfaceModemLocation *self,
                                                GAsyncReadyCallback callback,
                                                gpointer user_data)
 {
-    LocationGatheringContext *ctx;
-
-    ctx = g_slice_new (LocationGatheringContext);
-    ctx->self = g_object_ref (self);
-    ctx->result = g_simple_async_result_new (G_OBJECT (self),
-                                             callback,
-                                             user_data,
-                                             mm_common_cinterion_enable_location_gathering);
-    ctx->source = source;
+    GTask                          *task;
+    EnableLocationGatheringContext *ctx;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    ctx = g_slice_new0 (EnableLocationGatheringContext);
+    ctx->source   = source;
+    ctx->gps_step = ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST;
+    g_task_set_task_data (task, ctx, (GDestroyNotify) enable_location_gathering_context_free);
 
     /* Chain up parent's gathering enable */
     iface_modem_location_parent->enable_location_gathering (
         self,
         source,
         (GAsyncReadyCallback)parent_enable_location_gathering_ready,
-        ctx);
+        task);
 }
 
 /*****************************************************************************/
-- 
2.12.2



More information about the ModemManager-devel mailing list