linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ v0 0/5] HoG Suspend/Resume
@ 2012-08-17 21:08 Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 1/5] hog: Adds initial files for suspend support Claudio Takahasi
                   ` (6 more replies)
  0 siblings, 7 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series adds HID Control Point support. This control point
allows the report host(BlueZ) to notify the report device(HoG device)
when the host is entering or leaving the Suspend Mode.

The low power Suspend Mode concept is implementation specific. This
proposal adds the support for UPower backend. UPower signals Resuming
/Sleeping are used to trigger the control point writing.

Claudio Takahasi (5):
  hog: Adds initial files for suspend support
  hog: Add UPower Resuming/Suspending watch
  hog: Add Suspend/Resume callbacks
  hog: Move HoG device list to manager
  hog: Add writting Control Point

 Makefile.am                  |    3 +-
 profiles/input/hog_device.c  |   73 ++++++++++++++++++++----------
 profiles/input/hog_device.h  |    9 +++-
 profiles/input/hog_manager.c |   69 ++++++++++++++++++++++++++++-
 profiles/input/upower.c      |  101 ++++++++++++++++++++++++++++++++++++++++++
 profiles/input/upower.h      |   29 ++++++++++++
 6 files changed, 254 insertions(+), 30 deletions(-)
 create mode 100644 profiles/input/upower.c
 create mode 100644 profiles/input/upower.h

-- 
1.7.8.6


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v0 1/5] hog: Adds initial files for suspend support
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
@ 2012-08-17 21:08 ` Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 2/5] hog: Add UPower Resuming/Suspending watch Claudio Takahasi
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds the initial files to support HoG suspend. The first
supported backend is UPower. The suspend concept for HoG is
implementation specific. For UPower, Suspend/Resume will be triggered
by "Sleeping" and "Resuming" signals.

When setting the Control Point, the report device can execute actions to
save power. eg: Reduce the cycle of the key press detection or disable
LEDs.
---
 Makefile.am                  |    3 ++-
 profiles/input/hog_manager.c |   14 ++++++++++++++
 profiles/input/upower.c      |   37 +++++++++++++++++++++++++++++++++++++
 profiles/input/upower.h      |   25 +++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 1 deletions(-)
 create mode 100644 profiles/input/upower.c
 create mode 100644 profiles/input/upower.h

diff --git a/Makefile.am b/Makefile.am
index a74709d..ec86e90 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -184,7 +184,8 @@ endif
 if HOGPLUGIN
 builtin_modules += hog
 builtin_sources += profiles/input/hog_manager.c profiles/input/hog_device.h \
-			profiles/input/hog_device.c profiles/input/uhid_copy.h
+			profiles/input/hog_device.c profiles/input/uhid_copy.h \
+			profiles/input/upower.c profiles/input/upower.h
 endif
 
 if NETWORKPLUGIN
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index ddc5baf..52b2c8a 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -34,8 +34,11 @@
 #include "plugin.h"
 #include "hcid.h"
 #include "device.h"
+#include "upower.h"
 #include "hog_device.h"
 
+static gboolean upower_supported = FALSE;
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -63,11 +66,22 @@ static struct btd_device_driver hog_driver = {
 
 static int hog_manager_init(void)
 {
+	int err;
+
+	err = upower_init();
+	if (err < 0)
+		DBG("UPower: %s(%d)", strerror(-err), -err);
+	else
+		upower_supported = TRUE;
+
 	return btd_register_device_driver(&hog_driver);
 }
 
 static void hog_manager_exit(void)
 {
+	if (upower_supported)
+		upower_exit();
+
 	btd_unregister_device_driver(&hog_driver);
 }
 
diff --git a/profiles/input/upower.c b/profiles/input/upower.c
new file mode 100644
index 0000000..571b023
--- /dev/null
+++ b/profiles/input/upower.c
@@ -0,0 +1,37 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "upower.h"
+
+int upower_init(void)
+{
+	return 0;
+}
+
+void upower_exit(void)
+{
+}
diff --git a/profiles/input/upower.h b/profiles/input/upower.h
new file mode 100644
index 0000000..f898d07
--- /dev/null
+++ b/profiles/input/upower.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int upower_init(void);
+void upower_exit(void);
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v0 2/5] hog: Add UPower Resuming/Suspending watch
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 1/5] hog: Adds initial files for suspend support Claudio Takahasi
@ 2012-08-17 21:08 ` Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 3/5] hog: Add Suspend/Resume callbacks Claudio Takahasi
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds the DBus signal watcher for UPower Resuming, and
Suspending signals.
---
 profiles/input/hog_manager.c |   19 ++++++++++++---
 profiles/input/upower.c      |   51 +++++++++++++++++++++++++++++++++++++++++-
 profiles/input/upower.h      |    2 +-
 3 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 52b2c8a..5a5ac62 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -30,6 +30,7 @@
 #include "log.h"
 #include "../src/adapter.h"
 #include "../src/device.h"
+#include "gdbus.h"
 
 #include "plugin.h"
 #include "hcid.h"
@@ -38,6 +39,7 @@
 #include "hog_device.h"
 
 static gboolean upower_supported = FALSE;
+static DBusConnection *connection = NULL;
 
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
@@ -68,10 +70,16 @@ static int hog_manager_init(void)
 {
 	int err;
 
-	err = upower_init();
-	if (err < 0)
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+	if (connection == NULL)
+		return -EIO;
+
+	err = upower_init(connection);
+	if (err < 0) {
+		dbus_connection_unref(connection);
+		connection = NULL;
 		DBG("UPower: %s(%d)", strerror(-err), -err);
-	else
+	} else
 		upower_supported = TRUE;
 
 	return btd_register_device_driver(&hog_driver);
@@ -79,8 +87,11 @@ static int hog_manager_init(void)
 
 static void hog_manager_exit(void)
 {
-	if (upower_supported)
+	if (upower_supported) {
 		upower_exit();
+		dbus_connection_unref(connection);
+		connection = NULL;
+	}
 
 	btd_unregister_device_driver(&hog_driver);
 }
diff --git a/profiles/input/upower.c b/profiles/input/upower.c
index 571b023..18a4730 100644
--- a/profiles/input/upower.c
+++ b/profiles/input/upower.c
@@ -25,13 +25,62 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
+
+#include "gdbus.h"
+#include "log.h"
+
 #include "upower.h"
 
-int upower_init(void)
+#define UPOWER_BUS_NAME		"org.freedesktop.UPower"
+#define UPOWER_PATH		"/org/freedesktop/UPower"
+#define UPOWER_INTERFACE	UPOWER_BUS_NAME
+
+static DBusConnection *connection = NULL;
+static guint suspending_watch = 0;
+static guint resuming_watch = 0;
+
+static gboolean suspending_cb(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
 {
+	DBG("UPOWER: Suspending ...");
+
+	return TRUE;
+}
+
+static gboolean resuming_cb(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	DBG("UPOWER: Resuming ...");
+
+	return TRUE;
+}
+
+int upower_init(DBusConnection *conn)
+{
+	connection = dbus_connection_ref(conn);
+
+	suspending_watch = g_dbus_add_signal_watch(connection, UPOWER_BUS_NAME,
+						UPOWER_PATH, UPOWER_INTERFACE,
+						"Sleeping", suspending_cb,
+						NULL, NULL);
+
+	resuming_watch = g_dbus_add_signal_watch(connection, UPOWER_BUS_NAME,
+						UPOWER_PATH, UPOWER_INTERFACE,
+						"Resuming", resuming_cb,
+						NULL, NULL);
+
 	return 0;
 }
 
 void upower_exit(void)
 {
+	if (suspending_watch)
+		g_dbus_remove_watch(connection, suspending_watch);
+
+	if (resuming_watch)
+		g_dbus_remove_watch(connection, resuming_watch);
+
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
diff --git a/profiles/input/upower.h b/profiles/input/upower.h
index f898d07..90976ab 100644
--- a/profiles/input/upower.h
+++ b/profiles/input/upower.h
@@ -21,5 +21,5 @@
  *
  */
 
-int upower_init(void);
+int upower_init(DBusConnection *conn);
 void upower_exit(void);
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v0 3/5] hog: Add Suspend/Resume callbacks
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 1/5] hog: Adds initial files for suspend support Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 2/5] hog: Add UPower Resuming/Suspending watch Claudio Takahasi
@ 2012-08-17 21:08 ` Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 4/5] hog: Move HoG device list to manager Claudio Takahasi
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch declares the Suspend, and Resume callbacks that needs to
called when the system is entering or leaving suspend state.
---
 profiles/input/hog_manager.c |   10 +++++++++-
 profiles/input/upower.c      |   21 ++++++++++++++++++---
 profiles/input/upower.h      |    6 +++++-
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 5a5ac62..f32405d 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -41,6 +41,14 @@
 static gboolean upower_supported = FALSE;
 static DBusConnection *connection = NULL;
 
+static void suspend_event_cb(void)
+{
+}
+
+static void resume_event_cb(void)
+{
+}
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -74,7 +82,7 @@ static int hog_manager_init(void)
 	if (connection == NULL)
 		return -EIO;
 
