From owner-acpi-jp@jp.FreeBSD.org Sun Nov 10 05:33:14 2002
Received: (from daemon@localhost)
	by castle.jp.FreeBSD.org (8.11.6+3.4W/8.11.3) id gA9KXER63906;
	Sun, 10 Nov 2002 05:33:14 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from salmon.maths.tcd.ie (mmdf@salmon.maths.tcd.ie [2001:770:10:300::86e2:510b])
	by castle.jp.FreeBSD.org (8.11.6+3.4W/8.11.3) with SMTP/inet6 id gA9KXDm63900
	for <acpi-jp@jp.FreeBSD.org>; Sun, 10 Nov 2002 05:33:13 +0900 (JST)
	(envelope-from iedowse@maths.tcd.ie)
Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP
          id <aa99235@salmon>; 9 Nov 2002 20:33:06 +0000 (GMT)
To: Takanori Watanabe <takawata@axe-inc.co.jp>
cc: acpi-jp@jp.FreeBSD.org, current@freebsd.org,
   Frode Nordahl <frode@nordahl.net>
In-Reply-To: Your message of "Sun, 10 Nov 2002 04:22:45 +0900."
             <200211091922.EAA09939@axe-inc.co.jp> 
From: Ian Dowse <iedowse@maths.tcd.ie>
Message-ID:  <200211092033.aa99235@salmon.maths.tcd.ie>
Reply-To: acpi-jp@jp.FreeBSD.org
Precedence: list
Date: Sat, 09 Nov 2002 20:33:03 +0000
X-Sequence: acpi-jp 1933
Subject: [acpi-jp 1933] Re: acpid implementation? 
Errors-To: owner-acpi-jp@jp.FreeBSD.org
Sender: owner-acpi-jp@jp.FreeBSD.org
X-Originator: iedowse@maths.tcd.ie
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+021107

In message <200211091922.EAA09939@axe-inc.co.jp>, Takanori Watanabe writes:
>It is obious there will be good if we have a way to catch power 
>event from userland.
>
>I have some ideas to implement it.
>One way is implement with kqueue(2) and /dev/acpi to
>get power events. This way does not require daemons
>to wait the event exclusively. Each process that requires
>to get power event can handle it by the interface.
>I wrote the experimental code a years ago.

I've been using the following far-from-ideal patch for a while now -
it just supplies binary integers to /dev/acpi whenever the sleep
state changes. The choice of encoding of data is stupid, and the
acpiread() doesn't do blocking - I just use it in a script like

	while :; do
		sleep 5
		acpidat="`wc -c < /dev/acpi`"
		if [ "$acpidat" -gt 0 ]; then
			killall -HUP moused
		fi
	done

to send a SIGHUP to moused after a resume, which seems to be necessary
on my Vaio C1.

Ian

Index: acpi.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/acpica/acpi.c,v
retrieving revision 1.80
diff -u -r1.80 acpi.c
--- acpi.c	31 Oct 2002 20:23:41 -0000	1.80
+++ acpi.c	9 Nov 2002 20:20:10 -0000
@@ -32,6 +32,7 @@
 #include "opt_acpi.h"
 #include <sys/param.h>
 #include <sys/kernel.h>
+#include <sys/poll.h>
 #include <sys/proc.h>
 #include <sys/malloc.h>
 #include <sys/bus.h>
@@ -42,6 +43,7 @@
 #include <sys/ctype.h>
 #include <sys/linker.h>
 #include <sys/power.h>
+#include <sys/uio.h>
 
 #include <machine/clock.h>
 #include <machine/resource.h>
@@ -69,16 +71,18 @@
 
 static d_open_t		acpiopen;
 static d_close_t	acpiclose;
+static d_read_t		acpiread;
 static d_ioctl_t	acpiioctl;
