From owner-acpi-jp@jp.freebsd.org  Thu Jul 26 20:38:31 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id UAA95864;
	Thu, 26 Jul 2001 20:38:31 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from shidahara1.planet.sci.kobe-u.ac.jp (shidahara1.planet.sci.kobe-u.ac.jp [133.30.50.200])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id UAA95859
	for <acpi-jp@jp.freebsd.org>; Thu, 26 Jul 2001 20:38:31 +0900 (JST)
	(envelope-from takawata@shidahara1.planet.sci.kobe-u.ac.jp)
Received: from shidahara1.planet.sci.kobe-u.ac.jp (localhost [127.0.0.1])
	by shidahara1.planet.sci.kobe-u.ac.jp (8.9.3/8.9.3) with ESMTP id UAA86602
	for <acpi-jp@jp.freebsd.org>; Thu, 26 Jul 2001 20:46:17 +0900 (JST)
	(envelope-from takawata@shidahara1.planet.sci.kobe-u.ac.jp)
Message-Id: <200107261146.UAA86602@shidahara1.planet.sci.kobe-u.ac.jp>
To: acpi-jp@jp.freebsd.org
Date: Thu, 26 Jul 2001 20:46:17 +0900
From: Takanori Watanabe <takawata@shidahara1.planet.sci.kobe-u.ac.jp>
Reply-To: acpi-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: acpi-jp 1196
Subject: [acpi-jp 1196] CFR:ACPI kqueue stuff 
Errors-To: owner-acpi-jp@jp.freebsd.org
Sender: owner-acpi-jp@jp.freebsd.org
X-Originator: takawata@shidahara1.planet.sci.kobe-u.ac.jp

Hi,

This enables us notify acpi event to userland by installing EVFILT_READ 
kqueue filter.  

In this patch, event source is distinguished by kevent.fflags member.
if (kevent.fflags & (1<<ACPI_KNOTE_ACAD)) is true,AC adapter is 
inserted/removed from the machine. 

Supported event source:
Power/Sleep button.
Lid 
Wakeup Event
AC adaptor
Battery (up to 8 unit)
Thermal zone (up to 8 unit)

Supposed use:
 Send HUP signal to moused after wakeup.
 When the machine gets too hot or AC adaptor is ejected, suspend heavy job,
 like SETI@home or RC5-64 cracking.
 Fetch battery infomation only when battery status is changed.

Sample userland code:

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
main()
{
	int kq,fd;
	struct kevent cl,evl;
	int data,udata;
	int res;

	kq = kqueue();
  	fd=open("/dev/acpi",O_RDONLY);
	EV_SET(&cl, fd, EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR,
	       0xffffffff,&data,&udata);
	kevent(kq,&cl,1,NULL,0,NULL);
	for(;;){ 
		res = kevent(kq,NULL,0,&cl,1,NULL);
		printf("%d\n",res);
		printf("%x\n",cl.fflags);
	}  
}

=====8<=============8<==================

If there are no objection in 12 hours, I'll commit this.

Takanori Watanabe
<a href="http://www.planet.sci.kobe-u.ac.jp/~takawata/key.html">
Public Key</a>
Key fingerprint =  2C 51 E2 78 2C E1 C5 2D  0F F1 20 A3 11 3A 62 2A 


Index: acpi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi.c,v
retrieving revision 1.27
diff -u -r1.27 acpi.c
--- acpi.c	2001/07/22 19:13:49	1.27
+++ acpi.c	2001/07/26 10:51:33
@@ -67,6 +67,9 @@
 static d_open_t		acpiopen;
 static d_close_t	acpiclose;
 static d_ioctl_t	acpiioctl;
+static int acpikqfilter (dev_t, struct knote *);
+static int  filt_acpi(struct knote *, long );
+static void filt_acpidetach(struct knote *);
 
 #define CDEV_MAJOR 152
 static struct cdevsw acpi_cdevsw = {
@@ -82,7 +85,8 @@
     CDEV_MAJOR,
     nodump,
     nopsize,
-    0
+    D_KQFILTER,
+    acpikqfilter,
 };
 
 static const char* sleep_state_names[] = {
@@ -1114,6 +1118,7 @@
 	}
 	acpi_wakeup((UINT8)state);
 	DEVICE_RESUME(root_bus);
+	acpi_knote(ACPI_KNOTE_WAKEUP);
 	sc->acpi_sstate = ACPI_STATE_S0;
 	acpi_enable_fixed_events(sc);
 	break;
@@ -1216,6 +1221,7 @@
 
     FUNCTION_TRACE(__func__);
 
+    acpi_knote(ACPI_KNOTE_POWERBUTTON);
     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
 
     return_VALUE(INTERRUPT_HANDLED);
