Merge request !1383 from '1-24-suspend-bearer-timeout'
[1.24] base-manager: increase suspend timeout for each active bearer/disable unsolicited 3GPP events during quick suspend/resume https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1383
This commit is contained in:
+17
-7
@@ -64,10 +64,14 @@ sleeping_cb (MMSleepMonitor *sleep_monitor,
|
||||
{
|
||||
if (mm_context_get_test_low_power_suspend_resume ()) {
|
||||
mm_dbg ("removing devices and setting them in low power mode... (sleeping)");
|
||||
mm_base_manager_shutdown (manager, TRUE, TRUE, TRUE, ctx);
|
||||
mm_base_manager_cleanup (manager,
|
||||
MM_BASE_MANAGER_CLEANUP_DISABLE |
|
||||
MM_BASE_MANAGER_CLEANUP_LOW_POWER |
|
||||
MM_BASE_MANAGER_CLEANUP_REMOVE,
|
||||
ctx);
|
||||
} else {
|
||||
mm_dbg ("removing devices... (sleeping)");
|
||||
mm_base_manager_shutdown (manager, FALSE, FALSE, TRUE, ctx);
|
||||
mm_base_manager_cleanup (manager, MM_BASE_MANAGER_CLEANUP_REMOVE, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,11 +88,15 @@ sleeping_quick_cb (MMSleepMonitor *sleep_monitor,
|
||||
{
|
||||
if (mm_context_get_test_low_power_suspend_resume ()) {
|
||||
mm_dbg ("setting modem in low power mode... (sleeping)");
|
||||
mm_base_manager_shutdown (manager, TRUE, TRUE, FALSE, ctx);
|
||||
mm_base_manager_cleanup (manager,
|
||||
MM_BASE_MANAGER_CLEANUP_DISABLE |
|
||||
MM_BASE_MANAGER_CLEANUP_LOW_POWER,
|
||||
ctx);
|
||||
} else {
|
||||
/* Don't need to wait for anything; just suspend */
|
||||
mm_dbg ("leaving modem powered... (sleeping)");
|
||||
mm_sleep_context_complete (ctx, NULL);
|
||||
mm_dbg ("setting modem in terse mode... (only send important signals (call/text))");
|
||||
mm_base_manager_cleanup (manager,
|
||||
MM_BASE_MANAGER_CLEANUP_TERSE,
|
||||
ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +276,9 @@ main (int argc, char *argv[])
|
||||
(GCallback)shutdown_done,
|
||||
inner);
|
||||
|
||||
mm_base_manager_shutdown (manager, TRUE, FALSE, TRUE, ctx);
|
||||
mm_base_manager_cleanup (manager,
|
||||
MM_BASE_MANAGER_CLEANUP_DISABLE | MM_BASE_MANAGER_CLEANUP_REMOVE,
|
||||
ctx);
|
||||
|
||||
/* Wait for all modems to be disabled and removed, but don't wait
|
||||
* forever: if disabling the modems takes longer than 20s, just
|
||||
|
||||
+157
-96
@@ -17,6 +17,8 @@
|
||||
* Copyright (C) 2011 - 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#include "gio/gio.h"
|
||||
#include "glib.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
@@ -870,48 +872,42 @@ mm_base_manager_start (MMBaseManager *self,
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
DEVICE_SHUTDOWN_STEP_FIRST = 0,
|
||||
DEVICE_SHUTDOWN_STEP_DISABLE,
|
||||
DEVICE_SHUTDOWN_STEP_LOW_POWER,
|
||||
DEVICE_SHUTDOWN_STEP_REMOVE,
|
||||
DEVICE_SHUTDOWN_STEP_LAST,
|
||||
} DeviceShutdownStep;
|
||||
DEVICE_CLEANUP_STEP_FIRST = 0,
|
||||
DEVICE_CLEANUP_STEP_DISABLE,
|
||||
DEVICE_CLEANUP_STEP_LOW_POWER,
|
||||
DEVICE_CLEANUP_STEP_REMOVE,
|
||||
DEVICE_CLEANUP_STEP_TERSE,
|
||||
DEVICE_CLEANUP_STEP_LAST,
|
||||
} DeviceCleanupStep;
|
||||
|
||||
typedef struct {
|
||||
MMBaseModem *modem;
|
||||
gboolean disable;
|
||||
gboolean low_power;
|
||||
gboolean remove;
|
||||
MMBaseModem *modem;
|
||||
MMBaseManagerCleanupFlags flags;
|
||||
DeviceCleanupStep step;
|
||||
} DeviceCleanupContext;
|
||||
|
||||
DeviceShutdownStep step;
|
||||
} DeviceShutdownContext;
|
||||
static void device_cleanup_step (GTask *task);
|
||||
|
||||
static void device_shutdown_step (GTask *task);
|
||||
|
||||
static DeviceShutdownContext *
|
||||
device_shutdown_context_new (MMBaseModem *modem,
|
||||
gboolean disable,
|
||||
gboolean low_power,
|
||||
gboolean remove)
|
||||
static DeviceCleanupContext *
|
||||
device_cleanup_context_new (MMBaseModem *modem,
|
||||
MMBaseManagerCleanupFlags flags)
|
||||
{
|
||||
DeviceShutdownContext *ctx;
|
||||
DeviceCleanupContext *ctx;
|
||||
|
||||
ctx = g_slice_new0 (DeviceShutdownContext);
|
||||
ctx = g_slice_new0 (DeviceCleanupContext);
|
||||
if (modem)
|
||||
ctx->modem = g_object_ref (modem);
|
||||
ctx->step = DEVICE_SHUTDOWN_STEP_FIRST;
|
||||
ctx->disable = disable;
|
||||
ctx->low_power = low_power;
|
||||
ctx->remove = remove;
|
||||
ctx->step = DEVICE_CLEANUP_STEP_FIRST;
|
||||
ctx->flags = flags;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
device_shutdown_context_free (DeviceShutdownContext *ctx)
|
||||
device_cleanup_context_free (DeviceCleanupContext *ctx)
|
||||
{
|
||||
g_clear_object (&ctx->modem);
|
||||
g_slice_free (DeviceShutdownContext, ctx);
|
||||
g_slice_free (DeviceCleanupContext, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -919,7 +915,7 @@ modem_remove_ready (MMDevice *device,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
DeviceShutdownContext *ctx;
|
||||
DeviceCleanupContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
@@ -928,15 +924,15 @@ modem_remove_ready (MMDevice *device,
|
||||
mm_obj_warn (device, "removing modem failed: %s", error->message);
|
||||
|
||||
ctx->step++;
|
||||
device_shutdown_step (task);
|
||||
device_cleanup_step (task);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_low_power_ready (MMIfaceModem *modem,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
cleanup_low_power_ready (MMIfaceModem *modem,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
DeviceShutdownContext *ctx;
|
||||
DeviceCleanupContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
@@ -945,15 +941,15 @@ shutdown_low_power_ready (MMIfaceModem *modem,
|
||||
mm_obj_info (modem, "changing to low power state failed: %s", error->message);
|
||||
|
||||
ctx->step++;
|
||||
device_shutdown_step (task);
|
||||
device_cleanup_step (task);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_disable_ready (MMBaseModem *modem,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
cleanup_disable_ready (MMBaseModem *modem,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
DeviceShutdownContext *ctx;
|
||||
DeviceCleanupContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
@@ -966,57 +962,83 @@ shutdown_disable_ready (MMBaseModem *modem,
|
||||
/* If disabling failed there's no point in trying to low-power the
|
||||
* modem; just remove it.
|
||||
*/
|
||||
ctx->step = DEVICE_SHUTDOWN_STEP_REMOVE;
|
||||
ctx->step = DEVICE_CLEANUP_STEP_REMOVE;
|
||||
}
|
||||
|
||||
device_shutdown_step (task);
|
||||
device_cleanup_step (task);
|
||||
}
|
||||
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
static void
|
||||
cleanup_terse_ready (MMBaseModem *modem,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
DeviceCleanupContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
if (!mm_base_modem_terse_finish (modem, res, &error))
|
||||
mm_obj_info (modem, "setting terse failed: %s", error->message);
|
||||
|
||||
ctx->step++;
|
||||
|
||||
device_cleanup_step (task);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
has_cleanup_flag (MMBaseManagerCleanupFlags flags,
|
||||
MMBaseManagerCleanupFlags expected)
|
||||
{
|
||||
return flags & expected;
|
||||
}
|
||||
|
||||
static void
|
||||
device_shutdown_step (GTask *task)
|
||||
device_cleanup_step (GTask *task)
|
||||
{
|
||||
DeviceShutdownContext *ctx;
|
||||
DeviceCleanupContext *ctx;
|
||||
MMDevice *device;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
device = g_task_get_source_object (task);
|
||||
|
||||
switch (ctx->step) {
|
||||
case DEVICE_SHUTDOWN_STEP_FIRST:
|
||||
case DEVICE_CLEANUP_STEP_FIRST:
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case DEVICE_SHUTDOWN_STEP_DISABLE:
|
||||
if (ctx->disable && ctx->modem) {
|
||||
case DEVICE_CLEANUP_STEP_DISABLE:
|
||||
if (ctx->modem && has_cleanup_flag (ctx->flags, MM_BASE_MANAGER_CLEANUP_DISABLE)) {
|
||||
mm_obj_dbg (device,
|
||||
"disabling modem%d",
|
||||
mm_base_modem_get_dbus_id (ctx->modem));
|
||||
mm_base_modem_disable (ctx->modem,
|
||||
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED,
|
||||
MM_BASE_MODEM_OPERATION_PRIORITY_OVERRIDE,
|
||||
(GAsyncReadyCallback)shutdown_disable_ready,
|
||||
(GAsyncReadyCallback)cleanup_disable_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case DEVICE_SHUTDOWN_STEP_LOW_POWER:
|
||||
if (ctx->low_power && ctx->modem) {
|
||||
case DEVICE_CLEANUP_STEP_LOW_POWER:
|
||||
if (ctx->modem && has_cleanup_flag (ctx->flags, MM_BASE_MANAGER_CLEANUP_LOW_POWER)) {
|
||||
mm_obj_dbg (device,
|
||||
"setting modem%d to low-power state",
|
||||
mm_base_modem_get_dbus_id (ctx->modem));
|
||||
mm_iface_modem_set_power_state (MM_IFACE_MODEM (ctx->modem),
|
||||
MM_MODEM_POWER_STATE_LOW,
|
||||
(GAsyncReadyCallback)shutdown_low_power_ready,
|
||||
(GAsyncReadyCallback)cleanup_low_power_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case DEVICE_SHUTDOWN_STEP_REMOVE:
|
||||
if (ctx->remove && ctx->modem) {
|
||||
case DEVICE_CLEANUP_STEP_REMOVE:
|
||||
if (ctx->modem && has_cleanup_flag (ctx->flags, MM_BASE_MANAGER_CLEANUP_REMOVE)) {
|
||||
mm_obj_dbg (device,
|
||||
"removing modem%d",
|
||||
mm_base_modem_get_dbus_id (ctx->modem));
|
||||
@@ -1028,8 +1050,26 @@ device_shutdown_step (GTask *task)
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case DEVICE_SHUTDOWN_STEP_LAST:
|
||||
mm_obj_dbg (device, "device shutdown complete");
|
||||
case DEVICE_CLEANUP_STEP_TERSE:
|
||||
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
if (ctx->modem && has_cleanup_flag (ctx->flags, MM_BASE_MANAGER_CLEANUP_TERSE)) {
|
||||
mm_obj_dbg(device,
|
||||
"settting terse on modem%d",
|
||||
mm_base_modem_get_dbus_id (ctx->modem));
|
||||
mm_base_modem_terse (ctx->modem,
|
||||
MM_BASE_MODEM_OPERATION_LOCK_REQUIRED,
|
||||
(GAsyncReadyCallback)cleanup_terse_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case DEVICE_CLEANUP_STEP_LAST:
|
||||
mm_obj_dbg (device, "device cleanup complete");
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
@@ -1046,25 +1086,25 @@ typedef struct {
|
||||
GSList *tasks;
|
||||
GSList *devices_to_remove;
|
||||
MMSleepContext *sleep_ctx;
|
||||
} ManagerShutdownContext;
|
||||
} ManagerCleanupContext;
|
||||
|
||||
static ManagerShutdownContext *
|
||||
manager_shutdown_context_new (MMBaseManager *self,
|
||||
MMSleepContext *sleep_ctx)
|
||||
static ManagerCleanupContext *
|
||||
manager_cleanup_context_new (MMBaseManager *self,
|
||||
MMSleepContext *sleep_ctx)
|
||||
{
|
||||
ManagerShutdownContext *ctx;
|
||||
ManagerCleanupContext *ctx;
|
||||
|
||||
ctx = g_slice_new0 (ManagerShutdownContext);
|
||||
ctx = g_slice_new0 (ManagerCleanupContext);
|
||||
ctx->self = g_object_ref (self);
|
||||
ctx->sleep_ctx = g_object_ref (sleep_ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void
|
||||
manager_shutdown_context_maybe_complete (ManagerShutdownContext *ctx,
|
||||
GTask *task,
|
||||
MMDevice *device,
|
||||
gboolean remove)
|
||||
manager_cleanup_context_maybe_complete (ManagerCleanupContext *ctx,
|
||||
GTask *task,
|
||||
MMDevice *device,
|
||||
gboolean remove)
|
||||
{
|
||||
if (task)
|
||||
ctx->tasks = g_slist_remove (ctx->tasks, task);
|
||||
@@ -1085,50 +1125,49 @@ manager_shutdown_context_maybe_complete (ManagerShutdownContext *ctx,
|
||||
g_hash_table_remove (ctx->self->priv->devices, mm_device_get_uid (device));
|
||||
g_slist_free (ctx->devices_to_remove);
|
||||
|
||||
mm_obj_dbg (ctx->self, "shutdown complete");
|
||||
mm_obj_dbg (ctx->self, "cleanup complete");
|
||||
mm_sleep_context_complete (ctx->sleep_ctx, NULL);
|
||||
|
||||
g_object_unref (ctx->sleep_ctx);
|
||||
g_object_unref (ctx->self);
|
||||
g_slice_free (ManagerShutdownContext, ctx);
|
||||
g_slice_free (ManagerCleanupContext, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_shutdown_ready (MMDevice *device,
|
||||
GAsyncResult *res,
|
||||
ManagerShutdownContext *ctx)
|
||||
device_cleanup_ready (MMDevice *device,
|
||||
GAsyncResult *res,
|
||||
ManagerCleanupContext *ctx)
|
||||
{
|
||||
GTask *task;
|
||||
DeviceShutdownContext *dctx;
|
||||
DeviceCleanupContext *dctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
gboolean remove;
|
||||
|
||||
task = G_TASK (res);
|
||||
|
||||
if (!g_task_propagate_boolean (task, &error)) {
|
||||
mm_obj_info (ctx->self,
|
||||
"failed to shutdown device %s: %s",
|
||||
"failed to cleanup device %s: %s",
|
||||
mm_device_get_uid (device),
|
||||
error->message);
|
||||
}
|
||||
|
||||
dctx = g_task_get_task_data (task);
|
||||
manager_shutdown_context_maybe_complete (ctx,
|
||||
task,
|
||||
device,
|
||||
dctx->remove);
|
||||
remove = has_cleanup_flag (dctx->flags, MM_BASE_MANAGER_CLEANUP_REMOVE);
|
||||
manager_cleanup_context_maybe_complete (ctx, task, device, remove);
|
||||
}
|
||||
|
||||
void
|
||||
mm_base_manager_shutdown (MMBaseManager *self,
|
||||
gboolean disable,
|
||||
gboolean low_power,
|
||||
gboolean remove,
|
||||
MMSleepContext *sleep_ctx)
|
||||
mm_base_manager_cleanup (MMBaseManager *self,
|
||||
MMBaseManagerCleanupFlags flags,
|
||||
MMSleepContext *sleep_ctx)
|
||||
{
|
||||
ManagerShutdownContext *ctx;
|
||||
ManagerCleanupContext *ctx;
|
||||
GHashTableIter iter;
|
||||
MMDevice *device;
|
||||
gboolean disable, remove, low_power, terse;
|
||||
guint active_bearers = 0;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (MM_IS_BASE_MANAGER (self));
|
||||
@@ -1136,38 +1175,60 @@ mm_base_manager_shutdown (MMBaseManager *self,
|
||||
/* Cancel all ongoing auth requests */
|
||||
g_cancellable_cancel (self->priv->authp_cancellable);
|
||||
|
||||
disable = has_cleanup_flag (flags, MM_BASE_MANAGER_CLEANUP_DISABLE);
|
||||
low_power = has_cleanup_flag (flags, MM_BASE_MANAGER_CLEANUP_LOW_POWER);
|
||||
remove = has_cleanup_flag (flags, MM_BASE_MANAGER_CLEANUP_REMOVE);
|
||||
terse = has_cleanup_flag (flags, MM_BASE_MANAGER_CLEANUP_TERSE);
|
||||
mm_obj_dbg (self,
|
||||
"manager shutting down... (%s%s%s%s%s)",
|
||||
"manager shutting down... (%s%s%s%s%s%s%s)",
|
||||
disable ? "disable" : "",
|
||||
disable && (low_power || remove) ? "," : "",
|
||||
disable && (low_power || remove || terse) ? "," : "",
|
||||
low_power ? "low-power" : "",
|
||||
(low_power && remove) ? "," : "",
|
||||
remove ? "remove" : "");
|
||||
low_power && (remove || terse) ? "," : "",
|
||||
remove ? "remove" : "",
|
||||
(remove && terse) ? "," : "",
|
||||
terse ? "terse" : "");
|
||||
|
||||
ctx = manager_shutdown_context_new (self, sleep_ctx);
|
||||
ctx = manager_cleanup_context_new (self, sleep_ctx);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->priv->devices);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) {
|
||||
DeviceShutdownContext *dctx;
|
||||
GTask *task;
|
||||
DeviceCleanupContext *dctx;
|
||||
GTask *task;
|
||||
MMBaseModem *modem;
|
||||
|
||||
modem = mm_device_peek_modem (device);
|
||||
if (modem) {
|
||||
guint count = 0;
|
||||
|
||||
mm_iface_modem_count_bearers (MM_IFACE_MODEM (modem),
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE,
|
||||
&count,
|
||||
NULL,
|
||||
NULL);
|
||||
active_bearers += count;
|
||||
}
|
||||
|
||||
task = g_task_new (device,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)device_shutdown_ready,
|
||||
(GAsyncReadyCallback)device_cleanup_ready,
|
||||
ctx);
|
||||
ctx->tasks = g_slist_append (ctx->tasks, task);
|
||||
|
||||
dctx = device_shutdown_context_new (mm_device_peek_modem (device),
|
||||
disable,
|
||||
low_power,
|
||||
remove);
|
||||
g_task_set_task_data (task, dctx, (GDestroyNotify)device_shutdown_context_free);
|
||||
dctx = device_cleanup_context_new (modem, flags);
|
||||
g_task_set_task_data (task, dctx, (GDestroyNotify)device_cleanup_context_free);
|
||||
|
||||
device_shutdown_step (task);
|
||||
device_cleanup_step (task);
|
||||
}
|
||||
|
||||
/* Complete shutdown if there were no devices */
|
||||
manager_shutdown_context_maybe_complete (ctx, NULL, NULL, FALSE);
|
||||
/* Increase cleanup timeout for each connected bearer; disconnecting a
|
||||
* bearer can take many seconds.
|
||||
*/
|
||||
if (active_bearers)
|
||||
mm_sleep_context_timeout_backoff (sleep_ctx, active_bearers * 20);
|
||||
|
||||
/* Complete cleanup if there were no devices */
|
||||
manager_cleanup_context_maybe_complete (ctx, NULL, NULL, FALSE);
|
||||
}
|
||||
|
||||
guint32
|
||||
|
||||
+11
-5
@@ -72,11 +72,17 @@ MMBaseManager *mm_base_manager_new (GDBusConnection *bus,
|
||||
void mm_base_manager_start (MMBaseManager *manager,
|
||||
gboolean manual_scan);
|
||||
|
||||
void mm_base_manager_shutdown (MMBaseManager *manager,
|
||||
gboolean disable,
|
||||
gboolean power_low,
|
||||
gboolean remove,
|
||||
MMSleepContext *ctx);
|
||||
typedef enum {
|
||||
MM_BASE_MANAGER_CLEANUP_NONE = 0x0,
|
||||
MM_BASE_MANAGER_CLEANUP_DISABLE = 0x1,
|
||||
MM_BASE_MANAGER_CLEANUP_LOW_POWER = 0x2,
|
||||
MM_BASE_MANAGER_CLEANUP_REMOVE = 0x4,
|
||||
MM_BASE_MANAGER_CLEANUP_TERSE = 0x8,
|
||||
} MMBaseManagerCleanupFlags;
|
||||
|
||||
void mm_base_manager_cleanup (MMBaseManager *manager,
|
||||
MMBaseManagerCleanupFlags flags,
|
||||
MMSleepContext *ctx);
|
||||
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
void mm_base_manager_sync (MMBaseManager *manager);
|
||||
|
||||
@@ -730,6 +730,7 @@ typedef enum {
|
||||
STATE_OPERATION_TYPE_DISABLE,
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
STATE_OPERATION_TYPE_SYNC,
|
||||
STATE_OPERATION_TYPE_TERSE,
|
||||
#endif
|
||||
} StateOperationType;
|
||||
|
||||
@@ -855,6 +856,12 @@ state_operation (MMBaseModem *self,
|
||||
ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->sync;
|
||||
ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->sync_finish;
|
||||
break;
|
||||
case STATE_OPERATION_TYPE_TERSE:
|
||||
operation_description = "terse";
|
||||
optional = TRUE;
|
||||
ctx->operation = MM_BASE_MODEM_GET_CLASS (self)->terse;
|
||||
ctx->operation_finish = MM_BASE_MODEM_GET_CLASS (self)->terse_finish;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -909,6 +916,28 @@ mm_base_modem_sync (MMBaseModem *self,
|
||||
user_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_base_modem_terse_finish (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return state_operation_finish (self, res, error);
|
||||
}
|
||||
|
||||
void
|
||||
mm_base_modem_terse (MMBaseModem *self,
|
||||
MMBaseModemOperationLock operation_lock,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
state_operation (self,
|
||||
STATE_OPERATION_TYPE_TERSE,
|
||||
operation_lock,
|
||||
MM_BASE_MODEM_OPERATION_PRIORITY_DEFAULT,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
#endif /* WITH_SUSPEND_RESUME */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
+23
-7
@@ -109,6 +109,15 @@ struct _MMBaseModemClass {
|
||||
* this method triggers a synchronization of all modem interfaces */
|
||||
StateOperation sync;
|
||||
StateOperationFinish sync_finish;
|
||||
|
||||
/* Modem terse.
|
||||
* When suspending in quick suspend/resume mode,
|
||||
* this method disables unsolicited events on the 3GPP interface only.
|
||||
* This is enough for phones to suspend properly, but it
|
||||
* might be useful to extend it to all other interfaces
|
||||
* that support it as well */
|
||||
StateOperation terse;
|
||||
StateOperationFinish terse_finish;
|
||||
#endif
|
||||
|
||||
/* Allow plugins to subclass port object creation as needed */
|
||||
@@ -298,13 +307,20 @@ gboolean mm_base_modem_disable_finish (MMBaseModem *self,
|
||||
GError **error);
|
||||
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
void mm_base_modem_sync (MMBaseModem *self,
|
||||
MMBaseModemOperationLock operation_lock,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_base_modem_sync_finish (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
void mm_base_modem_sync (MMBaseModem *self,
|
||||
MMBaseModemOperationLock operation_lock,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_base_modem_sync_finish (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
void mm_base_modem_terse (MMBaseModem *self,
|
||||
MMBaseModemOperationLock operation_lock,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_base_modem_terse_finish (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
#endif
|
||||
|
||||
void mm_base_modem_teardown_ports (MMBaseModem *self,
|
||||
|
||||
@@ -1458,10 +1458,11 @@ load_settings_from_bearer (MMBearerMbim *self,
|
||||
guint max_multiplexed_bearers;
|
||||
const gchar *data_port_driver;
|
||||
|
||||
if (!mm_broadband_modem_get_active_multiplexed_bearers (MM_BROADBAND_MODEM (ctx->modem),
|
||||
¤t_multiplexed_bearers,
|
||||
&max_multiplexed_bearers,
|
||||
error))
|
||||
if (!mm_iface_modem_count_bearers (MM_IFACE_MODEM (ctx->modem),
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED,
|
||||
¤t_multiplexed_bearers,
|
||||
&max_multiplexed_bearers,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* Check multiplex support in the kernel and the device */
|
||||
|
||||
+5
-4
@@ -2424,10 +2424,11 @@ load_settings_from_bearer (MMBearerQmi *self,
|
||||
guint max_multiplexed_bearers;
|
||||
gboolean multiplex_supported = TRUE;
|
||||
|
||||
if (!mm_broadband_modem_get_active_multiplexed_bearers (MM_BROADBAND_MODEM (ctx->modem),
|
||||
¤t_multiplexed_bearers,
|
||||
&max_multiplexed_bearers,
|
||||
error))
|
||||
if (!mm_iface_modem_count_bearers (MM_IFACE_MODEM (ctx->modem),
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED,
|
||||
¤t_multiplexed_bearers,
|
||||
&max_multiplexed_bearers,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
/* Check multiplex support in the kernel and the device */
|
||||
|
||||
+99
-46
@@ -13158,6 +13158,103 @@ synchronize (MMBaseModem *self,
|
||||
syncing_step (task);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
TERSE_STEP_FIRST,
|
||||
TERSE_STEP_DISABLE_UNSOLICITED_EVENTS_3GPP,
|
||||
TERSE_STEP_LAST,
|
||||
} TerseStep;
|
||||
|
||||
typedef struct {
|
||||
TerseStep step;
|
||||
} TerseContext;
|
||||
|
||||
static void terse_step (GTask *task);
|
||||
|
||||
static gboolean
|
||||
terse_finish (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
static void
|
||||
iface_modem_3gpp_terse_ready (MMIfaceModem3gpp *self,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
TerseContext *ctx;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
if (!mm_iface_modem_3gpp_terse_finish (self, res, &error))
|
||||
mm_obj_warn (self, "3GPP interface disable unsolicited events failed: %s", error->message);
|
||||
|
||||
/* Go on to next step */
|
||||
ctx->step++;
|
||||
terse_step (task);
|
||||
}
|
||||
|
||||
static void
|
||||
terse_step (GTask *task)
|
||||
{
|
||||
MMBroadbandModem *self;
|
||||
TerseContext *ctx;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
switch (ctx->step) {
|
||||
case TERSE_STEP_FIRST:
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case TERSE_STEP_DISABLE_UNSOLICITED_EVENTS_3GPP:
|
||||
if (self->priv->modem_3gpp_dbus_skeleton &&
|
||||
(self->priv->modem_state >= MM_MODEM_STATE_ENABLED)) {
|
||||
mm_obj_msg (self, "terse state (%d/%d): 3GPP interface disable unsolicited events",
|
||||
ctx->step, TERSE_STEP_LAST);
|
||||
mm_iface_modem_3gpp_terse (MM_IFACE_MODEM_3GPP (self), (GAsyncReadyCallback)iface_modem_3gpp_terse_ready, task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case TERSE_STEP_LAST:
|
||||
mm_obj_msg (self, "setting terse state (%d/%d): all done",
|
||||
ctx->step, TERSE_STEP_LAST);
|
||||
/* We are done without errors! */
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
terse (MMBaseModem *self,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
TerseContext *ctx;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
|
||||
/* Create TerseContext */
|
||||
ctx = g_new0 (TerseContext, 1);
|
||||
ctx->step = TERSE_STEP_FIRST;
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)g_free);
|
||||
|
||||
terse_step (task);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -13702,52 +13799,6 @@ mm_broadband_modem_get_current_charset (MMBroadbandModem *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
bearer_count_multiplexed_connected (MMBaseBearer *bearer,
|
||||
guint *count)
|
||||
{
|
||||
/* The Multiplexed property is only set if connected, so it's enough to check
|
||||
* that one to see if we're connected and multiplexed */
|
||||
if (mm_gdbus_bearer_get_multiplexed (MM_GDBUS_BEARER (bearer)))
|
||||
*count += 1;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_broadband_modem_get_active_multiplexed_bearers (MMBroadbandModem *self,
|
||||
guint *out_current,
|
||||
guint *out_max,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(MMBearerList) list = NULL;
|
||||
guint max;
|
||||
guint count = 0;
|
||||
|
||||
g_object_get (self,
|
||||
MM_IFACE_MODEM_BEARER_LIST, &list,
|
||||
NULL);
|
||||
|
||||
if (!list) {
|
||||
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Bearer list unavailable");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
max = mm_bearer_list_get_max_active_multiplexed (list);
|
||||
|
||||
mm_bearer_list_foreach (list,
|
||||
(MMBearerListForeachFunc)bearer_count_multiplexed_connected,
|
||||
&count);
|
||||
g_assert (!(!max && count));
|
||||
|
||||
if (out_max)
|
||||
*out_max = max;
|
||||
if (out_current)
|
||||
*out_current = count;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gchar *
|
||||
mm_broadband_modem_create_device_identifier (MMBroadbandModem *self,
|
||||
const gchar *ati,
|
||||
@@ -14645,6 +14696,8 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass)
|
||||
#if defined WITH_SUSPEND_RESUME
|
||||
base_modem_class->sync = synchronize;
|
||||
base_modem_class->sync_finish = synchronize_finish;
|
||||
base_modem_class->terse = terse;
|
||||
base_modem_class->terse_finish = terse_finish;
|
||||
#endif
|
||||
|
||||
klass->setup_ports = setup_ports;
|
||||
|
||||
@@ -143,12 +143,6 @@ gboolean mm_broadband_modem_sim_hot_swap_ports_context_init (MMBroadbandModem
|
||||
GError **error);
|
||||
void mm_broadband_modem_sim_hot_swap_ports_context_reset (MMBroadbandModem *self);
|
||||
|
||||
/* Helper to manage multiplexed bearers */
|
||||
gboolean mm_broadband_modem_get_active_multiplexed_bearers (MMBroadbandModem *self,
|
||||
guint *out_current,
|
||||
guint *out_max,
|
||||
GError **error);
|
||||
|
||||
/* Helper to manage initial EPS bearer */
|
||||
gint mm_broadband_modem_get_initial_eps_bearer_cid (MMBroadbandModem *self);
|
||||
|
||||
|
||||
@@ -3232,6 +3232,8 @@ static void interface_syncing_step (GTask *task);
|
||||
|
||||
typedef enum {
|
||||
SYNCING_STEP_FIRST,
|
||||
SYNCING_STEP_ENABLE_UNSOLICITED_EVENTS,
|
||||
SYNCING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS,
|
||||
SYNCING_STEP_REFRESH_3GPP_REGISTRATION,
|
||||
SYNCING_STEP_REFRESH_EPS_BEARER,
|
||||
SYNCING_STEP_LAST
|
||||
@@ -3249,6 +3251,31 @@ mm_iface_modem_3gpp_sync_finish (MMIfaceModem3gpp *self,
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
#undef VOID_SYNC_REPLY_READY_FN
|
||||
#define VOID_SYNC_REPLY_READY_FN(NAME,DISPLAY) \
|
||||
static void \
|
||||
sync_##NAME##_ready (MMIfaceModem3gpp *self, \
|
||||
GAsyncResult *res, \
|
||||
GTask *task) \
|
||||
{ \
|
||||
DisablingContext *ctx; \
|
||||
g_autoptr(GError) error = NULL; \
|
||||
\
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->NAME##_finish (self, res, &error); \
|
||||
if (error) \
|
||||
mm_obj_dbg (self, "couldn't %s: %s", DISPLAY, error->message); \
|
||||
\
|
||||
/* Go on to next step */ \
|
||||
ctx = g_task_get_task_data (task); \
|
||||
ctx->step++; \
|
||||
interface_syncing_step (task); \
|
||||
}
|
||||
|
||||
VOID_SYNC_REPLY_READY_FN (enable_unsolicited_events,
|
||||
"enable unsolicited events")
|
||||
VOID_SYNC_REPLY_READY_FN (enable_unsolicited_registration_events,
|
||||
"enable unsolicited registration events")
|
||||
|
||||
static void
|
||||
sync_eps_bearer_ready (MMIfaceModem3gpp *self,
|
||||
GAsyncResult *res,
|
||||
@@ -3327,6 +3354,33 @@ interface_syncing_step (GTask *task)
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case SYNCING_STEP_ENABLE_UNSOLICITED_EVENTS:
|
||||
if (MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_events &&
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_events_finish) {
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)sync_enable_unsolicited_events_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case SYNCING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS:
|
||||
if (MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_registration_events &&
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_registration_events_finish) {
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->enable_unsolicited_registration_events (
|
||||
self,
|
||||
get_cs_network_supported (self),
|
||||
get_ps_network_supported (self),
|
||||
get_eps_network_supported (self),
|
||||
(GAsyncReadyCallback)sync_enable_unsolicited_registration_events_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case SYNCING_STEP_REFRESH_3GPP_REGISTRATION:
|
||||
/*
|
||||
* Refresh registration info to verify that the modem is still registered.
|
||||
@@ -3381,6 +3435,129 @@ mm_iface_modem_3gpp_sync (MMIfaceModem3gpp *self,
|
||||
interface_syncing_step (task);
|
||||
}
|
||||
|
||||
typedef struct _TerseContext TerseContext;
|
||||
static void interface_terse_step (GTask *task);
|
||||
|
||||
typedef enum {
|
||||
TERSE_STEP_FIRST,
|
||||
TERSE_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS,
|
||||
TERSE_STEP_DISABLE_UNSOLICITED_EVENTS,
|
||||
TERSE_STEP_LAST
|
||||
} TerseStep;
|
||||
|
||||
struct _TerseContext {
|
||||
TerseStep step;
|
||||
};
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_3gpp_terse_finish (MMIfaceModem3gpp *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (res), error);
|
||||
}
|
||||
|
||||
#undef VOID_TERSE_REPLY_READY_FN
|
||||
#define VOID_TERSE_REPLY_READY_FN(NAME,DISPLAY) \
|
||||
static void \
|
||||
terse_##NAME##_ready (MMIfaceModem3gpp *self, \
|
||||
GAsyncResult *res, \
|
||||
GTask *task) \
|
||||
{ \
|
||||
TerseContext *ctx; \
|
||||
g_autoptr(GError) error = NULL; \
|
||||
\
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->NAME##_finish (self, res, &error); \
|
||||
if (error) \
|
||||
mm_obj_dbg (self, "couldn't %s: %s", DISPLAY, error->message); \
|
||||
\
|
||||
/* Go on to next step */ \
|
||||
ctx = g_task_get_task_data (task); \
|
||||
ctx->step++; \
|
||||
interface_terse_step (task); \
|
||||
}
|
||||
|
||||
VOID_TERSE_REPLY_READY_FN (disable_unsolicited_events,
|
||||
"disable unsolicited events")
|
||||
VOID_TERSE_REPLY_READY_FN (disable_unsolicited_registration_events,
|
||||
"disable unsolicited registration events")
|
||||
|
||||
static void
|
||||
interface_terse_step (GTask *task)
|
||||
{
|
||||
MMIfaceModem3gpp *self;
|
||||
TerseContext *ctx;
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
switch (ctx->step) {
|
||||
case TERSE_STEP_FIRST:
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case TERSE_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS:
|
||||
if (MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_registration_events &&
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_registration_events_finish) {
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_registration_events (
|
||||
self,
|
||||
get_cs_network_supported (self),
|
||||
get_ps_network_supported (self),
|
||||
get_eps_network_supported (self),
|
||||
(GAsyncReadyCallback)terse_disable_unsolicited_registration_events_ready,
|
||||
task);
|
||||
mm_obj_msg (self, "terse state 3GPP (%d/%d): disable unsolicited registration events done",
|
||||
ctx->step, TERSE_STEP_LAST);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case TERSE_STEP_DISABLE_UNSOLICITED_EVENTS:
|
||||
if (MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_events &&
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_events_finish) {
|
||||
MM_IFACE_MODEM_3GPP_GET_IFACE (self)->disable_unsolicited_events (
|
||||
self,
|
||||
(GAsyncReadyCallback)terse_disable_unsolicited_events_ready,
|
||||
task);
|
||||
mm_obj_msg (self, "terse state 3GPP (%d/%d): disable unsolicited events done",
|
||||
ctx->step, TERSE_STEP_LAST);
|
||||
return;
|
||||
}
|
||||
ctx->step++;
|
||||
/* fall through */
|
||||
|
||||
case TERSE_STEP_LAST:
|
||||
/* We are done without errors! */
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
void
|
||||
mm_iface_modem_3gpp_terse (MMIfaceModem3gpp *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
TerseContext *ctx;
|
||||
GTask *task;
|
||||
|
||||
/* Create SyncingContext */
|
||||
ctx = g_new0 (TerseContext, 1);
|
||||
ctx->step = TERSE_STEP_FIRST;
|
||||
|
||||
/* Create sync steps task and execute it */
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)g_free);
|
||||
interface_terse_step (task);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -318,6 +318,13 @@ gboolean mm_iface_modem_3gpp_sync_finish (MMIfaceModem3gpp *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
void mm_iface_modem_3gpp_terse (MMIfaceModem3gpp *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean mm_iface_modem_3gpp_terse_finish (MMIfaceModem3gpp *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
#endif
|
||||
|
||||
/* Shutdown Modem 3GPP interface */
|
||||
|
||||
@@ -6720,6 +6720,74 @@ mm_iface_modem_get_current_modes (MMIfaceModem *self,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const MMIfaceModemCountBearersFlags flags;
|
||||
guint count;
|
||||
} CountBearersContext;
|
||||
|
||||
static void
|
||||
bearer_count (MMBaseBearer *bearer,
|
||||
CountBearersContext *ctx)
|
||||
{
|
||||
MMBearerStatus status;
|
||||
|
||||
status = mm_base_bearer_get_status (MM_BASE_BEARER (bearer));
|
||||
|
||||
if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED) {
|
||||
/* The Multiplexed property is only set if connected, so it's enough to check
|
||||
* that one to see if we're connected and multiplexed */
|
||||
if (mm_gdbus_bearer_get_multiplexed (MM_GDBUS_BEARER (bearer)))
|
||||
ctx->count++;
|
||||
} else if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_CONNECTED) {
|
||||
if (status == MM_BEARER_STATUS_CONNECTED)
|
||||
ctx->count++;
|
||||
} else if (ctx->flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE) {
|
||||
if (status >= MM_BEARER_STATUS_CONNECTING)
|
||||
ctx->count++;
|
||||
} else
|
||||
ctx->count++;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mm_iface_modem_count_bearers (MMIfaceModem *self,
|
||||
MMIfaceModemCountBearersFlags flags,
|
||||
guint *out_current,
|
||||
guint *out_max,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(MMBearerList) list = NULL;
|
||||
guint max = 0;
|
||||
CountBearersContext ctx = {
|
||||
.flags = flags,
|
||||
.count = 0,
|
||||
};
|
||||
|
||||
g_object_get (self,
|
||||
MM_IFACE_MODEM_BEARER_LIST, &list,
|
||||
NULL);
|
||||
if (!list) {
|
||||
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Bearer list unavailable");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (flags & MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED)
|
||||
max = mm_bearer_list_get_max_active_multiplexed (list);
|
||||
else
|
||||
max = mm_bearer_list_get_max_active (list);
|
||||
|
||||
mm_bearer_list_foreach (list, (MMBearerListForeachFunc)bearer_count, &ctx);
|
||||
g_assert (max >= ctx.count);
|
||||
|
||||
if (out_max)
|
||||
*out_max = max;
|
||||
if (out_current)
|
||||
*out_current = ctx.count;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
mm_iface_modem_default_init (MMIfaceModemInterface *iface)
|
||||
{
|
||||
|
||||
@@ -620,4 +620,19 @@ void mm_iface_modem_modify_sim (MMIfaceModem *self,
|
||||
|
||||
void mm_iface_modem_process_sim_event (MMIfaceModem *self);
|
||||
|
||||
typedef enum {
|
||||
/* Connecting or connected bearers */
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_ACTIVE = 0x1,
|
||||
/* Fully connected bearers */
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_CONNECTED = 0x2,
|
||||
/* Multiplexed implies connected */
|
||||
MM_IFACE_MODEM_COUNT_BEARERS_FLAG_MULTIPLEXED = 0x4,
|
||||
} MMIfaceModemCountBearersFlags;
|
||||
|
||||
gboolean mm_iface_modem_count_bearers (MMIfaceModem *self,
|
||||
MMIfaceModemCountBearersFlags flags,
|
||||
guint *out_current,
|
||||
guint *out_max,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_IFACE_MODEM_H */
|
||||
|
||||
+30
-3
@@ -27,6 +27,7 @@ G_DEFINE_TYPE_EXTENDED (MMSleepContext, mm_sleep_context, G_TYPE_OBJECT, 0,
|
||||
struct _MMSleepContextPrivate {
|
||||
GTask *task;
|
||||
guint timeout_id;
|
||||
gint64 timeout_start;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -52,6 +53,7 @@ timeout_cleanup (MMSleepContext *self)
|
||||
if (self->priv->timeout_id)
|
||||
g_source_remove (self->priv->timeout_id);
|
||||
self->priv->timeout_id = 0;
|
||||
self->priv->timeout_start = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -95,6 +97,33 @@ operation_ready (MMSleepContext *self,
|
||||
g_signal_emit (self, signals[DONE], 0, error);
|
||||
}
|
||||
|
||||
static void
|
||||
timeout_add (MMSleepContext *self,
|
||||
guint interval)
|
||||
{
|
||||
timeout_cleanup (self);
|
||||
self->priv->timeout_start = g_get_monotonic_time ();
|
||||
self->priv->timeout_id = g_timeout_add_seconds (interval,
|
||||
(GSourceFunc)operation_timeout,
|
||||
self);
|
||||
}
|
||||
|
||||
void
|
||||
mm_sleep_context_timeout_backoff (MMSleepContext *self,
|
||||
guint more_seconds)
|
||||
{
|
||||
gint64 cur_time;
|
||||
gint64 new_interval;
|
||||
|
||||
new_interval = more_seconds * G_USEC_PER_SEC;
|
||||
if (self->priv->timeout_start) {
|
||||
cur_time = g_get_monotonic_time ();
|
||||
new_interval += (cur_time - self->priv->timeout_start);
|
||||
}
|
||||
|
||||
timeout_add (self, new_interval / G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
MMSleepContext *
|
||||
@@ -107,9 +136,7 @@ mm_sleep_context_new (guint timeout_seconds)
|
||||
NULL,
|
||||
(GAsyncReadyCallback)operation_ready,
|
||||
NULL);
|
||||
self->priv->timeout_id = g_timeout_add_seconds (timeout_seconds,
|
||||
(GSourceFunc)operation_timeout,
|
||||
self);
|
||||
timeout_add (self, timeout_seconds);
|
||||
mm_obj_dbg (self, "new context with %d second timeout", timeout_seconds);
|
||||
|
||||
return self;
|
||||
|
||||
@@ -51,6 +51,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMSleepContext, g_object_unref)
|
||||
|
||||
MMSleepContext *mm_sleep_context_new (guint timeout_seconds);
|
||||
|
||||
void mm_sleep_context_timeout_backoff (MMSleepContext *self,
|
||||
guint more_seconds);
|
||||
|
||||
/* The MMSleepContext assumes ownership of @error */
|
||||
void mm_sleep_context_complete (MMSleepContext *self,
|
||||
GError *error);
|
||||
|
||||
Reference in New Issue
Block a user