-	err = upower_init(connection);
+	err = upower_init(connection, suspend_event_cb, resume_event_cb);
 	if (err < 0) {
 		dbus_connection_unref(connection);
 		connection = NULL;
diff --git a/profiles/input/upower.c b/profiles/input/upower.c
index 18a4730..27b4753 100644
--- a/profiles/input/upower.c
+++ b/profiles/input/upower.c
@@ -39,12 +39,16 @@
 static DBusConnection *connection = NULL;
 static guint suspending_watch = 0;
 static guint resuming_watch = 0;
+static suspend_event suspend_callback = NULL;
+static resume_event resume_callback = NULL;
 
 static gboolean suspending_cb(DBusConnection *conn, DBusMessage *msg,
 							void *user_data)
 {
 	DBG("UPOWER: Suspending ...");
 
+	suspend_callback();
+
 	return TRUE;
 }
 
@@ -53,22 +57,33 @@ static gboolean resuming_cb(DBusConnection *conn, DBusMessage *msg,
 {
 	DBG("UPOWER: Resuming ...");
 
+	resume_callback();
+
 	return TRUE;
 }
 
-int upower_init(DBusConnection *conn)
+int upower_init(DBusConnection *conn, suspend_event suspend_cb,
+					resume_event resume_cb)
 {
 	connection = dbus_connection_ref(conn);
 
-	suspending_watch = g_dbus_add_signal_watch(connection, UPOWER_BUS_NAME,
+	if (suspend_cb) {
+		suspending_watch = g_dbus_add_signal_watch(connection,
+						UPOWER_BUS_NAME,
 						UPOWER_PATH, UPOWER_INTERFACE,
 						"Sleeping", suspending_cb,
 						NULL, NULL);
+		suspend_callback = suspend_cb;
+	}
 
-	resuming_watch = g_dbus_add_signal_watch(connection, UPOWER_BUS_NAME,
+	if (resume_cb) {
+		resuming_watch = g_dbus_add_signal_watch(connection,
+						UPOWER_BUS_NAME,
 						UPOWER_PATH, UPOWER_INTERFACE,
 						"Resuming", resuming_cb,
 						NULL, NULL);
+		resume_callback = resume_cb;
+	}
 
 	return 0;
 }
diff --git a/profiles/input/upower.h b/profiles/input/upower.h
index 90976ab..0ccad43 100644
--- a/profiles/input/upower.h
+++ b/profiles/input/upower.h
@@ -21,5 +21,9 @@
  *
  */
 
-int upower_init(DBusConnection *conn);
+typedef void (*suspend_event) (void);
+typedef void (*resume_event) (void);
+
+int upower_init(DBusConnection *conn, suspend_event suspend_cb,
+					resume_event resume_cb);
 void upower_exit(void);
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v0 4/5] hog: Move HoG device list to manager
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
                   ` (2 preceding siblings ...)
  2012-08-17 21:08 ` [PATCH BlueZ v0 3/5] hog: Add Suspend/Resume callbacks Claudio Takahasi
@ 2012-08-17 21:08 ` Claudio Takahasi
  2012-08-17 21:08 ` [PATCH BlueZ v0 5/5] hog: Add writting Control Point Claudio Takahasi
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch moves the HoG device list from hog_device.c to hog_manager.c
in order to be possible to easily notify suspend/resume events to each
created device.
---
 profiles/input/hog_device.c  |   46 ++++++++++++++++++++---------------------
 profiles/input/hog_device.h  |    8 +++++-
 profiles/input/hog_manager.c |   22 ++++++++++++++++++-
 3 files changed, 48 insertions(+), 28 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 5a1de12..a561876 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -92,8 +92,6 @@ struct report {
 	struct hog_device	*hogdev;
 };
 
-static GSList *devices = NULL;
-
 static gint report_handle_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct report *report = a;
@@ -627,7 +625,7 @@ static void attio_disconnected_cb(gpointer user_data)
 	hogdev->attrib = NULL;
 }
 
-static struct hog_device *find_device_by_path(GSList *list, const char *path)
+struct hog_device *hog_device_find(GSList *list, const char *path)
 {
 	for (; list; list = list->next) {
 		struct hog_device *hogdev = list->data;
@@ -689,31 +687,33 @@ static void hog_device_free(struct hog_device *hogdev)
 	g_free(hogdev);
 }
 
-int hog_device_register(struct btd_device *device, const char *path)
+struct hog_device *hog_device_register(struct btd_device *device,
+					const char *path, int *perr)
 {
-	struct hog_device *hogdev;
 	struct gatt_primary *prim;
+	struct hog_device *hogdev;
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
-
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev)
-		return -EALREADY;
+	int err;
 
 	prim = load_hog_primary(device);
-	if (!prim)
-		return -EINVAL;
+	if (!prim) {
+		err = -EINVAL;
+		goto failed;
+	}
 
 	hogdev = hog_device_new(device, path);
-	if (!hogdev)
-		return -ENOMEM;
+	if (!hogdev) {
+		err = -ENOMEM;
+		goto failed;
+	}
 
 	hogdev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
 	if (hogdev->uhid_fd < 0) {
-		int err = -errno;
+		err = -errno;
 		error("Failed to open uHID device: %s", strerror(-err));
 		hog_device_free(hogdev);
-		return err;
+		goto failed;
 	}
 
 	io = g_io_channel_unix_new(hogdev->uhid_fd);
@@ -731,20 +731,19 @@ int hog_device_register(struct btd_device *device, const char *path)
 
 	device_set_auto_connect(device, TRUE);
 
-	devices = g_slist_append(devices, hogdev);
+	return hogdev;
 
-	return 0;
+failed:
+	if (perr)
+		*perr = err;
+
+	return NULL;
 }
 
-int hog_device_unregister(const char *path)
+int hog_device_unregister(struct hog_device *hogdev)
 {
-	struct hog_device *hogdev;
 	struct uhid_event ev;
 
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev == NULL)
-		return -EINVAL;
-
 	btd_device_remove_attio_callback(hogdev->device, hogdev->attioid);
 
 	if (hogdev->uhid_watch_id) {
@@ -760,7 +759,6 @@ int hog_device_unregister(const char *path)
 	close(hogdev->uhid_fd);
 	hogdev->uhid_fd = -1;
 
-	devices = g_slist_remove(devices, hogdev);
 	hog_device_free(hogdev);
 
 	return 0;
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index ce6a79e..5679527 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -24,5 +24,9 @@
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
-int hog_device_register(struct btd_device *device, const char *path);
-int hog_device_unregister(const char *path);
+struct hog_device;
+
+struct hog_device *hog_device_register(struct btd_device *device,
+						const char *path, int *perr);
+int hog_device_unregister(struct hog_device *hogdev);
+struct hog_device *hog_device_find(GSList *list, const char *path);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index f32405d..ce8e2ff 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -40,6 +40,7 @@
 
 static gboolean upower_supported = FALSE;
 static DBusConnection *connection = NULL;
+static GSList *devices = NULL;
 
 static void suspend_event_cb(void)
 {
@@ -52,19 +53,36 @@ static void resume_event_cb(void)
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
+	struct hog_device *hogdev;
+	int err;
 
 	DBG("path %s", path);
 
-	return hog_device_register(device, path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev)
+		return -EALREADY;
+
+	hogdev = hog_device_register(device, path, &err);
+	if (hogdev == NULL)
+		return err;
+
+	devices = g_slist_append(devices, hogdev);
+
+	return 0;
 }
 
 static void hog_device_remove(struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
+	struct hog_device *hogdev;
 
 	DBG("path %s", path);
 
-	hog_device_unregister(path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev) {
+		devices = g_slist_remove(devices, hogdev);
+		hog_device_unregister(hogdev);
+	}
 }
 
 static struct btd_device_driver hog_driver = {
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v0 5/5] hog: Add writting Control Point
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
                   ` (3 preceding siblings ...)
  2012-08-17 21:08 ` [PATCH BlueZ v0 4/5] hog: Move HoG device list to manager Claudio Takahasi
@ 2012-08-17 21:08 ` Claudio Takahasi
  2012-08-22 21:28 ` [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-17 21:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds GATT write without response operation when suspending
or resuming.
---
 profiles/input/hog_device.c  |   27 ++++++++++++++++++++++++++-
 profiles/input/hog_device.h  |    1 +
 profiles/input/hog_manager.c |   14 ++++++++++++++
 3 files changed, 41 insertions(+), 1 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index a561876..2e9293d 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -55,6 +55,7 @@
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
 #define HOG_PROTO_MODE_UUID	0x2A4E
+#define HOG_CONTROL_POINT_UUID	0x2A4C
 
 #define HOG_REPORT_TYPE_INPUT	1
 #define HOG_REPORT_TYPE_OUTPUT	2
@@ -82,6 +83,7 @@ struct hog_device {
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
 	uint16_t		proto_mode_handle;
+	uint16_t		ctrlpt_handle;
 	uint8_t			flags;
 };
 
@@ -437,7 +439,8 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
+	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid,
+		  ctrlpt_uuid;
 	struct report *report;
 	GSList *l;
 	uint16_t info_handle = 0, proto_mode_handle = 0;
@@ -452,6 +455,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
 	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
 	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
+	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
 
 	for (l = chars; l; l = g_slist_next(l)) {
 		struct gatt_char *chr, *next;
@@ -480,6 +484,8 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 			info_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
 			proto_mode_handle = chr->value_handle;
+		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
+			hogdev->ctrlpt_handle = chr->value_handle;
 	}
 
 	if (proto_mode_handle) {
@@ -763,3 +769,22 @@ int hog_device_unregister(struct hog_device *hogdev)
 
 	return 0;
 }
+
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend)
+{
+	uint8_t value = suspend ? 0x00 : 0x01;
+
+	if (hogdev->attrib == NULL)
+		return -ENOTCONN;
+
+	DBG("%s HID Control Point: %s", hogdev->path, suspend ?
+						"Suspend" : "Exit Suspend");
+
+	if (hogdev->ctrlpt_handle == 0)
+		return -ENOTSUP;
+
+	gatt_write_char(hogdev->attrib, hogdev->ctrlpt_handle, &value,
+					sizeof(value), NULL, NULL);
+
+	return 0;
+}
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index 5679527..54b2cde 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -30,3 +30,4 @@ struct hog_device *hog_device_register(struct btd_device *device,
 						const char *path, int *perr);
 int hog_device_unregister(struct hog_device *hogdev);
 struct hog_device *hog_device_find(GSList *list, const char *path);
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index ce8e2ff..7f1cdba 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -42,12 +42,26 @@ static gboolean upower_supported = FALSE;
 static DBusConnection *connection = NULL;
 static GSList *devices = NULL;
 
+static void set_suspend(gpointer data, gpointer user_data)
+{
+	struct hog_device *hogdev = data;
+	gboolean suspend = GPOINTER_TO_INT(user_data);
+
+	hog_device_set_control_point(hogdev, suspend);
+}
+
 static void suspend_event_cb(void)
 {
+	gboolean suspend = TRUE;
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static void resume_event_cb(void)
 {
+	gboolean suspend = FALSE;
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH BlueZ v0 0/5] HoG Suspend/Resume
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
                   ` (4 preceding siblings ...)
  2012-08-17 21:08 ` [PATCH BlueZ v0 5/5] hog: Add writting Control Point Claudio Takahasi
@ 2012-08-22 21:28 ` Claudio Takahasi
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-22 21:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

On Fri, Aug 17, 2012 at 6:08 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> This patch series adds HID Control Point support. This control point
> allows the report host(BlueZ) to notify the report device(HoG device)
> when the host is entering or leaving the Suspend Mode.
>
> The low power Suspend Mode concept is implementation specific. This
> proposal adds the support for UPower backend. UPower signals Resuming
> /Sleeping are used to trigger the control point writing.
>
> Claudio Takahasi (5):
>   hog: Adds initial files for suspend support
>   hog: Add UPower Resuming/Suspending watch
>   hog: Add Suspend/Resume callbacks
>   hog: Move HoG device list to manager
>   hog: Add writting Control Point
>
>  Makefile.am                  |    3 +-
>  profiles/input/hog_device.c  |   73 ++++++++++++++++++++----------
>  profiles/input/hog_device.h  |    9 +++-
>  profiles/input/hog_manager.c |   69 ++++++++++++++++++++++++++++-
>  profiles/input/upower.c      |  101 ++++++++++++++++++++++++++++++++++++++++++
>  profiles/input/upower.h      |   29 ++++++++++++
>  6 files changed, 254 insertions(+), 30 deletions(-)
>  create mode 100644 profiles/input/upower.c
>  create mode 100644 profiles/input/upower.h
>
> --
> 1.7.8.6
>

ping ...

Regards,
Claudio

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 0/6] HoG Suspend/Resume
  2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
                   ` (5 preceding siblings ...)
  2012-08-22 21:28 ` [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
@ 2012-08-29 20:53 ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 1/6] hog: Add initial files for suspend support Claudio Takahasi
                     ` (6 more replies)
  6 siblings, 7 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series adds HID Control Point support. This control point
allows the report host(BlueZ) to notify the report device(HoG device)
when the host is entering or leaving the Suspend Mode.

The low power Suspend Mode concept is implementation specific. This
proposal adds a selectable back-end for HoG Suspend/Resume control.
Each platform is free to write it's own HoG suspend back-end.
A dummy back-end based on a FIFO (/tmp/hogsuspend) is proposed for
reference and testing purpose only. Writting "suspend" or "resume"
in this FIFO will trigger the update of the HID Control Point.

Notify the HoG device is useful to save power. Devices can implement
different actions (diff than disconnect) when commands are written
on the HID control point. The HoG capable device cab reduce the key
press detection frequency or disable LEDs.

*** Changes from previous version:
Replaces UPower by a dummy selectable back-end. As discussed in IRC
tracking UPower "suspending" or "resuming" signals are not suitable
for desktops since the connection is dropped right after detecting
suspend.

Claudio Takahasi (6):
  hog: Add initial files for suspend support
  hog: Add suspend back-end selection
  hog: Add suspend/resume callbacks declaration
  hog: Create a FIFO for dummy suspend
  hog: Move HoG device list to manager
  hog: Add writting Control Point

 Makefile.am                    |   6 +-
 acinclude.m4                   |   7 ++
 profiles/input/hog_device.c    |  73 ++++++++++++++-------
 profiles/input/hog_device.h    |   9 ++-
 profiles/input/hog_manager.c   |  62 ++++++++++++++++-
 profiles/input/suspend-dummy.c | 146 +++++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       |  29 ++++++++
 7 files changed, 302 insertions(+), 30 deletions(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

-- 
1.7.12


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 1/6] hog: Add initial files for suspend support
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 2/6] hog: Add suspend back-end selection Claudio Takahasi
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds the initial files to support HoG suspend. The suspend
concept for HoG is implementation specific. The proposal is allowing
back-end selection at build time. Each Linux distribution/platform is
responsible for defining and writting their own policy to manage suspend
on HoG capable devices.

When setting the Control Point, the report device can execute actions to
save power. eg: Reduce the cycle of the key press detection or disable
LEDs.
---
 Makefile.am                    |  3 ++-
 profiles/input/hog_manager.c   | 14 ++++++++++++++
 profiles/input/suspend-dummy.c | 38 ++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       | 26 ++++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

diff --git a/Makefile.am b/Makefile.am
index 4977a05..f6eb96b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -184,7 +184,8 @@ endif
 if HOGPLUGIN
 builtin_modules += hog
 builtin_sources += profiles/input/hog_manager.c profiles/input/hog_device.h \
-			profiles/input/hog_device.c profiles/input/uhid_copy.h
+			profiles/input/hog_device.c profiles/input/uhid_copy.h \
+			profiles/input/suspend-dummy.c profiles/input/suspend.h
 endif
 
 if NETWORKPLUGIN
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index c544e79..149ed34 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -35,8 +35,11 @@
 #include "plugin.h"
 #include "hcid.h"
 #include "device.h"
+#include "suspend.h"
 #include "hog_device.h"
 
+static gboolean suspend_supported = FALSE;
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -64,11 +67,22 @@ static struct btd_device_driver hog_driver = {
 
 static int hog_manager_init(void)
 {
+	int err;
+
+	err = suspend_init();
+	if (err < 0)
+		DBG("Suspend: %s(%d)", strerror(-err), -err);
+	else
+		suspend_supported = TRUE;
+
 	return btd_register_device_driver(&hog_driver);
 }
 
 static void hog_manager_exit(void)
 {
+	if (suspend_supported)
+		suspend_exit();
+
 	btd_unregister_device_driver(&hog_driver);
 }
 
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
new file mode 100644
index 0000000..0a97158
--- /dev/null
+++ b/profiles/input/suspend-dummy.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "suspend.h"
+
+int suspend_init(void)
+{
+	return 0;
+}
+
+void suspend_exit(void)
+{
+}
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
new file mode 100644
index 0000000..3f37a29
--- /dev/null
+++ b/profiles/input/suspend.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int suspend_init(void);
+void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 2/6] hog: Add suspend back-end selection
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 1/6] hog: Add initial files for suspend support Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series introduces back-end selection for HoG suspend drivers.
The default back-end is called "dummy", added for testing purpose only.
---
 Makefile.am  | 3 +++
 acinclude.m4 | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index f6eb96b..198515b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -439,6 +439,9 @@ audio/telephony.c: audio/@TELEPHONY_DRIVER@
 profiles/sap/sap.c: profiles/sap/@SAP_DRIVER@
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
+profiles/input/suspend.c: profiles/input/@HOG_SUSPEND_DRIVER@
+	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
 scripts/%.rules:
 	$(AM_V_GEN)cp $(subst 97-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index 39b0a18..ed2d011 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -185,6 +185,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	datafiles_enable=yes
 	telephony_driver=dummy
 	sap_driver=dummy
+	hog_suspend_driver=dummy
 	dbusoob_enable=no
 	wiimote_enable=no
 	gatt_enable=no
@@ -288,6 +289,12 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		wiimote_enable=${enableval}
 	])
 
+	AC_ARG_WITH(gatt, AC_HELP_STRING([--with-hog-suspend=DRIVER], [select HoG suspend driver]), [
+		hog_suspend_driver=${withval}
+	])
+
+	AC_SUBST([HOG_SUSPEND_DRIVER], [suspend-${hog_suspend_driver}.c])
+
 	AC_ARG_ENABLE(gatt, AC_HELP_STRING([--enable-gatt], [enable gatt module]), [
 		gatt_enable=${enableval}
 	])
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 3/6] hog: Add suspend/resume callbacks declaration
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 1/6] hog: Add initial files for suspend support Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 2/6] hog: Add suspend back-end selection Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch declares the callbacks functions that intend to be used
by the suspend back-ends.
---
 profiles/input/hog_manager.c   | 12 +++++++++++-
 profiles/input/suspend-dummy.c | 10 +++++++++-
 profiles/input/suspend.h       |  5 ++++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 149ed34..9c23980 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -40,6 +40,16 @@
 
 static gboolean suspend_supported = FALSE;
 