@@ -1240,6 +1246,7 @@
 
     FUNCTION_TRACE(__func__);
 
+    acpi_knote(ACPI_KNOTE_SLEEPBUTTON);
     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
 
     return_VALUE(INTERRUPT_HANDLED);
@@ -1478,6 +1485,59 @@
     ACPI_UNLOCK;
     return(error);
 }
+static struct filterops acpi_filtops = 
+{ 1, NULL, filt_acpidetach, filt_acpi };
+static int acpikqfilter(dev_t dev, struct knote * kn)
+{
+	struct acpi_softc *sc = dev->si_drv1;
+	struct klist *kl = &sc->acpi_klist;
+	printf("KQFILT:%d\n",kn->kn_filter);
+	switch(kn->kn_filter){
+	case EVFILT_READ:
+		kn->kn_fop = & acpi_filtops;
+		break;
+	default:
+		return 1;
+	}
+	kn->kn_hook = (caddr_t) sc;
+	mtx_lock(&acpi_mutex);
+	SLIST_INSERT_HEAD(kl, kn, kn_selnext);
+	mtx_unlock(&acpi_mutex);
+	return 0;
+}
+static void filt_acpidetach(struct knote *kn)
+{
+	struct acpi_softc *sc = (struct acpi_softc *)kn->kn_hook;
+	mtx_lock(&acpi_mutex);
+	SLIST_REMOVE(&sc->acpi_klist, kn, knote, kn_selnext);
+	if(SLIST_EMPTY(&sc->acpi_klist)){
+	    sc->acpi_filter = -1;
+	}
+	mtx_unlock(&acpi_mutex);
+}
+ 
+static int filt_acpi(struct knote *kn, long hint)
+{
+	/*This assumes with acpi_mutex acquired*/
+	struct acpi_softc *sc = (struct acpi_softc *)kn->kn_hook;
+	if((sc->acpi_filter != -1)&&(kn->kn_sfflags&(1<<sc->acpi_filter))){
+		kn->kn_fflags |= (1<<sc->acpi_filter);
+		return 1;
+	}
+	return 0;
+}
+
+void acpi_knote(int filter){
+	struct acpi_softc *sc = devclass_get_softc(acpi_devclass,0);
+	if((filter <0) || (filter > 32)){
+	    panic("INVALID ARGUMENT for acpi_knote");
+	}
+	mtx_lock(&acpi_mutex);
+	sc->acpi_filter = filter; 
+	KNOTE(&sc->acpi_klist, 0);
+	mtx_unlock(&acpi_mutex);
+}
+
 
 static int
 acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
Index: acpi_acad.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_acad.c,v
retrieving revision 1.7
diff -u -r1.7 acpi_acad.c
--- acpi_acad.c	2001/07/25 16:08:58	1.7
+++ acpi_acad.c	2001/07/26 09:01:30
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/acpica/acpi_acad.c,v 1.7 2001/07/25 16:08:58 iwasaki Exp $
+ * $FreeBSD$
  */
 
 #include "opt_acpi.h"
@@ -103,6 +103,7 @@
 		/*Temporally. It is better to notify policy manager*/
 		AcpiOsQueueForExecution(OSD_PRIORITY_LO,
 		    acpi_acad_get_status,context);
+		acpi_knote(ACPI_KNOTE_ACAD);
 		break;
 	default:
 		break;
Index: acpi_cmbat.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_cmbat.c,v
retrieving revision 1.7
diff -u -r1.7 acpi_cmbat.c
--- acpi_cmbat.c	2001/06/24 02:39:08	1.7
+++ acpi_cmbat.c	2001/07/26 09:44:27
@@ -71,6 +71,7 @@
 	int		cap;
 	int		min;
 	int		full_charge_time;
+    	u_int32_t	bifgen;
 };
 
 static struct timespec	acpi_cmbat_info_lastupdated;
@@ -122,7 +123,7 @@
 	dest[sizeof(dest)-1] = '\0';					\
 } while(0)
 
