From owner-freebsd-bugs@FreeBSD.ORG Mon Jun 2 23:00:08 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 68934106567D for ; Mon, 2 Jun 2008 23:00:08 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 561218FC13 for ; Mon, 2 Jun 2008 23:00:08 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m52N07kr060947 for ; Mon, 2 Jun 2008 23:00:07 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m52N0772060946; Mon, 2 Jun 2008 23:00:07 GMT (envelope-from gnats) Resent-Date: Mon, 2 Jun 2008 23:00:07 GMT Resent-Message-Id: <200806022300.m52N0772060946@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Pietro Cerutti" Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2ECD61065675 for ; Mon, 2 Jun 2008 22:57:03 +0000 (UTC) (envelope-from gahr@FreeBSD.org) Received: from cpanel03.rubas-s03.net (cpanel03.rubas-s03.net [195.182.222.73]) by mx1.freebsd.org (Postfix) with ESMTP id C86DD8FC1C for ; Mon, 2 Jun 2008 22:57:02 +0000 (UTC) (envelope-from gahr@FreeBSD.org) Received: from [213.142.183.219] (helo=gahrtop.localhost) by cpanel03.rubas-s03.net with esmtpa (Exim 4.68) (envelope-from ) id 1K3IxZ-0001qQ-6o for FreeBSD-gnats-submit@freebsd.org; Tue, 03 Jun 2008 00:57:01 +0200 Received: from gahrtop.localhost (localhost [127.0.0.1]) by gahrtop.localhost (Postfix) with ESMTP id D8CF850841 for ; Tue, 3 Jun 2008 00:56:53 +0200 (CEST) Message-Id: <1212447413.32542@gahrtop.localhost> Date: Tue, 3 Jun 2008 00:56:53 +0200 From: "Pietro Cerutti" To: "FreeBSD gnats submit" X-Send-Pr-Version: gtk-send-pr 0.4.9 Cc: Subject: kern/124223: [patch] acpi_battery.c -- Notify user-defined critical level via devd(8) X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Jun 2008 23:00:08 -0000 >Number: 124223 >Category: kern >Synopsis: [patch] acpi_battery.c -- Notify user-defined critical level via devd(8) >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Mon Jun 02 23:00:07 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Pietro Cerutti >Release: FreeBSD 8.0-CURRENT i386 >Organization: The FreeBSD Project >Environment: System: FreeBSD 8.0-CURRENT #39: Mon Jun 2 20:33:05 CEST 2008 root@gahrtop.localhost:/usr/obj/usr/src/sys/MSI1034 >Description: Critically low battery levels are notified by the ACPI subsystem via the acpi_cmbat.c module. This prints a line on the console. The problem with cmbat is that the "critically low level" value is not configurable. The following patch implements a kernel process within acpi_battery.c. Two sysctl OIDs are exported in order to control the polling rate and the life % to be considered critical. When this critical level is reached, acpi_battery.c notifies userland via devd(8), allowing for a devd.conf(5) configuration such as: notify 10 { match "system" "ACPI"; match "subsystem" "Battery"; match "notify" "0x80"; action "logger -p kern.emerg 'WARNING: Low battery!'"; }; >How-To-Repeat: >Fix: --- acpi_battery.c.diff begins here --- Index: acpi_battery.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi_battery.c,v retrieving revision 1.26 diff -u -u -r1.26 acpi_battery.c --- acpi_battery.c 20 Nov 2007 18:35:36 -0000 1.26 +++ acpi_battery.c 23 May 2008 14:35:21 -0000 @@ -31,10 +31,12 @@ #include "opt_acpi.h" #include #include +#include #include #include #include #include +#include #include #include @@ -43,6 +45,14 @@ /* Default seconds before re-sampling the battery state. */ #define ACPI_BATTERY_INFO_EXPIRE 5 +/* Check for battery low level each 60 seconds */ +#define BATT_POLLRATE 60 + +/* Default level to notify devd */ +#define BATT_LOWLEVEL 5 + +#define BATT_NOTIFY_LOWLEVEL 0x80 + static int acpi_batteries_initted; static int acpi_battery_info_expire = ACPI_BATTERY_INFO_EXPIRE; static struct acpi_battinfo acpi_battery_battinfo; @@ -56,8 +66,16 @@ static device_t acpi_battery_find_dev(u_int logical_unit); static int acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg); static int acpi_battery_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_battery_rate_sysctl(SYSCTL_HANDLER_ARGS); +static int acpi_battery_crit_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_battery_init(void); +static void acpi_battery_thread(void *); + +static struct proc *acpi_battery_proc; +static int acpi_battery_pollrate = BATT_POLLRATE; +static int acpi_battery_lowlevel = BATT_LOWLEVEL; +static int acpi_battery_previous = -1; int acpi_battery_register(device_t dev) @@ -69,6 +87,8 @@ if (!acpi_batteries_initted) error = acpi_battery_init(); ACPI_SERIAL_END(battery); + if(error) return (error); + error = kproc_create(acpi_battery_thread, NULL, &acpi_battery_proc, RFHIGHPID, 0, "acpi_battery"); return (error); } @@ -422,6 +442,36 @@ } static int +acpi_battery_rate_sysctl(SYSCTL_HANDLER_ARGS) +{ + int error; + + error = sysctl_handle_int(oidp, &acpi_battery_pollrate, 0, req); + + if(error || !req->newptr) + return (error); + + acpi_battery_pollrate = *(int *)req->newptr; + + wakeup(&acpi_battery_proc); + return (error); +} + +static int +acpi_battery_crit_sysctl(SYSCTL_HANDLER_ARGS) +{ + int error; + + error = sysctl_handle_int(oidp, &acpi_battery_lowlevel, 0, req); + + if(error || !req->newptr) + return (error); + + acpi_battery_lowlevel = *(int *)req->newptr; + return (error); +} + +static int acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS) { int count, error; @@ -489,6 +539,16 @@ OID_AUTO, "info_expire", CTLFLAG_RW, &acpi_battery_info_expire, 0, "time in seconds until info is refreshed"); + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), + OID_AUTO, "polling_rate", CTLTYPE_INT | CTLFLAG_RW, + NULL, 0, acpi_battery_rate_sysctl, "I", + "polling rate in seconds"); + SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx, + SYSCTL_CHILDREN(acpi_battery_sysctl_tree), + OID_AUTO, "critical_level", CTLTYPE_INT | CTLFLAG_RW, + NULL, 0, acpi_battery_crit_sysctl, "I", + "critical level in percent"); acpi_batteries_initted = TRUE; @@ -501,3 +561,31 @@ } return (error); } + +/* + * ACPI Battery monitor thread + */ +static void +acpi_battery_thread(void *arg) +{ + (void) arg; /* not used */ + struct acpi_battinfo battinfo; + device_t dev; + ACPI_HANDLE h; + + if(!(dev = devclass_get_device(devclass_find("acpi"), 0))) + return; + + h = acpi_get_handle(dev); + + while(1) + { + if(!acpi_battery_get_battinfo(NULL, &battinfo)) + { + if(battinfo.cap <= acpi_battery_lowlevel && battinfo.cap < acpi_battery_previous) + acpi_UserNotify("Battery", h, BATT_NOTIFY_LOWLEVEL); + acpi_battery_previous = battinfo.cap; + } + tsleep(&acpi_battery_proc, 0, "batpol", hz * acpi_battery_pollrate); + } +} --- acpi_battery.c.diff ends here --- >Release-Note: >Audit-Trail: >Unformatted: