aboutsummaryrefslogtreecommitdiff
path: root/src/mm-device.c
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2018-12-07 16:12:35 +0100
committerAleksander Morgado <aleksander@aleksander.es>2019-01-03 21:05:58 +0100
commit2212d3e054fbe218c64fa76eeac8480f82d9f623 (patch)
treeb654130c0e9bd7e74498d9a71a81ee3d141e7c13 /src/mm-device.c
parente3766aef5d93d6cfec27432c81da3548bdd18ea6 (diff)
api,manager: new InhibitDevice() method
This new method allows users of the ModemManager API to take full control of a given device. Unlike other operations in the API, the inhibition is maintained as long as the caller exists in the bus, or until the same caller uninhibits the device. https://gitlab.freedesktop.org/mobile-broadband/ModemManager/issues/98
Diffstat (limited to 'src/mm-device.c')
-rw-r--r--src/mm-device.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/mm-device.c b/src/mm-device.c
index 1e53870a..4b3d3066 100644
--- a/src/mm-device.c
+++ b/src/mm-device.c
@@ -36,6 +36,7 @@ enum {
PROP_MODEM,
PROP_HOTPLUGGED,
PROP_VIRTUAL,
+ PROP_INHIBITED,
PROP_LAST
};
@@ -79,6 +80,9 @@ struct _MMDevicePrivate {
/* Whether the device was hot-plugged. */
gboolean hotplugged;
+ /* Whether the device is inhibited. */
+ gboolean inhibited;
+
/* Virtual ports */
gchar **virtual_ports;
};
@@ -370,6 +374,12 @@ mm_device_create_modem (MMDevice *self,
g_assert (self->priv->modem == NULL);
g_assert (self->priv->object_manager == NULL);
+ if (self->priv->inhibited) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Device is inhibited");
+ return FALSE;
+ }
+
if (!self->priv->virtual) {
if (!self->priv->port_probes) {
g_set_error (error,
@@ -520,6 +530,85 @@ mm_device_get_hotplugged (MMDevice *self)
return self->priv->hotplugged;
}
+gboolean
+mm_device_get_inhibited (MMDevice *self)
+{
+ return self->priv->inhibited;
+}
+
+/*****************************************************************************/
+
+gboolean
+mm_device_inhibit_finish (MMDevice *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+inhibit_disable_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMDevice *self;
+ GError *error = NULL;
+
+ self = g_task_get_source_object (task);
+
+ if (!mm_base_modem_disable_finish (modem, res, &error))
+ g_task_return_error (task, error);
+ else {
+ g_cancellable_cancel (mm_base_modem_peek_cancellable (modem));
+ mm_device_remove_modem (self);
+ g_task_return_boolean (task, TRUE);
+ }
+ g_object_unref (task);
+}
+
+void
+mm_device_inhibit (MMDevice *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ /* We want to allow inhibiting only devices that are currently
+ * exported in the bus, because otherwise we may be inhibiting
+ * in the middle of port probing and that may lead to some ports
+ * tracked inside the device object during inhibition and some
+ * other ports tracked in the base manager. So, if the device
+ * does not have a valid modem created and exposed, do not allow
+ * the inhibition. */
+ if (!self->priv->modem || !g_dbus_object_get_object_path (G_DBUS_OBJECT (self->priv->modem))) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
+ "Modem not exported in the bus");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Flag as inhibited right away */
+ g_assert (!self->priv->inhibited);
+ self->priv->inhibited = TRUE;
+
+ /* Make sure modem is disabled while inhibited */
+ mm_base_modem_disable (self->priv->modem,
+ (GAsyncReadyCallback)inhibit_disable_ready,
+ task);
+}
+
+gboolean
+mm_device_uninhibit (MMDevice *self,
+ GDBusObjectManagerServer *object_manager,
+ GError **error)
+{
+ g_assert (self->priv->inhibited);
+ self->priv->inhibited = FALSE;
+ return mm_device_create_modem (self, object_manager, error);
+}
+
/*****************************************************************************/
void
@@ -602,6 +691,9 @@ set_property (GObject *object,
case PROP_VIRTUAL:
self->priv->virtual = g_value_get_boolean (value);
break;
+ case PROP_INHIBITED:
+ self->priv->inhibited = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -632,6 +724,9 @@ get_property (GObject *object,
case PROP_VIRTUAL:
g_value_set_boolean (value, self->priv->virtual);
break;
+ case PROP_INHIBITED:
+ g_value_set_boolean (value, self->priv->inhibited);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -719,6 +814,14 @@ mm_device_class_init (MMDeviceClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_VIRTUAL, properties[PROP_VIRTUAL]);
+ properties[PROP_INHIBITED] =
+ g_param_spec_boolean (MM_DEVICE_INHIBITED,
+ "Inhibited",
+ "Whether the modem is inhibited",
+ FALSE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_INHIBITED, properties[PROP_INHIBITED]);
+
signals[SIGNAL_PORT_GRABBED] =
g_signal_new (MM_DEVICE_PORT_GRABBED,
G_OBJECT_CLASS_TYPE (object_class),