-#define	BATTERY_INFO_EXPIRE	5
+#define	BATTERY_INFO_EXPIRE	60
 static __inline int
 acpi_cmbat_info_expired(struct timespec *lastupdated)
 {
@@ -292,9 +293,14 @@
 	switch (notify) {
 	case ACPI_BATTERY_BST_CHANGE:
 		timespecclear(&sc->bst_lastupdated);
+ 	        acpi_knote(ACPI_KNOTE_BAT_START+device_get_unit(dev));
 		break;
 	case ACPI_BATTERY_BIF_CHANGE:
 		timespecclear(&sc->bif_lastupdated);
+		ACPI_LOCK;
+		sc->bifgen++;
+		ACPI_UNLOCK;
+ 	        acpi_knote(ACPI_KNOTE_BAT_START+device_get_unit(dev));
 		break;
 	default:
 		break;
@@ -331,7 +337,7 @@
 	bzero(&sc->bif_buffer, sizeof(sc->bif_buffer));
 	bzero(&sc->bst_buffer, sizeof(sc->bst_buffer));
 	sc->dev = dev;
-
+	sc->bifgen = 0;
 	timespecclear(&sc->bif_lastupdated);
 	timespecclear(&sc->bst_lastupdated);
 
@@ -420,6 +426,9 @@
 		bstp->rate = sc->bst.rate;
 		bstp->cap = sc->bst.cap;
 		bstp->volt = sc->bst.volt;
+#if 0
+		bstp->bifgen = sc->bifgen;
+#endif
 		break;
 	}
 
Index: acpi_thermal.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_thermal.c,v
retrieving revision 1.13
diff -u -r1.13 acpi_thermal.c
--- acpi_thermal.c	2001/07/21 10:24:32	1.13
+++ acpi_thermal.c	2001/07/26 08:52:47
@@ -37,7 +37,7 @@
 #include "acpi.h"
 
 #include <dev/acpica/acpivar.h>
-
+#include <dev/acpica/acpiio.h>
 /*
  * Hooks for the ACPI CA debugging infrastructure
  */
@@ -65,6 +65,7 @@
     int		tc2;
     int		tsp;
     int		tzp;
+    int		generation;	
 };
 
 
@@ -612,11 +613,14 @@
     switch(notify) {
     case TZ_NOTIFY_TEMPERATURE:
 	/* temperature change occurred */
+	acpi_knote(device_get_unit(sc->tz_dev)+ACPI_KNOTE_THRM_START);
 	device_printf(sc->tz_dev, "notified of temperature reaching setpoint\n");
 	AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_monitor, sc);
 	break;
     case TZ_NOTIFY_DEVICES:
     case TZ_NOTIFY_LEVELS:
+	sc->tz_zone.generation++;
+	acpi_knote(device_get_unit(sc->tz_dev)+ACPI_KNOTE_THRM_START);
 	/* zone devices/setpoints changed */
 	device_printf(sc->tz_dev, "notified of zone configuration change\n");
 	AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_establish, sc);
Index: acpiio.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpiio.h,v
retrieving revision 1.5
diff -u -r1.5 acpiio.h
--- acpiio.h	2001/06/23 10:38:25	1.5
+++ acpiio.h	2001/07/26 08:52:48
@@ -70,6 +70,9 @@
 	u_int32_t rate;				/* Present Rate */
 	u_int32_t cap;				/* Remaining Capacity */
 	u_int32_t volt;				/* Present Voltage */
+#if 0
+	u_int32_t bifgen;                       /*Battery Info Generation*/
+#endif
 };
 
 #define ACPI_BATT_STAT_DISCHARG		0x0001
@@ -99,6 +102,15 @@
 #define ACPIIO_CMBAT_GET_BST	_IOWR('B', 0x11, union acpi_battery_ioctl_arg)
 
 #define ACPIIO_ACAD_GET_STATUS	_IOR('A', 1, int)
+/*Kqueue releated stuff (1<<bit) represents the value*/
+
+#define ACPI_KNOTE_POWERBUTTON 0
+#define ACPI_KNOTE_SLEEPBUTTON 1
+#define ACPI_KNOTE_LID         2
+#define ACPI_KNOTE_ACAD        3
+#define ACPI_KNOTE_WAKEUP      4
+#define ACPI_KNOTE_BAT_START   8
+#define ACPI_KNOTE_THRM_START  16
 
 #ifdef _KERNEL
 extern int	acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg);
Index: acpivar.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpivar.h,v
retrieving revision 1.14
diff -u -r1.14 acpivar.h
--- acpivar.h	2001/07/21 10:24:32	1.14
+++ acpivar.h	2001/07/26 10:04:40
@@ -31,7 +31,7 @@
 #include "bus_if.h"
 #include <sys/eventhandler.h>
 #include <sys/sysctl.h>
-
+#include <sys/event.h>
 #include <machine/bus.h>
 #include <machine/resource.h>
 
@@ -64,6 +64,9 @@
 
     struct sysctl_ctx_list	 acpi_battery_sysctl_ctx;
     struct sysctl_oid		*acpi_battery_sysctl_tree;
+    /*KNOTE STUFF*/
+    struct klist	acpi_klist;
+    int			acpi_filter;
 };
 
 struct acpi_device {
@@ -297,3 +300,5 @@
 
 typedef void (*powerprofile_change_hook)(void *);
 EVENTHANDLER_DECLARE(powerprofile_change, powerprofile_change_hook);
+/*KNOTE STUFF*/
+extern void     acpi_knote(int filter);
