diff options
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); -} |