summaryrefslogtreecommitdiff
path: root/src/mm-iface-modem-location.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2012-01-17 23:43:20 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:14:52 +0100
commit71125777d38126f41c18a2b04a0dbfdb6b2628d6 (patch)
tree8b125822fea8b1787ddb17a12009185731e1d9d1 /src/mm-iface-modem-location.c
parent5fa8918847fffa7f373c2f863ed765091db659d3 (diff)
downloadModemManager-71125777d38126f41c18a2b04a0dbfdb6b2628d6.tar.gz
iface-modem-location: handle 3GPP location
Diffstat (limited to 'src/mm-iface-modem-location.c')
-rw-r--r--src/mm-iface-modem-location.c208
1 files changed, 181 insertions, 27 deletions
diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c
index 51ffea354..96af97e35 100644
--- a/src/mm-iface-modem-location.c
+++ b/src/mm-iface-modem-location.c
@@ -18,6 +18,7 @@
#include "mm-iface-modem.h"
#include "mm-iface-modem-location.h"
+#include "mm-common-location-3gpp.h"
#include "mm-log.h"
#define LOCATION_CONTEXT_TAG "location-context-tag"
@@ -66,9 +67,31 @@ dbus_call_context_new (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
typedef struct {
- gboolean interface_enabled;
+ /* 3GPP location */
+ MMCommonLocation3gpp *location_3gpp;
} LocationContext;
+static void
+location_context_free (LocationContext *ctx)
+{
+ if (ctx->location_3gpp)
+ g_object_unref (ctx->location_3gpp);
+ g_free (ctx);
+}
+
+static void
+clear_location_context (MMIfaceModemLocation *self)
+{
+ if (G_UNLIKELY (!location_context_quark))
+ location_context_quark = (g_quark_from_static_string (
+ LOCATION_CONTEXT_TAG));
+
+ /* Clear all location data */
+ g_object_set_qdata (G_OBJECT (self),
+ location_context_quark,
+ NULL);
+}
+
static LocationContext *
get_location_context (MMIfaceModemLocation *self)
{
@@ -87,7 +110,7 @@ get_location_context (MMIfaceModemLocation *self)
G_OBJECT (self),
location_context_quark,
ctx,
- (GDestroyNotify)g_free);
+ (GDestroyNotify)location_context_free);
}
return ctx;
@@ -95,6 +118,138 @@ get_location_context (MMIfaceModemLocation *self)
/*****************************************************************************/
+static GVariant *
+build_location_dictionary (MMCommonLocation3gpp *location_3gpp)
+{
+ GVariant *location_3gpp_value = NULL;
+ GVariantBuilder builder;
+
+ if (location_3gpp)
+ location_3gpp_value = mm_common_location_3gpp_get_string_variant (location_3gpp);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{uv}"));
+ if (location_3gpp_value)
+ g_variant_builder_add (&builder,
+ "{uv}",
+ MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI,
+ location_3gpp_value);
+ return g_variant_builder_end (&builder);
+}
+
+static void
+notify_location_update (MMIfaceModemLocation *self,
+ MmGdbusModemLocation *skeleton,
+ MMCommonLocation3gpp *location_3gpp)
+{
+ const gchar *dbus_path;
+
+ dbus_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (self));
+ mm_info ("Modem %s: 3GPP location updated "
+ "(MCC: '%u', MNC: '%u', Location area code: '%lX', Cell ID: '%lX')",
+ dbus_path,
+ mm_common_location_3gpp_get_mobile_country_code (location_3gpp),
+ mm_common_location_3gpp_get_mobile_network_code (location_3gpp),
+ mm_common_location_3gpp_get_location_area_code (location_3gpp),
+ mm_common_location_3gpp_get_cell_id (location_3gpp));
+
+ /* 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 (location_3gpp));
+}
+
+void
+mm_iface_modem_location_3gpp_update_mcc_mnc (MMIfaceModemLocation *self,
+ guint mobile_country_code,
+ guint mobile_network_code)
+{
+ 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)) {
+ guint changed = 0;
+
+ if (G_UNLIKELY (!ctx->location_3gpp))
+ ctx->location_3gpp = mm_common_location_3gpp_new ();
+
+ changed += mm_common_location_3gpp_set_mobile_country_code (ctx->location_3gpp,
+ mobile_country_code);
+ changed += mm_common_location_3gpp_set_mobile_network_code (ctx->location_3gpp,
+ mobile_network_code);
+ if (changed)
+ notify_location_update (self, skeleton, ctx->location_3gpp);
+ }
+
+ g_object_unref (skeleton);
+}
+
+void
+mm_iface_modem_location_3gpp_update_lac_ci (MMIfaceModemLocation *self,
+ gulong location_area_code,
+ gulong cell_id)
+{
+ 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)) {
+ guint changed = 0;
+
+ if (G_UNLIKELY (!ctx->location_3gpp))
+ ctx->location_3gpp = mm_common_location_3gpp_new ();
+
+ changed += mm_common_location_3gpp_set_location_area_code (ctx->location_3gpp,
+ location_area_code);
+ changed += mm_common_location_3gpp_set_cell_id (ctx->location_3gpp,
+ cell_id);
+ if (changed)
+ notify_location_update (self, skeleton, ctx->location_3gpp);
+ }
+
+ g_object_unref (skeleton);
+}
+
+void
+mm_iface_modem_location_3gpp_clear (MMIfaceModemLocation *self)
+{
+ 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)) {
+ guint changed = 0;
+
+ if (G_UNLIKELY (!ctx->location_3gpp))
+ ctx->location_3gpp = mm_common_location_3gpp_new ();
+
+ changed += mm_common_location_3gpp_set_location_area_code (ctx->location_3gpp, 0);
+ changed += mm_common_location_3gpp_set_cell_id (ctx->location_3gpp, 0);
+ changed += mm_common_location_3gpp_set_mobile_country_code (ctx->location_3gpp, 0);
+ changed += mm_common_location_3gpp_set_mobile_network_code (ctx->location_3gpp, 0);
+ if (changed)
+ notify_location_update (self, skeleton, ctx->location_3gpp);
+ }
+
+ g_object_unref (skeleton);
+}
+
+/*****************************************************************************/
+
static void
enable_location_gathering_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
@@ -127,6 +282,7 @@ disable_location_gathering_ready (MMIfaceModemLocation *self,
&error))
g_dbus_method_invocation_take_error (ctx->invocation, error);
else {
+ clear_location_context (self);
mm_gdbus_modem_location_set_enabled (ctx->skeleton, FALSE);
mm_gdbus_modem_location_complete_enable (ctx->skeleton,
ctx->invocation);
@@ -142,12 +298,11 @@ handle_enable (MmGdbusModemLocation *skeleton,
gboolean signal_location,
MMIfaceModemLocation *self)
{
- LocationContext *ctx;
-
- ctx = get_location_context (self);
-
/* Enabling */
if (enable) {
+ LocationContext *ctx;
+
+ ctx = get_location_context (self);
mm_dbg ("Enabling location gathering%s...",
signal_location ? " (with signaling)" : "");
@@ -155,18 +310,19 @@ handle_enable (MmGdbusModemLocation *skeleton,
if (mm_gdbus_modem_location_get_signals_location (skeleton) != signal_location) {
mm_dbg ("%s location signaling",
signal_location ? "Enabling" : "Disabling");
- mm_gdbus_modem_location_set_signals_location (skeleton, signal_location);
- if (!signal_location)
- /* If disabling, cleanup currently available value */
- mm_gdbus_modem_location_set_location (skeleton, NULL);
+ mm_gdbus_modem_location_set_signals_location (skeleton,
+ signal_location);
+ mm_gdbus_modem_location_set_location (skeleton,
+ build_location_dictionary (signal_location ?
+ ctx->location_3gpp :
+ NULL));
}
/* If already enabled, just done */
if (mm_gdbus_modem_location_get_enabled (skeleton))
mm_gdbus_modem_location_complete_enable (skeleton, invocation);
/* Plugins can run custom actions to enable location gathering */
- else if (ctx->interface_enabled &&
- MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering &&
+ else if (MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering &&
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering_finish)
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->enable_location_gathering (
self,
@@ -188,8 +344,7 @@ handle_enable (MmGdbusModemLocation *skeleton,
if (!mm_gdbus_modem_location_get_enabled (skeleton))
mm_gdbus_modem_location_complete_enable (skeleton, invocation);
/* Plugins can run custom actions to disable location gathering */
- else if (ctx->interface_enabled &&
- MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering &&
+ else if (MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering &&
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering_finish)
MM_IFACE_MODEM_LOCATION_GET_INTERFACE (self)->disable_location_gathering (
self,
@@ -199,6 +354,7 @@ handle_enable (MmGdbusModemLocation *skeleton,
self));
else {
/* If no plugin-specific setup needed, or interface not yet enabled, just done */
+ clear_location_context (self);
mm_gdbus_modem_location_set_enabled (skeleton, FALSE);
mm_gdbus_modem_location_complete_enable (skeleton, invocation);
}
@@ -210,11 +366,18 @@ handle_enable (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
static gboolean
-handle_get_location (MmGdbusModemLocation *object,
+handle_get_location (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation,
MMIfaceModemLocation *self)
{
- return FALSE;
+ LocationContext *ctx;
+
+ ctx = get_location_context (self);
+ mm_gdbus_modem_location_complete_get_location (
+ skeleton,
+ invocation,
+ build_location_dictionary (ctx->location_3gpp));
+ return TRUE;
}
/*****************************************************************************/
@@ -303,10 +466,6 @@ disabling_location_gathering_ready (MMIfaceModemLocation *self,
static void
interface_disabling_step (DisablingContext *ctx)
{
- LocationContext *location_context;
-
- location_context = get_location_context (ctx->self);
-
switch (ctx->step) {
case DISABLING_STEP_FIRST:
/* Fall down to next step */
@@ -327,7 +486,6 @@ interface_disabling_step (DisablingContext *ctx)
case DISABLING_STEP_LAST:
/* We are done without errors! */
- location_context->interface_enabled = FALSE;
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
disabling_context_complete_and_free (ctx);
return;
@@ -430,10 +588,6 @@ enabling_location_gathering_ready (MMIfaceModemLocation *self,
static void
interface_enabling_step (EnablingContext *ctx)
{
- LocationContext *location_context;
-
- location_context = get_location_context (ctx->self);
-
switch (ctx->step) {
case ENABLING_STEP_FIRST:
/* Fall down to next step */
@@ -454,7 +608,6 @@ interface_enabling_step (EnablingContext *ctx)
case ENABLING_STEP_LAST:
/* We are done without errors! */
- location_context->interface_enabled = TRUE;
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
enabling_context_complete_and_free (ctx);
return;
@@ -644,7 +797,8 @@ mm_iface_modem_location_initialize (MMIfaceModemLocation *self,
mm_gdbus_modem_location_set_capabilities (skeleton, MM_MODEM_LOCATION_SOURCE_NONE);
mm_gdbus_modem_location_set_enabled (skeleton, TRUE);
mm_gdbus_modem_location_set_signals_location (skeleton, FALSE);
- mm_gdbus_modem_location_set_location (skeleton, NULL);
+ mm_gdbus_modem_location_set_location (skeleton,
+ build_location_dictionary (NULL));
g_object_set (self,
MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, skeleton,