+static void suspend_callback(void)
+{
+	DBG("Suspending ...");
+}
+
+static void resume_callback(void)
+{
+	DBG("Resuming ...");
+}
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -69,7 +79,7 @@ static int hog_manager_init(void)
 {
 	int err;
 
-	err = suspend_init();
+	err = suspend_init(suspend_callback, resume_callback);
 	if (err < 0)
 		DBG("Suspend: %s(%d)", strerror(-err), -err);
 	else
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 0a97158..282d3fb 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,10 +26,18 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+
 #include "suspend.h"
 
-int suspend_init(void)
+static suspend_event suspend_cb = NULL;
+static resume_event resume_cb = NULL;
+
+int suspend_init(suspend_event suspend, resume_event resume)
 {
+	suspend_cb = suspend;
+	resume_cb = resume;
+
 	return 0;
 }
 
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
index 3f37a29..bfee3cf 100644
--- a/profiles/input/suspend.h
+++ b/profiles/input/suspend.h
@@ -22,5 +22,8 @@
  *
  */
 
-int suspend_init(void);
+typedef void (*suspend_event) (void);
+typedef void (*resume_event) (void);
+
+int suspend_init(suspend_event suspend, resume_event resume);
 void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 4/6] hog: Create a FIFO for dummy suspend
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
                     ` (2 preceding siblings ...)
  2012-08-29 20:53   ` [PATCH BlueZ v1 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 5/6] hog: Move HoG device list to manager Claudio Takahasi
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch creates a FIFO on "/tmp/hogsuspend" to allow the users to
test the HoG suspend(HID Control Point) when the dummy back-end is
enabled.
---
 profiles/input/suspend-dummy.c | 102 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 282d3fb..f2941fe 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,21 +26,121 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include <glib.h>
+
+#include "log.h"
 #include "suspend.h"
 
+#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
+
 static suspend_event suspend_cb = NULL;
 static resume_event resume_cb = NULL;
