summaryrefslogblamecommitdiffstats
path: root/source/a/upower/patches/linux-Properly-detect-bluetooth-mice-and-keyboards-t.patch
blob: 55de33b7d38f9112941efbfe13ff13abac600a08 (plain) (tree)












































































































































                                                                                                                      
From 6c706ff03365e462e1b076155428decbed0f55c6 Mon Sep 17 00:00:00 2001
From: Marc Deslauriers <marc.deslauriers@ubuntu.com>
Date: Mon, 4 May 2015 19:31:31 -0400
Subject: [PATCH] linux: Properly detect bluetooth mice and keyboards that are
 HID devices

https://bugs.freedesktop.org/show_bug.cgi?id=90222
---
 src/linux/integration-test   | 41 +++++++++++++++++++++++++++++++++++++
 src/linux/up-device-supply.c | 48 ++++++++++++++++++++++++++++----------------
 2 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/src/linux/integration-test b/src/linux/integration-test
index ad7152a..b83f80d 100755
--- a/src/linux/integration-test
+++ b/src/linux/integration-test
@@ -761,6 +761,47 @@ class Tests(unittest.TestCase):
         self.assertEqual(self.get_dbus_dev_property(mb1_up, 'Percentage'), 30)
         self.assertEqual(self.get_dbus_dev_property(mb1_up, 'PowerSupply'), False)
 
+    def test_bluetooth_hid_mouse(self):
+        '''bluetooth HID mouse battery'''
+
+        self.testbed.add_device('hid',
+                                'usb1/bluetooth/hci0/hci0:01',
+                                None,
+                                [], [])
+
+        self.testbed.add_device(
+            'input',
+            'usb1/bluetooth/hci0/hci0:01/input/input2/mouse3',
+            None,
+            [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1'])
+
+        self.testbed.add_device(
+            'power_supply',
+            'usb1/bluetooth/hci0/hci0:01/1/power_supply/hid-00:11:22:33:44:55-battery',
+            None,
+            ['type', 'Battery',
+             'scope', 'Device',
+             'present', '1',
+             'online', '1',
+             'status', 'Discharging',
+             'capacity', '30',
+             'model_name', 'Fancy BT mouse'],
+            [])
+
+        self.start_daemon()
+        devs = self.proxy.EnumerateDevices()
+        self.assertEqual(len(devs), 1)
+        mousebat0_up = devs[0]
+
+        self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy BT mouse')
+        self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 30)
+        self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False)
+        # 5 == mouse
+        self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), 5)
+        self.assertEqual(self.get_dbus_property('OnBattery'), False)
+        self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE)
+        self.stop_daemon()
+
     def test_bluetooth_keyboard(self):
         '''bluetooth keyboard battery'''
 
diff --git a/src/linux/up-device-supply.c b/src/linux/up-device-supply.c
index 1f86382..b96080b 100644
--- a/src/linux/up-device-supply.c
+++ b/src/linux/up-device-supply.c
@@ -932,9 +932,12 @@ up_device_supply_coldplug (UpDevice *device)
 	const gchar *scope;
 	gchar *device_type = NULL;
 	gchar *input_path = NULL;
+	gchar *subdir = NULL;
 	GDir *dir = NULL;
 	GError *error = NULL;
 	UpDeviceKind type = UP_DEVICE_KIND_UNKNOWN;
+	guint i;
+	const char *class[] = { "hid", "bluetooth" };
 
 	up_device_supply_reset_values (supply);
 
@@ -970,28 +973,39 @@ up_device_supply_coldplug (UpDevice *device)
 		if (g_ascii_strcasecmp (device_type, "mains") == 0) {
 			type = UP_DEVICE_KIND_LINE_POWER;
 		} else if (g_ascii_strcasecmp (device_type, "battery") == 0) {
+			for (i = 0; i < G_N_ELEMENTS(class) && type == UP_DEVICE_KIND_UNKNOWN; i++) {
+				/* Detect if the battery comes from bluetooth keyboard or mouse. */
+				bluetooth = g_udev_device_get_parent_with_subsystem (native, class[i], NULL);
+				if (bluetooth != NULL) {
+					device_path = g_udev_device_get_sysfs_path (bluetooth);
+
+					/* There may be an extra subdirectory here */
+					subdir = g_build_filename (device_path, "input", NULL);
+					if (!g_file_test (subdir, G_FILE_TEST_IS_DIR)) {
+						g_free(subdir);
+						subdir = g_strdup (device_path);
+					}
 
-			/* Detect if the battery comes from bluetooth keyboard or mouse. */
-			bluetooth = g_udev_device_get_parent_with_subsystem (native, "bluetooth", NULL);
-			if (bluetooth != NULL) {
-				device_path = g_udev_device_get_sysfs_path (bluetooth);
-				if ((dir = g_dir_open (device_path, 0, &error))) {
-					while ((file = g_dir_read_name (dir))) {
-						/* Check if it is an input device. */
-						if (g_str_has_prefix (file, "input")) {
-							input_path = g_build_filename (device_path, file, NULL);
-							break;
+					if ((dir = g_dir_open (subdir, 0, &error))) {
+						while ((file = g_dir_read_name (dir))) {
+							/* Check if it is an input device. */
+							if (g_str_has_prefix (file, "input")) {
+								input_path = g_build_filename (subdir, file, NULL);
+								break;
+							}
 						}
+						g_dir_close (dir);
+					} else {
+						g_warning ("Can not open folder %s: %s", device_path, error->message);
+						g_error_free (error);
 					}
-					g_dir_close (dir);
-				} else {
-					g_warning ("Can not open folder %s: %s", device_path, error->message);
-					g_error_free (error);
+					g_free (subdir);
+					g_object_unref (bluetooth);
 				}
-				g_object_unref (bluetooth);
-			}
 
-			if (input_path != NULL) {
+				if (input_path == NULL)
+					continue;
+
 				if ((dir = g_dir_open (input_path, 0, &error))) {
 					while ((file = g_dir_read_name (dir))) {
 						/* Check if it is a mouse device. */
-- 
2.6.3