2009-07-27 16:40:11 +01:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
|
|
|
|
*
|
2011-01-04 18:05:09 +00:00
|
|
|
* Copyright (C) 2010 Richard Hughes <richard@hughsie.com>
|
2009-07-27 16:40:11 +01:00
|
|
|
*
|
|
|
|
|
* Licensed under the GNU General Public License Version 2
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2010-01-27 16:27:15 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2009-07-27 16:40:11 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
2010-07-07 11:20:47 +02:00
|
|
|
#include <sys/wait.h>
|
2009-07-27 16:40:11 +01:00
|
|
|
#include <glib/gi18n.h>
|
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
#include <gudev/gudev.h>
|
|
|
|
|
|
2010-01-18 12:26:55 +00:00
|
|
|
#include "up-backend.h"
|
|
|
|
|
#include "up-daemon.h"
|
|
|
|
|
#include "up-marshal.h"
|
|
|
|
|
#include "up-device.h"
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:26:55 +00:00
|
|
|
#include "up-device-supply.h"
|
|
|
|
|
#include "up-device-csr.h"
|
2012-08-07 00:11:19 +02:00
|
|
|
#include "up-device-lg-unifying.h"
|
2010-01-18 12:26:55 +00:00
|
|
|
#include "up-device-wup.h"
|
|
|
|
|
#include "up-device-hid.h"
|
|
|
|
|
#include "up-input.h"
|
2011-01-04 18:05:09 +00:00
|
|
|
#include "up-dock.h"
|
2011-03-14 11:01:12 +00:00
|
|
|
#include "up-config.h"
|
2010-05-28 01:56:35 +01:00
|
|
|
#ifdef HAVE_IDEVICE
|
|
|
|
|
#include "up-device-idevice.h"
|
|
|
|
|
#endif /* HAVE_IDEVICE */
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2012-07-11 15:06:04 +01:00
|
|
|
#include <dbus/dbus-glib.h>
|
|
|
|
|
#include <dbus/dbus-glib-lowlevel.h>
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
|
#include <systemd/sd-daemon.h>
|
|
|
|
|
|
|
|
|
|
#define SD_HIBERNATE_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Hibernate 'true'"
|
|
|
|
|
#define SD_SUSPEND_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Suspend 'true'"
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
static void up_backend_class_init (UpBackendClass *klass);
|
|
|
|
|
static void up_backend_init (UpBackend *backend);
|
|
|
|
|
static void up_backend_finalize (GObject *object);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
#define UP_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_BACKEND, UpBackendPrivate))
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
struct UpBackendPrivate
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
2010-01-18 12:35:47 +00:00
|
|
|
UpDaemon *daemon;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDeviceList *device_list;
|
2009-07-27 16:40:11 +01:00
|
|
|
GUdevClient *gudev_client;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDeviceList *managed_devices;
|
2011-01-04 18:05:09 +00:00
|
|
|
UpDock *dock;
|
2011-03-14 11:01:12 +00:00
|
|
|
UpConfig *config;
|
2012-07-11 15:06:04 +01:00
|
|
|
DBusConnection *connection;
|
2009-07-27 16:40:11 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
SIGNAL_DEVICE_ADDED,
|
|
|
|
|
SIGNAL_DEVICE_REMOVED,
|
2012-07-11 15:06:04 +01:00
|
|
|
SIGNAL_RESUMING,
|
2009-07-27 16:40:11 +01:00
|
|
|
SIGNAL_LAST
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals [SIGNAL_LAST] = { 0 };
|
|
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
G_DEFINE_TYPE (UpBackend, up_backend, G_TYPE_OBJECT)
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
static gboolean up_backend_device_add (UpBackend *backend, GUdevDevice *native);
|
|
|
|
|
static void up_backend_device_remove (UpBackend *backend, GUdevDevice *native);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-07-07 10:07:37 +01:00
|
|
|
#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/pm-suspend"
|
|
|
|
|
#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/pm-hibernate"
|
|
|
|
|
#define UP_BACKEND_POWERSAVE_TRUE_COMMAND "/usr/sbin/pm-powersave true"
|
|
|
|
|
#define UP_BACKEND_POWERSAVE_FALSE_COMMAND "/usr/sbin/pm-powersave false"
|
2010-03-29 16:42:35 +01:00
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_device_new:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
2010-01-18 12:49:30 +00:00
|
|
|
static UpDevice *
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_new (UpBackend *backend, GUdevDevice *native)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
|
|
|
|
const gchar *subsys;
|
|
|
|
|
const gchar *native_path;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDevice *device = NULL;
|
2010-01-18 13:15:47 +00:00
|
|
|
UpInput *input;
|
2009-07-27 16:40:11 +01:00
|
|
|
gboolean ret;
|
|
|
|
|
|
|
|
|
|
subsys = g_udev_device_get_subsystem (native);
|
|
|
|
|
if (g_strcmp0 (subsys, "power_supply") == 0) {
|
|
|
|
|
|
|
|
|
|
/* are we a valid power supply */
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (up_device_supply_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
2009-07-27 16:40:11 +01:00
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
|
|
|
|
|
/* no valid power supply object */
|
|
|
|
|
device = NULL;
|
|
|
|
|
|
|
|
|
|
} else if (g_strcmp0 (subsys, "tty") == 0) {
|
|
|
|
|
|
|
|
|
|
/* try to detect a Watts Up? Pro monitor */
|
2011-03-14 11:01:12 +00:00
|
|
|
ret = up_config_get_boolean (backend->priv->config,
|
|
|
|
|
"EnableWattsUpPro");
|
|
|
|
|
if (ret) {
|
|
|
|
|
device = UP_DEVICE (up_device_wup_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
|
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
}
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2009-09-11 12:05:16 +01:00
|
|
|
/* no valid TTY object */
|
2009-07-27 16:40:11 +01:00
|
|
|
device = NULL;
|
|
|
|
|
|
Fix device matching for recent kernels
In recent kernels, hiddev* devices now have class "usbmisc", rather
than "usb" (see http://www.spinics.net/lists/linux-usb/msg62276.html).
This change translates into a change in SUBSYSTEM matching for hiddev*
devices. This fix addresses this for recent kernels while retaining
existing behavior. For reference, here is an attribute-walk for a
CyberPower CPS 1500C on kernel 3.7.0:
[Ubuntu bug #1091702: udev rules fail to match hid devices with new kernels]
udevadm info --attribute-walk --path=/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0/usbmisc/hiddev0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0/usbmisc/hiddev0':
KERNEL=="hiddev0"
SUBSYSTEM=="usbmisc"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0':
KERNELS=="4-1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usbhid"
ATTRS{bInterfaceClass}=="03"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bNumEndpoints}=="01"
ATTRS{supports_autosuspend}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1':
KERNELS=="4-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1"
ATTRS{idVendor}=="0764"
ATTRS{speed}=="1.5"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{busnum}=="4"
ATTRS{devnum}=="2"
ATTRS{configuration}==""
ATTRS{bMaxPower}==" 50mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="c0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0001"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="36"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="CPS"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0501"
ATTRS{bDeviceClass}=="00"
ATTRS{product}==" CP 1500C"
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4':
KERNELS=="usb4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="0"
ATTRS{idVendor}=="1d6b"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="4"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{bMaxPower}==" 0mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="2"
ATTRS{bcdDevice}=="0307"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{serial}=="0000:00:1d.2"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="50"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 3.7.0-030700-generic uhci_hcd"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0001"
ATTRS{bDeviceClass}=="09"
ATTRS{product}=="UHCI Host Controller"
looking at parent device '/devices/pci0000:00/0000:00:1d.2':
KERNELS=="0000:00:1d.2"
SUBSYSTEMS=="pci"
DRIVERS=="uhci_hcd"
ATTRS{irq}=="18"
ATTRS{subsystem_vendor}=="0x1028"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0300"
ATTRS{consistent_dma_mask_bits}=="32"
ATTRS{dma_mask_bits}=="32"
ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,000000ff"
ATTRS{device}=="0x268a"
ATTRS{msi_bus}==""
ATTRS{local_cpulist}=="0-7"
ATTRS{vendor}=="0x8086"
ATTRS{subsystem_device}=="0x021e"
ATTRS{numa_node}=="-1"
ATTRS{d3cold_allowed}=="0"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Richard Hughes <richard@hughsie.com>
2012-12-23 15:45:01 -05:00
|
|
|
} else if (g_strcmp0 (subsys, "usb") == 0 || g_strcmp0 (subsys, "usbmisc") == 0) {
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-05-28 01:56:35 +01:00
|
|
|
#ifdef HAVE_IDEVICE
|
|
|
|
|
/* see if this is an iDevice */
|
|
|
|
|
device = UP_DEVICE (up_device_idevice_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
|
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
#endif /* HAVE_IDEVICE */
|
|
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
/* see if this is a CSR mouse or keyboard */
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (up_device_csr_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
2009-07-27 16:40:11 +01:00
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
|
|
|
|
|
/* try to detect a HID UPS */
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (up_device_hid_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
2009-07-27 16:40:11 +01:00
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
|
2009-09-11 12:05:16 +01:00
|
|
|
/* no valid USB object */
|
2009-07-27 16:40:11 +01:00
|
|
|
device = NULL;
|
|
|
|
|
|
|
|
|
|
} else if (g_strcmp0 (subsys, "input") == 0) {
|
|
|
|
|
|
|
|
|
|
/* check input device */
|
2010-01-18 13:15:47 +00:00
|
|
|
input = up_input_new ();
|
|
|
|
|
ret = up_input_coldplug (input, backend->priv->daemon, native);
|
2012-08-07 00:11:19 +02:00
|
|
|
if (ret) {
|
|
|
|
|
/* we now have a lid */
|
|
|
|
|
up_daemon_set_lid_is_present (backend->priv->daemon, TRUE);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2012-08-07 00:11:19 +02:00
|
|
|
/* not a power device */
|
|
|
|
|
up_device_list_insert (backend->priv->managed_devices, G_OBJECT (native), G_OBJECT (input));
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2012-08-07 00:11:19 +02:00
|
|
|
/* no valid input object */
|
|
|
|
|
device = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
g_object_unref (input);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2012-08-07 00:11:19 +02:00
|
|
|
/* see if this is a Unifying mouse or keyboard */
|
|
|
|
|
device = UP_DEVICE (up_device_unifying_new ());
|
|
|
|
|
ret = up_device_coldplug (device, backend->priv->daemon, G_OBJECT (native));
|
|
|
|
|
if (!ret) {
|
|
|
|
|
g_object_unref (device);
|
|
|
|
|
/* no valid input object */
|
|
|
|
|
device = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-27 16:40:11 +01:00
|
|
|
} else {
|
|
|
|
|
native_path = g_udev_device_get_sysfs_path (native);
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("native path %s (%s) ignoring", native_path, subsys);
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
out:
|
|
|
|
|
return device;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-11 12:05:16 +01:00
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_device_changed:
|
2009-09-11 12:05:16 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_changed (UpBackend *backend, GUdevDevice *native)
|
2009-09-11 12:05:16 +01:00
|
|
|
{
|
|
|
|
|
GObject *object;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDevice *device;
|
2009-09-11 12:05:16 +01:00
|
|
|
gboolean ret;
|
|
|
|
|
|
|
|
|
|
/* first, check the device and add it if it doesn't exist */
|
2010-01-18 12:49:30 +00:00
|
|
|
object = up_device_list_lookup (backend->priv->device_list, G_OBJECT (native));
|
2009-09-11 12:05:16 +01:00
|
|
|
if (object == NULL) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("treating change event as add on %s", g_udev_device_get_sysfs_path (native));
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_add (backend, native);
|
2009-09-11 12:05:16 +01:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* need to refresh device */
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (object);
|
|
|
|
|
ret = up_device_refresh_internal (device);
|
2009-09-11 12:05:16 +01:00
|
|
|
if (!ret) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("no changes on %s", up_device_get_object_path (device));
|
2009-09-11 12:05:16 +01:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
out:
|
2009-09-11 12:34:25 +01:00
|
|
|
if (object != NULL)
|
|
|
|
|
g_object_unref (object);
|
2009-09-11 12:05:16 +01:00
|
|
|
}
|
|
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_device_add:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static gboolean
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_add (UpBackend *backend, GUdevDevice *native)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
|
|
|
|
GObject *object;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDevice *device;
|
2009-07-27 16:40:11 +01:00
|
|
|
gboolean ret = TRUE;
|
|
|
|
|
|
|
|
|
|
/* does device exist in db? */
|
2010-01-18 12:49:30 +00:00
|
|
|
object = up_device_list_lookup (backend->priv->device_list, G_OBJECT (native));
|
2009-07-27 16:40:11 +01:00
|
|
|
if (object != NULL) {
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (object);
|
2009-07-27 16:40:11 +01:00
|
|
|
/* we already have the device; treat as change event */
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("treating add event as change event on %s", up_device_get_object_path (device));
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_changed (backend, native);
|
2009-07-27 16:40:11 +01:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* get the right sort of device */
|
2010-01-18 12:32:06 +00:00
|
|
|
device = up_backend_device_new (backend, native);
|
2009-07-27 16:40:11 +01:00
|
|
|
if (device == NULL) {
|
|
|
|
|
ret = FALSE;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* emit */
|
2009-09-11 12:05:16 +01:00
|
|
|
g_signal_emit (backend, signals[SIGNAL_DEVICE_ADDED], 0, native, device);
|
2009-07-27 16:40:11 +01:00
|
|
|
out:
|
2009-09-11 12:34:25 +01:00
|
|
|
if (object != NULL)
|
|
|
|
|
g_object_unref (object);
|
2009-07-27 16:40:11 +01:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_device_remove:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_remove (UpBackend *backend, GUdevDevice *native)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
|
|
|
|
GObject *object;
|
2010-01-18 12:49:30 +00:00
|
|
|
UpDevice *device;
|
2009-07-27 16:40:11 +01:00
|
|
|
|
|
|
|
|
/* does device exist in db? */
|
2010-01-18 12:49:30 +00:00
|
|
|
object = up_device_list_lookup (backend->priv->device_list, G_OBJECT (native));
|
2009-07-27 16:40:11 +01:00
|
|
|
if (object == NULL) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("ignoring remove event on %s", g_udev_device_get_sysfs_path (native));
|
2009-09-11 12:34:25 +01:00
|
|
|
goto out;
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
2009-09-11 12:34:25 +01:00
|
|
|
|
2010-01-18 12:49:30 +00:00
|
|
|
device = UP_DEVICE (object);
|
2009-09-11 12:34:25 +01:00
|
|
|
/* emit */
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("emitting device-removed: %s", g_udev_device_get_sysfs_path (native));
|
2009-09-11 12:34:25 +01:00
|
|
|
g_signal_emit (backend, signals[SIGNAL_DEVICE_REMOVED], 0, native, device);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (object != NULL)
|
|
|
|
|
g_object_unref (object);
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_uevent_signal_handler_cb:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_uevent_signal_handler_cb (GUdevClient *client, const gchar *action,
|
2009-07-27 16:40:11 +01:00
|
|
|
GUdevDevice *device, gpointer user_data)
|
|
|
|
|
{
|
2010-01-18 12:32:06 +00:00
|
|
|
UpBackend *backend = UP_BACKEND (user_data);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
|
|
|
|
if (g_strcmp0 (action, "add") == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("SYSFS add %s", g_udev_device_get_sysfs_path (device));
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_add (backend, device);
|
2009-07-27 16:40:11 +01:00
|
|
|
} else if (g_strcmp0 (action, "remove") == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("SYSFS remove %s", g_udev_device_get_sysfs_path (device));
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_remove (backend, device);
|
2009-07-27 16:40:11 +01:00
|
|
|
} else if (g_strcmp0 (action, "change") == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("SYSFS change %s", g_udev_device_get_sysfs_path (device));
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_changed (backend, device);
|
2009-07-27 16:40:11 +01:00
|
|
|
} else {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("unhandled action '%s' on %s", action, g_udev_device_get_sysfs_path (device));
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_coldplug:
|
|
|
|
|
* @backend: The %UpBackend class instance
|
2010-01-18 12:35:47 +00:00
|
|
|
* @daemon: The %UpDaemon controlling instance
|
2009-07-27 16:40:11 +01:00
|
|
|
*
|
|
|
|
|
* Finds all the devices already plugged in, and emits device-add signals for
|
|
|
|
|
* each of them.
|
|
|
|
|
*
|
|
|
|
|
* Return value: %TRUE for success
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
2010-01-18 12:35:47 +00:00
|
|
|
up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
|
|
|
|
GUdevDevice *native;
|
|
|
|
|
GList *devices;
|
|
|
|
|
GList *l;
|
|
|
|
|
guint i;
|
2011-01-04 18:05:09 +00:00
|
|
|
gboolean ret;
|
Fix device matching for recent kernels
In recent kernels, hiddev* devices now have class "usbmisc", rather
than "usb" (see http://www.spinics.net/lists/linux-usb/msg62276.html).
This change translates into a change in SUBSYSTEM matching for hiddev*
devices. This fix addresses this for recent kernels while retaining
existing behavior. For reference, here is an attribute-walk for a
CyberPower CPS 1500C on kernel 3.7.0:
[Ubuntu bug #1091702: udev rules fail to match hid devices with new kernels]
udevadm info --attribute-walk --path=/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0/usbmisc/hiddev0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0/usbmisc/hiddev0':
KERNEL=="hiddev0"
SUBSYSTEM=="usbmisc"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1/4-1:1.0':
KERNELS=="4-1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usbhid"
ATTRS{bInterfaceClass}=="03"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bNumEndpoints}=="01"
ATTRS{supports_autosuspend}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4/4-1':
KERNELS=="4-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1"
ATTRS{idVendor}=="0764"
ATTRS{speed}=="1.5"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{busnum}=="4"
ATTRS{devnum}=="2"
ATTRS{configuration}==""
ATTRS{bMaxPower}==" 50mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="c0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0001"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="36"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="CPS"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0501"
ATTRS{bDeviceClass}=="00"
ATTRS{product}==" CP 1500C"
looking at parent device '/devices/pci0000:00/0000:00:1d.2/usb4':
KERNELS=="usb4"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="0"
ATTRS{idVendor}=="1d6b"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="4"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{bMaxPower}==" 0mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="2"
ATTRS{bcdDevice}=="0307"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{serial}=="0000:00:1d.2"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="50"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 3.7.0-030700-generic uhci_hcd"
ATTRS{removable}=="unknown"
ATTRS{idProduct}=="0001"
ATTRS{bDeviceClass}=="09"
ATTRS{product}=="UHCI Host Controller"
looking at parent device '/devices/pci0000:00/0000:00:1d.2':
KERNELS=="0000:00:1d.2"
SUBSYSTEMS=="pci"
DRIVERS=="uhci_hcd"
ATTRS{irq}=="18"
ATTRS{subsystem_vendor}=="0x1028"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0300"
ATTRS{consistent_dma_mask_bits}=="32"
ATTRS{dma_mask_bits}=="32"
ATTRS{local_cpus}=="00000000,00000000,00000000,00000000,00000000,00000000,00000000,000000ff"
ATTRS{device}=="0x268a"
ATTRS{msi_bus}==""
ATTRS{local_cpulist}=="0-7"
ATTRS{vendor}=="0x8086"
ATTRS{subsystem_device}=="0x021e"
ATTRS{numa_node}=="-1"
ATTRS{d3cold_allowed}=="0"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Richard Hughes <richard@hughsie.com>
2012-12-23 15:45:01 -05:00
|
|
|
const gchar *subsystems[] = {"power_supply", "usb", "usbmisc", "tty", "input", NULL};
|
2009-07-27 16:40:11 +01:00
|
|
|
|
|
|
|
|
backend->priv->daemon = g_object_ref (daemon);
|
2010-01-18 12:35:47 +00:00
|
|
|
backend->priv->device_list = up_daemon_get_device_list (daemon);
|
2009-09-11 09:58:46 +01:00
|
|
|
backend->priv->gudev_client = g_udev_client_new (subsystems);
|
|
|
|
|
g_signal_connect (backend->priv->gudev_client, "uevent",
|
2010-01-18 12:32:06 +00:00
|
|
|
G_CALLBACK (up_backend_uevent_signal_handler_cb), backend);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
|
|
|
|
/* add all subsystems */
|
|
|
|
|
for (i=0; subsystems[i] != NULL; i++) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("registering subsystem : %s", subsystems[i]);
|
2009-07-27 16:40:11 +01:00
|
|
|
devices = g_udev_client_query_by_subsystem (backend->priv->gudev_client, subsystems[i]);
|
|
|
|
|
for (l = devices; l != NULL; l = l->next) {
|
|
|
|
|
native = l->data;
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_device_add (backend, native);
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
g_list_foreach (devices, (GFunc) g_object_unref, NULL);
|
|
|
|
|
g_list_free (devices);
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-04 18:05:09 +00:00
|
|
|
/* add dock update object */
|
|
|
|
|
backend->priv->dock = up_dock_new ();
|
2011-03-14 11:01:12 +00:00
|
|
|
ret = up_config_get_boolean (backend->priv->config, "PollDockDevices");
|
|
|
|
|
g_debug ("Polling docks: %s", ret ? "YES" : "NO");
|
2011-03-03 14:02:27 +00:00
|
|
|
up_dock_set_should_poll (backend->priv->dock, ret);
|
2011-01-04 18:05:09 +00:00
|
|
|
ret = up_dock_coldplug (backend->priv->dock, daemon);
|
|
|
|
|
if (!ret)
|
|
|
|
|
g_warning ("failed to coldplug dock devices");
|
|
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 14:16:11 +01:00
|
|
|
/**
|
|
|
|
|
* up_backend_supports_sleep_state:
|
2010-06-13 21:07:31 -05:00
|
|
|
*
|
|
|
|
|
* use pm-is-supported to test for supported sleep states
|
2010-03-29 14:16:11 +01:00
|
|
|
**/
|
|
|
|
|
static gboolean
|
|
|
|
|
up_backend_supports_sleep_state (const gchar *state)
|
|
|
|
|
{
|
2010-06-13 21:07:31 -05:00
|
|
|
gboolean ret = FALSE;
|
|
|
|
|
gchar *command;
|
2010-03-29 14:16:11 +01:00
|
|
|
GError *error = NULL;
|
2010-06-13 21:07:31 -05:00
|
|
|
gint exit_status;
|
2010-03-29 14:16:11 +01:00
|
|
|
|
2010-06-13 21:07:31 -05:00
|
|
|
/* run script from pm-utils */
|
|
|
|
|
command = g_strdup_printf ("/usr/bin/pm-is-supported --%s", state);
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("excuting command: %s", command);
|
2010-06-13 21:07:31 -05:00
|
|
|
ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error);
|
2010-03-29 14:16:11 +01:00
|
|
|
if (!ret) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("failed to run script: %s", error->message);
|
2010-03-29 14:16:11 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2011-09-22 17:34:45 +02:00
|
|
|
ret = (WIFEXITED(exit_status) && (WEXITSTATUS(exit_status) == EXIT_SUCCESS));
|
|
|
|
|
|
2010-03-29 14:16:11 +01:00
|
|
|
out:
|
2010-06-13 21:07:31 -05:00
|
|
|
g_free (command);
|
2010-03-29 14:16:11 +01:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* up_backend_kernel_can_suspend:
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
up_backend_kernel_can_suspend (UpBackend *backend)
|
|
|
|
|
{
|
2010-06-13 21:07:31 -05:00
|
|
|
return up_backend_supports_sleep_state ("suspend");
|
2010-03-29 14:16:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* up_backend_kernel_can_hibernate:
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
up_backend_kernel_can_hibernate (UpBackend *backend)
|
|
|
|
|
{
|
2010-06-13 21:07:31 -05:00
|
|
|
return up_backend_supports_sleep_state ("hibernate");
|
2010-03-29 14:16:11 +01:00
|
|
|
}
|
|
|
|
|
|
2010-03-29 14:18:42 +01:00
|
|
|
/**
|
|
|
|
|
* up_backend_has_encrypted_swap:
|
|
|
|
|
*
|
|
|
|
|
* user@local:~$ cat /proc/swaps
|
|
|
|
|
* Filename Type Size Used Priority
|
|
|
|
|
* /dev/mapper/cryptswap1 partition 4803392 35872 -1
|
|
|
|
|
*
|
|
|
|
|
* user@local:~$ cat /etc/crypttab
|
|
|
|
|
* # <target name> <source device> <key file> <options>
|
|
|
|
|
* cryptswap1 /dev/sda5 /dev/urandom swap,cipher=aes-cbc-essiv:sha256
|
|
|
|
|
*
|
|
|
|
|
* Loop over the swap partitions in /proc/swaps, looking for matches in /etc/crypttab
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
up_backend_has_encrypted_swap (UpBackend *backend)
|
|
|
|
|
{
|
|
|
|
|
gchar *contents_swaps = NULL;
|
|
|
|
|
gchar *contents_crypttab = NULL;
|
|
|
|
|
gchar **lines_swaps = NULL;
|
|
|
|
|
gchar **lines_crypttab = NULL;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
gboolean encrypted_swap = FALSE;
|
|
|
|
|
const gchar *filename_swaps = "/proc/swaps";
|
|
|
|
|
const gchar *filename_crypttab = "/etc/crypttab";
|
|
|
|
|
GPtrArray *devices = NULL;
|
|
|
|
|
gchar *device;
|
|
|
|
|
guint i, j;
|
|
|
|
|
|
|
|
|
|
/* get swaps data */
|
|
|
|
|
ret = g_file_get_contents (filename_swaps, &contents_swaps, NULL, &error);
|
|
|
|
|
if (!ret) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("failed to open %s: %s", filename_swaps, error->message);
|
2010-03-29 14:18:42 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* get crypttab data */
|
|
|
|
|
ret = g_file_get_contents (filename_crypttab, &contents_crypttab, NULL, &error);
|
|
|
|
|
if (!ret) {
|
2012-01-17 19:02:29 -07:00
|
|
|
if (error->code != G_FILE_ERROR_NOENT) {
|
|
|
|
|
g_warning ("failed to open %s: %s", filename_crypttab, error->message);
|
|
|
|
|
}
|
2010-03-29 14:18:42 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* split both into lines */
|
|
|
|
|
lines_swaps = g_strsplit (contents_swaps, "\n", -1);
|
|
|
|
|
lines_crypttab = g_strsplit (contents_crypttab, "\n", -1);
|
|
|
|
|
|
|
|
|
|
/* get valid swap devices */
|
|
|
|
|
devices = g_ptr_array_new_with_free_func (g_free);
|
|
|
|
|
for (i=0; lines_swaps[i] != NULL; i++) {
|
|
|
|
|
|
|
|
|
|
/* is a device? */
|
|
|
|
|
if (lines_swaps[i][0] != '/')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* only look at first parameter */
|
|
|
|
|
g_strdelimit (lines_swaps[i], "\t ", '\0');
|
|
|
|
|
|
|
|
|
|
/* add base device to list */
|
|
|
|
|
device = g_path_get_basename (lines_swaps[i]);
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("adding swap device: %s", device);
|
2010-03-29 14:18:42 +01:00
|
|
|
g_ptr_array_add (devices, device);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* no swap devices? */
|
|
|
|
|
if (devices->len == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("no swap devices");
|
2010-03-29 14:18:42 +01:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* find matches in crypttab */
|
|
|
|
|
for (i=0; lines_crypttab[i] != NULL; i++) {
|
|
|
|
|
|
|
|
|
|
/* ignore invalid lines */
|
|
|
|
|
if (lines_crypttab[i][0] == '#' ||
|
|
|
|
|
lines_crypttab[i][0] == '\n' ||
|
|
|
|
|
lines_crypttab[i][0] == '\t' ||
|
|
|
|
|
lines_crypttab[i][0] == '\0')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* only look at first parameter */
|
|
|
|
|
g_strdelimit (lines_crypttab[i], "\t ", '\0');
|
|
|
|
|
|
|
|
|
|
/* is a swap device? */
|
|
|
|
|
for (j=0; j<devices->len; j++) {
|
|
|
|
|
device = g_ptr_array_index (devices, j);
|
|
|
|
|
if (g_strcmp0 (device, lines_crypttab[i]) == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("swap device %s is encrypted (so cannot hibernate)", device);
|
2010-03-29 14:18:42 +01:00
|
|
|
encrypted_swap = TRUE;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("swap device %s is not encrypted (allows hibernate)", device);
|
2010-03-29 14:18:42 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (devices != NULL)
|
|
|
|
|
g_ptr_array_unref (devices);
|
|
|
|
|
g_free (contents_swaps);
|
|
|
|
|
g_free (contents_crypttab);
|
|
|
|
|
g_strfreev (lines_swaps);
|
|
|
|
|
g_strfreev (lines_crypttab);
|
|
|
|
|
return encrypted_swap;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 14:21:51 +01:00
|
|
|
/**
|
|
|
|
|
* up_backend_get_used_swap:
|
|
|
|
|
*
|
2010-07-07 15:01:27 +02:00
|
|
|
* Return value: a percentage value how much of the available swap memory would
|
|
|
|
|
* be taken by currently active memory
|
2010-03-29 14:21:51 +01:00
|
|
|
**/
|
|
|
|
|
gfloat
|
|
|
|
|
up_backend_get_used_swap (UpBackend *backend)
|
|
|
|
|
{
|
|
|
|
|
gchar *contents = NULL;
|
|
|
|
|
gchar **lines = NULL;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
gchar **tokens;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
guint active = 0;
|
|
|
|
|
guint swap_free = 0;
|
|
|
|
|
guint swap_total = 0;
|
|
|
|
|
guint len;
|
|
|
|
|
guint i;
|
|
|
|
|
gfloat percentage = 0.0f;
|
|
|
|
|
const gchar *filename = "/proc/meminfo";
|
|
|
|
|
|
|
|
|
|
/* get memory data */
|
|
|
|
|
ret = g_file_get_contents (filename, &contents, NULL, &error);
|
|
|
|
|
if (!ret) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_warning ("failed to open %s: %s", filename, error->message);
|
2010-03-29 14:21:51 +01:00
|
|
|
g_error_free (error);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* process each line */
|
|
|
|
|
lines = g_strsplit (contents, "\n", -1);
|
|
|
|
|
for (i=1; lines[i] != NULL; i++) {
|
|
|
|
|
tokens = g_strsplit_set (lines[i], ": ", -1);
|
|
|
|
|
len = g_strv_length (tokens);
|
|
|
|
|
if (len > 3) {
|
|
|
|
|
if (g_strcmp0 (tokens[0], "SwapFree") == 0)
|
|
|
|
|
swap_free = atoi (tokens[len-2]);
|
|
|
|
|
if (g_strcmp0 (tokens[0], "SwapTotal") == 0)
|
|
|
|
|
swap_total = atoi (tokens[len-2]);
|
2010-05-29 13:12:57 +01:00
|
|
|
else if (g_strcmp0 (tokens[0], "Active(anon)") == 0)
|
2010-03-29 14:21:51 +01:00
|
|
|
active = atoi (tokens[len-2]);
|
|
|
|
|
}
|
|
|
|
|
g_strfreev (tokens);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* first check if we even have swap, if not consider all swap space used */
|
|
|
|
|
if (swap_total == 0) {
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("no swap space found");
|
2010-03-29 14:21:51 +01:00
|
|
|
percentage = 100.0f;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* work out how close to the line we are */
|
|
|
|
|
if (swap_free > 0 && active > 0)
|
|
|
|
|
percentage = (active * 100) / swap_free;
|
2010-11-01 11:28:31 +00:00
|
|
|
g_debug ("total swap available %i kb, active memory %i kb (%.1f%%)", swap_free, active, percentage);
|
2010-03-29 14:21:51 +01:00
|
|
|
out:
|
|
|
|
|
g_free (contents);
|
|
|
|
|
g_strfreev (lines);
|
|
|
|
|
return percentage;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 16:42:35 +01:00
|
|
|
/**
|
|
|
|
|
* up_backend_get_suspend_command:
|
|
|
|
|
**/
|
|
|
|
|
const gchar *
|
|
|
|
|
up_backend_get_suspend_command (UpBackend *backend)
|
|
|
|
|
{
|
2012-07-11 15:06:04 +01:00
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
|
if (sd_booted ())
|
|
|
|
|
return SD_SUSPEND_COMMAND;
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2010-03-29 16:42:35 +01:00
|
|
|
return UP_BACKEND_SUSPEND_COMMAND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* up_backend_get_hibernate_command:
|
|
|
|
|
**/
|
|
|
|
|
const gchar *
|
|
|
|
|
up_backend_get_hibernate_command (UpBackend *backend)
|
|
|
|
|
{
|
2012-07-11 15:06:04 +01:00
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
|
if (sd_booted ())
|
|
|
|
|
return SD_HIBERNATE_COMMAND;
|
|
|
|
|
else
|
|
|
|
|
#endif
|
2010-03-29 16:42:35 +01:00
|
|
|
return UP_BACKEND_HIBERNATE_COMMAND;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-11 15:06:04 +01:00
|
|
|
gboolean
|
|
|
|
|
up_backend_emits_resuming (UpBackend *backend)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SYSTEMD
|
2012-09-02 04:36:13 +02:00
|
|
|
if (sd_booted ())
|
|
|
|
|
return TRUE;
|
|
|
|
|
else
|
2012-07-11 15:06:04 +01:00
|
|
|
#endif
|
2012-09-02 04:36:13 +02:00
|
|
|
return FALSE;
|
2012-07-11 15:06:04 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-07 10:07:37 +01:00
|
|
|
/**
|
|
|
|
|
* up_backend_get_powersave_command:
|
|
|
|
|
**/
|
|
|
|
|
const gchar *
|
|
|
|
|
up_backend_get_powersave_command (UpBackend *backend, gboolean powersave)
|
|
|
|
|
{
|
|
|
|
|
if (powersave)
|
|
|
|
|
return UP_BACKEND_POWERSAVE_TRUE_COMMAND;
|
|
|
|
|
return UP_BACKEND_POWERSAVE_FALSE_COMMAND;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_class_init:
|
|
|
|
|
* @klass: The UpBackendClass
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_class_init (UpBackendClass *klass)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2010-01-18 12:32:06 +00:00
|
|
|
object_class->finalize = up_backend_finalize;
|
2009-07-27 16:40:11 +01:00
|
|
|
|
|
|
|
|
signals [SIGNAL_DEVICE_ADDED] =
|
|
|
|
|
g_signal_new ("device-added",
|
|
|
|
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
2010-01-18 12:32:06 +00:00
|
|
|
G_STRUCT_OFFSET (UpBackendClass, device_added),
|
2010-01-18 13:08:31 +00:00
|
|
|
NULL, NULL, up_marshal_VOID__POINTER_POINTER,
|
2009-09-11 12:05:16 +01:00
|
|
|
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
|
2009-07-27 16:40:11 +01:00
|
|
|
signals [SIGNAL_DEVICE_REMOVED] =
|
|
|
|
|
g_signal_new ("device-removed",
|
|
|
|
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
2010-01-18 12:32:06 +00:00
|
|
|
G_STRUCT_OFFSET (UpBackendClass, device_removed),
|
2010-01-18 13:08:31 +00:00
|
|
|
NULL, NULL, up_marshal_VOID__POINTER_POINTER,
|
2009-07-27 16:40:11 +01:00
|
|
|
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
|
2012-07-11 15:06:04 +01:00
|
|
|
signals [SIGNAL_RESUMING] =
|
|
|
|
|
g_signal_new ("resuming",
|
|
|
|
|
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
|
|
|
|
G_STRUCT_OFFSET (UpBackendClass, resuming),
|
|
|
|
|
NULL, NULL, g_cclosure_marshal_VOID__VOID,
|
|
|
|
|
G_TYPE_NONE, 0);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
g_type_class_add_private (klass, sizeof (UpBackendPrivate));
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
2012-07-11 15:06:04 +01:00
|
|
|
static DBusHandlerResult
|
|
|
|
|
message_filter (DBusConnection *connection,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
UpBackend *backend = user_data;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_is_signal (message, "org.freedesktop.UPower", "Resuming")) {
|
|
|
|
|
g_debug ("received Resuming signal");
|
|
|
|
|
g_signal_emit (backend, signals[SIGNAL_RESUMING], 0);
|
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-27 16:40:11 +01:00
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_init:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_init (UpBackend *backend)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
2010-01-18 12:32:06 +00:00
|
|
|
backend->priv = UP_BACKEND_GET_PRIVATE (backend);
|
2011-03-14 11:01:12 +00:00
|
|
|
backend->priv->config = up_config_new ();
|
2009-07-27 16:40:11 +01:00
|
|
|
backend->priv->daemon = NULL;
|
|
|
|
|
backend->priv->device_list = NULL;
|
2010-01-18 12:49:30 +00:00
|
|
|
backend->priv->managed_devices = up_device_list_new ();
|
2012-07-11 15:06:04 +01:00
|
|
|
|
|
|
|
|
#ifdef HAVE_SYSTEMD
|
|
|
|
|
if (sd_booted ()) {
|
|
|
|
|
DBusGConnection *bus;
|
|
|
|
|
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
|
|
|
|
|
backend->priv->connection = dbus_g_connection_get_connection (bus);
|
|
|
|
|
dbus_connection_add_filter (backend->priv->connection, message_filter, backend, NULL);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_finalize:
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
|
|
|
|
static void
|
2010-01-18 12:32:06 +00:00
|
|
|
up_backend_finalize (GObject *object)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
2010-01-18 12:32:06 +00:00
|
|
|
UpBackend *backend;
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
g_return_if_fail (UP_IS_BACKEND (object));
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
backend = UP_BACKEND (object);
|
2009-07-27 16:40:11 +01:00
|
|
|
|
2011-03-14 11:01:12 +00:00
|
|
|
g_object_unref (backend->priv->config);
|
2009-07-27 16:40:11 +01:00
|
|
|
if (backend->priv->daemon != NULL)
|
|
|
|
|
g_object_unref (backend->priv->daemon);
|
|
|
|
|
if (backend->priv->device_list != NULL)
|
|
|
|
|
g_object_unref (backend->priv->device_list);
|
|
|
|
|
if (backend->priv->gudev_client != NULL)
|
|
|
|
|
g_object_unref (backend->priv->gudev_client);
|
|
|
|
|
|
|
|
|
|
g_object_unref (backend->priv->managed_devices);
|
|
|
|
|
|
2012-07-11 15:06:04 +01:00
|
|
|
if (backend->priv->connection)
|
|
|
|
|
dbus_connection_remove_filter (backend->priv->connection, message_filter, backend);
|
|
|
|
|
|
2010-01-18 12:32:06 +00:00
|
|
|
G_OBJECT_CLASS (up_backend_parent_class)->finalize (object);
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-01-18 12:32:06 +00:00
|
|
|
* up_backend_new:
|
2009-07-27 16:40:11 +01:00
|
|
|
*
|
2010-01-18 12:32:06 +00:00
|
|
|
* Return value: a new %UpBackend object.
|
2009-07-27 16:40:11 +01:00
|
|
|
**/
|
2010-01-18 12:32:06 +00:00
|
|
|
UpBackend *
|
|
|
|
|
up_backend_new (void)
|
2009-07-27 16:40:11 +01:00
|
|
|
{
|
2010-01-18 12:32:06 +00:00
|
|
|
UpBackend *backend;
|
|
|
|
|
backend = g_object_new (UP_TYPE_BACKEND, NULL);
|
|
|
|
|
return UP_BACKEND (backend);
|
2009-07-27 16:40:11 +01:00
|
|
|
}
|
|
|
|
|
|