--- epplets/E-Power.c.orig	2011-11-26 11:38:40.000000000 +0100
+++ epplets/E-Power.c	2012-10-10 15:01:17.000000000 +0200
@@ -1,9 +1,22 @@
+/*-
+ * Copyright 2008, Pietro Cerutti <gahr@FreeBSD.org> (FreeBSD adaptation)
+ */
+
 #define _GNU_SOURCE
 #include "epplet.h"
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
 
+#ifdef __FreeBSD__
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <dev/acpica/acpiio.h>
+#ifdef __i386__
+#include <machine/apm_bios.h>
+#endif
+#endif
+
 /* Modified by Attila ZIMLER <hijaszu@hlfslinux.hu>, 2003/11/16
    Added ACPI power management support.
 */
@@ -11,6 +24,20 @@
 /* Length of explain strings in /proc/acpi/battery/BAT0 data files */
 #define DATA_EXPLAIN_STR_LEN	25
 
+/* Power management modes */
+#define MODE_NONE 0x0
+#define MODE_APM  0x1
+#define MODE_ACPI 0x2
+#define MODE_SYS  0x3
+static unsigned mode = MODE_NONE;
+
+#ifdef __FreeBSD__
+#define ACPI_DEV "/dev/acpi"
+#define APM_DEV  "/dev/apm"
+static int apm_fd  = -1,
+           acpi_fd = -1;
+#endif
+
 int                 prev_bat_val = 110;
 int                 bat_val = 0;
 int                 time_val = 0;
@@ -33,14 +60,37 @@
 static void
 cb_timer(void *data)
 {
+#ifdef linux
    struct stat         st;
 
    if ((stat("/proc/apm", &st) > -1) && S_ISREG(st.st_mode))
-      cb_timer_apm(data);
+       mode = MODE_APM;
    else if ((stat("/proc/acpi/battery", &st) > -1) && S_ISDIR(st.st_mode))
-      cb_timer_acpi(data);
+       mode = MODE_ACPI;
    else if ((stat("/sys/class/power_supply", &st) > -1) && S_ISDIR(st.st_mode))
-      cb_timer_sys(data);
+       mode = MODE_SYS;
+   else
+       mode = MODE_NONE;
+#elif defined (__FreeBSD__)
+   /*
+    * Try ACPI first, if it doesn't work, revert to APM
+    */
+   if (acpi_fd != 1 || ((acpi_fd = open(ACPI_DEV, O_RDONLY)) != -1))
+       mode = MODE_ACPI;
+   else if (apm_fd != 1 || (apm_fd = open(APM_DEV, O_RDONLY)) != -1)
+       mode = MODE_APM;
+   else
+       mode = MODE_NONE;
+#else
+   mode = MODE_NONE;
+#endif
+
+   if (mode & MODE_APM)
+       cb_timer_apm(data);
+   else if (mode & MODE_ACPI)
+       cb_timer_acpi(data);
+   else if (mode & MODE_SYS)
+       tb_timer_sys(data);
 }
 
 static void
@@ -61,9 +111,8 @@
    int                 bat_level = 0;
    int                 bat_drain = 1;
 
-   int                 bat_val = 0;
-
    char                current_status[256];
+
    char               *line = 0;
    size_t              lsize = 0;
    int                 discharging = 0;
@@ -77,6 +126,8 @@
 
    int                 hours, minutes;
 
+#ifdef linux
+
    /* Read some information on first run. */
    dirp = opendir("/proc/acpi/battery");
    if (dirp)
@@ -207,27 +258,74 @@
    else
       snprintf(current_status, sizeof(current_status), "Full");
 
