Re: [ANNOUNCE] System Inactivity Monitor v1.0
Vojtech Pavlik <[EMAIL PROTECTED]> writes: > Mine problem here is that the input device doesn't care about suspend/resume > cycles (it is a straight char driver), probably because it doesn't need to (so > far.) Low-level drivers (kbd & co) on the contrary are all bus or platform > drivers, hooking directly into suspend/resume callbacks. > > Do you mean that I should back-propagate a suspend/resume event from the > low-level drivers to the input one? Yes, but not as a callback, but instead as an input event. Hum. Usually I'm not so dumb, really. Problem) I need to know when the system goes to sleep in drivers/input/input.c. For example, as a consequence of 'echo mem >/sys/power/state'. Solution 1) My ideal input layer model would be: | SUBSYSTEM INPUT DEVICE* | ^ ^ ^ ^ +--+ | ++ +--+ events | | | | |KEYBOARD| |MOUSE | |TOUCHSCREEN| |MISC | |DEVICE | |DEVICE| |DEVICE | |DEVICE| | SUBSYSTEM INPUT DEVICE* | | | | | +--+ | ++ +--+ suspend()/resume() callbacks v v v v |KEYBOARD| |MOUSE | |TOUCHSCREEN| |MISC | |DEVICE | |DEVICE| |DEVICE | |DEVICE| Solution 2) On the contrary, you are suggesting to do this: | INPUT DEVICE | ^ ^ ^ ^ +--+ | ++ +--+ events plus || | | suspend/resume |KEYBOARD | |MOUSE| |TOUCHSCREEN| |MISC | |SUBSYSTEM| |SUBSYSTEM| |SUBSYSTEM | |SUBSYSTEM | |DEVICE* | |DEVICE* | |DEVICE*| |DEVICE* | Right? * or whatever provides suspend/resume callbacks -- >From their experience or from the recorded experience of others (history), men learn only what their passions and their metaphysical prejudices allow them to learn. - Aldous Huxley - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Vojtech Pavlik <[EMAIL PROTECTED]> writes: On Mon, Jan 29, 2007 at 11:42:08PM +0100, Alessandro Di Marco wrote: > OK, but what about the time-warp problem?. To fix it I need to know when the > system goes to sleep/resumes. In SIN I've solved via the platform driver, > introducing suspend() resume() callbacks... Well, you just need to make sure that a resume() actually is a visible event ... Sorry, but I don't see the point. Visible to what? Mine problem here is that the input device doesn't care about suspend/resume cycles (it is a straight char driver), probably because it doesn't need to (so far.) Low-level drivers (kbd & co) on the contrary are all bus or platform drivers, hooking directly into suspend/resume callbacks. Do you mean that I should back-propagate a suspend/resume event from the low-level drivers to the input one? -- There is only one thing a philosopher can be relied upon to do, and that is to contradict other philosophers. - William James - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: Hi! >The /proc/bus/input/devices has an extensible structure. You can just >add an "A:" line (for Activity) instead of adding a new proc file. > > I know, but IMO there is too much stuff to parse in there. Activity counters > are frequently accessed by daemons, and four or five concurrent daemons are the > norm in a typical X11 linux box... Syscalls are fast enough, and the file is _very_ easy (=> fast) to parse. >Also, the activity counters should IMO coincide with the event times >passed through /dev/input/event, and should not be jiffies based. >Ideally, both should be based on clock_gettime(CLOCK_MONOTONIC). > > In evdev.c do_gettimeofday() is used. Anyway I just need of a monotonic > counter, so get_jiffies_64() wouldn't be better? It isn't affected by wrapping > issues and it is probably faster than do_gtod(). Just use same time source rest of inputs already do... OK, but what about the time-warp problem?. To fix it I need to know when the system goes to sleep/resumes. In SIN I've solved via the platform driver, introducing suspend() resume() callbacks... greets, -- Technology is dominated by two types of people: those who understand what they do not manage, and those who manage what they do not understand. - Putt's Law - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Vojtech Pavlik <[EMAIL PROTECTED]> writes: On Sat, Jan 27, 2007 at 05:45:25PM +, Pavel Machek wrote: > Hi! > > >Well, I do not think your kernel code is mergeable. But bits to enable > >similar functionality in userspace probably would be mergeable. > > > > You said it :-) > > > > This patch exports to the user space the inactivity time (in msecs) of a given > > input device. Example follows: > > Looks okay to me. I guess you should sign it off, and ask Dmitry > (input maintainer) for a merge? Pavel, the submitted patch was not meant for production use: it still suffers of the time-warp problem. To fix it I need to know when the system goes to sleep/resumes. In SIN I've solved via the platform driver, introducing suspend() resume() callbacks. What do you think about? The /proc/bus/input/devices has an extensible structure. You can just add an "A:" line (for Activity) instead of adding a new proc file. I know, but IMO there is too much stuff to parse in there. Activity counters are frequently accessed by daemons, and four or five concurrent daemons are the norm in a typical X11 linux box... Anyway, I believe this should be also available through sysfs, if not only there. Pavel gives me clearance for only bits of code, so I've recycled something already done. No problem for me to switch /sys. Also, the activity counters should IMO coincide with the event times passed through /dev/input/event, and should not be jiffies based. Ideally, both should be based on clock_gettime(CLOCK_MONOTONIC). In evdev.c do_gettimeofday() is used. Anyway I just need of a monotonic counter, so get_jiffies_64() wouldn't be better? It isn't affected by wrapping issues and it is probably faster than do_gtod(). Best, -- Ambition is a poor excuse for not having sense enough to be lazy. - Edgar Bergen - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: Well, I do not think your kernel code is mergeable. But bits to enable similar functionality in userspace probably would be mergeable. You said it :-) This patch exports to the user space the inactivity time (in msecs) of a given input device. Example follows: <0> $ cat /proc/bus/input/activity 0011 0001 0001 ab41 1 0011 0002 0008 3160799 0011 0002 0008 7321 549991 0019 0005 3160799 0019 0001 3454901 0010 104d 3160799 0010 104d 2162833 The device ordering matches the /proc/bus/input/devices one, anyway I reported also vendor, product, etc. Now the daemon is trivial... Bye Ah, the interesting column is the fifth ;-) diff -ur OLD/drivers/input/input.c NEW/drivers/input/input.c --- OLD/drivers/input/input.c 2007-01-26 16:59:36.0 +0100 +++ NEW/drivers/input/input.c 2007-01-26 17:04:38.0 +0100 @@ -49,6 +49,8 @@ { struct input_handle *handle; + dev->last_activity = jiffies; + if (type > EV_MAX || !test_bit(type, dev->evbit)) return; @@ -482,6 +484,30 @@ return seq_open(file, &input_devices_seq_ops); } +static int input_activity_seq_show(struct seq_file *seq, void *v) +{ + struct input_dev *dev = container_of(v, struct input_dev, node); + + seq_printf(seq, "%04x %04x %04x %04x\t%u\n", + dev->id.bustype, dev->id.vendor, + dev->id.product, dev->id.version, + jiffies_to_msecs((long) jiffies - (long) dev->last_activity)); + + return 0; +} + +static struct seq_operations input_activity_seq_ops = { + .start = input_devices_seq_start, + .next = input_devices_seq_next, + .stop = input_devices_seq_stop, + .show = input_activity_seq_show, +}; + +static int input_proc_activity_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &input_activity_seq_ops); +} + static struct file_operations input_devices_fileops = { .owner = THIS_MODULE, .open = input_proc_devices_open, @@ -491,6 +517,15 @@ .release = seq_release, }; +static struct file_operations input_activity_fileops = { + .owner = THIS_MODULE, + .open = input_proc_activity_open, + .poll = input_proc_devices_poll, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) { /* acquire lock here ... Yes, we do need locking, I knowi, I know... */ @@ -558,15 +593,23 @@ entry->owner = THIS_MODULE; entry->proc_fops = &input_devices_fileops; - entry = create_proc_entry("handlers", 0, proc_bus_input_dir); + entry = create_proc_entry("activity", 0, proc_bus_input_dir); if (!entry) goto fail2; entry->owner = THIS_MODULE; + entry->proc_fops = &input_activity_fileops; + + entry = create_proc_entry("handlers", 0, proc_bus_input_dir); + if (!entry) + goto fail3; + + entry->owner = THIS_MODULE; entry->proc_fops = &input_handlers_fileops; return 0; + fail3: remove_proc_entry("activity", proc_bus_input_dir); fail2: remove_proc_entry("devices", proc_bus_input_dir); fail1: remove_proc_entry("input", proc_bus); return -ENOMEM; diff -ur OLD/include/linux/input.h NEW/include/linux/input.h --- OLD/include/linux/input.h 2007-01-26 16:59:38.0 +0100 +++ NEW/include/linux/input.h 2007-01-26 17:31:29.0 +0100 @@ -949,6 +949,8 @@ const char *uniq; struct input_id id; + unsigned long last_activity; + unsigned long evbit[NBITS(EV_MAX)]; unsigned long keybit[NBITS(KEY_MAX)]; unsigned long relbit[NBITS(REL_MAX)]; -- I don't think anyone should write their autobiography until after they're dead. - Samuel Goldwyn
Re: [ANNOUNCE] System Inactivity Monitor v1.0
"Scott Preece" <[EMAIL PROTECTED]> writes: On 1/25/07, Bodo Eggert <[EMAIL PROTECTED]> wrote: > Imagine one computer serving two users. Two monitors, two keyboards ... --- Good point! Of late I've been working on single-user systems, so it was not at the front of my brain, despite years of building and using multi-user systems. It's a point that multi-user systems have struggled with forever (when somebody inserts a CR in the drive mounted in the system box, which user do you pop up a media player for?). sed s/user X's screensaver/suspend to disk/g
[ANNOUNCE] System Inactivity Notifier v1.6
Hi all, I've attached the final version of SIN, a user inactivity monitor posted few days ago on this list. Since then a couple of things have been improved. For example, the acpi events have been substituted by _uevents_ (thanks Arjan for the hint!), _sysfs_ has been preferred to procfs and the event triggering logic has been optimized. Moreover, this version takes advantage from the PM callbacks, in order to correctly preserve the state among several suspend/resume cycles. The patch also contains what is needed to test conveniently the driver with udev-103. Thanks to all for the support. Best, Alessandro diff -ur --new-file SIN/Makefile SIN-NEW/Makefile --- SIN/Makefile 1970-01-01 01:00:00.0 +0100 +++ SIN-NEW/Makefile 2007-01-25 14:07:44.0 +0100 @@ -0,0 +1,43 @@ +MODLPATH = kernel/drivers/char + +#DEBUG="-D SIN_DEBUG" + +MODL = sinmod +OBJS = sin.o sysfs.o table.o input_enumerator.o + +SRCS := $(patsubst %.o,%.c,$(OBJS)) +HDRS := $(patsubst %.o,%.h,$(OBJS)) +CMDS := $(patsubst %.o,.%.o.cmd,$(OBJS)) + +ifneq ($(KERNELRELEASE),) + EXTRA_CFLAGS := $(DEBUG) + obj-m := $(MODL).o + $(MODL)-objs := $(OBJS) +else + KDIR := /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + +all: $(MODL).ko + +$(MODL).ko: $(SRCS) $(HDRS) + @$(MAKE) -C $(KDIR) M=$(PWD) modules + +im: $(MODL).ko + @sudo insmod $(MODL).ko + +rm: + @sudo rmmod $(MODL) + +rmf: + @sudo rmmod -f $(MODL) + +install: + @sudo $(MAKE) INSTALL_MOD_DIR=$(MODLPATH) -C $(KDIR) M=$(PWD) modules_install + +modules_install: + @$(MAKE) INSTALL_MOD_DIR=$(MODLPATH) -C $(KDIR) M=$(PWD) modules_install + +clean: + @$(MAKE) -C $(KDIR) M=$(PWD) clean + @rm -f Module.symvers +endif diff -ur --new-file SIN/debug.h SIN-NEW/debug.h --- SIN/debug.h 1970-01-01 01:00:00.0 +0100 +++ SIN-NEW/debug.h 2007-01-25 14:07:39.0 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007 Alessandro Di Marco + */ + +/* + * This file is part of SIN. + * + * SIN 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; version 2 of the License. + * + * SIN 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 SIN; if not, write to the Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef SIN_DEBUG +extern int debug; +#define set_debug(val) debug = (val) +#define printd(fmt...) if (unlikely(debug)) { printk("SIN: " fmt); } +#else +#define SORRY "SIN: debugging support was disabled at compile time, sorry!\n" + +#define set_debug(val) if (val) { printk(KERN_DEBUG SORRY); } +#define printd(fmt...) +#endif + +#endif /* DEBUG_H */ diff -ur --new-file SIN/etc/sin/rules.sh SIN-NEW/etc/sin/rules.sh --- SIN/etc/sin/rules.sh 1970-01-01 01:00:00.0 +0100 +++ SIN-NEW/etc/sin/rules.sh 2007-01-25 14:16:30.0 +0100 @@ -0,0 +1,43 @@ +#!/bin/bash + +set $* + +case "${HINT}" in +resume) +# if [ -f /dev/shm/blanked ] ; then +# XAUTHORITY=/home/`/bin/ps x | /bin/grep tty11 | /bin/grep auth | /usr/bin/cut -d / -f 3`/.Xauthority xset -display :0 dpms force on +# /usr/bin/smartdimmer -f `cat /dev/shm/light` -e ${UNBLANK_SPEED} +# rm -f /dev/shm/light +# rm -f /dev/shm/blanked +# else +# /usr/bin/smartdimmer -f `cat /dev/shm/light` -e ${FADING_SPEED} +# rm -f /dev/shm/light +# fi + + logger "resuming..." + ;; + +dim) +# /usr/bin/smartdimmer -g | /usr/bin/cut -d ':' -f 2 > /dev/shm/light +# /usr/bin/smartdimmer -f 1 -e ${FADING_SPEED} + + logger "dimming..." + ;; + +blank) +# XAUTHORITY=/home/`/bin/ps x | /bin/grep tty11 | /bin/grep auth | /usr/bin/cut -d / -f 3`/.Xauthority xset -display :0 dpms force off +# touch /dev/shm/blanked + + logger "blanking..." + ;; + +sleep) +# echo mem >/sys/power/state + + logger "suspending..." + ;; + +*) + logger "SIN hint unhandled: ${HINT}" + ;; +esac diff -ur --new-file SIN/etc/sin/setup.sh SIN-NEW/etc/sin/setup.sh --- SIN/etc/sin/setup.sh 1970-01-01 01:00:00.0 +0100 +++ SIN-NEW/etc/sin/setup.sh 2007-01-25 14:13:59.0 +0100 @@ -0,0 +1,11 @@ +#!/bin/bash + +set $* + +STATE="`cat /proc/acpi/ac_adapter/ACAD/state | grep off-line`" + +if [ -n "${STATE}" ] ; then +cat /etc/sin/table.bat >/sys/class/misc/sin/table +else +cat /etc/sin/table.ac >/sys/class/misc/sin/table +fi diff -ur --new-file SIN/etc/sin/table.ac SIN-NEW/etc/sin/table.ac --- SIN/etc/sin/table.ac 1970-01-01 01:00:00.0 +0100 +++ SIN-NEW/etc/sin/table.ac 2007-01-25 14:14:15.0 +0100 @@ -0
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: > For example, the subsystem provides at kernel-level handy > hiberante/suspend/resume callbacks that I use to turn on/off the timer, > avoiding the time-warp problem. Doing that at user-level would be far more > messy... Imagine for a moment that we solve time-warp somehow. Any other problems? [I'd really like to get "is user idle" solved, but it really should not be in kernel unless it _has_ to. And time-warp probably causes problems not only for your daemon.] Hi, the two patches in attachment fix the time-warp problem and remove the procfs support. Feel free to contact me when you'll find a better way, maybe I could help. Best, >From 602a3340fa5b11e6cfff91719f85668980bb338b Mon Sep 17 00:00:00 2001 From: Alessandro Di Marco <[EMAIL PROTECTED]> Date: Wed, 24 Jan 2007 18:28:47 +0100 Subject: [PATCH] Time-warp bug fixed --- Makefile |2 + debug.h | 36 + sin.c| 174 + sin.h| 13 + table.c | 45 +--- table.h |6 +-- 6 files changed, 239 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index d45fa58..8b80de6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ MODLPATH = kernel/drivers/char +#DEBUG="-D SIN_DEBUG" + MODL = sinmod OBJS = sin.o procfs.o sysfs.o table.o input_enumerator.o acpi_enumerator.o diff --git a/debug.h b/debug.h new file mode 100644 index 000..e1c4bcc --- /dev/null +++ b/debug.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007 Alessandro Di Marco + */ + +/* + * This file is part of SIN. + * + * SIN 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; version 2 of the License. + * + * SIN 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 SIN; if not, write to the Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef SIN_DEBUG +extern int debug; +#define set_debug(val) debug = (val) +#define printd(fmt...) if (unlikely(debug)) { printk("SIN: " fmt); } +#else +#define SORRY "SIN: debugging support was disabled at compile time, sorry!\n" + +#define set_debug(val) if (val) { printk(KERN_DEBUG SORRY); } +#define printd(fmt...) +#endif + +#endif /* DEBUG_H */ diff --git a/sin.c b/sin.c index c3633ff..bf06999 100644 --- a/sin.c +++ b/sin.c @@ -24,6 +24,9 @@ #include #include #include +#include + +#include "debug.h" #include "sin.h" #include "table.h" @@ -36,7 +39,11 @@ MODULE_AUTHOR("Alessandro Di Marco <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION("System Inactivity Notifier"); MODULE_LICENSE("GPL v2"); -MODULE_VERSION("1.4"); +MODULE_VERSION("1.5"); + +#ifdef SIN_DEBUG +int debug; +#endif static struct acpi_device *acpi_device; @@ -68,27 +75,33 @@ inline void signal_interaction(void) WARN_ON(test_bit(RULE_OVER, &status) && timer_pending(&timer)); - clear_bit(RULE_WRAP, &status); - clear_bit(RULE_OVER, &status); - next = occasionally_generate_event(acpi_device, last_activity(&uact)); if (!shutdown) { - (void) mod_timer(&timer, next); + printd("mod_timer() last = %lu, next = %lu\n", + last_activity(&uact) / HZ, next / HZ); + + if (likely(mod_timer(&timer, next))) { + WARN_ON(test_bit(RULE_OVER, &status)); + } } + + clear_bit(RULE_WRAP, &status); + clear_bit(RULE_OVER, &status); } } inline void simulate_event(void) { - signal_interaction(); (void) simulate_activity(); + signal_interaction(); } static void event(struct input_handle *handle, unsigned int type, unsigned int code, int value) { + printd("user interaction at %lu\n", jiffies / HZ); simulate_event(); } @@ -122,6 +135,8 @@ void timer_fn(unsigned long data) if (!shutdown) { unsigned long next; + printd(">>>>>>>>>>>> timer_fn()\n"); + set_bit(RULE_LOCK, &status); next = timely_generate_event(acpi_device,
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: Imagine for a moment that we solve time-warp somehow. Any other problems? Well, a user-level daemon have to process a lot of data just to detect user interaction. Considering that the trackpad bandwidth is nearly 5KB/sec, probably would be better to leave my panel alone... :-/ I'd really like to get "is user idle" solved, but it really should not be in kernel unless it _has_ to. And time-warp probably causes problems not only for your daemon. IMHO signal the user-space is a kernel duty and no user-space daemon will ever make it better. There are plenty of PM daemons out there, but Linux still lacks of a decent power management. Thanks to SIN, acpid and a silly bash script I'm able to save a lot of battery and furthermore, when my friends see the dimming panel they break out: WOW, how do you succeed in running MacOS on your Vaio!?! :-( Best, -- Gratitude is not only the greatest of virtues, but the parent of all the others. - Cicero - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
"Scott Preece" <[EMAIL PROTECTED]> writes: My own hot button is making sure that the definition of what constitutes user activity is managed in exactly one place, whether in the kernel or not. My naive model would be to put the response at user level, but to provide a single point of definition in the kernel (say, /dev/useractivity or the equivalent) that the user-level daemon could listen to. Unfortunately the term "user activity" seems a bit too vague for this. IMHO different users (but also applications) present different needs that you cannot fit with a single device node. Example. The user expects that the keyboard light is turned off after 10 minutes of keyboard inactivity, disregarding the mouse movements. This makes sense since the glare at the bottom disturb the Quake sessions. :-) However when the screen is blanked, the user expects that either keyboard or mouse events can unblank it... -- All of the significant battles are waged within the self. - Sheldon Kopp - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: >But I still believe it can be out. > > Do you believe it could be a user-space daemon or what? Yes, what prevents userspace daemon watching /dev/input/event* to provide this functionality? Well that was my first attempt. Just an hack, but it works. Nonetheless I found the kernel-level approach fitting better the problem: it is elegant, simpler and more efficient than user-level one. For example, the subsystem provides at kernel-level handy hiberante/suspend/resume callbacks that I use to turn on/off the timer, avoiding the time-warp problem. Doing that at user-level would be far more messy... Bye -- An age is called Dark not because the light fails to shine, but because people refuse to see it. - James Michener, Space - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: Hi! >> +if [ ! -d "/proc/sin" ]; then >> +echo "/proc/sin not found, has sinmod been loaded?" >> +exit >> +fi > >No new /proc files, please. > > This was merely a prototype realized in a hurry, not a production > driver. Really, I did't think it could be interesting for anybody. > > Would be /sys ok? If it has to be in kernel, /sys/power is probably ok. Doh! The attached patch introduces /sys/class/misc (along with some bug-fixes.) In case I'll change it again. Ah, there is still a time-warp bug pending. In practice I have to turn off the timer just before suspending, hibernating, etc or it will give you hell on the next system resume... But I still believe it can be out. Do you believe it could be a user-space daemon or what? Best, >From f97e411d29d5771e3ac3d9c8e8aa4ad3ae0a27e2 Mon Sep 17 00:00:00 2001 From: Alessandro Di Marco <[EMAIL PROTECTED]> Date: Tue, 23 Jan 2007 02:21:07 +0100 Subject: [PATCH] Added sysfs support; various timer bugfix, but time warp bug is still with us. --- Makefile |2 +- acpi_enumerator.c | 27 +++-- acpi_enumerator.h |5 +- gentable | 17 +++--- input_enumerator.c | 28 -- input_enumerator.h |4 +- procfs.c | 157 procfs.h | 12 ++-- sin.c | 86 ++-- sin.h |9 ++- sysfs.c| 146 sysfs.h| 28 + table.c| 128 -- table.h|8 ++- 14 files changed, 476 insertions(+), 181 deletions(-) diff --git a/Makefile b/Makefile index a72fb3c..d45fa58 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ MODLPATH = kernel/drivers/char MODL = sinmod -OBJS = sin.o procfs.o table.o input_enumerator.o acpi_enumerator.o +OBJS = sin.o procfs.o sysfs.o table.o input_enumerator.o acpi_enumerator.o SRCS := $(patsubst %.o,%.c,$(OBJS)) HDRS := $(patsubst %.o,%.h,$(OBJS)) diff --git a/acpi_enumerator.c b/acpi_enumerator.c index c9033e5..c25a268 100644 --- a/acpi_enumerator.c +++ b/acpi_enumerator.c @@ -35,6 +35,12 @@ int get_handlers(void) return ahsize; } +size_t get_handlers_desc(char **buf) +{ + *buf = page; + return size; +} + char *get_hardware_id(int handle) { return ah[handle].hardware_id; @@ -75,11 +81,15 @@ static int acpi_show(struct acpi_device *device, struct acpi_driver *driver) return -ENOENT; } -int acpi_enum(char *buf) +int acpi_enum(void) { struct acpi_driver ad; + int err = -ENOMEM; - page = buf; + page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!page) { + goto out; + } ad.ops.match = acpi_show; (void) acpi_bus_register_driver(&ad); @@ -87,7 +97,8 @@ int acpi_enum(char *buf) if (!ahsize) { printk(KERN_NOTICE "no acpi handlers found\n"); - return -ENODEV; + err = -ENODEV; + goto cleanout; } ah = kmalloc(ahsize * sizeof (struct acpi_handlers), GFP_KERNEL); @@ -95,14 +106,19 @@ int acpi_enum(char *buf) ahsize = 0; if (!ah) { - return -ENOMEM; + goto cleanout; } ad.ops.match = acpi_store; (void) acpi_bus_register_driver(&ad); acpi_bus_unregister_driver(&ad); - return size; + return 0; + +cleanout: + kfree(page); +out: + return err; } void free_acpi_enum(void) @@ -110,5 +126,6 @@ void free_acpi_enum(void) if (ahsize) { ahsize = 0; kfree(ah); + kfree(page); } } diff --git a/acpi_enumerator.h b/acpi_enumerator.h index 998db65..0b75a09 100644 --- a/acpi_enumerator.h +++ b/acpi_enumerator.h @@ -29,8 +29,11 @@ struct acpi_handlers { }; extern int get_handlers(void); +extern size_t get_handlers_desc(char **buf); + extern char *get_hardware_id(int handle); -extern int acpi_enum(char *page); + +extern int acpi_enum(void); extern void free_acpi_enum(void); #endif /* ACPI_ENUMERATOR_H */ diff --git a/gentable b/gentable index 3a322df..49af1f4 100755 --- a/gentable +++ b/gentable @@ -119,22 +119,21 @@ interaction occurs when SIN, as well as the kernel, cannot capture it. As a consequence, no event will ever be generated and the system will remain in the state associated with the next-to-last rule (e.g. blanked screen, wireless powered off, etc.). The next option allows you to request a special event, -resetting the global counter to an arbitrary value, so to restart the rule-list -evaluation. Possible value ranges are described below, where N is the maximum -counter in the current rule list: +restarting the rule-list evaluation from an arbitrary position. Possible value +ranges are described below, where N is the rule-list size: -[0, N]=> reset the global counter to the specified value -otherwise => do nothing, the glob
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Pavel Machek <[EMAIL PROTECTED]> writes: > +if [ ! -d "/proc/sin" ]; then > +echo "/proc/sin not found, has sinmod been loaded?" > +exit > +fi No new /proc files, please. This was merely a prototype realized in a hurry, not a production driver. Really, I did't think it could be interesting for anybody. Would be /sys ok? > +cat < + > +SIN wakes up periodically and checks for user activity occurred in the > +meantime; this options lets you to specify how much frequently SIN should be > +woken-up. Its value is expressed in tenth of seconds. Heh. We'll waste power trying to save it. Well, not just a power saver. For example I use SIN to auto-logoff my bash session as well (detaching the screen session.) If you have to hook it into kernel, can you at least do it properly? Of course. You can find attached a patch fixing this. Now SIN wakes up just when it expects to do something: if in the meantime the user interacts with the system, SIN simply recalculates the next wake-up time on the basis of the last user's activity date and goes to sleep again. Best, --- gentable | 72 +- procfs.c |2 +- sin.c| 68 sin.h| 36 - table.c | 132 -- table.h | 21 +- 6 files changed, 176 insertions(+), 155 deletions(-) diff --git a/gentable b/gentable index 44b4f77..3a322df 100755 --- a/gentable +++ b/gentable @@ -31,23 +31,9 @@ fi cat < reset the global counter to the specified value @@ -150,7 +134,7 @@ if [ -z "${reset}" ]; then reset="-1" fi -echo -e "[EMAIL PROTECTED] [EMAIL PROTECTED]@]}\n${handle}\n${reset}\n${resume}" > $1 +echo -e "[EMAIL PROTECTED] [EMAIL PROTECTED]@]}\n${handle}\n${reset}\n${resume}" > $1 for (( i = 0; ${i}<[EMAIL PROTECTED]; i++ )); do echo "${rules[${i}]}" >> $1 @@ -163,8 +147,8 @@ All done. Now you can try your newly generated table as follows: # modprobe sinmod # echo $1 >/proc/sin/table -An "Invalid argument" error indicates a mismatch in the table file, usually -due to specifying an invalid acpi or input device. In that case, restart from +An "Invalid argument" error indicates a mismatch in the table file, usually due +to specifying an invalid acpi or input device. In that case, restart from scratch, double checking your inputs. Have fun! EOF diff --git a/procfs.c b/procfs.c index 4424645..5929f90 100644 --- a/procfs.c +++ b/procfs.c @@ -174,7 +174,7 @@ int start_procfs(void) goto cleanout9; } - interact->data = (void *) simulate_interaction; + interact->data = (void *) simulate_event; interact->write_proc = fake_write_proc; interact->owner = THIS_MODULE; diff --git a/sin.c b/sin.c index c490daa..0d9b9c4 100644 --- a/sin.c +++ b/sin.c @@ -28,18 +28,19 @@ #include "table.h" #include "procfs.h" -MODULE_AUTHOR("Alessandro Di Marco <[EMAIL PROTECTED]>"); +MODULE_AUTHOR("Alessandro Di Marco <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION("System Inactivity Notifier"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("blanker"); - -MODULE_VERSION("1.2"); +MODULE_VERSION("1.3"); static struct acpi_device *acpi_device; -static atomic_t interactions; -static unsigned long notify; +static struct user_activity uact = { + .lock = SPIN_LOCK_UNLOCKED, +}; + +static unsigned long status; static struct timer_list timer; static int shutdown; @@ -49,20 +50,31 @@ static struct input_handler ih; static DEFINE_MUTEX(runlock); static int running; +inline unsigned long simulate_activity(void) +{ + return register_activity(&uact); +} + inline void signal_interaction(void) { - if (unlikely(test_and_clear_bit(0, ¬ify))) { - clear_bit(1, ¬ify); + if (unlikely(test_bit(RULE_LOCK, &status))) { + set_bit(RULE_MARK, &status); + } else if (unlikely(test_and_clear_bit(RULE_TRIG, &status))) { + clear_bit(RULE_WRAP, &status); occasionally_generate_event(acpi_device); } } -static void event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +inline void simulate_event(void) { signal_interaction(); + (void) simulate_activity(); +} - atomic_inc(&interactions); +static void event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ + simulate_event(); } static struct input_handle *connect(struct input_handler *handler, @@ -90,20 +102,23 @@ static void disconnect(struct input_handle *handle) kfree(handle); } -void timer_fn(unsigned long pace) +void timer_fn(unsigned long data) { if (!shutdown) { - if (unlikely(test_and_clear_bit(1, ¬ify) && - test_and_clear_bit(0, ¬ify))) { - o
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Bill Davidsen <[EMAIL PROTECTED]> writes: Alessandro Di Marco wrote: > Hi all, > > this is a new 2.6.20 module implementing a user inactivity trigger. Basically > it acts as an event sniffer, issuing an ACPI event when no user activity is > detected for more than a certain amount of time. This event can be successively > grabbed and managed by an user-level daemon such as acpid, blanking the screen, > dimming the lcd-panel light à la mac, etc... Any idea how much power this saves? And for the vast rest of us who do run X, this seems to parallel the work of a well-tuned screensaver. This is just a notifier; to make it work as a screensaver you'll have to rely on some external programs. Personally I use smartdimmer to dim my vaio panel. Obviously you can keep your toaster flying, if you like, simply calling the flying-toaster module instead of smartdimmer. Anyway I would use the latter on battery. ;-) Best, -- "What made the deepest impression upon you?" inquired a friend one day of Lincoln, "when you stood in the presence of the Falls of Niagara, the greatest of natural wonders?" "The thing that stuck me most forcibly when I saw the Falls," Lincoln responded with the characteristic deliberation, "was where in the world did all that water come from?" - Author Unknown - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [ANNOUNCE] System Inactivity Monitor v1.0
Arjan van de Ven <[EMAIL PROTECTED]> writes: On Thu, 2007-01-18 at 20:29 +0100, Alessandro Di Marco wrote: > Hi all, > > this is a new 2.6.20 module implementing a user inactivity trigger. Basically > it acts as an event sniffer, issuing an ACPI event when no user activity is > detected for more than a certain amount of time. This event can be successively > grabbed and managed by an user-level daemon such as acpid, blanking the screen, > dimming the lcd-panel light à la mac, etc... Hi, why did you chose an ACPI event? I'd expect a uevent (which dbus captures etc) to be a more logical choice.. Laziness... :) Just an idea realized in a hurry to dim my laptop panel when it is in idle (I don't use X11, so no xscreensaver et simila.) Anyway I can accommodate it, if someone of you thinks that it is interesting enough to be carried on the business. The patch in attachment fixes some silly bugs of the previous version. Regards, diff -uN old/procfs.c new/procfs.c --- old/procfs.c 2007-01-19 15:24:12.0 +0100 +++ new/procfs.c 2007-01-19 15:20:26.0 +0100 @@ -89,9 +89,19 @@ return err; } +static int fake_write_proc(struct file *file, const __user char *ubuf, + unsigned long count, void *data) +{ + void (*func)(void) = data; + + func(); + return count; +} + int start_procfs(void) { - struct proc_dir_entry *inputd, *acpid, *table, *ilink, *alink; + struct proc_dir_entry *inputd, *acpid, + *table, *interact, *ilink, *alink; int err = -ENOMEM; @@ -159,24 +169,35 @@ table->write_proc = write_proc; table->owner = THIS_MODULE; + interact = create_proc_entry("interact", 0200, rootdir); + if (!interact) { + goto cleanout9; + } + + interact->data = (void *) simulate_interaction; + interact->write_proc = fake_write_proc; + interact->owner = THIS_MODULE; + ilink = proc_symlink("sources", rootdir, "input"); if (!ilink) { - goto cleanout9; + goto cleanout10; } ilink->owner = THIS_MODULE; alink = proc_symlink("destinations", rootdir, "acpi"); if (!alink) { - goto cleanout10; + goto cleanout11; } alink->owner = THIS_MODULE; return 0; -cleanout10: +cleanout11: remove_proc_entry("sources", rootdir); +cleanout10: + remove_proc_entry("interact", rootdir); cleanout9: remove_proc_entry("table", rootdir); cleanout8: @@ -203,6 +224,7 @@ { remove_proc_entry("destinations", rootdir); remove_proc_entry("sources", rootdir); + remove_proc_entry("interact", rootdir); remove_proc_entry("table", rootdir); remove_proc_entry("acpi", rootdir); remove_proc_entry("input", rootdir); diff -uN old/sin.c new/sin.c --- old/sin.c 2007-01-19 15:24:12.0 +0100 +++ new/sin.c 2007-01-19 15:20:26.0 +0100 @@ -34,7 +34,7 @@ MODULE_ALIAS("blanker"); -MODULE_VERSION("1.0"); +MODULE_VERSION("1.2"); static struct acpi_device *acpi_device; @@ -49,13 +49,18 @@ static DEFINE_MUTEX(runlock); static int running; -static void event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) +inline void signal_interaction(void) { if (unlikely(test_and_clear_bit(0, ¬ify))) { clear_bit(1, ¬ify); occasionally_generate_event(acpi_device); } +} + +static void event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ + signal_interaction(); atomic_inc(&interactions); } @@ -166,8 +171,13 @@ if (running) { shutdown = 1; del_timer_sync(&timer); + input_unregister_handler(&ih); kfree(ih.id_table); + + signal_interaction(); + cleanup_table(); + running = 0; } @@ -176,14 +186,14 @@ static int __init sih_init(void) { - printk("System Inactivity Notifier 1.0 - (c) Alessandro Di Marco <[EMAIL PROTECTED]>\n"); + printk("System Inactivity Notifier 1.2 - (c) Alessandro Di Marco <[EMAIL PROTECTED]>\n"); return start_procfs(); } static void __exit sih_exit(void) { stop_procfs(); - stop_monitor(); + (void) stop_monitor(); } module_init(sih_init); diff -uN old/sin.h new/sin.h --- old/sin.h 2007-01-19 15:24:12.0 +0100 +++ new/sin.h 2007-01-19 15:20:26.0 +0100 @@ -26,6 +26,8 @@ #define MODULE_NAME "sin" +extern void signal_interaction(void); + extern int start_monitor(char *ids, struct input_device_id *idi, unsigned long pace); extern void stop_monitor(void); diff -uN old/table.c new/table.c --- old/table.c 2007-01-19 15:24:12.0 +0100 +++ new/table.c 2007-01-19 15:20:26.0 +0100 @@ -32,7 +32,7 @@ #include "acpi_enumerator.h" static struct table rt; -static int debug; +static int counter, action; /* * WARNING: sonypi, buttons and others issue a spurious event when removed from @@ -42,7 +
[ANNOUNCE] System Inactivity Monitor v1.0
Hi all, this is a new 2.6.20 module implementing a user inactivity trigger. Basically it acts as an event sniffer, issuing an ACPI event when no user activity is detected for more than a certain amount of time. This event can be successively grabbed and managed by an user-level daemon such as acpid, blanking the screen, dimming the lcd-panel light à la mac, etc... For the interested guys I have included a bash configuration helper (called gentable) that covers the details. Best, diff -uN SIN/Makefile SIN.new/Makefile --- SIN/Makefile 1970-01-01 01:00:00.0 +0100 +++ SIN.new/Makefile 2007-01-18 19:20:59.0 +0100 @@ -0,0 +1,41 @@ +MODLPATH = kernel/drivers/char + +MODL = sinmod +OBJS = sin.o procfs.o table.o input_enumerator.o acpi_enumerator.o + +SRCS := $(patsubst %.o,%.c,$(OBJS)) +HDRS := $(patsubst %.o,%.h,$(OBJS)) +CMDS := $(patsubst %.o,.%.o.cmd,$(OBJS)) + +ifneq ($(KERNELRELEASE),) + EXTRA_CFLAGS := $(DEBUG) + obj-m := $(MODL).o + $(MODL)-objs := $(OBJS) +else + KDIR := /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + +all: $(MODL).ko + +$(MODL).ko: $(SRCS) $(HDRS) + @$(MAKE) -C $(KDIR) M=$(PWD) modules + +im: $(MODL).ko + @sudo insmod $(MODL).ko + +rm: + @sudo rmmod $(MODL) + +rmf: + @sudo rmmod -f $(MODL) + +install: + @sudo $(MAKE) INSTALL_MOD_DIR=$(MODLPATH) -C $(KDIR) M=$(PWD) modules_install + +modules_install: + @$(MAKE) INSTALL_MOD_DIR=$(MODLPATH) -C $(KDIR) M=$(PWD) modules_install + +clean: + @$(MAKE) -C $(KDIR) M=$(PWD) clean + @rm -f Module.symvers +endif diff -uN SIN/acpi_enumerator.c SIN.new/acpi_enumerator.c --- SIN/acpi_enumerator.c 1970-01-01 01:00:00.0 +0100 +++ SIN.new/acpi_enumerator.c 2007-01-18 19:20:53.0 +0100 @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2007 Alessandro Di Marco + */ + +/* + * This file is part of SIN. + * + * SIN 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; version 2 of the License. + * + * SIN 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 SIN; if not, write to the Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "acpi_enumerator.h" + +static struct acpi_handlers *ah; +static int ahsize; + +static char *page; +static size_t size; + +int get_handlers(void) +{ + return ahsize; +} + +char *get_hardware_id(int handle) +{ + return ah[handle].hardware_id; +} + +static int acpi_store(struct acpi_device *device, struct acpi_driver *driver) +{ + if (device->flags.hardware_id) { + strcpy(ah[ahsize++].hardware_id, + acpi_device_hid(device)); + } + + return -ENOENT; +} + +static int acpi_show(struct acpi_device *device, struct acpi_driver *driver) +{ + if (device->flags.hardware_id && size < PAGE_SIZE) { + int err; + + err = snprintf(&page[size], + PAGE_SIZE - size, + "%d: %s [%s, %lx]\n", + ahsize++, + acpi_device_hid(device), + acpi_device_bid(device), + acpi_device_adr(device)); + + if (err >= PAGE_SIZE - size) { + err = PAGE_SIZE - size; + } + + if (err > 0) { + size += err; + } + } + + return -ENOENT; +} + +int acpi_enum(char *buf) +{ + struct acpi_driver ad; + + page = buf; + + ad.ops.match = acpi_show; + (void) acpi_bus_register_driver(&ad); + acpi_bus_unregister_driver(&ad); + + if (!ahsize) { + printk(KERN_NOTICE "no acpi handlers found\n"); + return -ENODEV; + } + + ah = kmalloc(ahsize * sizeof (struct acpi_handlers), GFP_KERNEL); + + ahsize = 0; + + if (!ah) { + return -ENOMEM; + } + + ad.ops.match = acpi_store; + (void) acpi_bus_register_driver(&ad); + acpi_bus_unregister_driver(&ad); + + return size; +} + +void free_acpi_enum(void) +{ + if (ahsize) { + ahsize = 0; + kfree(ah); + } +} diff -uN SIN/acpi_enumerator.h SIN.new/acpi_enumerator.h --- SIN/acpi_enumerator.h 1970-01-01 01:00:00.0 +0100 +++ SIN.new/acpi_enumerator.h 2007-01-18 19:20:53.00000 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007 Alessandro Di Marco + */ + +/* + * This file is part of SIN. + * + * SIN 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; version 2 of the License. + * + * SIN 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 alo