$OpenBSD: patch-src_openbsd_up-backend_c,v 1.17 2014/05/23 19:21:07 landry Exp $

From 4bed9c99c1d459f0d1bc760716573e2a2af5e0e1 Mon Sep 17 00:00:00 2001
From: Jasper Lievisse Adriaanse <jasper@humppa.nl>
Date: Sun, 20 Apr 2014 18:15:36 +0000
Subject: Update lid status when updating ac status.
         https://bugs.freedesktop.org/show_bug.cgi?id=77692

--- src/openbsd/up-backend.c.orig	Tue Oct 29 11:37:08 2013
+++ src/openbsd/up-backend.c	Sat May 17 17:55:23 2014
@@ -34,6 +34,7 @@ static void	up_backend_finalize	(GObject		*object);
 static gboolean	up_backend_apm_get_power_info(struct apm_power_info*);
 UpDeviceState up_backend_apm_get_battery_state_value(u_char battery_state);
 static void	up_backend_update_acpibat_state(UpDevice*, struct sensordev);
+static void	up_backend_update_lid_status(UpDaemon*);
 
 static gboolean		up_apm_device_get_on_battery	(UpDevice *device, gboolean *on_battery);
 static gboolean		up_apm_device_get_online		(UpDevice *device, gboolean *online);
@@ -128,10 +129,10 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *dae
 	UpApmNative *acnative = NULL;
 	UpApmNative *battnative = NULL;
 	backend->priv->daemon = g_object_ref (daemon);
-	/* XXX no way to get lid status atm */
-	up_daemon_set_lid_is_present (backend->priv->daemon, FALSE);
+
 	if (backend->priv->is_laptop)
 	{
+		up_backend_update_lid_status(daemon);
 		acnative = up_apm_native_new("/ac");
 		if (!up_device_coldplug (backend->priv->ac, backend->priv->daemon, G_OBJECT(acnative)))
 			g_warning ("failed to coldplug ac");
@@ -215,6 +216,7 @@ up_backend_update_ac_state(UpDevice* device)
 	gboolean ret, new_is_online, cur_is_online;
 	struct apm_power_info a;
 
+	up_backend_update_lid_status(up_device_get_daemon(device));
 	ret = up_backend_apm_get_power_info(&a);
 	if (!ret)
 		return ret;
@@ -319,8 +321,8 @@ up_backend_update_acpibat_state(UpDevice* device, stru
 {
 	enum sensor_type type;
 	int numt;
-	gdouble bst_volt, bst_rate, bif_lastfullcap, bst_cap, bif_lowcap;
-	/* gdouble bif_dvolt, bif_dcap, capacity; */
+	gdouble bst_volt, bst_rate, bif_cap, bif_lastfullcap, bst_cap, bif_lowcap, capacity;
+	/* gdouble bif_dvolt; */
 	struct sensor sens;
 	size_t slen = sizeof(sens);
 	int mib[] = {CTL_HW, HW_SENSORS, 0, 0, 0};
@@ -335,6 +337,9 @@ up_backend_update_acpibat_state(UpDevice* device, stru
 			else if (slen > 0 && (sens.flags & SENSOR_FINVALID) == 0) {
 				if (sens.type == SENSOR_VOLTS_DC && !strcmp(sens.desc, "current voltage"))
 					bst_volt = sens.value / 1000000.0f;
+				if ((sens.type == SENSOR_AMPHOUR || sens.type == SENSOR_WATTHOUR) && !strcmp(sens.desc, "design capacity")) {
+					bif_cap = (sens.type == SENSOR_AMPHOUR ? bst_volt : 1) * sens.value / 1000000.0f;
+				}
 				if ((sens.type == SENSOR_AMPHOUR || sens.type == SENSOR_WATTHOUR) && !strcmp(sens.desc, "last full capacity")) {
 					bif_lastfullcap = (sens.type == SENSOR_AMPHOUR ? bst_volt : 1) * sens.value / 1000000.0f;
 				}
@@ -349,19 +354,30 @@ up_backend_update_acpibat_state(UpDevice* device, stru
 				}
 				/*
 				bif_dvolt = "voltage" = unused ?
-				capacity = lastfull/dcap * 100 ?
 				amphour1 = warning capacity ?
 				raw0 = battery state
 				*/
 			}
 		}
 	}
+
+	capacity = 0.0f;
+	if(bif_lastfullcap > 0 && bif_cap > 0) {
+		capacity = (bif_lastfullcap / bif_cap) * 100.0f;
+		if (capacity < 0)
+			capacity = 0.0f;
+		if (capacity > 100.0)
+			capacity = 100.0f;
+	}
+
 	g_object_set (device,
 		"energy", bst_cap,
 		"energy-full", bif_lastfullcap,
+		"energy-full-design", bif_cap,
 		"energy-rate", bst_rate,
 		"energy-empty", bif_lowcap,
 		"voltage", bst_volt,
+		"capacity", capacity,
 		(void*) NULL);
 }
 
@@ -405,6 +421,70 @@ up_apm_device_refresh(UpDevice* device)
 	}
 
 	return ret;
+}
+
+/*
+ * Check the lid status, return TRUE if one was found, FALSE otherwise.
+ */
+static void
+up_backend_update_lid_status(UpDaemon *daemon) {
+
+	/* Use hw.sensors.acpibtn0.indicator0=On (lid open) */
+	struct sensordev sensordev;
+	struct sensor sensor;
+	size_t sdlen, slen;
+	int dev, numt, mib[5] = {CTL_HW, HW_SENSORS, 0, 0, 0};
+	gboolean lid_found = FALSE;
+	gboolean lid_open = FALSE;
+
+	sdlen = sizeof(struct sensordev);
+	slen  = sizeof(struct sensor);
+
+	/* go through all acpibtn devices, and check if one of the values match "lid"
+	   if so, use that device.
+	*/
+	for (dev = 0; SENSOR_MAX_TYPES; dev++) {
+		mib[2] = dev;
+		if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
+			if (errno == ENXIO)
+				continue;
+			if (errno == ENOENT)
+				break;
+		}
+
+		if (strstr(sensordev.xname, "acpibtn") != NULL) {
+			mib[3] = SENSOR_INDICATOR;
+			for (numt = 0; numt < sensordev.maxnumt[SENSOR_INDICATOR]; numt++) {
+				mib[4] = numt;
+				if (sysctl(mib, 5, &sensor, &slen, NULL, 0) == -1) {
+					if (errno != ENOENT) {
+						g_warning("failed to get sensor data from %s",
+							  sensordev.xname);
+						continue;
+					}
+				}
+
+				/*
+				 * Found an acpibtn device, now check if the
+				 * description has got anything with a lid in it.
+				 */
+				if (strstr(sensor.desc, "lid open") == NULL) {
+					g_warning ("nothing here for %s with %s\n",
+						   sensordev.xname, sensor.desc);
+					continue;
+				} else {
+					lid_found = TRUE;
+					if (sensor.value)
+						lid_open = TRUE;
+					else
+						lid_open = FALSE;
+				}
+			}
+		}
+	}
+
+	up_daemon_set_lid_is_present (daemon, lid_found);
+	up_daemon_set_lid_is_closed (daemon, !lid_open);
 }
 
 /* thread doing kqueue() on apm device */
