iface-location: allow enabling without SIM

When the modem is in a failed state because of a SIM-related error,
like a missing SIM, or if the modem is SIM-locked, allow the
Location interface to initialize and be enabled anyway.

This allows someone without a SIM to use the GPS, which does not
particularly require a phone subscription. It also allows
someone with a SIM to use the GPS even if the SIM is still
locked.

This patch was reworked, while keeping the original idea, by:
Aleksander Morgado <aleksander@aleksander.es>

Fixes #183
This commit is contained in:
Raphaël Jakse
2023-12-11 12:37:42 +00:00
committed by Aleksander Morgado
parent 224c04065d
commit 63dd4ad263
5 changed files with 108 additions and 132 deletions
+12 -12
View File
@@ -12339,13 +12339,13 @@ typedef enum {
INITIALIZE_STEP_IFACE_3GPP_PROFILE_MANAGER,
INITIALIZE_STEP_IFACE_3GPP_USSD,
INITIALIZE_STEP_IFACE_CDMA,
INITIALIZE_STEP_IFACE_LOCATION,
INITIALIZE_STEP_IFACE_MESSAGING,
INITIALIZE_STEP_IFACE_TIME,
INITIALIZE_STEP_IFACE_SIGNAL,
INITIALIZE_STEP_IFACE_OMA,
INITIALIZE_STEP_IFACE_SAR,
INITIALIZE_STEP_FALLBACK_LIMITED,
INITIALIZE_STEP_IFACE_LOCATION,
INITIALIZE_STEP_IFACE_VOICE,
INITIALIZE_STEP_IFACE_FIRMWARE,
INITIALIZE_STEP_IFACE_SIMPLE,
@@ -12637,14 +12637,6 @@ initialize_step (GTask *task)
ctx->step++;
/* fall through */
case INITIALIZE_STEP_IFACE_LOCATION:
/* Initialize the Location interface */
mm_iface_modem_location_initialize (MM_IFACE_MODEM_LOCATION (ctx->self),
g_task_get_cancellable (task),
(GAsyncReadyCallback)iface_modem_location_initialize_ready,
task);
return;
case INITIALIZE_STEP_IFACE_MESSAGING:
/* Initialize the Messaging interface */
mm_iface_modem_messaging_initialize (MM_IFACE_MODEM_MESSAGING (ctx->self),
@@ -12691,6 +12683,14 @@ initialize_step (GTask *task)
ctx->step++;
/* fall through */
case INITIALIZE_STEP_IFACE_LOCATION:
/* Initialize the Location interface */
mm_iface_modem_location_initialize (MM_IFACE_MODEM_LOCATION (ctx->self),
g_task_get_cancellable (task),
(GAsyncReadyCallback)iface_modem_location_initialize_ready,
task);
return;
case INITIALIZE_STEP_IFACE_VOICE:
/* Initialize the Voice interface */
mm_iface_modem_voice_initialize (MM_IFACE_MODEM_VOICE (ctx->self),
@@ -12731,16 +12731,16 @@ initialize_step (GTask *task)
"Modem in failed state: %s",
mm_modem_state_failed_reason_get_string (reason));
/* Ensure we only leave the Modem, Voice and Firmware interfaces
/* Ensure we only leave the Modem, Voice, Location and Firmware interfaces
* around. A failure could be caused by firmware issues, which
* a firmware update, switch, or provisioning could fix. We also
* leave the Voice interface around so that we can attempt
* emergency voice calls.
* emergency voice calls, and the Location interface so that we can use
* GNSS without a SIM card
*/
mm_iface_modem_3gpp_profile_manager_shutdown (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (ctx->self));
mm_iface_modem_3gpp_ussd_shutdown (MM_IFACE_MODEM_3GPP_USSD (ctx->self));
mm_iface_modem_cdma_shutdown (MM_IFACE_MODEM_CDMA (ctx->self));
mm_iface_modem_location_shutdown (MM_IFACE_MODEM_LOCATION (ctx->self));
mm_iface_modem_signal_shutdown (MM_IFACE_MODEM_SIGNAL (ctx->self));
mm_iface_modem_messaging_shutdown (MM_IFACE_MODEM_MESSAGING (ctx->self));
mm_iface_modem_time_shutdown (MM_IFACE_MODEM_TIME (ctx->self));
+78 -99
View File
@@ -890,11 +890,11 @@ setup_gathering (MMIfaceModemLocation *self,
/*****************************************************************************/
typedef struct {
MmGdbusModemLocation *skeleton;
MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self;
guint32 sources;
gboolean signal_location;
MMIfaceModemLocation *self;
guint32 sources;
gboolean signal_location;
} HandleSetupContext;
static void
@@ -903,13 +903,13 @@ handle_setup_context_free (HandleSetupContext *ctx)
g_object_unref (ctx->skeleton);
g_object_unref (ctx->invocation);
g_object_unref (ctx->self);
g_free (ctx);
g_slice_free (HandleSetupContext, ctx);
}
static void
setup_gathering_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
HandleSetupContext *ctx)
GAsyncResult *res,
HandleSetupContext *ctx)
{
GError *error = NULL;
@@ -922,15 +922,16 @@ setup_gathering_ready (MMIfaceModemLocation *self,
}
static void
handle_setup_auth_ready (MMBaseModem *self,
GAsyncResult *res,
handle_setup_auth_ready (MMBaseModem *self,
GAsyncResult *res,
HandleSetupContext *ctx)
{
GError *error = NULL;
MMModemState modem_state;
MMModemLocationSource not_supported;
LocationContext *location_ctx;
gchar *str;
GError *error = NULL;
MMModemState modem_state;
MMModemLocationSource not_supported;
MMModemLocationSource require_enabled;
LocationContext *location_ctx;
g_autofree gchar *str = NULL;
if (!mm_base_modem_authorize_finish (self, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error);
@@ -938,17 +939,6 @@ handle_setup_auth_ready (MMBaseModem *self,
return;
}
modem_state = MM_MODEM_STATE_UNKNOWN;
g_object_get (self,
MM_IFACE_MODEM_STATE, &modem_state,
NULL);
if (modem_state < MM_MODEM_STATE_ENABLED) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot setup location: device not yet enabled");
handle_setup_context_free (ctx);
return;
}
/* If any of the location sources being enabled is NOT supported, set error */
not_supported = ((mm_gdbus_modem_location_get_capabilities (ctx->skeleton) ^ ctx->sources) & ctx->sources);
if (not_supported != MM_MODEM_LOCATION_SOURCE_NONE) {
@@ -956,7 +946,26 @@ handle_setup_auth_ready (MMBaseModem *self,
mm_dbus_method_invocation_return_error (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
"Cannot enable unsupported location sources: '%s'", str);
handle_setup_context_free (ctx);
g_free (str);
return;
}
modem_state = MM_MODEM_STATE_UNKNOWN;
g_object_get (self,
MM_IFACE_MODEM_STATE, &modem_state,
NULL);
/* Location sources that require any kind of network access may be
* enabled only when the modem is enabled. Generic standalone GPS may be
* enabled even without a SIM card */
require_enabled = ctx->sources & (MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI |
MM_MODEM_LOCATION_SOURCE_CDMA_BS |
MM_MODEM_LOCATION_SOURCE_AGPS_MSA |
MM_MODEM_LOCATION_SOURCE_AGPS_MSB);
if (require_enabled && (modem_state < MM_MODEM_STATE_ENABLED)) {
str = mm_modem_location_source_build_string_from_mask (require_enabled);
mm_dbus_method_invocation_return_error (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot enable location '%s': device not yet enabled", str);
handle_setup_context_free (ctx);
return;
}
@@ -983,7 +992,6 @@ handle_setup_auth_ready (MMBaseModem *self,
str = mm_modem_location_source_build_string_from_mask (ctx->sources);
mm_obj_dbg (self, "setting up location sources: '%s'", str);
g_free (str);
/* Go on to enable or disable the requested sources */
setup_gathering (ctx->self,
@@ -993,15 +1001,15 @@ handle_setup_auth_ready (MMBaseModem *self,
}
static gboolean
handle_setup (MmGdbusModemLocation *skeleton,
handle_setup (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation,
guint32 sources,
gboolean signal_location,
MMIfaceModemLocation *self)
guint32 sources,
gboolean signal_location,
MMIfaceModemLocation *self)
{
HandleSetupContext *ctx;
ctx = g_new (HandleSetupContext, 1);
ctx = g_slice_new0 (HandleSetupContext);
ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self);
@@ -1019,10 +1027,10 @@ handle_setup (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
typedef struct {
MmGdbusModemLocation *skeleton;
MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self;
gchar *supl;
MMIfaceModemLocation *self;
gchar *supl;
} HandleSetSuplServerContext;
static void
@@ -1036,8 +1044,8 @@ handle_set_supl_server_context_free (HandleSetSuplServerContext *ctx)
}
static void
set_supl_server_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
set_supl_server_ready (MMIfaceModemLocation *self,
GAsyncResult *res,
HandleSetSuplServerContext *ctx)
{
GError *error = NULL;
@@ -1053,12 +1061,11 @@ set_supl_server_ready (MMIfaceModemLocation *self,
}
static void
handle_set_supl_server_auth_ready (MMBaseModem *self,
GAsyncResult *res,
handle_set_supl_server_auth_ready (MMBaseModem *self,
GAsyncResult *res,
HandleSetSuplServerContext *ctx)
{
GError *error = NULL;
MMModemState modem_state;
if (!mm_base_modem_authorize_finish (self, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error);
@@ -1066,17 +1073,6 @@ handle_set_supl_server_auth_ready (MMBaseModem *self,
return;
}
modem_state = MM_MODEM_STATE_UNKNOWN;
g_object_get (self,
MM_IFACE_MODEM_STATE, &modem_state,
NULL);
if (modem_state < MM_MODEM_STATE_ENABLED) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot set SUPL server: device not yet enabled");
handle_set_supl_server_context_free (ctx);
return;
}
/* If A-GPS is NOT supported, set error */
if (!(mm_gdbus_modem_location_get_capabilities (ctx->skeleton) & (MM_MODEM_LOCATION_SOURCE_AGPS_MSA | MM_MODEM_LOCATION_SOURCE_AGPS_MSB))) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
@@ -1109,14 +1105,14 @@ handle_set_supl_server_auth_ready (MMBaseModem *self,
}
static gboolean
handle_set_supl_server (MmGdbusModemLocation *skeleton,
handle_set_supl_server (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation,
const gchar *supl,
MMIfaceModemLocation *self)
const gchar *supl,
MMIfaceModemLocation *self)
{
HandleSetSuplServerContext *ctx;
ctx = g_slice_new (HandleSetSuplServerContext);
ctx = g_slice_new0 (HandleSetSuplServerContext);
ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self);
@@ -1160,7 +1156,6 @@ inject_assistance_data_ready (MMIfaceModemLocation *self,
mm_dbus_method_invocation_take_error (ctx->invocation, error);
else
mm_gdbus_modem_location_complete_inject_assistance_data (ctx->skeleton, ctx->invocation);
handle_inject_assistance_data_context_free (ctx);
}
@@ -1214,7 +1209,7 @@ handle_inject_assistance_data (MmGdbusModemLocation *skeleton,
{
HandleInjectAssistanceDataContext *ctx;
ctx = g_slice_new (HandleInjectAssistanceDataContext);
ctx = g_slice_new0 (HandleInjectAssistanceDataContext);
ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self);
@@ -1231,9 +1226,9 @@ handle_inject_assistance_data (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
typedef struct {
MmGdbusModemLocation *skeleton;
MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self;
MMIfaceModemLocation *self;
guint rate;
} HandleSetGpsRefreshRateContext;
@@ -1247,12 +1242,11 @@ handle_set_gps_refresh_rate_context_free (HandleSetGpsRefreshRateContext *ctx)
}
static void
handle_set_gps_refresh_rate_auth_ready (MMBaseModem *self,
GAsyncResult *res,
handle_set_gps_refresh_rate_auth_ready (MMBaseModem *self,
GAsyncResult *res,
HandleSetGpsRefreshRateContext *ctx)
{
GError *error = NULL;
MMModemState modem_state;
if (!mm_base_modem_authorize_finish (self, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error);
@@ -1260,17 +1254,6 @@ handle_set_gps_refresh_rate_auth_ready (MMBaseModem *self,
return;
}
modem_state = MM_MODEM_STATE_UNKNOWN;
g_object_get (self,
MM_IFACE_MODEM_STATE, &modem_state,
NULL);
if (modem_state < MM_MODEM_STATE_ENABLED) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot set SUPL server: device not yet enabled");
handle_set_gps_refresh_rate_context_free (ctx);
return;
}
/* If GPS is NOT supported, set error */
if (!(mm_gdbus_modem_location_get_capabilities (ctx->skeleton) & ((MM_MODEM_LOCATION_SOURCE_GPS_RAW |
MM_MODEM_LOCATION_SOURCE_GPS_NMEA)))) {
@@ -1287,14 +1270,14 @@ handle_set_gps_refresh_rate_auth_ready (MMBaseModem *self,
}
static gboolean
handle_set_gps_refresh_rate (MmGdbusModemLocation *skeleton,
handle_set_gps_refresh_rate (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation,
guint rate,
MMIfaceModemLocation *self)
guint rate,
MMIfaceModemLocation *self)
{
HandleSetGpsRefreshRateContext *ctx;
ctx = g_slice_new (HandleSetGpsRefreshRateContext);
ctx = g_slice_new0 (HandleSetGpsRefreshRateContext);
ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self);
@@ -1311,9 +1294,9 @@ handle_set_gps_refresh_rate (MmGdbusModemLocation *skeleton,
/*****************************************************************************/
typedef struct {
MmGdbusModemLocation *skeleton;
MmGdbusModemLocation *skeleton;
GDBusMethodInvocation *invocation;
MMIfaceModemLocation *self;
MMIfaceModemLocation *self;
} HandleGetLocationContext;
static void
@@ -1322,17 +1305,16 @@ handle_get_location_context_free (HandleGetLocationContext *ctx)
g_object_unref (ctx->skeleton);
g_object_unref (ctx->invocation);
g_object_unref (ctx->self);
g_free (ctx);
g_slice_free (HandleGetLocationContext, ctx);
}
static void
handle_get_location_auth_ready (MMBaseModem *self,
GAsyncResult *res,
handle_get_location_auth_ready (MMBaseModem *self,
GAsyncResult *res,
HandleGetLocationContext *ctx)
{
MMModemState modem_state;
LocationContext *location_ctx;
GError *error = NULL;
GError *error = NULL;
if (!mm_base_modem_authorize_finish (self, res, &error)) {
mm_dbus_method_invocation_take_error (ctx->invocation, error);
@@ -1340,17 +1322,6 @@ handle_get_location_auth_ready (MMBaseModem *self,
return;
}
modem_state = MM_MODEM_STATE_UNKNOWN;
g_object_get (self,
MM_IFACE_MODEM_STATE, &modem_state,
NULL);
if (modem_state < MM_MODEM_STATE_ENABLED) {
mm_dbus_method_invocation_return_error_literal (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
"Cannot get location: device not yet enabled");
handle_get_location_context_free (ctx);
return;
}
location_ctx = get_location_context (ctx->self);
mm_gdbus_modem_location_complete_get_location (
ctx->skeleton,
@@ -1364,13 +1335,13 @@ handle_get_location_auth_ready (MMBaseModem *self,
}
static gboolean
handle_get_location (MmGdbusModemLocation *skeleton,
handle_get_location (MmGdbusModemLocation *skeleton,
GDBusMethodInvocation *invocation,
MMIfaceModemLocation *self)
MMIfaceModemLocation *self)
{
HandleGetLocationContext *ctx;
ctx = g_new (HandleGetLocationContext, 1);
ctx = g_slice_new0 (HandleGetLocationContext);
ctx->skeleton = g_object_ref (skeleton);
ctx->invocation = g_object_ref (invocation);
ctx->self = g_object_ref (self);
@@ -1450,6 +1421,10 @@ interface_disabling_step (GTask *task)
/* fall through */
case DISABLING_STEP_DISABLE_GATHERING:
/* We disable all sources here. It is true that the user may have enabled GPS
* early before getting the modem enabled, and that we may have left it active
* once the modem transitions to enabled state, but for the disabling phase
* we reset everything. */
setup_gathering (self,
MM_MODEM_LOCATION_SOURCE_NONE,
(GAsyncReadyCallback)disabling_location_gathering_ready,
@@ -1573,6 +1548,7 @@ interface_enabling_step (GTask *task)
case ENABLING_STEP_ENABLE_GATHERING: {
MMModemLocationSource default_sources;
MMModemLocationSource currently_enabled;
/* By default, we'll enable all NON-GPS sources */
default_sources = mm_gdbus_modem_location_get_capabilities (ctx->skeleton);
@@ -1582,8 +1558,11 @@ interface_enabling_step (GTask *task)
MM_MODEM_LOCATION_SOURCE_AGPS_MSA |
MM_MODEM_LOCATION_SOURCE_AGPS_MSB);
/* If standalone GPS was already enabled, we keep it enabled */
currently_enabled = mm_gdbus_modem_location_get_enabled (ctx->skeleton);
setup_gathering (self,
default_sources,
default_sources | currently_enabled,
(GAsyncReadyCallback)enabling_location_gathering_ready,
task);
return;