+static GIOChannel *fifoio = NULL;
+
+static int fifo_open(void);
+
+static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
+{
+	gchar buffer[12];
+	gsize offset, left, bread;
+	GIOStatus iostatus;
+
+	if (cond & (G_IO_ERR | G_IO_HUP))
+		goto failed;
+
+	offset = 0;
+	left = sizeof(buffer) - 1;
+	memset(buffer, 0, sizeof(buffer));
+
+	do {
+		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
+								&bread, NULL);
+
+		offset += bread;
+		left -= bread;
+		if (left == 0)
+			break;
+	} while (iostatus == G_IO_STATUS_NORMAL);
+
+	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
+		suspend_cb();
+	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
+		resume_cb();
+
+	return TRUE;
+
+failed:
+	/*
+	 * Both ends needs to be open simultaneously before proceeding any input
+	 * or output operation. When the remote closes the channel, hup signal is
+	 * received on this end.
+	 */
+
+	g_io_channel_unref(fifoio);
+	fifoio = NULL;
+
+	fifo_open();
+
+	return FALSE;
+}
+
+static int fifo_open(void)
+{
+	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
+	int fd;
+
+	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		int err = -errno;
+		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	fifoio = g_io_channel_unix_new(fd);
+	g_io_channel_set_close_on_unref(fifoio, TRUE);
+
+	g_io_add_watch(fifoio, condition, read_fifo, NULL);
+
+	return 0;
+}
 
 int suspend_init(suspend_event suspend, resume_event resume)
 {
+	int ret;
+
 	suspend_cb = suspend;
 	resume_cb = resume;
 
-	return 0;
+	if (mkfifo(HOG_SUSPEND_FIFO, S_IRWXU) < 0) {
+		int err = -errno;
+		error("Can't create FIFO (%s) : %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	ret = fifo_open();
+	if (ret < 0)
+		remove(HOG_SUSPEND_FIFO);
+
+	return ret;
 }
 
 void suspend_exit(void)
 {
+	if (fifoio) {
+		g_io_channel_shutdown(fifoio, FALSE, NULL);
+		g_io_channel_unref(fifoio);
+	}
+
+	remove(HOG_SUSPEND_FIFO);
 }
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 5/6] hog: Move HoG device list to manager
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
                     ` (3 preceding siblings ...)
  2012-08-29 20:53   ` [PATCH BlueZ v1 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-08-29 20:53   ` [PATCH BlueZ v1 6/6] hog: Add writting Control Point Claudio Takahasi
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch moves the HoG device list from hog_device.c to hog_manager.c
in order to be possible to easily notify suspend/resume events to each
created device.
---
 profiles/input/hog_device.c  | 46 +++++++++++++++++++++-----------------------
 profiles/input/hog_device.h  |  8 ++++++--
 profiles/input/hog_manager.c | 22 +++++++++++++++++++--
 3 files changed, 48 insertions(+), 28 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 000f173..af21f24 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -93,8 +93,6 @@ struct report {
 	struct hog_device	*hogdev;
 };
 
-static GSList *devices = NULL;
-
 static gint report_handle_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct report *report = a;
@@ -628,7 +626,7 @@ static void attio_disconnected_cb(gpointer user_data)
 	hogdev->attrib = NULL;
 }
 
-static struct hog_device *find_device_by_path(GSList *list, const char *path)
+struct hog_device *hog_device_find(GSList *list, const char *path)
 {
 	for (; list; list = list->next) {
 		struct hog_device *hogdev = list->data;
@@ -690,31 +688,33 @@ static void hog_device_free(struct hog_device *hogdev)
 	g_free(hogdev);
 }
 
-int hog_device_register(struct btd_device *device, const char *path)
+struct hog_device *hog_device_register(struct btd_device *device,
+					const char *path, int *perr)
 {
-	struct hog_device *hogdev;
 	struct gatt_primary *prim;
+	struct hog_device *hogdev;
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
-
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev)
-		return -EALREADY;
+	int err;
 
 	prim = load_hog_primary(device);
-	if (!prim)
-		return -EINVAL;
+	if (!prim) {
+		err = -EINVAL;
+		goto failed;
+	}
 
 	hogdev = hog_device_new(device, path);
-	if (!hogdev)
-		return -ENOMEM;
+	if (!hogdev) {
+		err = -ENOMEM;
+		goto failed;
+	}
 
 	hogdev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
 	if (hogdev->uhid_fd < 0) {
-		int err = -errno;
+		err = -errno;
 		error("Failed to open uHID device: %s", strerror(-err));
 		hog_device_free(hogdev);
-		return err;
+		goto failed;
 	}
 
 	io = g_io_channel_unix_new(hogdev->uhid_fd);
@@ -732,20 +732,19 @@ int hog_device_register(struct btd_device *device, const char *path)
 
 	device_set_auto_connect(device, TRUE);
 
-	devices = g_slist_append(devices, hogdev);
+	return hogdev;
 
-	return 0;
+failed:
+	if (perr)
+		*perr = err;
+
+	return NULL;
 }
 
-int hog_device_unregister(const char *path)
+int hog_device_unregister(struct hog_device *hogdev)
 {
-	struct hog_device *hogdev;
 	struct uhid_event ev;
 
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev == NULL)
-		return -EINVAL;
-
 	btd_device_remove_attio_callback(hogdev->device, hogdev->attioid);
 
 	if (hogdev->uhid_watch_id) {
@@ -761,7 +760,6 @@ int hog_device_unregister(const char *path)
 	close(hogdev->uhid_fd);
 	hogdev->uhid_fd = -1;
 
-	devices = g_slist_remove(devices, hogdev);
 	hog_device_free(hogdev);
 
 	return 0;
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index 597dc7c..efb7b4f 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -25,5 +25,9 @@
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
-int hog_device_register(struct btd_device *device, const char *path);
-int hog_device_unregister(const char *path);
+struct hog_device;
+
+struct hog_device *hog_device_register(struct btd_device *device,
+						const char *path, int *perr);
+int hog_device_unregister(struct hog_device *hogdev);
+struct hog_device *hog_device_find(GSList *list, const char *path);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 9c23980..c83c345 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -39,6 +39,7 @@
 #include "hog_device.h"
 
 static gboolean suspend_supported = FALSE;
+static GSList *devices = NULL;
 
 static void suspend_callback(void)
 {
@@ -53,19 +54,36 @@ static void resume_callback(void)
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
+	struct hog_device *hogdev;
+	int err;
 
 	DBG("path %s", path);
 
-	return hog_device_register(device, path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev)
+		return -EALREADY;
+
+	hogdev = hog_device_register(device, path, &err);
+	if (hogdev == NULL)
+		return err;
+
+	devices = g_slist_append(devices, hogdev);
+
+	return 0;
 }
 
 static void hog_device_remove(struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
+	struct hog_device *hogdev;
 
 	DBG("path %s", path);
 
-	hog_device_unregister(path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev) {
+		devices = g_slist_remove(devices, hogdev);
+		hog_device_unregister(hogdev);
+	}
 }
 
 static struct btd_device_driver hog_driver = {
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v1 6/6] hog: Add writting Control Point
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
                     ` (4 preceding siblings ...)
  2012-08-29 20:53   ` [PATCH BlueZ v1 5/6] hog: Move HoG device list to manager Claudio Takahasi
@ 2012-08-29 20:53   ` Claudio Takahasi
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-08-29 20:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds GATT write without response operation when suspending
or resuming.
---
 profiles/input/hog_device.c  | 27 ++++++++++++++++++++++++++-
 profiles/input/hog_device.h  |  1 +
 profiles/input/hog_manager.c | 16 ++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index af21f24..369afd2 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -56,6 +56,7 @@
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
 #define HOG_PROTO_MODE_UUID	0x2A4E
+#define HOG_CONTROL_POINT_UUID	0x2A4C
 
 #define HOG_REPORT_TYPE_INPUT	1
 #define HOG_REPORT_TYPE_OUTPUT	2
@@ -83,6 +84,7 @@ struct hog_device {
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
 	uint16_t		proto_mode_handle;
+	uint16_t		ctrlpt_handle;
 	uint8_t			flags;
 };
 
@@ -438,7 +440,8 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
+	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid,
+		  ctrlpt_uuid;
 	struct report *report;
 	GSList *l;
 	uint16_t info_handle = 0, proto_mode_handle = 0;
@@ -453,6 +456,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
 	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
 	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
+	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
 
 	for (l = chars; l; l = g_slist_next(l)) {
 		struct gatt_char *chr, *next;
@@ -481,6 +485,8 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 			info_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
 			proto_mode_handle = chr->value_handle;
+		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
+			hogdev->ctrlpt_handle = chr->value_handle;
 	}
 
 	if (proto_mode_handle) {
@@ -764,3 +770,22 @@ int hog_device_unregister(struct hog_device *hogdev)
 
 	return 0;
 }
+
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend)
+{
+	uint8_t value = suspend ? 0x00 : 0x01;
+
+	if (hogdev->attrib == NULL)
+		return -ENOTCONN;
+
+	DBG("%s HID Control Point: %s", hogdev->path, suspend ?
+						"Suspend" : "Exit Suspend");
+
+	if (hogdev->ctrlpt_handle == 0)
+		return -ENOTSUP;
+
+	gatt_write_char(hogdev->attrib, hogdev->ctrlpt_handle, &value,
+					sizeof(value), NULL, NULL);
+
+	return 0;
+}
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index efb7b4f..03f1c90 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -31,3 +31,4 @@ struct hog_device *hog_device_register(struct btd_device *device,
 						const char *path, int *perr);
 int hog_device_unregister(struct hog_device *hogdev);
 struct hog_device *hog_device_find(GSList *list, const char *path);
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index c83c345..97f2519 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -41,14 +41,30 @@
 static gboolean suspend_supported = FALSE;
 static GSList *devices = NULL;
 
+static void set_suspend(gpointer data, gpointer user_data)
+{
+	struct hog_device *hogdev = data;
+	gboolean suspend = GPOINTER_TO_INT(user_data);
+
+	hog_device_set_control_point(hogdev, suspend);
+}
+
 static void suspend_callback(void)
 {
+	gboolean suspend = TRUE;
+
 	DBG("Suspending ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static void resume_callback(void)
 {
+	gboolean suspend = FALSE;
+
 	DBG("Resuming ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 0/6] HoG Suspend/Resume
  2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
                     ` (5 preceding siblings ...)
  2012-08-29 20:53   ` [PATCH BlueZ v1 6/6] hog: Add writting Control Point Claudio Takahasi
@ 2012-09-03 18:23   ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 1/6] hog: Add initial files for suspend support Claudio Takahasi
                       ` (6 more replies)
  6 siblings, 7 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series adds HID Control Point support. This control point
allows the report host(BlueZ) to notify the report device(HoG device)
when the host is entering or leaving the Suspend Mode.

The low power Suspend Mode concept is implementation specific. This
proposal adds a selectable back-end for HoG Suspend/Resume control.
Each platform is free to write it's own HoG suspend back-end.
A dummy back-end based on a FIFO (/tmp/hogsuspend) is proposed for
reference and testing purpose only. Writting "suspend" or "resume"
in this FIFO will trigger the update of the HID Control Point.

Notify the HoG device is useful to save power. Devices can implement
different actions (diff than disconnect) when commands are written
on the HID control point. The HoG capable device cab reduce the key
press detection frequency or disable LEDs.

*** v1 changes:
Replaces UPower by a dummy selectable back-end. As discussed in IRC
tracking UPower "suspending" or "resuming" signals are not suitable
for desktops since the connection is dropped right after detecting
suspend.

*** v2 changes:
Code rebased and fixed conflicts with the recent changes. Due the
new profile abstraction (btd_device drivers replaces) v1 doesn't apply.

Claudio Takahasi (6):
  hog: Add initial files for suspend support
  hog: Add suspend back-end selection
  hog: Add suspend/resume callbacks declaration
  hog: Create a FIFO for dummy suspend
  hog: Move HoG device list to manager
  hog: Add writting Control Point

 Makefile.am                    |   6 +-
 acinclude.m4                   |   7 ++
 profiles/input/hog_device.c    |  73 ++++++++++++++-------
 profiles/input/hog_device.h    |   9 ++-
 profiles/input/hog_manager.c   |  62 ++++++++++++++++-
 profiles/input/suspend-dummy.c | 146 +++++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       |  29 ++++++++
 7 files changed, 302 insertions(+), 30 deletions(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

-- 
1.7.12


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 1/6] hog: Add initial files for suspend support
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 2/6] hog: Add suspend back-end selection Claudio Takahasi
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds the initial files to support HoG suspend. The suspend
concept for HoG is implementation specific. The proposal is allowing
back-end selection at build time. Each Linux distribution/platform is
responsible for defining and writting their own policy to manage suspend
on HoG capable devices.

When setting the Control Point, the report device can execute actions to
save power. eg: Reduce the cycle of the key press detection or disable
LEDs.
---
 Makefile.am                    |  3 ++-
 profiles/input/hog_manager.c   | 14 ++++++++++++++
 profiles/input/suspend-dummy.c | 38 ++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       | 26 ++++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

diff --git a/Makefile.am b/Makefile.am
index 4977a05..f6eb96b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -184,7 +184,8 @@ endif
 if HOGPLUGIN
 builtin_modules += hog
 builtin_sources += profiles/input/hog_manager.c profiles/input/hog_device.h \
-			profiles/input/hog_device.c profiles/input/uhid_copy.h
+			profiles/input/hog_device.c profiles/input/uhid_copy.h \
+			profiles/input/suspend-dummy.c profiles/input/suspend.h
 endif
 
 if NETWORKPLUGIN
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 6d971fa..79cd712 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -36,8 +36,11 @@
 #include "plugin.h"
 #include "hcid.h"
 #include "device.h"
+#include "suspend.h"
 #include "hog_device.h"
 
+static gboolean suspend_supported = FALSE;
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -65,11 +68,22 @@ static struct btd_profile hog_profile = {
 
 static int hog_manager_init(void)
 {
+	int err;
+
+	err = suspend_init();
+	if (err < 0)
+		DBG("Suspend: %s(%d)", strerror(-err), -err);
+	else
+		suspend_supported = TRUE;
+
 	return btd_profile_register(&hog_profile);
 }
 
 static void hog_manager_exit(void)
 {
+	if (suspend_supported)
+		suspend_exit();
+
 	btd_profile_register(&hog_profile);
 }
 
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
new file mode 100644
index 0000000..0a97158
--- /dev/null
+++ b/profiles/input/suspend-dummy.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "suspend.h"
+
+int suspend_init(void)
+{
+	return 0;
+}
+
+void suspend_exit(void)
+{
+}
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
new file mode 100644
index 0000000..3f37a29
--- /dev/null
+++ b/profiles/input/suspend.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int suspend_init(void);
+void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 2/6] hog: Add suspend back-end selection
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 1/6] hog: Add initial files for suspend support Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series introduces back-end selection for HoG suspend drivers.
The default back-end is called "dummy", added for testing purpose only.
---
 Makefile.am  | 3 +++
 acinclude.m4 | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index f6eb96b..198515b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -439,6 +439,9 @@ audio/telephony.c: audio/@TELEPHONY_DRIVER@
 profiles/sap/sap.c: profiles/sap/@SAP_DRIVER@
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
+profiles/input/suspend.c: profiles/input/@HOG_SUSPEND_DRIVER@
+	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
 scripts/%.rules:
 	$(AM_V_GEN)cp $(subst 97-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index 39b0a18..ed2d011 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -185,6 +185,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	datafiles_enable=yes
 	telephony_driver=dummy
 	sap_driver=dummy
+	hog_suspend_driver=dummy
 	dbusoob_enable=no
 	wiimote_enable=no
 	gatt_enable=no
@@ -288,6 +289,12 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		wiimote_enable=${enableval}
 	])
 
+	AC_ARG_WITH(gatt, AC_HELP_STRING([--with-hog-suspend=DRIVER], [select HoG suspend driver]), [
+		hog_suspend_driver=${withval}
+	])
+
+	AC_SUBST([HOG_SUSPEND_DRIVER], [suspend-${hog_suspend_driver}.c])
+
 	AC_ARG_ENABLE(gatt, AC_HELP_STRING([--enable-gatt], [enable gatt module]), [
 		gatt_enable=${enableval}
 	])
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 3/6] hog: Add suspend/resume callbacks declaration
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 1/6] hog: Add initial files for suspend support Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 2/6] hog: Add suspend back-end selection Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch declares the callbacks functions that intend to be used
by the suspend back-ends.
---
 profiles/input/hog_manager.c   | 12 +++++++++++-
 profiles/input/suspend-dummy.c | 10 +++++++++-
 profiles/input/suspend.h       |  5 ++++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 79cd712..98f8158 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -41,6 +41,16 @@
 
 static gboolean suspend_supported = FALSE;
 
+static void suspend_callback(void)
+{
+	DBG("Suspending ...");
+}
+
+static void resume_callback(void)
+{
+	DBG("Resuming ...");
+}
+
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
@@ -70,7 +80,7 @@ static int hog_manager_init(void)
 {
 	int err;
 
-	err = suspend_init();
+	err = suspend_init(suspend_callback, resume_callback);
 	if (err < 0)
 		DBG("Suspend: %s(%d)", strerror(-err), -err);
 	else
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 0a97158..282d3fb 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,10 +26,18 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+
 #include "suspend.h"
 
-int suspend_init(void)
+static suspend_event suspend_cb = NULL;
+static resume_event resume_cb = NULL;
+
+int suspend_init(suspend_event suspend, resume_event resume)
 {
+	suspend_cb = suspend;
+	resume_cb = resume;
+
 	return 0;
 }
 
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
index 3f37a29..bfee3cf 100644
--- a/profiles/input/suspend.h
+++ b/profiles/input/suspend.h
@@ -22,5 +22,8 @@
  *
  */
 
-int suspend_init(void);
+typedef void (*suspend_event) (void);
+typedef void (*resume_event) (void);
+
+int suspend_init(suspend_event suspend, resume_event resume);
 void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 4/6] hog: Create a FIFO for dummy suspend
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
                       ` (2 preceding siblings ...)
  2012-09-03 18:23     ` [PATCH BlueZ v2 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 5/6] hog: Move HoG device list to manager Claudio Takahasi
                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch creates a FIFO on "/tmp/hogsuspend" to allow the users to
test the HoG suspend(HID Control Point) when the dummy back-end is
enabled.
---
 profiles/input/suspend-dummy.c | 102 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 282d3fb..f2941fe 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,21 +26,121 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include <glib.h>
+
+#include "log.h"
 #include "suspend.h"
 
+#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
+
 static suspend_event suspend_cb = NULL;
 static resume_event resume_cb = NULL;
+static GIOChannel *fifoio = NULL;
+
+static int fifo_open(void);
+
+static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
+{
+	gchar buffer[12];
+	gsize offset, left, bread;
+	GIOStatus iostatus;
+
+	if (cond & (G_IO_ERR | G_IO_HUP))
+		goto failed;
+
+	offset = 0;
+	left = sizeof(buffer) - 1;
+	memset(buffer, 0, sizeof(buffer));
+
+	do {
+		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
+								&bread, NULL);
+
+		offset += bread;
+		left -= bread;
+		if (left == 0)
+			break;
+	} while (iostatus == G_IO_STATUS_NORMAL);
+
+	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
+		suspend_cb();
+	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
+		resume_cb();
+
+	return TRUE;
+
+failed:
+	/*
+	 * Both ends needs to be open simultaneously before proceeding any input
+	 * or output operation. When the remote closes the channel, hup signal is
+	 * received on this end.
+	 */
+
+	g_io_channel_unref(fifoio);
+	fifoio = NULL;
+
+	fifo_open();
+
+	return FALSE;
+}
+
+static int fifo_open(void)
+{
+	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
+	int fd;
+
+	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		int err = -errno;
+		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	fifoio = g_io_channel_unix_new(fd);
+	g_io_channel_set_close_on_unref(fifoio, TRUE);
+
+	g_io_add_watch(fifoio, condition, read_fifo, NULL);
+
+	return 0;
+}
 
 int suspend_init(suspend_event suspend, resume_event resume)
 {
+	int ret;
+
 	suspend_cb = suspend;
 	resume_cb = resume;
 
-	return 0;
+	if (mkfifo(HOG_SUSPEND_FIFO, S_IRWXU) < 0) {
+		int err = -errno;
+		error("Can't create FIFO (%s) : %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	ret = fifo_open();
+	if (ret < 0)
+		remove(HOG_SUSPEND_FIFO);
+
+	return ret;
 }
 
 void suspend_exit(void)
 {
+	if (fifoio) {
+		g_io_channel_shutdown(fifoio, FALSE, NULL);
+		g_io_channel_unref(fifoio);
+	}
+
+	remove(HOG_SUSPEND_FIFO);
 }
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 5/6] hog: Move HoG device list to manager
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
                       ` (3 preceding siblings ...)
  2012-09-03 18:23     ` [PATCH BlueZ v2 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-03 18:23     ` [PATCH BlueZ v2 6/6] hog: Add writting Control Point Claudio Takahasi
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch moves the HoG device list from hog_device.c to hog_manager.c
in order to be possible to easily notify suspend/resume events to each
created device.
---
 profiles/input/hog_device.c  | 46 +++++++++++++++++++++-----------------------
 profiles/input/hog_device.h  |  8 ++++++--
 profiles/input/hog_manager.c | 22 +++++++++++++++++++--
 3 files changed, 48 insertions(+), 28 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 664c52b..6f73ede 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -94,8 +94,6 @@ struct report {
 	struct hog_device	*hogdev;
 };
 
-static GSList *devices = NULL;
-
 static gint report_handle_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct report *report = a;
@@ -629,7 +627,7 @@ static void attio_disconnected_cb(gpointer user_data)
 	hogdev->attrib = NULL;
 }
 
-static struct hog_device *find_device_by_path(GSList *list, const char *path)
+struct hog_device *hog_device_find(GSList *list, const char *path)
 {
 	for (; list; list = list->next) {
 		struct hog_device *hogdev = list->data;
@@ -691,31 +689,33 @@ static void hog_device_free(struct hog_device *hogdev)
 	g_free(hogdev);
 }
 
-int hog_device_register(struct btd_device *device, const char *path)
+struct hog_device *hog_device_register(struct btd_device *device,
+					const char *path, int *perr)
 {
-	struct hog_device *hogdev;
 	struct gatt_primary *prim;
+	struct hog_device *hogdev;
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
-
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev)
-		return -EALREADY;
+	int err;
 
 	prim = load_hog_primary(device);
-	if (!prim)
-		return -EINVAL;
+	if (!prim) {
+		err = -EINVAL;
+		goto failed;
+	}
 
 	hogdev = hog_device_new(device, path);
-	if (!hogdev)
-		return -ENOMEM;
+	if (!hogdev) {
+		err = -ENOMEM;
+		goto failed;
+	}
 
 	hogdev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
 	if (hogdev->uhid_fd < 0) {
-		int err = -errno;
+		err = -errno;
 		error("Failed to open uHID device: %s", strerror(-err));
 		hog_device_free(hogdev);
-		return err;
+		goto failed;
 	}
 
 	io = g_io_channel_unix_new(hogdev->uhid_fd);
@@ -733,20 +733,19 @@ int hog_device_register(struct btd_device *device, const char *path)
 
 	device_set_auto_connect(device, TRUE);
 
-	devices = g_slist_append(devices, hogdev);
+	return hogdev;
 
-	return 0;
+failed:
+	if (perr)
+		*perr = err;
+
+	return NULL;
 }
 
-int hog_device_unregister(const char *path)
+int hog_device_unregister(struct hog_device *hogdev)
 {
-	struct hog_device *hogdev;
 	struct uhid_event ev;
 
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev == NULL)
-		return -EINVAL;
-
 	btd_device_remove_attio_callback(hogdev->device, hogdev->attioid);
 
 	if (hogdev->uhid_watch_id) {
@@ -762,7 +761,6 @@ int hog_device_unregister(const char *path)
 	close(hogdev->uhid_fd);
 	hogdev->uhid_fd = -1;
 
-	devices = g_slist_remove(devices, hogdev);
 	hog_device_free(hogdev);
 
 	return 0;
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index 597dc7c..efb7b4f 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -25,5 +25,9 @@
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
-int hog_device_register(struct btd_device *device, const char *path);
-int hog_device_unregister(const char *path);
+struct hog_device;
+
+struct hog_device *hog_device_register(struct btd_device *device,
+						const char *path, int *perr);
+int hog_device_unregister(struct hog_device *hogdev);
+struct hog_device *hog_device_find(GSList *list, const char *path);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 98f8158..25974c4 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -40,6 +40,7 @@
 #include "hog_device.h"
 
 static gboolean suspend_supported = FALSE;
+static GSList *devices = NULL;
 
 static void suspend_callback(void)
 {
@@ -54,19 +55,36 @@ static void resume_callback(void)
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
 {
 	const char *path = device_get_path(device);
+	struct hog_device *hogdev;
+	int err;
 
 	DBG("path %s", path);
 
-	return hog_device_register(device, path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev)
+		return -EALREADY;
+
+	hogdev = hog_device_register(device, path, &err);
+	if (hogdev == NULL)
+		return err;
+
+	devices = g_slist_append(devices, hogdev);
+
+	return 0;
 }
 
 static void hog_device_remove(struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
+	struct hog_device *hogdev;
 
 	DBG("path %s", path);
 
-	hog_device_unregister(path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev) {
+		devices = g_slist_remove(devices, hogdev);
+		hog_device_unregister(hogdev);
+	}
 }
 
 static struct btd_profile hog_profile = {
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v2 6/6] hog: Add writting Control Point
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
                       ` (4 preceding siblings ...)
  2012-09-03 18:23     ` [PATCH BlueZ v2 5/6] hog: Move HoG device list to manager Claudio Takahasi
@ 2012-09-03 18:23     ` Claudio Takahasi
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
  6 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-03 18:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds GATT write without response operation when suspending
or resuming.
---
 profiles/input/hog_device.c  | 27 ++++++++++++++++++++++++++-
 profiles/input/hog_device.h  |  1 +
 profiles/input/hog_manager.c | 16 ++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 6f73ede..e68134c 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -57,6 +57,7 @@
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
 #define HOG_PROTO_MODE_UUID	0x2A4E
+#define HOG_CONTROL_POINT_UUID	0x2A4C
 
 #define HOG_REPORT_TYPE_INPUT	1
 #define HOG_REPORT_TYPE_OUTPUT	2
@@ -84,6 +85,7 @@ struct hog_device {
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
 	uint16_t		proto_mode_handle;
+	uint16_t		ctrlpt_handle;
 	uint8_t			flags;
 };
 
@@ -439,7 +441,8 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
+	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid,
+		  ctrlpt_uuid;
 	struct report *report;
 	GSList *l;
 	uint16_t info_handle = 0, proto_mode_handle = 0;
@@ -454,6 +457,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
 	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
 	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
+	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
 
 	for (l = chars; l; l = g_slist_next(l)) {
 		struct gatt_char *chr, *next;
@@ -482,6 +486,8 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 			info_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
 			proto_mode_handle = chr->value_handle;
+		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
+			hogdev->ctrlpt_handle = chr->value_handle;
 	}
 
 	if (proto_mode_handle) {
@@ -765,3 +771,22 @@ int hog_device_unregister(struct hog_device *hogdev)
 
 	return 0;
 }
+
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend)
+{
+	uint8_t value = suspend ? 0x00 : 0x01;
+
+	if (hogdev->attrib == NULL)
+		return -ENOTCONN;
+
+	DBG("%s HID Control Point: %s", hogdev->path, suspend ?
+						"Suspend" : "Exit Suspend");
+
+	if (hogdev->ctrlpt_handle == 0)
+		return -ENOTSUP;
+
+	gatt_write_char(hogdev->attrib, hogdev->ctrlpt_handle, &value,
+					sizeof(value), NULL, NULL);
+
+	return 0;
+}
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index efb7b4f..03f1c90 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -31,3 +31,4 @@ struct hog_device *hog_device_register(struct btd_device *device,
 						const char *path, int *perr);
 int hog_device_unregister(struct hog_device *hogdev);
 struct hog_device *hog_device_find(GSList *list, const char *path);
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 25974c4..d770b2a 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -42,14 +42,30 @@
 static gboolean suspend_supported = FALSE;
 static GSList *devices = NULL;
 
+static void set_suspend(gpointer data, gpointer user_data)
+{
+	struct hog_device *hogdev = data;
+	gboolean suspend = GPOINTER_TO_INT(user_data);
+
+	hog_device_set_control_point(hogdev, suspend);
+}
+
 static void suspend_callback(void)
 {
+	gboolean suspend = TRUE;
+
 	DBG("Suspending ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static void resume_callback(void)
 {
+	gboolean suspend = FALSE;
+
 	DBG("Resuming ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static int hog_device_probe(struct btd_device *device, GSList *uuids)
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 0/6] HoG Suspend/Resume
  2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
                       ` (5 preceding siblings ...)
  2012-09-03 18:23     ` [PATCH BlueZ v2 6/6] hog: Add writting Control Point Claudio Takahasi
@ 2012-09-25 15:34     ` Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 1/6] hog: Add initial files for suspend support Claudio Takahasi
                         ` (5 more replies)
  6 siblings, 6 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series adds HID Control Point support. This control point
allows the report host(BlueZ) to notify the report device(HoG device)
when the host is entering or leaving the Suspend Mode.

The low power Suspend Mode concept is implementation specific. This
proposal adds a selectable back-end for HoG Suspend/Resume control.
Each platform is free to write it's own HoG suspend back-end.
A dummy back-end based on a FIFO (/tmp/hogsuspend) is proposed for
reference and testing purpose only. Writting "suspend" or "resume"
in this FIFO will trigger the update of the HID Control Point.

Notify the HoG device is useful to save power. Devices can implement
different actions (diff than disconnect) when commands are written
on the HID control point. The HoG capable device can reduce the key
press detection frequency or disable LEDs.

*** v1 changes:
Replaces UPower by a dummy selectable back-end. As discussed in IRC
tracking UPower "suspending" or "resuming" signals are not suitable
for desktops since the connection is dropped right after detecting
	suspend.

*** v2 changes:
Code rebased and fixed conflicts with the recent changes. Due the
new profile abstraction (btd_device drivers replaces) v1 doesn't apply.

*** v3 changes:
Code rebased: conflicts with profile parameter in device probe.

Claudio Takahasi (6):
  hog: Add initial files for suspend support
  hog: Add suspend back-end selection
  hog: Add suspend/resume callbacks declaration
  hog: Create a FIFO for dummy suspend
  hog: Move HoG device list to manager
  hog: Add writting Control Point

 Makefile.am                    |   6 +-
 acinclude.m4                   |   7 ++
 profiles/input/hog_device.c    |  73 ++++++++++++++-------
 profiles/input/hog_device.h    |   9 ++-
 profiles/input/hog_manager.c   |  62 ++++++++++++++++-
 profiles/input/suspend-dummy.c | 146 +++++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       |  29 ++++++++
 7 files changed, 302 insertions(+), 30 deletions(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

-- 
1.7.12


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 1/6] hog: Add initial files for suspend support
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 2/6] hog: Add suspend back-end selection Claudio Takahasi
                         ` (4 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds the initial files to support HoG suspend. The suspend
concept for HoG is implementation specific. The proposal is allowing
back-end selection at build time. Each Linux distribution/platform is
responsible for defining and writting their own policy to manage suspend
on HoG capable devices.

When setting the Control Point, the report device can execute actions to
save power. eg: Reduce the cycle of the key press detection or disable
LEDs.
---
 Makefile.am                    |  3 ++-
 profiles/input/hog_manager.c   | 14 ++++++++++++++
 profiles/input/suspend-dummy.c | 38 ++++++++++++++++++++++++++++++++++++++
 profiles/input/suspend.h       | 26 ++++++++++++++++++++++++++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 profiles/input/suspend-dummy.c
 create mode 100644 profiles/input/suspend.h

diff --git a/Makefile.am b/Makefile.am
index 372111a..93558b2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -183,7 +183,8 @@ endif
 if HOGPLUGIN
 builtin_modules += hog
 builtin_sources += profiles/input/hog_manager.c profiles/input/hog_device.h \
-			profiles/input/hog_device.c profiles/input/uhid_copy.h
+			profiles/input/hog_device.c profiles/input/uhid_copy.h \
+			profiles/input/suspend-dummy.c profiles/input/suspend.h
 endif
 
 if NETWORKPLUGIN
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 612c12a..8ddaf2f 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -37,8 +37,11 @@
 #include "plugin.h"
 #include "hcid.h"
 #include "device.h"
+#include "suspend.h"
 #include "hog_device.h"
 
+static gboolean suspend_supported = FALSE;
+
 static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
 								GSList *uuids)
 {
@@ -67,11 +70,22 @@ static struct btd_profile hog_profile = {
 
 static int hog_manager_init(void)
 {
+	int err;
+
+	err = suspend_init();
+	if (err < 0)
+		DBG("Suspend: %s(%d)", strerror(-err), -err);
+	else
+		suspend_supported = TRUE;
+
 	return btd_profile_register(&hog_profile);
 }
 
 static void hog_manager_exit(void)
 {
+	if (suspend_supported)
+		suspend_exit();
+
 	btd_profile_register(&hog_profile);
 }
 
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
new file mode 100644
index 0000000..0a97158
--- /dev/null
+++ b/profiles/input/suspend-dummy.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "suspend.h"
+
+int suspend_init(void)
+{
+	return 0;
+}
+
+void suspend_exit(void)
+{
+}
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
new file mode 100644
index 0000000..3f37a29
--- /dev/null
+++ b/profiles/input/suspend.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nordic Semiconductor Inc.
+ *  Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ *  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
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int suspend_init(void);
+void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 2/6] hog: Add suspend back-end selection
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 1/6] hog: Add initial files for suspend support Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch series introduces back-end selection for HoG suspend drivers.
The default back-end is called "dummy", added for testing purpose only.
---
 Makefile.am  | 3 +++
 acinclude.m4 | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 93558b2..444c341 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -439,6 +439,9 @@ audio/telephony.c: audio/@TELEPHONY_DRIVER@
 profiles/sap/sap.c: profiles/sap/@SAP_DRIVER@
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
+profiles/input/suspend.c: profiles/input/@HOG_SUSPEND_DRIVER@
+	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
 scripts/%.rules:
 	$(AM_V_GEN)cp $(subst 97-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index 39b0a18..ed2d011 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -185,6 +185,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	datafiles_enable=yes
 	telephony_driver=dummy
 	sap_driver=dummy
+	hog_suspend_driver=dummy
 	dbusoob_enable=no
 	wiimote_enable=no
 	gatt_enable=no
@@ -288,6 +289,12 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		wiimote_enable=${enableval}
 	])
 
+	AC_ARG_WITH(gatt, AC_HELP_STRING([--with-hog-suspend=DRIVER], [select HoG suspend driver]), [
+		hog_suspend_driver=${withval}
+	])
+
+	AC_SUBST([HOG_SUSPEND_DRIVER], [suspend-${hog_suspend_driver}.c])
+
 	AC_ARG_ENABLE(gatt, AC_HELP_STRING([--enable-gatt], [enable gatt module]), [
 		gatt_enable=${enableval}
 	])
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 3/6] hog: Add suspend/resume callbacks declaration
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 1/6] hog: Add initial files for suspend support Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 2/6] hog: Add suspend back-end selection Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch declares the callbacks functions that intend to be used
by the suspend back-ends.
---
 profiles/input/hog_manager.c   | 12 +++++++++++-
 profiles/input/suspend-dummy.c | 10 +++++++++-
 profiles/input/suspend.h       |  5 ++++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 8ddaf2f..6d173cc 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -42,6 +42,16 @@
 
 static gboolean suspend_supported = FALSE;
 
