diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-08-13 19:14:30 +0200 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2018-08-21 17:06:55 +0000 |
commit | 59e79c996b4863448f68a262bf8be053416a1344 (patch) | |
tree | 160bdf4b1d6bbc69e39a899a10a2df658ebbb511 /plugins/cinterion/mm-common-cinterion.c | |
parent | 6e9bf39ecf97aedd8474577811c147b62d37585e (diff) |
cinterion: new 'MMSharedCinterion' interface
Implement a new interface to keep the code shared between the QMI and
non-QMI modem implementations.
While doing that, also fix the parent interface pointer handling, so
that it isn't a static pointer applicable to all modems, and make it a
per-modem specific pointer. Without this fix, ModemManager would crash
if e.g. running with both a QMI and non-QMI Cinterion modem at the
same time.
The new shared Cinterion logic will be in charge of managing all GPS
sources not already managed by the parent interface. E.g. if the
parent implementation already supports QMI-based GPS location (using
the LOC service for example) prefer that to the custom AT-based
logic.
Diffstat (limited to 'plugins/cinterion/mm-common-cinterion.c')
-rw-r--r-- | plugins/cinterion/mm-common-cinterion.c | 802 |
1 files changed, 0 insertions, 802 deletions
diff --git a/plugins/cinterion/mm-common-cinterion.c b/plugins/cinterion/mm-common-cinterion.c deleted file mode 100644 index 67bc5b3b..00000000 --- a/plugins/cinterion/mm-common-cinterion.c +++ /dev/null @@ -1,802 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2014 Ammonit Measurement GmbH - * Author: Aleksander Morgado <aleksander@aleksander.es> - */ - -#include "mm-common-cinterion.h" -#include "mm-base-modem-at.h" -#include "mm-log.h" - -static MMIfaceModemLocation *iface_modem_location_parent; - -/*****************************************************************************/ - -#define CINTERION_LOCATION_CONTEXT_TAG "cinterion-location-tag" -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; - FeatureSupport sgpsc_support; -} LocationContext; - -static void -location_context_free (LocationContext *ctx) -{ - g_slice_free (LocationContext, ctx); -} - -static LocationContext * -get_location_context (MMBaseModem *self) -{ - LocationContext *ctx; - - if (G_UNLIKELY (!cinterion_location_context_quark)) - cinterion_location_context_quark = (g_quark_from_static_string ( - CINTERION_LOCATION_CONTEXT_TAG)); - - ctx = g_object_get_qdata (G_OBJECT (self), cinterion_location_context_quark); - if (!ctx) { - /* 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; - ctx->sgpsc_support = FEATURE_SUPPORT_UNKNOWN; - - g_object_set_qdata_full ( - G_OBJECT (self), - cinterion_location_context_quark, - ctx, - (GDestroyNotify)location_context_free); - } - - return ctx; -} - -/*****************************************************************************/ -/* GPS trace received */ - -static void -trace_received (MMPortSerialGps *port, - const gchar *trace, - MMIfaceModemLocation *self) -{ - /* Helper to debug GPS location related issues. Don't depend on a real GPS - * fix for debugging, just use some random values to update */ -#if 0 - if (g_str_has_prefix (trace, "$GPGGA")) { - GString *str; - GDateTime *now; - - now = g_date_time_new_now_utc (); - str = g_string_new (""); - g_string_append_printf (str, - "$GPGGA,%02u%02u%02u,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47", - g_date_time_get_hour (now), - g_date_time_get_minute (now), - g_date_time_get_second (now)); - mm_iface_modem_location_gps_update (self, str->str); - g_string_free (str, TRUE); - g_date_time_unref (now); - return; - } -#endif - - mm_iface_modem_location_gps_update (self, trace); -} - -/*****************************************************************************/ -/* 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) -{ - GError *inner_error = NULL; - gssize aux; - - aux = g_task_propagate_int (G_TASK (res), &inner_error); - if (inner_error) { - g_propagate_error (error, inner_error); - return MM_MODEM_LOCATION_SOURCE_NONE; - } - return (MMModemLocationSource) aux; -} - -static void probe_gps_features (GTask *task); - -static void -sgpsc_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->sgpsc_support = FEATURE_NOT_SUPPORTED; - else { - /* ^SGPSC supported! */ - location_ctx->sgpsc_support = FEATURE_SUPPORTED; - /* It may happen that the modem was started with GPS already enabled, or - * maybe ModemManager got rebooted and it was left enabled before. We'll - * make sure that it is disabled when we initialize the modem. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"Engine\",\"0\"", 3, FALSE, NULL, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"Power/Antenna\",\"off\"", 3, FALSE, NULL, NULL); - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSC=\"NMEA/Output\",\"off\"", 3, FALSE, NULL, NULL); - } - - probe_gps_features (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 { - /* ^SGPSS supported! */ - location_ctx->sgpss_support = FEATURE_SUPPORTED; - - /* Flag ^SGPSC as unsupported, even if it may be supported, so that we - * only use one set of commands to enable/disable GPS. */ - location_ctx->sgpsc_support = FEATURE_NOT_SUPPORTED; - - /* It may happen that the modem was started with GPS already enabled, or - * maybe ModemManager got rebooted and it was left enabled before. We'll - * make sure that it is disabled when we initialize the modem. */ - mm_base_modem_at_command (MM_BASE_MODEM (self), "AT^SGPSS=0", 3, FALSE, NULL, NULL); - } - - 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; - } - - /* Need to check if SGPSC supported... */ - if (location_ctx->sgpsc_support == FEATURE_SUPPORT_UNKNOWN) { - mm_base_modem_at_command (self, "AT^SGPSC=?", 3, TRUE, (GAsyncReadyCallback) sgpsc_test_ready, task); - return; - } - - /* All GPS features probed, check if GPS supported */ - if (location_ctx->sgpss_support == FEATURE_SUPPORTED || location_ctx->sgpsc_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); - - /* Add handler for the NMEA traces in the GPS data port */ - mm_port_serial_gps_add_trace_handler (mm_base_modem_peek_port_gps (MM_BASE_MODEM (self)), - (MMPortSerialGpsTraceFn)trace_received, - self, - NULL); - } 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, - GTask *task) -{ - LoadCapabilitiesContext *ctx; - GError *error = NULL; - - ctx = (LoadCapabilitiesContext *) g_task_get_task_data (task); - - ctx->sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); - if (error) { - 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; - } - - /* Probe all GPS features */ - probe_gps_features (task); -} - -void -mm_common_cinterion_location_load_capabilities (MMIfaceModemLocation *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - LoadCapabilitiesContext *ctx; - - task = g_task_new (self, NULL, callback, user_data); - - 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, - task); -} - -/*****************************************************************************/ -/* Disable location gathering (Location interface) */ - -typedef enum { - DISABLE_LOCATION_GATHERING_GPS_STEP_FIRST, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSS, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA, - DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT, - DISABLE_LOCATION_GATHERING_GPS_STEP_LAST, -} DisableLocationGatheringGpsStep; - -typedef struct { - MMModemLocationSource source; - DisableLocationGatheringGpsStep gps_step; - GError *sgpss_error; - GError *sgpsc_error; -} DisableLocationGatheringContext; - -static void -disable_location_gathering_context_free (DisableLocationGatheringContext *ctx) -{ - if (ctx->sgpss_error) - g_error_free (ctx->sgpss_error); - if (ctx->sgpsc_error) - g_error_free (ctx->sgpsc_error); - g_slice_free (DisableLocationGatheringContext, ctx); -} - -gboolean -mm_common_cinterion_disable_location_gathering_finish (MMIfaceModemLocation *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void disable_location_gathering_context_gps_step (GTask *task); - -static void -disable_sgpsc_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableLocationGatheringContext *ctx; - GError *error = NULL; - - ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task); - - /* Store error, if not one available already, and continue */ - if (!mm_base_modem_at_command_finish (self, res, &error)) { - if (!ctx->sgpsc_error) - ctx->sgpsc_error = error; - else - g_error_free (error); - } - - ctx->gps_step++; - disable_location_gathering_context_gps_step (task); -} - -static void -disable_sgpss_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - DisableLocationGatheringContext *ctx; - - ctx = (DisableLocationGatheringContext *) g_task_get_task_data (task); - - /* Store error, if any, and continue */ - g_assert (!ctx->sgpss_error); - mm_base_modem_at_command_finish (self, res, &ctx->sgpss_error); - - ctx->gps_step++; - disable_location_gathering_context_gps_step (task); -} - -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)); - - /* Only one of both supported */ - g_assert ((location_ctx->sgpss_support == FEATURE_SUPPORTED) || (location_ctx->sgpsc_support == FEATURE_SUPPORTED)); - g_assert (!((location_ctx->sgpss_support == FEATURE_SUPPORTED) && (location_ctx->sgpsc_support == FEATURE_SUPPORTED))); - - 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: - if (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; - } - ctx->gps_step++; - /* Fall down to next step */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* Engine off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Engine\",\"0\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* Antenna off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Power/Antenna\",\"off\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - case DISABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* NMEA output off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"NMEA/Output\",\"off\"", - 3, FALSE, (GAsyncReadyCallback) disable_sgpsc_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - 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 if (ctx->sgpsc_error) { - g_task_return_error (task, ctx->sgpsc_error); - g_clear_error (&ctx->sgpsc_error); - } else - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } -} - -static void -internal_disable_location_gathering (GTask *task) -{ - 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 (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 | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - location_ctx->enabled_sources &= ~ctx->source; - - if (!(location_ctx->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - stop_gps = TRUE; - } - - /* Run GPS stop sequence only if required to do so */ - if (stop_gps) { - disable_location_gathering_context_gps_step (task); - return; - } - - /* For any other location (e.g. 3GPP), or if still some GPS needed, just return */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -parent_disable_location_gathering_ready (MMIfaceModemLocation *self, - GAsyncResult *res, - GTask *task) -{ - 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)) { - /* 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 (task); -} - -void -mm_common_cinterion_disable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - 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) { - iface_modem_location_parent->disable_location_gathering ( - self, - source, - (GAsyncReadyCallback)parent_disable_location_gathering_ready, - task); - return; - } - - internal_disable_location_gathering (task); -} - -/*****************************************************************************/ -/* Enable location gathering (Location interface) */ - -/* We will retry the SGPSC command that enables the Engine */ -#define MAX_SGPSC_ENGINE_RETRIES 3 - -/* Cinterion asks for 100ms some time between GPS commands, but we'll give up - * to 2000ms before setting the Engine configuration as 100ms didn't seem always - * enough (we would get +CME ERROR: 767 errors reported). */ -#define GPS_COMMAND_TIMEOUT_DEFAULT_MS 100 -#define GPS_COMMAND_TIMEOUT_ENGINE_MS 2000 - -typedef enum { - ENABLE_LOCATION_GATHERING_GPS_STEP_FIRST, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSS, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA, - ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE, - ENABLE_LOCATION_GATHERING_GPS_STEP_LAST, -} EnableLocationGatheringGpsStep; - -typedef struct { - MMModemLocationSource source; - EnableLocationGatheringGpsStep gps_step; - guint sgpsc_engine_retries; -} 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) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void enable_location_gathering_context_gps_step (GTask *task); - -static gboolean -enable_location_gathering_context_gps_step_schedule_cb (GTask *task) -{ - /* Run the scheduled step */ - enable_location_gathering_context_gps_step (task); - return G_SOURCE_REMOVE; -} - -static void -enable_sgpsc_or_sgpss_ready (MMBaseModem *self, - GAsyncResult *res, - GTask *task) -{ - EnableLocationGatheringContext *ctx; - GError *error = NULL; - - ctx = (EnableLocationGatheringContext *) g_task_get_task_data (task); - - if (!mm_base_modem_at_command_finish (self, res, &error)) { - /* The GPS setup may sometimes report "+CME ERROR 767" when enabling the - * Engine; so we'll run some retries of the same command ourselves. */ - if (ctx->gps_step == ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE) { - ctx->sgpsc_engine_retries++; - mm_dbg ("GPS Engine setup failed (%u/%u)", ctx->sgpsc_engine_retries, MAX_SGPSC_ENGINE_RETRIES); - if (ctx->sgpsc_engine_retries < MAX_SGPSC_ENGINE_RETRIES) { - g_clear_error (&error); - goto schedule; - } - } - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - /* Go on to next step */ - ctx->gps_step++; - -schedule: - g_timeout_add (ctx->gps_step == ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE ? GPS_COMMAND_TIMEOUT_ENGINE_MS : GPS_COMMAND_TIMEOUT_DEFAULT_MS, - (GSourceFunc) enable_location_gathering_context_gps_step_schedule_cb, task); -} - -static void -enable_location_gathering_context_gps_step (GTask *task) -{ - EnableLocationGatheringContext *ctx; - MMBaseModem *self; - LocationContext *location_ctx; - - 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)); - - /* Only one of both supported */ - g_assert ((location_ctx->sgpss_support == FEATURE_SUPPORTED) || (location_ctx->sgpsc_support == FEATURE_SUPPORTED)); - g_assert (!((location_ctx->sgpss_support == FEATURE_SUPPORTED) && (location_ctx->sgpsc_support == FEATURE_SUPPORTED))); - - 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: - if (location_ctx->sgpss_support == FEATURE_SUPPORTED) { - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSS=4", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_OUTPUT: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* NMEA output off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"NMEA/Output\",\"on\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ANTENNA: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* Antenna off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Power/Antenna\",\"on\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - case ENABLE_LOCATION_GATHERING_GPS_STEP_SGPSC_ENGINE: - if (location_ctx->sgpsc_support == FEATURE_SUPPORTED) { - /* Engine off */ - mm_base_modem_at_command (MM_BASE_MODEM (self), - "AT^SGPSC=\"Engine\",\"1\"", - 3, FALSE, (GAsyncReadyCallback) enable_sgpsc_or_sgpss_ready, task); - return; - } - ctx->gps_step++; - /* Fall down to next step */ - - case ENABLE_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; - 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; - } -} - -static void -internal_enable_location_gathering (GTask *task) -{ - EnableLocationGatheringContext *ctx; - LocationContext *location_ctx; - gboolean start_gps = FALSE; - - 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 | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { - /* Only start GPS engine if not done already */ - if (!(location_ctx->enabled_sources & (MM_MODEM_LOCATION_SOURCE_GPS_NMEA | - MM_MODEM_LOCATION_SOURCE_GPS_RAW | - MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) - start_gps = TRUE; - location_ctx->enabled_sources |= ctx->source; - } - - if (start_gps) { - enable_location_gathering_context_gps_step (task); - return; - } - - /* For any other location (e.g. 3GPP), or if GPS already running just return */ - 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 -mm_common_cinterion_enable_location_gathering (MMIfaceModemLocation *self, - MMModemLocationSource source, - GAsyncReadyCallback callback, - gpointer user_data) -{ - 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, - task); -} - -/*****************************************************************************/ - -void -mm_common_cinterion_peek_parent_location_interface (MMIfaceModemLocation *iface) -{ - iface_modem_location_parent = g_type_interface_peek_parent (iface); -} |