ports/x11/gnome-applets/files/patch-battstat-acpi
Joe Marcus Clarke c51dcddf13 Check to make sure we were able to open /var/run/devd.pipe successfully
once before continually trying to reopen it.  Because of this, some users
not using the devd patch to process dynamic ACPI updates were bitten by
the file descriptor leak.  Thus, I am bumping PORTREVISION for this commit.
2005-07-03 20:31:43 +00:00

576 lines
15 KiB
Text
Raw Blame History

--- battstat/Makefile.in.orig Mon Jan 24 20:20:49 2005
+++ battstat/Makefile.in Mon Jan 24 20:22:02 2005
@@ -55,9 +55,10 @@
PROGRAMS = $(libexec_PROGRAMS)
am_battstat_applet_2_OBJECTS = properties.$(OBJEXT) \
battstat_applet.$(OBJEXT) power-management.$(OBJEXT) \
- acpi-linux.$(OBJEXT)
+ acpi-freebsd.$(OBJEXT) acpi-linux.$(OBJEXT)
battstat_applet_2_OBJECTS = $(am_battstat_applet_2_OBJECTS)
am__DEPENDENCIES_1 =
+ACPIINC = @ACPIINC@
@HAVE_LIBAPM_FALSE@@NEED_LIBAPM_TRUE@am__DEPENDENCIES_2 = \
@HAVE_LIBAPM_FALSE@@NEED_LIBAPM_TRUE@ apmlib/libapm.a
battstat_applet_2_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@@ -66,6 +67,7 @@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/acpi-linux.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/acpi-freebsd.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/battstat_applet.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/power-management.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/properties.Po
@@ -336,6 +338,7 @@
$(GNOME_APPLETS_CFLAGS) \
$(LIBGLADE_CFLAGS) \
$(APMINC) \
+ $(ACPIINC) \
-DG_LOG_DOMAIN=\"battstat_applet\"
battstat_applet_2_SOURCES = \
@@ -345,7 +348,9 @@
battstat_applet.c \
power-management.c \
acpi-linux.c \
- acpi-linux.h
+ acpi-linux.h \
+ acpi-freebsd.c \
+ acpi-freebsd.h
battstat_applet_2_LDADD = \
$(GNOME_APPLETS_LIBS) \
@@ -439,6 +444,7 @@
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acpi-linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acpi-freebsd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/battstat_applet.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/power-management.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/properties.Po@am__quote@
--- battstat/battstat_applet.c.orig Mon Jan 24 12:51:51 2005
+++ battstat/battstat_applet.c Mon Jan 24 20:20:50 2005
@@ -953,6 +953,7 @@
"Seth Nickell <snickell@stanford.edu> (GNOME2 port)",
"Davyd Madeley <davyd@madeley.id.au>",
"Ryan Lortie <desrt@desrt.ca>",
+ "Joe Marcus Clarke <marcus@FreeBSD.org> (FreeBSD ACPI support)",
NULL
};
--- battstat/properties.c.orig Fri Jan 14 23:38:18 2005
+++ battstat/properties.c Mon Mar 14 19:49:26 2005
@@ -27,7 +27,7 @@
#include <stdio.h>
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) && defined(__i386__)
#include <machine/apm_bios.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/param.h>
@@ -61,6 +61,9 @@
#include <panel-applet-gconf.h>
/*#include <status-docklet.h>*/
+#if defined(__FreeBSD__) && !defined(__i386__)
+#include "acpi-freebsd.h"
+#endif
#include "battstat.h"
#ifndef gettext_noop
--- battstat/acpi-freebsd.c.orig Sun Jul 3 16:00:01 2005
+++ battstat/acpi-freebsd.c Sun Jul 3 16:23:26 2005
@@ -0,0 +1,280 @@
+/* battstat A GNOME battery meter for laptops.
+ * Copyright (C) 2000 by J<>rgen Pehrson <jp@spektr.eu.org>
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ $Id: patch-battstat-acpi,v 1.13 2005/02/28 08:02:03 marcus Exp $
+ */
+
+/*
+ * ACPI battery functions for FreeBSD >= 5.2.
+ * September 2004 by Joe Marcus Clarke <marcus@FreeBSD.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef __FreeBSD__
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#if defined(__i386__)
+#include <machine/apm_bios.h>
+#endif
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <glib.h>
+
+#include <dev/acpica/acpiio.h>
+
+#include "acpi-freebsd.h"
+
+static gboolean
+update_ac_info(struct acpi_info * acpiinfo)
+{
+ int acline;
+ size_t len = sizeof(acline);
+
+ acpiinfo->ac_online = FALSE;
+
+ if (sysctlbyname(ACPI_ACLINE, &acline, &len, NULL, 0) == -1) {
+ return FALSE;
+ }
+
+ acpiinfo->ac_online = acline ? TRUE : FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+update_battery_info(struct acpi_info * acpiinfo)
+{
+ union acpi_battery_ioctl_arg battio;
+ int i;
+
+ /* We really don't have to do this here. All of the relevant battery
+ * info can be obtained through sysctl. However, one day, the rate
+ * may be useful to get time left to full charge.
+ */
+
+ for(i = BATT_MIN; i < BATT_MAX; i++) {
+ battio.unit = i;
+ if (ioctl(acpiinfo->acpifd, ACPIIO_CMBAT_GET_BIF, &battio) == -1) {
+ continue;
+ }
+
+ acpiinfo->max_capacity += battio.bif.lfcap;
+ acpiinfo->low_capacity += battio.bif.wcap;
+ acpiinfo->critical_capacity += battio.bif.lcap;
+ }
+
+ return TRUE;
+}
+
+gboolean
+acpi_freebsd_init(struct acpi_info * acpiinfo)
+{
+ int acpi_fd;
+ int event_fd;
+
+ g_assert(acpiinfo);
+
+ if (acpiinfo->acpifd == -1) {
+ acpi_fd = open(ACPIDEV, O_RDONLY);
+ if (acpi_fd >= 0) {
+ acpiinfo->acpifd = acpi_fd;
+ }
+ else {
+ acpiinfo->acpifd = -1;
+ return FALSE;
+ }
+ }
+
+ event_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (event_fd >= 0) {
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, "/var/run/devd.pipe");
+ if (connect(event_fd, (struct sockaddr *) &addr, sizeof(addr)) == 0) {
+ acpiinfo->event_fd = event_fd;
+ acpiinfo->event_inited = TRUE;
+ acpiinfo->channel = g_io_channel_unix_new(event_fd);
+ }
+ else {
+ close(event_fd);
+ acpiinfo->event_fd = -1;
+ acpiinfo->event_inited = FALSE;
+ }
+ }
+
+ update_battery_info(acpiinfo);
+ update_ac_info(acpiinfo);
+
+ return TRUE;
+}
+
+#define ACPI_EVENT_IGNORE 0
+#define ACPI_EVENT_AC 1
+#define ACPI_EVENT_BATTERY_INFO 2
+
+static int parse_acpi_event(GString *buffer)
+{
+ if (strstr(buffer->str, "system=ACPI")) {
+ if (strstr(buffer->str, "subsystem=ACAD"))
+ return ACPI_EVENT_AC;
+ if (strstr(buffer->str, "subsystem=CMBAT"))
+ return ACPI_EVENT_BATTERY_INFO;
+ }
+
+ return ACPI_EVENT_IGNORE;
+}
+
+void acpi_freebsd_update(struct acpi_info *acpiinfo)
+{
+ /* XXX This is needed for systems where devd does not have permissions
+ * to allow for event-driven updates.
+ */
+ update_ac_info(acpiinfo);
+ update_battery_info(acpiinfo);
+}
+
+gboolean acpi_process_event(struct acpi_info *acpiinfo, gboolean *read_error)
+{
+ gsize i;
+ int evt;
+ gboolean result = FALSE;
+ GString *buffer;
+ GIOStatus stat;
+ buffer = g_string_new(NULL);
+
+ *read_error = FALSE;
+ stat = g_io_channel_read_line_string(acpiinfo->channel, buffer, &i, NULL);
+
+ if (stat == G_IO_STATUS_ERROR || stat == G_IO_STATUS_EOF) {
+ *read_error = TRUE;
+ g_string_free(buffer, TRUE);
+ return FALSE;
+ }
+
+ evt = parse_acpi_event(buffer);
+ switch (evt) {
+ case ACPI_EVENT_AC:
+ update_ac_info(acpiinfo);
+ result = TRUE;
+ break;
+ case ACPI_EVENT_BATTERY_INFO:
+ update_battery_info(acpiinfo);
+ result = TRUE;
+ break;
+ }
+
+ g_string_free(buffer, TRUE);
+ return result;
+}
+
+void
+acpi_freebsd_cleanup(struct acpi_info * acpiinfo)
+{
+ g_assert(acpiinfo);
+
+ if (acpiinfo->acpifd >= 0) {
+ close(acpiinfo->acpifd);
+ acpiinfo->acpifd = -1;
+ }
+
+ if (acpiinfo->event_fd >= 0) {
+ g_io_channel_unref(acpiinfo->channel);
+ close(acpiinfo->event_fd);
+ acpiinfo->event_fd = -1;
+ }
+}
+
+gboolean
+acpi_freebsd_read(struct apm_info *apminfo, struct acpi_info * acpiinfo)
+{
+ int time;
+ int life;
+ int acline;
+ int state;
+ size_t len;
+ int rate;
+ int remain;
+ union acpi_battery_ioctl_arg battio;
+ gboolean charging;
+ int i;
+
+ g_assert(acpiinfo);
+
+ charging = FALSE;
+
+ for(i = BATT_MIN; i < BATT_MAX; i++) {
+ battio.unit = i;
+ if (ioctl(acpiinfo->acpifd, ACPIIO_CMBAT_GET_BST, &battio) == -1) {
+ continue;
+ }
+
+ remain += battio.bst.cap;
+ rate += battio.bst.rate;
+ }
+
+ len = sizeof(time);
+ if (sysctlbyname(ACPI_TIME, &time, &len, NULL, 0) == -1) {
+ return FALSE;
+ }
+
+ len = sizeof(life);
+ if (sysctlbyname(ACPI_LIFE, &life, &len, NULL, 0) == -1) {
+ return FALSE;
+ }
+
+ len = sizeof(state);
+ if (sysctlbyname(ACPI_STATE, &state, &len, NULL, 0) == -1) {
+ return FALSE;
+ }
+
+ apminfo->ai_acline = acpiinfo->ac_online ? 1 : 0;
+ if (state & ACPI_BATT_STAT_CHARGING) {
+ apminfo->ai_batt_stat = 3;
+ charging = TRUE;
+ }
+ else if (state & ACPI_BATT_STAT_CRITICAL) {
+ /* Add a special check here since FreeBSD's ACPI interface will tell us
+ * when the battery is critical.
+ */
+ apminfo->ai_batt_stat = 2;
+ }
+ else {
+ apminfo->ai_batt_stat = remain < acpiinfo->low_capacity ? 1 : remain < acpiinfo->critical_capacity ? 2 : 0;
+ }
+ apminfo->ai_batt_life = life;
+ if (!charging) {
+ apminfo->ai_batt_time = time;
+ }
+ else if (charging && rate > 0) {
+ apminfo->ai_batt_time = (int) ((acpiinfo->max_capacity-remain)/(float)rate);
+ }
+ else
+ apminfo->ai_batt_time = -1;
+
+ return TRUE;
+}
+#endif
--- battstat/acpi-freebsd.h.orig Sun Jul 3 16:00:01 2005
+++ battstat/acpi-freebsd.h Sun Jul 3 16:23:56 2005
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004 by Joe Marcus Clarke <marcus@FreeBSD.org>
+ *
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ACPI_FREEBSD_H__
+#define __ACPI_FREEBSD_H__
+
+#define ACPIDEV "/dev/acpi"
+
+#define BATT_MIN 0
+#define BATT_MAX 64
+
+#define ACPI_ACLINE "hw.acpi.acline"
+#define ACPI_TIME "hw.acpi.battery.time"
+#define ACPI_LIFE "hw.acpi.battery.life"
+#define ACPI_STATE "hw.acpi.battery.state"
+
+/* XXX: AMD64 does not have machine/apm_bios.h. */
+#if !defined(__i386__)
+struct apm_info {
+ guint ai_acline;
+ guint ai_batt_stat;
+ guint ai_batt_life;
+ int ai_batt_time;
+ guint ai_status;
+};
+#endif
+
+struct acpi_info {
+ gboolean ac_online;
+ gboolean event_inited;
+ int acpifd;
+ int event_fd;
+ int max_capacity;
+ int low_capacity;
+ int critical_capacity;
+ GIOChannel * channel;
+};
+
+gboolean acpi_freebsd_read(struct apm_info *apminfo, struct acpi_info * acpiinfo);
+void acpi_freebsd_update(struct acpi_info * acpiinfo);
+gboolean acpi_process_event(struct acpi_info * acpiinfo, gboolean *read_error);
+gboolean acpi_freebsd_init(struct acpi_info * acpiinfo);
+void acpi_freebsd_cleanup(struct acpi_info * acpiinfo);
+
+#endif /* __ACPI_FREEBSD_H__ */
--- battstat/power-management.c.orig Sun Mar 20 05:20:55 2005
+++ battstat/power-management.c Sun Jul 3 16:21:42 2005
@@ -73,12 +73,42 @@ static int pm_initialised;
* the problem might be. This error message is not to be freed.
*/
-#ifdef __FreeBSD__
-
+#if defined(__FreeBSD__)
+#if defined(__i386__)
#include <machine/apm_bios.h>
+#endif
+#include "acpi-freebsd.h"
+
+static struct acpi_info acpiinfo;
+static gboolean using_acpi;
+static int acpi_count;
+static int acpiwatch;
+static struct apm_info apminfo;
+
+gboolean acpi_freebsd_read(struct apm_info *apminfo, struct acpi_info *acpiinfo);
#define APMDEVICE "/dev/apm"
+static gboolean acpi_callback (GIOChannel * chan, GIOCondition cond, gpointer data)
+{
+ gboolean read_error;
+
+ if (cond & (G_IO_ERR | G_IO_HUP)) {
+ acpi_freebsd_cleanup(&acpiinfo);
+ return FALSE;
+ }
+
+ if (acpi_process_event(&acpiinfo, &read_error)) {
+ acpi_freebsd_read(&apminfo, &acpiinfo);
+ }
+ else if (read_error) {
+ acpi_freebsd_cleanup(&acpiinfo);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static const char *
apm_readinfo (BatteryStatus *status)
{
@@ -86,32 +116,56 @@ apm_readinfo (BatteryStatus *status)
FreeBSD. Each time this functions is called (once every second)
the APM device is opened, read from and then closed.
*/
- struct apm_info apminfo;
int fd;
if (DEBUG) g_print("apm_readinfo() (FreeBSD)\n");
- fd = open(APMDEVICE, O_RDONLY);
- if (fd == -1)
- {
- pm_initialised = 0;
- return ERR_OPEN_APMDEV;
+ if (using_acpi && (!acpiinfo.event_inited || acpiinfo.event_fd >= 0)) {
+ if (acpi_count <= 0) {
+ acpi_count = 30;
+ if (!acpiinfo.event_inited) {
+ acpi_freebsd_update(&acpiinfo);
+ }
+ acpi_freebsd_read(&apminfo, &acpiinfo);
+ }
+ acpi_count--;
+ }
+ else if (using_acpi && acpiinfo.event_inited) {
+ if (acpi_freebsd_init(&acpiinfo)) {
+ acpiwatch = g_io_add_watch (acpiinfo.channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ acpi_callback, NULL);
+ acpi_freebsd_read(&apminfo, &acpiinfo);
+ }
}
+ else {
+#if defined(__i386__)
+ fd = open(APMDEVICE, O_RDONLY);
+ if (fd == -1) {
+ return ERR_OPEN_APMDEV;
+ }
- if (ioctl(fd, APMIO_GETINFO, &apminfo) == -1)
- err(1, "ioctl(APMIO_GETINFO)");
+ if (ioctl(fd, APMIO_GETINFO, &apminfo) == -1)
+ err(1, "ioctl(APMIO_GETINFO)");
- close(fd);
+ close(fd);
- if(apminfo.ai_status == 0)
- return ERR_APM_E;
+ if(apminfo.ai_status == 0)
+ return ERR_APM_E;
+#else
+ return ERR_OPEN_APMDEV;
+#endif
+ }
status->present = TRUE;
status->on_ac_power = apminfo.ai_acline ? 1 : 0;
status->state = apminfo.ai_batt_stat;
status->percent = apminfo.ai_batt_life;
status->charging = (status->state == 3) ? TRUE : FALSE;
- status->minutes = apminfo.ai_batt_time;
+ if (using_acpi)
+ status->minutes = apminfo.ai_batt_time;
+ else
+ status->minutes = (int) (apminfo.ai_batt_time/60.0);
return NULL;
}
@@ -339,6 +393,19 @@ power_management_initialise( void )
G_IO_IN | G_IO_ERR | G_IO_HUP,
acpi_callback, NULL);
}
+#elif defined(__FreeBSD__)
+ if (acpi_freebsd_init(&acpiinfo)) {
+ using_acpi = TRUE;
+ acpi_count = 0;
+ }
+ else
+ using_acpi = FALSE;
+
+ if (using_acpi && acpiinfo.event_fd >= 0) {
+ acpiwatch = g_io_add_watch (acpiinfo.channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ acpi_callback, NULL);
+ }
#endif
pm_initialised = 1;
@@ -360,6 +427,13 @@ power_management_cleanup( void )
g_source_remove(acpiwatch);
acpiwatch = 0;
acpi_linux_cleanup(&acpiinfo);
+ }
+#elif defined(__FreeBSD__)
+ if (using_acpi) {
+ if (acpiwatch != 0)
+ g_source_remove(acpiwatch);
+ acpiwatch = 0;
+ acpi_freebsd_cleanup(&acpiinfo);
}
#endif