DORMANTno replies

[PATCH 2/4] Bluez: input: ps3remote driver power-saving

From: Ruslan N. Marchenko <hidden>
Date: 2009-09-26 14:29:01
Subsystem: the rest · Maintainer: Linus Torvalds

PS3 Remote driver is now using IdleTimeout config parameter for
power-saving purpose. It disconnects BT channel when remote is
idle for IdleTimeout seconds, and remote after loosing BT channel
enters low-power mode. To minimize delay caused by re-connecting,
uinput device handler is held for daemon's lifetime, thus key-press
which forced remote to reconnect is sent immediately to the OS.
Default timeout, when IdleTimeout is not specified, or is less
then 5 seconds - is 15 seconds.

Signed-off-by: Ruslan N. Marchenko <redacted>
---
 input/fakehid.c |   39 ++++++++++++++++++++++++++++++++++-----
 input/fakehid.h |    1 +
 2 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/input/fakehid.c b/input/fakehid.c
index 75c2650..b068e22 100644
--- a/input/fakehid.c
+++ b/input/fakehid.c
@@ -31,11 +31,13 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <sys/stat.h>

 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/hidp.h>
 #include <bluetooth/sdp.h>
+#include <bluetooth/hci.h>

 #include <glib.h>
 #include <dbus/dbus.h>
@@ -208,6 +210,22 @@ error:
 	return -1;
 }

+static gboolean ps3remote_out(GIOChannel *chan, GIOCondition cond,
+                                gpointer data)
+{
+	struct ps3remote_data *ps3 = ((struct fake_input *)data)->data;
+	const struct input_device *idev = ((struct fake_input *)data)->idev;
+	uint16_t to = (ps3->timeout < 5) ? 15 : ps3->timeout;
+	gulong ms;
+
+	if(g_timer_elapsed(ps3->timer,&ms) > to) {
+		DBG("idle timeout, disconnecting BT channel");
+		device_request_disconnect(idev->device, NULL);
+		return FALSE;
+	} else
+		usleep(100);
+	return TRUE;
+}
 static gboolean ps3remote_event(GIOChannel *chan, GIOCondition cond,
 				gpointer data)
 {
@@ -264,11 +282,9 @@ static gboolean ps3remote_event(GIOChannel *chan,
GIOCondition cond,
 	return TRUE;

 failed:
-	ioctl(fake->uinput, UI_DEV_DESTROY);
-	close(fake->uinput);
-	fake->uinput = -1;
+	g_timer_stop(ps3->timer);
 	g_io_channel_unref(fake->io);
-
+	DBG("Event failed");
 	return FALSE;
 }
@@ -277,8 +293,19 @@ static int ps3remote_setup_uinput(struct fake_input *fake,
 {
 	struct uinput_dev dev;
 	struct ps3remote_data *ps3 = (struct ps3remote_data *)fake->data;
+	struct stat sbuf;
 	int i;

+	/* check if uinput already open */
+	if(fake->uinput > 0) {
+		if(!(i=fstat(fake->uinput, &sbuf))) {
+			DBG("input %d is opened", fake->uinput);
+			return 0;
+		} else
+			DBG("fstat(%d): error[%d]: %s", fake->uinput, i,
+							strerror(errno));
+	}
+	/* create uinput device */
 	fake->uinput = open("/dev/input/uinput", O_RDWR);
 	if (fake->uinput < 0) {
 		fake->uinput = open("/dev/uinput", O_RDWR);
@@ -334,6 +361,7 @@ static gboolean ps3remote_connect(struct
fake_input *fake, GError **err)
 {
 	if(!fake->data) {
 		struct ps3remote_data *ps3 = g_new0(struct ps3remote_data, 1);
+		ps3->timer = g_timer_new();
 		ps3->timeout = fake->idev->conf->timeout;
 		ps3->keymap = ps3remote_keymap;
 		fake->data = ps3;
@@ -359,6 +387,7 @@ static struct fake_hid fake_hid_table[] = {
 		.connect	= ps3remote_connect,
 		.disconnect	= fake_hid_common_disconnect,
 		.event		= ps3remote_event,
+		.oevent		= ps3remote_out,
 		.setup_uinput	= ps3remote_setup_uinput,
 		.fakes		= NULL,
 	},
@@ -419,6 +448,6 @@ int fake_hid_connadd(struct fake_input *fake,
GIOChannel *intr_io,
 	g_io_channel_set_close_on_unref(fake->io, TRUE);
 	g_io_add_watch(fake->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 					(GIOFunc) fake_hid->event, fake);
-
+	g_io_add_watch(fake->io, G_IO_OUT, (GIOFunc) fake_hid->oevent, fake);
 	return 0;
 }
diff --git a/input/fakehid.h b/input/fakehid.h
index bda4f43..dfac4f6 100644
--- a/input/fakehid.h
+++ b/input/fakehid.h
@@ -30,6 +30,7 @@ struct fake_hid {
 	gboolean (*connect) (struct fake_input *fake_input, GError **err);
 	int (*disconnect) (struct fake_input *fake_input);
 	gboolean (*event) (GIOChannel *chan, GIOCondition cond, gpointer data);
+	gboolean (*oevent) (GIOChannel *chan, GIOCondition cond, gpointer data);
 	int (*setup_uinput) (struct fake_input *fake, struct fake_hid *fake_hid);
 	GSList *fakes;
 };
-- 
1.6.0.4



-- 
Looking forward to reading yours.
     Ruslan N. Marchenko
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help