+static d_poll_t		acpipoll;
 
 #define CDEV_MAJOR 152
 static struct cdevsw acpi_cdevsw = {
     acpiopen,
     acpiclose,
-    noread,
+    acpiread,
     nowrite,
     acpiioctl,
-    nopoll,
+    acpipoll,
     nommap,
     nostrategy,
     "acpi",
@@ -1327,6 +1331,9 @@
 	}
 
 	sc->acpi_sstate = state;
+	if (sc->acpi_usereventq_len < ACPI_USER_EVENTQ_LEN)
+		sc->acpi_usereventq[sc->acpi_usereventq_len++] = state;
+	selwakeup(&sc->acpi_selp);
 	sc->acpi_sleep_disabled = 1;
 
 	/*
@@ -1375,6 +1382,9 @@
 	AcpiLeaveSleepState((UINT8)state);
 	DEVICE_RESUME(root_bus);
 	sc->acpi_sstate = ACPI_STATE_S0;
+	if (sc->acpi_usereventq_len < ACPI_USER_EVENTQ_LEN)
+		sc->acpi_usereventq[sc->acpi_usereventq_len++] = ACPI_STATE_S0;
+	selwakeup(&sc->acpi_selp);
 	acpi_enable_fixed_events(sc);
 	break;
 
@@ -1808,6 +1818,35 @@
     return(0);
 }
 
+int
+acpiread(dev_t dev, struct uio *uio, int flag)
+{
+    struct acpi_softc		*sc;
+    int				bytes, error, events, i;
+
+    ACPI_LOCK;
+
+    sc = dev->si_drv1;
+
+    error = 0;
+    if (uio->uio_resid >= sizeof(int) && sc->acpi_usereventq_len > 0) {
+	events = sc->acpi_usereventq_len;
+	if (events > uio->uio_resid / sizeof(int))
+	    events = uio->uio_resid / sizeof(int);
+	bytes = events * sizeof(int);
+	error = uiomove((caddr_t)sc->acpi_usereventq, bytes, uio);
+	if (!error) {
+	    for (i = 0; i < sc->acpi_usereventq_len - events; i++)
+		sc->acpi_usereventq[i] = sc->acpi_usereventq[i + events];
+	    sc->acpi_usereventq_len -= events;
+	}
+    }
+
+    ACPI_UNLOCK;
+
+    return (error);
+}
+
 static int
 acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
 {
@@ -1871,6 +1910,25 @@
 out:
     ACPI_UNLOCK;
     return(error);
+}
+
+static  int
+acpipoll(dev_t dev, int events, d_thread_t *td)
+{
+    struct acpi_softc		*sc;
+    int				revents;
+
+    ACPI_LOCK;
+    sc = dev->si_drv1;
+
+    revents = events & (POLLOUT | POLLWRNORM);
+    if ((events & (POLLIN | POLLRDNORM)) && sc->acpi_usereventq_len > 0) {
+	revents |= (POLLIN | POLLRDNORM);
+	selrecord(td, &sc->acpi_selp);
+    }
+
+    ACPI_UNLOCK;
+    return (revents);
 }
 
 static int
Index: acpivar.h
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/dev/acpica/acpivar.h,v
retrieving revision 1.37
diff -u -r1.37 acpivar.h
--- acpivar.h	31 Oct 2002 17:58:38 -0000	1.37
+++ acpivar.h	9 Nov 2002 20:20:10 -0000
@@ -30,6 +30,7 @@
 
 #include "bus_if.h"
 #include <sys/eventhandler.h>
+#include <sys/selinfo.h>
 #include <sys/sysctl.h>
 #if __FreeBSD_version >= 500000
 #include <sys/lock.h>
@@ -50,6 +51,11 @@
     int			acpi_enabled;
     int			acpi_sstate;
     int			acpi_sleep_disabled;
+
+#define ACPI_USER_EVENTQ_LEN		4
+    int			acpi_usereventq[ACPI_USER_EVENTQ_LEN];
+    int			acpi_usereventq_len;
+    struct selinfo	acpi_selp;
 
     struct sysctl_ctx_list acpi_sysctl_ctx;
     struct sysctl_oid	*acpi_sysctl_tree;