+static void suspend_callback(void)
+{
+	DBG("Suspending ...");
+}
+
+static void resume_callback(void)
+{
+	DBG("Resuming ...");
+}
+
 static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
 								GSList *uuids)
 {
@@ -72,7 +82,7 @@ static int hog_manager_init(void)
 {
 	int err;
 
-	err = suspend_init();
+	err = suspend_init(suspend_callback, resume_callback);
 	if (err < 0)
 		DBG("Suspend: %s(%d)", strerror(-err), -err);
 	else
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 0a97158..282d3fb 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,10 +26,18 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+
 #include "suspend.h"
 
-int suspend_init(void)
+static suspend_event suspend_cb = NULL;
+static resume_event resume_cb = NULL;
+
+int suspend_init(suspend_event suspend, resume_event resume)
 {
+	suspend_cb = suspend;
+	resume_cb = resume;
+
 	return 0;
 }
 
diff --git a/profiles/input/suspend.h b/profiles/input/suspend.h
index 3f37a29..bfee3cf 100644
--- a/profiles/input/suspend.h
+++ b/profiles/input/suspend.h
@@ -22,5 +22,8 @@
  *
  */
 
-int suspend_init(void);
+typedef void (*suspend_event) (void);
+typedef void (*resume_event) (void);
+
+int suspend_init(suspend_event suspend, resume_event resume);
 void suspend_exit(void);
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
                         ` (2 preceding siblings ...)
  2012-09-25 15:34       ` [PATCH BlueZ v3 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  2012-09-28  9:58         ` Johan Hedberg
  2012-09-25 15:34       ` [PATCH BlueZ v3 5/6] hog: Move HoG device list to manager Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 6/6] hog: Add writting Control Point Claudio Takahasi
  5 siblings, 1 reply; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch creates a FIFO on "/tmp/hogsuspend" to allow the users to
test the HoG suspend(HID Control Point) when the dummy back-end is
enabled.
---
 profiles/input/suspend-dummy.c | 102 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 101 insertions(+), 1 deletion(-)

diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
index 282d3fb..f2941fe 100644
--- a/profiles/input/suspend-dummy.c
+++ b/profiles/input/suspend-dummy.c
@@ -26,21 +26,121 @@
 #include <config.h>
 #endif
 
+#include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
+#include <glib.h>
+
+#include "log.h"
 #include "suspend.h"
 
+#define HOG_SUSPEND_FIFO	"/tmp/hogsuspend"
+
 static suspend_event suspend_cb = NULL;
 static resume_event resume_cb = NULL;
+static GIOChannel *fifoio = NULL;
+
+static int fifo_open(void);
+
+static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
+{
+	gchar buffer[12];
+	gsize offset, left, bread;
+	GIOStatus iostatus;
+
+	if (cond & (G_IO_ERR | G_IO_HUP))
+		goto failed;
+
+	offset = 0;
+	left = sizeof(buffer) - 1;
+	memset(buffer, 0, sizeof(buffer));
+
+	do {
+		iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
+								&bread, NULL);
+
+		offset += bread;
+		left -= bread;
+		if (left == 0)
+			break;
+	} while (iostatus == G_IO_STATUS_NORMAL);
+
+	if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
+		suspend_cb();
+	else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
+		resume_cb();
+
+	return TRUE;
+
+failed:
+	/*
+	 * Both ends needs to be open simultaneously before proceeding any input
+	 * or output operation. When the remote closes the channel, hup signal is
+	 * received on this end.
+	 */
+
+	g_io_channel_unref(fifoio);
+	fifoio = NULL;
+
+	fifo_open();
+
+	return FALSE;
+}
+
+static int fifo_open(void)
+{
+	GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
+	int fd;
+
+	fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		int err = -errno;
+		error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	fifoio = g_io_channel_unix_new(fd);
+	g_io_channel_set_close_on_unref(fifoio, TRUE);
+
+	g_io_add_watch(fifoio, condition, read_fifo, NULL);
+
+	return 0;
+}
 
 int suspend_init(suspend_event suspend, resume_event resume)
 {
+	int ret;
+
 	suspend_cb = suspend;
 	resume_cb = resume;
 
-	return 0;
+	if (mkfifo(HOG_SUSPEND_FIFO, S_IRWXU) < 0) {
+		int err = -errno;
+		error("Can't create FIFO (%s) : %s(%d)", HOG_SUSPEND_FIFO,
+							strerror(-err), -err);
+		return err;
+	}
+
+	ret = fifo_open();
+	if (ret < 0)
+		remove(HOG_SUSPEND_FIFO);
+
+	return ret;
 }
 
 void suspend_exit(void)
 {
+	if (fifoio) {
+		g_io_channel_shutdown(fifoio, FALSE, NULL);
+		g_io_channel_unref(fifoio);
+	}
+
+	remove(HOG_SUSPEND_FIFO);
 }
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 5/6] hog: Move HoG device list to manager
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
                         ` (3 preceding siblings ...)
  2012-09-25 15:34       ` [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  2012-09-25 15:34       ` [PATCH BlueZ v3 6/6] hog: Add writting Control Point Claudio Takahasi
  5 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch moves the HoG device list from hog_device.c to hog_manager.c
in order to be possible to easily notify suspend/resume events to each
created device.
---
 profiles/input/hog_device.c  | 46 +++++++++++++++++++++-----------------------
 profiles/input/hog_device.h  |  8 ++++++--
 profiles/input/hog_manager.c | 22 +++++++++++++++++++--
 3 files changed, 48 insertions(+), 28 deletions(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 03af931..4b43d67 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -94,8 +94,6 @@ struct report {
 	struct hog_device	*hogdev;
 };
 
-static GSList *devices = NULL;
-
 static gint report_handle_cmp(gconstpointer a, gconstpointer b)
 {
 	const struct report *report = a;
@@ -629,7 +627,7 @@ static void attio_disconnected_cb(gpointer user_data)
 	hogdev->attrib = NULL;
 }
 
-static struct hog_device *find_device_by_path(GSList *list, const char *path)
+struct hog_device *hog_device_find(GSList *list, const char *path)
 {
 	for (; list; list = list->next) {
 		struct hog_device *hogdev = list->data;
@@ -691,31 +689,33 @@ static void hog_device_free(struct hog_device *hogdev)
 	g_free(hogdev);
 }
 
-int hog_device_register(struct btd_device *device, const char *path)
+struct hog_device *hog_device_register(struct btd_device *device,
+					const char *path, int *perr)
 {
-	struct hog_device *hogdev;
 	struct gatt_primary *prim;
+	struct hog_device *hogdev;
 	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
 	GIOChannel *io;
-
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev)
-		return -EALREADY;
+	int err;
 
 	prim = load_hog_primary(device);
-	if (!prim)
-		return -EINVAL;
+	if (!prim) {
+		err = -EINVAL;
+		goto failed;
+	}
 
 	hogdev = hog_device_new(device, path);
-	if (!hogdev)
-		return -ENOMEM;
+	if (!hogdev) {
+		err = -ENOMEM;
+		goto failed;
+	}
 
 	hogdev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
 	if (hogdev->uhid_fd < 0) {
-		int err = -errno;
+		err = -errno;
 		error("Failed to open uHID device: %s", strerror(-err));
 		hog_device_free(hogdev);
-		return err;
+		goto failed;
 	}
 
 	io = g_io_channel_unix_new(hogdev->uhid_fd);
@@ -733,20 +733,19 @@ int hog_device_register(struct btd_device *device, const char *path)
 
 	device_set_auto_connect(device, TRUE);
 
-	devices = g_slist_append(devices, hogdev);
+	return hogdev;
 
-	return 0;
+failed:
+	if (perr)
+		*perr = err;
+
+	return NULL;
 }
 
-int hog_device_unregister(const char *path)
+int hog_device_unregister(struct hog_device *hogdev)
 {
-	struct hog_device *hogdev;
 	struct uhid_event ev;
 
-	hogdev = find_device_by_path(devices, path);
-	if (hogdev == NULL)
-		return -EINVAL;
-
 	btd_device_remove_attio_callback(hogdev->device, hogdev->attioid);
 
 	if (hogdev->uhid_watch_id) {
@@ -762,7 +761,6 @@ int hog_device_unregister(const char *path)
 	close(hogdev->uhid_fd);
 	hogdev->uhid_fd = -1;
 
-	devices = g_slist_remove(devices, hogdev);
 	hog_device_free(hogdev);
 
 	return 0;
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index 597dc7c..efb7b4f 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -25,5 +25,9 @@
 
 #define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
 
-int hog_device_register(struct btd_device *device, const char *path);
-int hog_device_unregister(const char *path);
+struct hog_device;
+
+struct hog_device *hog_device_register(struct btd_device *device,
+						const char *path, int *perr);
+int hog_device_unregister(struct hog_device *hogdev);
+struct hog_device *hog_device_find(GSList *list, const char *path);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 6d173cc..3888c2b 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -41,6 +41,7 @@
 #include "hog_device.h"
 
 static gboolean suspend_supported = FALSE;
+static GSList *devices = NULL;
 
 static void suspend_callback(void)
 {
@@ -56,19 +57,36 @@ static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
 								GSList *uuids)
 {
 	const char *path = device_get_path(device);
+	struct hog_device *hogdev;
+	int err;
 
 	DBG("path %s", path);
 
-	return hog_device_register(device, path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev)
+		return -EALREADY;
+
+	hogdev = hog_device_register(device, path, &err);
+	if (hogdev == NULL)
+		return err;
+
+	devices = g_slist_append(devices, hogdev);
+
+	return 0;
 }
 
 static void hog_device_remove(struct btd_profile *p, struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
+	struct hog_device *hogdev;
 
 	DBG("path %s", path);
 
-	hog_device_unregister(path);
+	hogdev = hog_device_find(devices, path);
+	if (hogdev) {
+		devices = g_slist_remove(devices, hogdev);
+		hog_device_unregister(hogdev);
+	}
 }
 
 static struct btd_profile hog_profile = {
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH BlueZ v3 6/6] hog: Add writting Control Point
  2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
                         ` (4 preceding siblings ...)
  2012-09-25 15:34       ` [PATCH BlueZ v3 5/6] hog: Move HoG device list to manager Claudio Takahasi
@ 2012-09-25 15:34       ` Claudio Takahasi
  5 siblings, 0 replies; 30+ messages in thread
From: Claudio Takahasi @ 2012-09-25 15:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

This patch adds GATT write without response operation when suspending
or resuming.
---
 profiles/input/hog_device.c  | 27 ++++++++++++++++++++++++++-
 profiles/input/hog_device.h  |  1 +
 profiles/input/hog_manager.c | 16 ++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 4b43d67..a558110 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -57,6 +57,7 @@
 #define HOG_REPORT_MAP_UUID	0x2A4B
 #define HOG_REPORT_UUID		0x2A4D
 #define HOG_PROTO_MODE_UUID	0x2A4E
+#define HOG_CONTROL_POINT_UUID	0x2A4C
 
 #define HOG_REPORT_TYPE_INPUT	1
 #define HOG_REPORT_TYPE_OUTPUT	2
@@ -84,6 +85,7 @@ struct hog_device {
 	uint16_t		bcdhid;
 	uint8_t			bcountrycode;
 	uint16_t		proto_mode_handle;
+	uint16_t		ctrlpt_handle;
 	uint8_t			flags;
 };
 
@@ -439,7 +441,8 @@ static void proto_mode_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
 static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 {
 	struct hog_device *hogdev = user_data;
-	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid;
+	bt_uuid_t report_uuid, report_map_uuid, info_uuid, proto_mode_uuid,
+		  ctrlpt_uuid;
 	struct report *report;
 	GSList *l;
 	uint16_t info_handle = 0, proto_mode_handle = 0;
@@ -454,6 +457,7 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 	bt_uuid16_create(&report_map_uuid, HOG_REPORT_MAP_UUID);
 	bt_uuid16_create(&info_uuid, HOG_INFO_UUID);
 	bt_uuid16_create(&proto_mode_uuid, HOG_PROTO_MODE_UUID);
+	bt_uuid16_create(&ctrlpt_uuid, HOG_CONTROL_POINT_UUID);
 
 	for (l = chars; l; l = g_slist_next(l)) {
 		struct gatt_char *chr, *next;
@@ -482,6 +486,8 @@ static void char_discovered_cb(GSList *chars, guint8 status, gpointer user_data)
 			info_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
 			proto_mode_handle = chr->value_handle;
+		else if (bt_uuid_cmp(&uuid, &ctrlpt_uuid) == 0)
+			hogdev->ctrlpt_handle = chr->value_handle;
 	}
 
 	if (proto_mode_handle) {
@@ -765,3 +771,22 @@ int hog_device_unregister(struct hog_device *hogdev)
 
 	return 0;
 }
+
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend)
+{
+	uint8_t value = suspend ? 0x00 : 0x01;
+
+	if (hogdev->attrib == NULL)
+		return -ENOTCONN;
+
+	DBG("%s HID Control Point: %s", hogdev->path, suspend ?
+						"Suspend" : "Exit Suspend");
+
+	if (hogdev->ctrlpt_handle == 0)
+		return -ENOTSUP;
+
+	gatt_write_char(hogdev->attrib, hogdev->ctrlpt_handle, &value,
+					sizeof(value), NULL, NULL);
+
+	return 0;
+}
diff --git a/profiles/input/hog_device.h b/profiles/input/hog_device.h
index efb7b4f..03f1c90 100644
--- a/profiles/input/hog_device.h
+++ b/profiles/input/hog_device.h
@@ -31,3 +31,4 @@ struct hog_device *hog_device_register(struct btd_device *device,
 						const char *path, int *perr);
 int hog_device_unregister(struct hog_device *hogdev);
 struct hog_device *hog_device_find(GSList *list, const char *path);
+int hog_device_set_control_point(struct hog_device *hogdev, gboolean suspend);
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index 3888c2b..2d72444 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -43,14 +43,30 @@
 static gboolean suspend_supported = FALSE;
 static GSList *devices = NULL;
 
+static void set_suspend(gpointer data, gpointer user_data)
+{
+	struct hog_device *hogdev = data;
+	gboolean suspend = GPOINTER_TO_INT(user_data);
+
+	hog_device_set_control_point(hogdev, suspend);
+}
+
 static void suspend_callback(void)
 {
+	gboolean suspend = TRUE;
+
 	DBG("Suspending ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static void resume_callback(void)
 {
+	gboolean suspend = FALSE;
+
 	DBG("Resuming ...");
+
+	g_slist_foreach(devices, set_suspend, GINT_TO_POINTER(suspend));
 }
 
 static int hog_device_probe(struct btd_profile *p, struct btd_device *device,
-- 
1.7.12


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend
  2012-09-25 15:34       ` [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
@ 2012-09-28  9:58         ` Johan Hedberg
  2012-09-28 11:14           ` Johan Hedberg
  0 siblings, 1 reply; 30+ messages in thread
From: Johan Hedberg @ 2012-09-28  9:58 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth

Hi Claudio,

On Tue, Sep 25, 2012, Claudio Takahasi wrote:
> This patch creates a FIFO on "/tmp/hogsuspend" to allow the users to
> test the HoG suspend(HID Control Point) when the dummy back-end is
> enabled.
> ---
>  profiles/input/suspend-dummy.c | 102 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 101 insertions(+), 1 deletion(-)

Patches 1-3 have been applied but this one has issues:

Applying: hog: Create a FIFO for dummy suspend
WARNING:LONG_LINE: line over 80 characters
#64: FILE: profiles/input/suspend-dummy.c:84:
+	 * or output operation. When the remote closes the channel, hup signal is

Please fix and resend.

Johan

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend
  2012-09-28  9:58         ` Johan Hedberg
@ 2012-09-28 11:14           ` Johan Hedberg
  0 siblings, 0 replies; 30+ messages in thread
From: Johan Hedberg @ 2012-09-28 11:14 UTC (permalink / raw)
  To: Claudio Takahasi, linux-bluetooth

Hi Claudio,

On Fri, Sep 28, 2012, Johan Hedberg wrote:
> Hi Claudio,
> 
> On Tue, Sep 25, 2012, Claudio Takahasi wrote:
> > This patch creates a FIFO on "/tmp/hogsuspend" to allow the users to
> > test the HoG suspend(HID Control Point) when the dummy back-end is
> > enabled.
> > ---
> >  profiles/input/suspend-dummy.c | 102 ++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 101 insertions(+), 1 deletion(-)
> 
> Patches 1-3 have been applied but this one has issues:
> 
> Applying: hog: Create a FIFO for dummy suspend
> WARNING:LONG_LINE: line over 80 characters
> #64: FILE: profiles/input/suspend-dummy.c:84:
> +	 * or output operation. When the remote closes the channel, hup signal is
> 
> Please fix and resend.

Nevermind. I decided to fix this myself since I wanna move forward with
merging more patches that depend on this.

Johan

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2012-09-28 11:14 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-17 21:08 [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
2012-08-17 21:08 ` [PATCH BlueZ v0 1/5] hog: Adds initial files for suspend support Claudio Takahasi
2012-08-17 21:08 ` [PATCH BlueZ v0 2/5] hog: Add UPower Resuming/Suspending watch Claudio Takahasi
2012-08-17 21:08 ` [PATCH BlueZ v0 3/5] hog: Add Suspend/Resume callbacks Claudio Takahasi
2012-08-17 21:08 ` [PATCH BlueZ v0 4/5] hog: Move HoG device list to manager Claudio Takahasi
2012-08-17 21:08 ` [PATCH BlueZ v0 5/5] hog: Add writting Control Point Claudio Takahasi
2012-08-22 21:28 ` [PATCH BlueZ v0 0/5] HoG Suspend/Resume Claudio Takahasi
2012-08-29 20:53 ` [PATCH BlueZ v1 0/6] " Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 1/6] hog: Add initial files for suspend support Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 2/6] hog: Add suspend back-end selection Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 5/6] hog: Move HoG device list to manager Claudio Takahasi
2012-08-29 20:53   ` [PATCH BlueZ v1 6/6] hog: Add writting Control Point Claudio Takahasi
2012-09-03 18:23   ` [PATCH BlueZ v2 0/6] HoG Suspend/Resume Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 1/6] hog: Add initial files for suspend support Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 2/6] hog: Add suspend back-end selection Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 5/6] hog: Move HoG device list to manager Claudio Takahasi
2012-09-03 18:23     ` [PATCH BlueZ v2 6/6] hog: Add writting Control Point Claudio Takahasi
2012-09-25 15:34     ` [PATCH BlueZ v3 0/6] HoG Suspend/Resume Claudio Takahasi
2012-09-25 15:34       ` [PATCH BlueZ v3 1/6] hog: Add initial files for suspend support Claudio Takahasi
2012-09-25 15:34       ` [PATCH BlueZ v3 2/6] hog: Add suspend back-end selection Claudio Takahasi
2012-09-25 15:34       ` [PATCH BlueZ v3 3/6] hog: Add suspend/resume callbacks declaration Claudio Takahasi
2012-09-25 15:34       ` [PATCH BlueZ v3 4/6] hog: Create a FIFO for dummy suspend Claudio Takahasi
2012-09-28  9:58         ` Johan Hedberg
2012-09-28 11:14           ` Johan Hedberg
2012-09-25 15:34       ` [PATCH BlueZ v3 5/6] hog: Move HoG device list to manager Claudio Takahasi
2012-09-25 15:34       ` [PATCH BlueZ v3 6/6] hog: Add writting Control Point Claudio Takahasi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).