+   /* Final steps before ending the status update. */
+   data = NULL;
+   if (lsize)
+      free(line);
+
+#elif defined(__FreeBSD__)
+   union acpi_battery_ioctl_arg batt;
+   int c;
+   batt.unit = 0;
+   if(ioctl(acpi_fd, ACPIIO_BATT_GET_BATTINFO, &batt) == -1)
+      return;
+
+   /*
+    * Get percent
+    */
+   if(batt.battinfo.cap == -1) {
+      c = snprintf(current_status, sizeof(current_status), "???");
+      bat_val = 0;
+   }
+   else {
+      c = snprintf(current_status, sizeof(current_status), "%d%%",
+            batt.battinfo.cap);
+      bat_val = batt.battinfo.cap;
+   }
+
+   /*
+    * Get online status
+    */
+   if(batt.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT)
+      c += snprintf(&current_status[c], sizeof(current_status) - c, " NONE\n");
+   else if(batt.battinfo.state == ACPI_BATT_STAT_DISCHARG || batt.battinfo.state == ACPI_BATT_STAT_CRITICAL)
+      c += snprintf(&current_status[c], sizeof(current_status) - c, " OFF\n");
+   else
+      c += snprintf(&current_status[c], sizeof(current_status) - c, " ON\n");
+
+   /*
+    * Get remaining time
+    */
+   if(batt.battinfo.min == -1) {
+      if(batt.battinfo.state == ACPI_BATT_STAT_DISCHARG ||
+         batt.battinfo.state == ACPI_BATT_STAT_CRITICAL ||
+         batt.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT)
+      snprintf(&current_status[c], sizeof(current_status) - c, "?:??");
+   }
+   else {
+      snprintf(&current_status[c], sizeof(current_status) - c, "%d:%2d",
+            batt.battinfo.min / 60, batt.battinfo.min % 60);
+   }
+
+#endif
    /* Display current status */
    Epplet_change_label(label, current_status);
    sprintf(current_status, "E-Power-Bat-%i.png", ((bat_val + 5) / 10) * 10);
    Epplet_change_image(image, 44, 24, current_status);
    Epplet_timer(cb_timer, NULL, 5.0, "TIMER");
-
-   /* Final steps before ending the status update. */
-   data = NULL;
-   if (lsize)
-      free(line);
 }
 
 static void
 cb_timer_apm(void *data)
 {
+   char s[256];
+#ifdef linux
    static FILE        *f;
 
    f = fopen("/proc/apm", "r");
    if (f)
      {
-	char                s[256], s1[32], s2[32], s3[32];
+	char                s1[32], s2[32], s3[32];
 	int                 apm_flags, ac_stat, bat_stat, bat_flags;
 	int                 i, hours, minutes, up, up2;
 	char               *s_ptr;
@@ -300,14 +398,57 @@
 	     else
 		s_ptr += sprintf(s_ptr, "%i:%02i", hours, minutes);
 	  }
-	Epplet_change_label(label, s);
+   prev_bat_val = bat_val;
+#elif defined(__FreeBSD__) && defined(__i386__)
+   struct apm_info apm;
+   int c;
+   if(ioctl(apm_fd, APMIO_GETINFO, &apm) == -1)
+      return;
+
+   /*
+    * Get percent
+    */
+   if(apm.ai_batt_life == 0xff) {
+      c = snprintf(s, sizeof(s), "???");
+      bat_val = 0;
+   }
+   else {
+      c = snprintf(s, sizeof(s), "%d%%", apm.ai_batt_life);
+      bat_val = apm.ai_batt_life;
+   }
+
+   /*
+    * Get online status
+    */
+   if(apm.ai_acline == 0xff)
+      c += snprintf(&s[c], sizeof(s) - c, " NONE\n");
+   else if(apm.ai_acline)
+      c += snprintf(&s[c], sizeof(s) - c, " ON\n");
+   else
+      c += snprintf(&s[c], sizeof(s) - c , " OFF\n");
+
+   /*
+    * Get remaining time
+    */
+   if(apm.ai_batt_time == -1) {
+      if(apm.ai_acline == 0xff || !apm.ai_acline)
+         snprintf(&s[c], sizeof(s) - c, "?:??");
+   }
+   else
+      snprintf(&s[c], sizeof(s) - c, "%d:%2d",
+            apm.ai_batt_time / 3600, apm.ai_batt_time / 60 % 60);
+#endif
 
+   /* Display current status */
+	Epplet_change_label(label, s);
 	sprintf(s, "E-Power-Bat-%i.png", ((bat_val + 5) / 10) * 10);
 	Epplet_change_image(image, 44, 24, s);
+#ifdef linux
 	Epplet_timer(cb_timer, NULL, 30.0, "TIMER");
+#else
+	Epplet_timer(cb_timer, NULL, 5.0, "TIMER");
+#endif
 
-	prev_bat_val = bat_val;
-     }
    data = NULL;
 }
 
@@ -530,7 +671,14 @@
 static void
 cb_suspend(void *data)
 {
+#ifdef __FreeBSD__
+   if(mode & MODE_ACPI)
+      system("/usr/sbin/acpiconf -s 5");
+   else if(mode & MODE_APM)
+      system("/usr/sbin/apm -z");
+#else
    system("/usr/bin/apm -s");
+#endif
    return;
    data = NULL;
 }
@@ -538,7 +686,14 @@
 static void
 cb_sleep(void *data)
 {
+#ifdef __FreeBSD__
+   if(mode & MODE_ACPI)
+      system("/usr/sbin/acpiconf -s 1");
+   else if(mode & MODE_APM)
+      system("/usr/sbin/amp -z");
+#else
    system("/usr/bin/apm -S");
+#endif
    return;
    data = NULL;
 }
