diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-27 17:15:57 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-29 09:18:03 +0200 |
commit | 53b500c11dc648cff834be2885886f5e575046e4 (patch) | |
tree | c1827fbb6fcd80cbb9bfecbf41ff8bcce9092bc6 | |
parent | 0012b7118656afd127097d3cbfa27e9190cedd47 (diff) | |
download | ModemManager-53b500c11dc648cff834be2885886f5e575046e4.tar.gz |
iface-modem-location: handle the NMEA-based GPS location source
-rw-r--r-- | src/mm-iface-modem-location.c | 153 | ||||
-rw-r--r-- | src/mm-iface-modem-location.h | 4 |
2 files changed, 140 insertions, 17 deletions
diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c index dc5e0805b..064bd7704 100644 --- a/src/mm-iface-modem-location.c +++ b/src/mm-iface-modem-location.c @@ -21,6 +21,8 @@ #include "mm-iface-modem-location.h" #include "mm-log.h" +#define MM_LOCATION_GPS_REFRESH_TIME_SECS 30 + #define LOCATION_CONTEXT_TAG "location-context-tag" static GQuark location_context_quark; @@ -38,6 +40,9 @@ mm_iface_modem_location_bind_simple_status (MMIfaceModemLocation *self, typedef struct { /* 3GPP location */ MMLocation3gpp *location_3gpp; + /* GPS location */ + time_t location_gps_last_time; + MMLocationGpsNmea *location_gps_nmea; } LocationContext; static void @@ -45,6 +50,8 @@ location_context_free (LocationContext *ctx) { if (ctx->location_3gpp) g_object_unref (ctx->location_3gpp); + if (ctx->location_gps_nmea) + g_object_unref (ctx->location_gps_nmea); g_free (ctx); } @@ -88,27 +95,122 @@ get_location_context (MMIfaceModemLocation *self) /*****************************************************************************/ static GVariant * -build_location_dictionary (MMLocation3gpp *location_3gpp) +build_location_dictionary (GVariant *previous, + MMLocation3gpp *location_3gpp, + MMLocationGpsNmea *location_gps_nmea) { GVariant *location_3gpp_value = NULL; + GVariant *location_gps_nmea_value = NULL; GVariantBuilder builder; - if (location_3gpp) - location_3gpp_value = mm_location_3gpp_get_string_variant (location_3gpp); + /* If a previous dictionary given, parse its values */ + if (previous) { + guint source; + GVariant *value; + GVariantIter iter; + + g_variant_iter_init (&iter, previous); + while (g_variant_iter_next (&iter, "{uv}", &source, &value)) { + switch (source) { + case MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI: + location_3gpp_value = value; + break; + case MM_MODEM_LOCATION_SOURCE_GPS_NMEA: + location_gps_nmea_value = value; + break; + default: + g_warn_if_reached (); + break; + } + } + } + /* Build the new one */ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{uv}")); - if (location_3gpp_value) + + /* If a new one given, use it */ + if (location_3gpp) { + if (location_3gpp_value) + g_variant_unref (location_3gpp_value); + location_3gpp_value = mm_location_3gpp_get_string_variant (location_3gpp); + } + + if (location_3gpp_value) { g_variant_builder_add (&builder, "{uv}", MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI, location_3gpp_value); + } + + /* If a new one given, use it */ + if (location_gps_nmea) { + if (location_gps_nmea_value) + g_variant_unref (location_gps_nmea_value); + location_gps_nmea_value = mm_location_gps_nmea_get_string_variant (location_gps_nmea); + } + + if (location_gps_nmea_value) + g_variant_builder_add (&builder, + "{uv}", + MM_MODEM_LOCATION_SOURCE_GPS_NMEA, + location_gps_nmea_value); + return g_variant_builder_end (&builder); } +/*****************************************************************************/ + +static void +notify_gps_location_update (MMIfaceModemLocation *self, + MmGdbusModemLocation *skeleton, + MMLocationGpsNmea *location_gps_nmea) +{ + const gchar *dbus_path; + + dbus_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (self)); + mm_info ("Modem %s: GPS location updated", + dbus_path); + + /* We only update the property if we are supposed to signal + * location */ + if (mm_gdbus_modem_location_get_signals_location (skeleton)) + mm_gdbus_modem_location_set_location ( + skeleton, + build_location_dictionary (mm_gdbus_modem_location_get_location (skeleton), + NULL, + location_gps_nmea)); +} + +void +mm_iface_modem_location_gps_update (MMIfaceModemLocation *self, + const gchar *nmea_trace) +{ + MmGdbusModemLocation *skeleton; + LocationContext *ctx; + + ctx = get_location_context (self); + g_object_get (self, + MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &skeleton, + NULL); + + if (mm_gdbus_modem_location_get_enabled (skeleton) & MM_MODEM_LOCATION_SOURCE_GPS_NMEA) { + g_assert (ctx->location_gps_nmea != NULL); + if (mm_location_gps_nmea_add_trace (ctx->location_gps_nmea, nmea_trace) && + ctx->location_gps_last_time >= MM_LOCATION_GPS_REFRESH_TIME_SECS) { + ctx->location_gps_last_time = time (NULL); + notify_gps_location_update (self, skeleton, ctx->location_gps_nmea); + } + } + + g_object_unref (skeleton); +} + +/*****************************************************************************/ + static void -notify_location_update (MMIfaceModemLocation *self, - MmGdbusModemLocation *skeleton, - MMLocation3gpp *location_3gpp) +notify_3gpp_location_update (MMIfaceModemLocation *self, + MmGdbusModemLocation *skeleton, + MMLocation3gpp *location_3gpp) { const gchar *dbus_path; @@ -126,7 +228,9 @@ notify_location_update (MMIfaceModemLocation *self, if (mm_gdbus_modem_location_get_signals_location (skeleton)) mm_gdbus_modem_location_set_location ( skeleton, - build_location_dictionary (location_3gpp)); + build_location_dictionary (mm_gdbus_modem_location_get_location (skeleton), + location_3gpp, + NULL)); } void @@ -151,7 +255,7 @@ mm_iface_modem_location_3gpp_update_mcc_mnc (MMIfaceModemLocation *self, changed += mm_location_3gpp_set_mobile_network_code (ctx->location_3gpp, mobile_network_code); if (changed) - notify_location_update (self, skeleton, ctx->location_3gpp); + notify_3gpp_location_update (self, skeleton, ctx->location_3gpp); } g_object_unref (skeleton); @@ -179,7 +283,7 @@ mm_iface_modem_location_3gpp_update_lac_ci (MMIfaceModemLocation *self, changed += mm_location_3gpp_set_cell_id (ctx->location_3gpp, cell_id); if (changed) - notify_location_update (self, skeleton, ctx->location_3gpp); + notify_3gpp_location_update (self, skeleton, ctx->location_3gpp); } g_object_unref (skeleton); @@ -205,7 +309,7 @@ mm_iface_modem_location_3gpp_clear (MMIfaceModemLocation *self) changed += mm_location_3gpp_set_mobile_country_code (ctx->location_3gpp, 0); changed += mm_location_3gpp_set_mobile_network_code (ctx->location_3gpp, 0); if (changed) - notify_location_update (self, skeleton, ctx->location_3gpp); + notify_3gpp_location_update (self, skeleton, ctx->location_3gpp); } g_object_unref (skeleton); @@ -245,6 +349,13 @@ update_location_source_status (MMIfaceModemLocation *self, } else g_clear_object (&ctx->location_3gpp); break; + case MM_MODEM_LOCATION_SOURCE_GPS_NMEA: + if (enabled) { + if (!ctx->location_gps_nmea) + ctx->location_gps_nmea = mm_location_gps_nmea_new (); + } else + g_clear_object (&ctx->location_gps_nmea); + break; default: break; } @@ -564,10 +675,16 @@ handle_setup_auth_ready (MMBaseModem *self, ctx->signal_location ? "Enabling" : "Disabling"); mm_gdbus_modem_location_set_signals_location (ctx->skeleton, ctx->signal_location); - mm_gdbus_modem_location_set_location (ctx->skeleton, - build_location_dictionary (ctx->signal_location ? - location_ctx->location_3gpp : - NULL)); + if (ctx->signal_location) + mm_gdbus_modem_location_set_location ( + ctx->skeleton, + build_location_dictionary (mm_gdbus_modem_location_get_location (ctx->skeleton), + location_ctx->location_3gpp, + location_ctx->location_gps_nmea)); + else + mm_gdbus_modem_location_set_location ( + ctx->skeleton, + build_location_dictionary (NULL, NULL, NULL)); } str = mm_modem_location_source_build_string_from_mask (ctx->sources); @@ -655,7 +772,9 @@ handle_get_location_auth_ready (MMBaseModem *self, mm_gdbus_modem_location_complete_get_location ( ctx->skeleton, ctx->invocation, - build_location_dictionary (location_ctx->location_3gpp)); + build_location_dictionary (NULL, + location_ctx->location_3gpp, + location_ctx->location_gps_nmea)); } static gboolean @@ -1123,7 +1242,7 @@ mm_iface_modem_location_initialize (MMIfaceModemLocation *self, mm_gdbus_modem_location_set_enabled (skeleton, MM_MODEM_LOCATION_SOURCE_NONE); mm_gdbus_modem_location_set_signals_location (skeleton, FALSE); mm_gdbus_modem_location_set_location (skeleton, - build_location_dictionary (NULL)); + build_location_dictionary (NULL, NULL, NULL)); g_object_set (self, MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, skeleton, diff --git a/src/mm-iface-modem-location.h b/src/mm-iface-modem-location.h index 19f760e4d..ea64bb8f9 100644 --- a/src/mm-iface-modem-location.h +++ b/src/mm-iface-modem-location.h @@ -100,6 +100,10 @@ void mm_iface_modem_location_3gpp_update_lac_ci (MMIfaceModemLocation *self, gulong location_area_code, gulong cell_id); +/* Update GPS location */ +void mm_iface_modem_location_gps_update (MMIfaceModemLocation *self, + const gchar *nmea_trace); + /* Bind properties for simple GetStatus() */ void mm_iface_modem_location_bind_simple_status (MMIfaceModemLocation *self, MMSimpleStatus *status); |