iface-modem-location: handle 3GPP location
This commit is contained in:
@@ -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)
|
||||
{
|
||||
/* Enabling */
|
||||
if (enable) {
|
||||
LocationContext *ctx;
|
||||
|
||||
ctx = get_location_context (self);
|
||||
|
||||
/* Enabling */
|
||||
if (enable) {
|
||||
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,
|
||||
|
@@ -88,6 +88,15 @@ gboolean mm_iface_modem_location_disable_finish (MMIfaceModemLocation *self,
|
||||
/* Shutdown Location interface */
|
||||
void mm_iface_modem_location_shutdown (MMIfaceModemLocation *self);
|
||||
|
||||
/* Update 3GPP (LAC/CI) location */
|
||||
void mm_iface_modem_location_3gpp_clear (MMIfaceModemLocation *self);
|
||||
void mm_iface_modem_location_3gpp_update_mcc_mnc (MMIfaceModemLocation *self,
|
||||
guint mobile_country_code,
|
||||
guint mobile_network_code);
|
||||
void mm_iface_modem_location_3gpp_update_lac_ci (MMIfaceModemLocation *self,
|
||||
gulong location_area_code,
|
||||
gulong cell_id);
|
||||
|
||||
/* Bind properties for simple GetStatus() */
|
||||
void mm_iface_modem_location_bind_simple_status (MMIfaceModemLocation *self,
|
||||
MMCommonSimpleProperties *status);
|
||||
|
Reference in New Issue
Block a user