Module Name:    src
Committed By:   jruoho
Date:           Thu Apr  8 17:32:30 UTC 2010

Modified Files:
        src/sys/arch/amd64/conf: GENERIC
        src/sys/arch/i386/conf: GENERIC
        src/sys/dev/acpi/wmi: files.wmi
Added Files:
        src/sys/dev/acpi/wmi: wmi_hp.c

Log Message:
Add WMI mappings for HP laptops. Requested by ceg...@.
Thanks to apb@ and cegger@ for initial testing.

XXX: This conflicts with hpqlb(4). Someone with the suitable hardware needs
     to complete the list of hotkeys before -- and if -- this can replace
     hpqlb(4). For now, the driver was left uncommented in the GENERICs.


To generate a diff of this commit:
cvs rdiff -u -r1.273 -r1.274 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.976 -r1.977 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/acpi/wmi/files.wmi
cvs rdiff -u -r0 -r1.1 src/sys/dev/acpi/wmi/wmi_hp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.273 src/sys/arch/amd64/conf/GENERIC:1.274
--- src/sys/arch/amd64/conf/GENERIC:1.273	Thu Apr  8 09:45:17 2010
+++ src/sys/arch/amd64/conf/GENERIC	Thu Apr  8 17:32:30 2010
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.273 2010/04/08 09:45:17 jruoho Exp $
+# $NetBSD: GENERIC,v 1.274 2010/04/08 17:32:30 jruoho Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"GENERIC-$Revision: 1.273 $"
+#ident 		"GENERIC-$Revision: 1.274 $"
 
 maxusers	64		# estimated number of users
 
@@ -305,6 +305,7 @@
 wb*		at acpi?		# Winbond W83L518D SD/MMC reader
 sdmmc*		at wb?			# SD/MMC bus
 wmidell*	at acpiwmibus?		# Dell WMI mappings
+#wmihp*		at acpiwmibus?		# HP WMI mappings
 
 #apm0	at mainbus0			# Advanced power management
 

Index: src/sys/arch/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.976 src/sys/arch/i386/conf/GENERIC:1.977
--- src/sys/arch/i386/conf/GENERIC:1.976	Thu Apr  8 09:45:17 2010
+++ src/sys/arch/i386/conf/GENERIC	Thu Apr  8 17:32:30 2010
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.976 2010/04/08 09:45:17 jruoho Exp $
+# $NetBSD: GENERIC,v 1.977 2010/04/08 17:32:30 jruoho Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"GENERIC-$Revision: 1.976 $"
+#ident 		"GENERIC-$Revision: 1.977 $"
 
 maxusers	64		# estimated number of users
 
@@ -381,6 +381,7 @@
 wb*		at acpi?		# Winbond W83L518D SD/MMC reader
 sdmmc*		at wb?			# SD/MMC bus
 wmidell*	at acpiwmibus?		# Dell WMI mappings
+#wmihp*		at acpiwmibus?		# HP WMI mappings
 wss*		at acpi?		# NeoMagic 256AV in wss mode
 ym*		at acpi?		# Yamaha OPL3-SA[23] audio
 

Index: src/sys/dev/acpi/wmi/files.wmi
diff -u src/sys/dev/acpi/wmi/files.wmi:1.2 src/sys/dev/acpi/wmi/files.wmi:1.3
--- src/sys/dev/acpi/wmi/files.wmi:1.2	Thu Apr  8 12:14:19 2010
+++ src/sys/dev/acpi/wmi/files.wmi	Thu Apr  8 17:32:30 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.wmi,v 1.2 2010/04/08 12:14:19 jruoho Exp $
+#	$NetBSD: files.wmi,v 1.3 2010/04/08 17:32:30 jruoho Exp $
 
 define	acpiwmibus { }
 
@@ -11,3 +11,8 @@
 device	wmidell: sysmon_power
 attach	wmidell at acpiwmibus
 file	dev/acpi/wmi/wmi_dell.c		wmidell
+
+# HP WMI mappings
+device	wmihp: sysmon_envsys
+attach	wmihp at acpiwmibus
+file	dev/acpi/wmi/wmi_hp.c		wmihp

Added files:

Index: src/sys/dev/acpi/wmi/wmi_hp.c
diff -u /dev/null src/sys/dev/acpi/wmi/wmi_hp.c:1.1
--- /dev/null	Thu Apr  8 17:32:31 2010
+++ src/sys/dev/acpi/wmi/wmi_hp.c	Thu Apr  8 17:32:30 2010
@@ -0,0 +1,528 @@
+/*	$NetBSD: wmi_hp.c,v 1.1 2010/04/08 17:32:30 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 2009 Michael Gmelin <free...@grem.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: wmi_hp.c,v 1.1 2010/04/08 17:32:30 jruoho Exp $");
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/wmi/wmi_acpivar.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#define _COMPONENT			ACPI_RESOURCE_COMPONENT
+ACPI_MODULE_NAME			("wmi_hp")
+
+#define WMI_HP_METHOD_ARG_READ		0x01
+#define WMI_HP_METHOD_ARG_WRITE		0x02
+#define WMI_HP_METHOD_ARG_WRITE_SIZE	0x04
+#define WMI_HP_METHOD_ARG_MAGIC		0x55434553
+#define WMI_HP_METHOD_ARG_SIZE		0x05 * sizeof(uint32_t)
+
+#define WMI_HP_METHOD_CMD_DISPLAY	0x01
+#define WMI_HP_METHOD_CMD_HDDTEMP	0x02
+#define WMI_HP_METHOD_CMD_ALS		0x03
+#define WMI_HP_METHOD_CMD_DOCK		0x04
+#define WMI_HP_METHOD_CMD_SWITCH	0x05
+#define WMI_HP_METHOD_CMD_HOTKEY	0x0C
+
+#define WMI_HP_EVENT_DOCK		0x01
+#define WMI_HP_EVENT_HOTKEY		0x04
+#define WMI_HP_EVENT_SWITCH		0x05
+/*      WMI_HP_EVENT_UNKNOWN		0xXX */
+
+#define WMI_HP_HOTKEY_BRIGHTNESS_UP	0x02
+#define WMI_HP_HOTKEY_BRIGHTNESS_DOWN	0x03
+/*      WMI_HP_HOTKEY_UNKNOWN		0xXX */
+
+#define WMI_HP_SWITCH_WLAN		0x01
+#define WMI_HP_SWITCH_BT		0x02
+#define WMI_HP_SWITCH_WWAN		0x04
+
+#define WMI_HP_SWITCH_ARG_WLAN_OFF	0x100
+#define WMI_HP_SWITCH_ARG_WLAN_ON	0x101
+#define WMI_HP_SWITCH_ARG_BT_OFF	0x200
+#define WMI_HP_SWITCH_ARG_BT_ON		0x202
+#define WMI_HP_SWITCH_ARG_WWAN_OFF	0x400
+#define WMI_HP_SWITCH_ARG_WWAN_ON	0x404
+
+#define WMI_HP_SWITCH_MASK_WLAN_ONAIR	__BIT(8)
+#define WMI_HP_SWITCH_MASK_WLAN_ENABLED	__BIT(9)
+#define WMI_HP_SWITCH_MASK_WLAN_RADIO	__BIT(11)
+#define WMI_HP_SWITCH_MASK_BT_ONAIR	__BIT(16)
+#define WMI_HP_SWITCH_MASK_BT_ENABLED	__BIT(17)
+#define WMI_HP_SWITCH_MASK_BT_RADIO	__BIT(19)
+#define WMI_HP_SWITCH_MASK_WWAN_ONAIR	__BIT(24)
+#define WMI_HP_SWITCH_MASK_WWAN_ENABLED	__BIT(25)
+#define WMI_HP_SWITCH_MASK_WWAN_RADIO	__BIT(27)
+
+#define WMI_HP_GUID_EVENT		"95F24279-4D7B-4334-9387-ACCDC67EF61C"
+#define WMI_HP_GUID_METHOD		"5FB7F034-2C63-45E9-BE91-3D44E2C707E4"
+
+#define WMI_HP_SENSOR_WLAN		0
+#define WMI_HP_SENSOR_BT		1
+#define WMI_HP_SENSOR_WWAN		2
+#define WMI_HP_SENSOR_COUNT		3
+#define WMI_HP_SENSOR_SIZE		3 * sizeof(envsys_data_t)
+
+struct wmi_hp_softc {
+	device_t		sc_dev;
+	device_t		sc_parent;
+	struct sysmon_envsys   *sc_sme;
+	envsys_data_t	       *sc_sensor;
+	uint32_t	       *sc_arg;
+	uint32_t		sc_val;
+};
+
+static int	wmi_hp_match(device_t, cfdata_t, void *);
+static void	wmi_hp_attach(device_t, device_t, void *);
+static int	wmi_hp_detach(device_t, int);
+static bool	wmi_hp_suspend(device_t, const pmf_qual_t *);
+static bool	wmi_hp_resume(device_t, const pmf_qual_t *);
+static void	wmi_hp_notify_handler(ACPI_HANDLE, uint32_t, void *);
+static void	wmi_hp_hotkey(void *);
+static bool	wmi_hp_method(struct wmi_hp_softc *);
+static bool	wmi_hp_method_read(struct wmi_hp_softc *, uint8_t);
+
+#if 0
+static bool	wmi_hp_method_write(struct wmi_hp_softc *, uint8_t, uint32_t);
+#endif
+
+static void	wmi_hp_sensor_init(struct wmi_hp_softc *);
+static void	wmi_hp_sensor_update(void *);
+
+CFATTACH_DECL_NEW(wmihp, sizeof(struct wmi_hp_softc),
+    wmi_hp_match, wmi_hp_attach, wmi_hp_detach, NULL);
+
+static int
+wmi_hp_match(device_t parent, cfdata_t match, void *aux)
+{
+	return acpi_wmi_guid_match(parent, WMI_HP_GUID_METHOD);
+}
+
+static void
+wmi_hp_attach(device_t parent, device_t self, void *aux)
+{
+	struct wmi_hp_softc *sc = device_private(self);
+	ACPI_STATUS rv = AE_ERROR;
+
+	sc->sc_dev = self;
+	sc->sc_parent = parent;
+
+	sc->sc_sme = NULL;
+	sc->sc_sensor = NULL;
+
+	sc->sc_arg = kmem_alloc(WMI_HP_METHOD_ARG_SIZE, KM_SLEEP);
+
+	if (sc->sc_arg == NULL)
+		return;
+
+	aprint_naive("\n");
+	aprint_normal(": HP WMI mappings\n");
+
+	(void)pmf_device_register(sc->sc_dev, wmi_hp_suspend, wmi_hp_resume);
+
+	if (acpi_wmi_guid_match(parent, WMI_HP_GUID_EVENT) != 0)
+		rv = acpi_wmi_event_register(parent, wmi_hp_notify_handler);
+
+	if (ACPI_FAILURE(rv))
+		return;
+
+	sc->sc_sensor = kmem_alloc(WMI_HP_SENSOR_SIZE, KM_SLEEP);
+
+	if (sc->sc_sensor == NULL)
+		return;
+
+	wmi_hp_sensor_init(sc);
+}
+
+static int
+wmi_hp_detach(device_t self, int flags)
+{
+	struct wmi_hp_softc *sc = device_private(self);
+	device_t parent = sc->sc_parent;
+
+	(void)acpi_wmi_event_deregister(parent);
+
+	if (sc->sc_sme != NULL)
+		sysmon_envsys_unregister(sc->sc_sme);
+
+	if (sc->sc_sensor != NULL)
+		kmem_free(sc->sc_sensor, WMI_HP_SENSOR_SIZE);
+
+	if (sc->sc_arg != NULL)
+		kmem_free(sc->sc_arg, WMI_HP_METHOD_ARG_SIZE);
+
+	pmf_device_deregister(self);
+
+	return 0;
+}
+
+static bool
+wmi_hp_suspend(device_t self, const pmf_qual_t *qual)
+{
+	struct wmi_hp_softc *sc = device_private(self);
+	device_t parent = sc->sc_parent;
+
+	if (sc->sc_sensor != NULL)
+		(void)acpi_wmi_event_deregister(parent);
+
+	return true;
+}
+
+static bool
+wmi_hp_resume(device_t self, const pmf_qual_t *qual)
+{
+	struct wmi_hp_softc *sc = device_private(self);
+	device_t parent = sc->sc_parent;
+
+	if (sc->sc_sensor != NULL)
+		(void)acpi_wmi_event_register(parent, wmi_hp_notify_handler);
+
+	return true;
+}
+
+static void
+wmi_hp_notify_handler(ACPI_HANDLE hdl, uint32_t evt, void *aux)
+{
+	static const int handler = OSL_NOTIFY_HANDLER;
+	struct wmi_hp_softc *sc;
+	device_t self = aux;
+	ACPI_OBJECT *obj;
+	ACPI_BUFFER buf;
+	ACPI_STATUS rv;
+	uint32_t val;
+
+	sc = device_private(self);
+	rv = acpi_wmi_event_get(sc->sc_parent, evt, &buf);
+
+	if (ACPI_FAILURE(rv))
+		goto out;
+
+	obj = buf.Pointer;
+
+	if (obj->Type != ACPI_TYPE_BUFFER) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	if (obj->Buffer.Length != 8) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	val = *((uint8_t *)obj->Buffer.Pointer);
+
+	if (val == 0x00) {
+		rv = AE_BAD_DATA;
+		goto out;
+	}
+
+	switch (val) {
+
+	case WMI_HP_EVENT_SWITCH:
+		rv = AcpiOsExecute(handler, wmi_hp_sensor_update, self);
+		break;
+
+	case WMI_HP_EVENT_HOTKEY:
+		rv = AcpiOsExecute(handler, wmi_hp_hotkey, self);
+		break;
+
+	case WMI_HP_EVENT_DOCK:	/* FALLTHROUGH */
+
+	default:
+		aprint_debug_dev(sc->sc_dev, "unknown event 0x%02X\n", evt);
+		break;
+	}
+
+out:
+	if (buf.Pointer != NULL)
+		ACPI_FREE(buf.Pointer);
+
+	if (ACPI_FAILURE(rv))
+		aprint_error_dev(sc->sc_dev, "failed to get data for "
+		    "event 0x%02X: %s\n", evt, AcpiFormatException(rv));
+}
+
+static void
+wmi_hp_hotkey(void *aux)
+{
+	struct wmi_hp_softc *sc;
+	device_t self = aux;
+
+	sc = device_private(self);
+
+	if (wmi_hp_method_read(sc, WMI_HP_METHOD_CMD_HOTKEY) != true)
+		return;
+
+	switch (sc->sc_val) {
+
+	case WMI_HP_HOTKEY_BRIGHTNESS_UP:
+		pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_UP);
+		break;
+
+	case WMI_HP_HOTKEY_BRIGHTNESS_DOWN:
+		pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_DOWN);
+		break;
+
+	default:
+		aprint_debug_dev(self, "unknown hotkey 0x%02x\n", sc->sc_val);
+		break;
+	}
+}
+
+static bool
+wmi_hp_method(struct wmi_hp_softc *sc)
+{
+	ACPI_BUFFER ibuf, obuf;
+	ACPI_STATUS rv = AE_OK;
+	ACPI_OBJECT *obj;
+	uint32_t cmd, *val;
+
+	cmd = sc->sc_arg[2];
+
+	KDASSERT(cmd != 0);
+	KDASSERT(sc->sc_arg[0] == WMI_HP_METHOD_ARG_MAGIC);
+
+	ibuf.Pointer = sc->sc_arg;
+	ibuf.Length = WMI_HP_METHOD_ARG_SIZE;
+
+	rv = acpi_wmi_method(sc->sc_parent,
+	    WMI_HP_GUID_METHOD, 0, 3, &ibuf, &obuf);
+
+	if (ACPI_FAILURE(rv))
+		goto out;
+
+	obj = obuf.Pointer;
+
+	if (obj->Type != ACPI_TYPE_BUFFER) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	/*
+	 *	val[0]	unknown
+	 *	val[1]	error code
+	 *	val[2]	return value
+	 */
+	val = (uint32_t *)obj->Buffer.Pointer;
+
+	if (val[1] != 0) {
+		rv = AE_ERROR;
+		goto out;
+	}
+
+	sc->sc_val = val[2];
+
+out:
+	if (obuf.Pointer != NULL)
+		ACPI_FREE(obuf.Pointer);
+
+	if (ACPI_FAILURE(rv)) {
+		aprint_debug_dev(sc->sc_dev, "failed to evaluate method "
+		    "(cmd = 0x%02X): %s\n", cmd, AcpiFormatException(rv));
+		return false;
+	}
+
+	return true;
+}
+
+static bool
+wmi_hp_method_read(struct wmi_hp_softc *sc, uint8_t cmd)
+{
+
+	sc->sc_arg[0] = WMI_HP_METHOD_ARG_MAGIC;
+	sc->sc_arg[1] = WMI_HP_METHOD_ARG_READ;
+	sc->sc_arg[2] = cmd;
+	sc->sc_arg[3] = 0;
+	sc->sc_arg[4] = 0;
+
+	return wmi_hp_method(sc);
+}
+
+#if 0
+static bool
+wmi_hp_method_write(struct wmi_hp_softc *sc, uint8_t cmd, uint32_t val)
+{
+
+	sc->sc_arg[0] = WMI_HP_METHOD_ARG_MAGIC;
+	sc->sc_arg[1] = WMI_HP_METHOD_ARG_WRITE;
+	sc->sc_arg[2] = cmd;
+	sc->sc_arg[3] = WMI_HP_METHOD_ARG_WRITE_SIZE;
+	sc->sc_arg[4] = val;
+
+	return wmi_hp_method(sc);
+}
+#endif
+
+static void
+wmi_hp_sensor_init(struct wmi_hp_softc *sc)
+{
+	int i, j, sensor[3];
+
+	const char desc[][ENVSYS_DESCLEN] = {
+		"wireless", "bluetooth", "mobile"
+	};
+
+	KDASSERT(sc->sc_sme == NULL);
+	KDASSERT(sc->sc_sensor != NULL);
+
+	(void)memset(sc->sc_sensor, 0, WMI_HP_SENSOR_SIZE);
+
+	if (wmi_hp_method_read(sc, WMI_HP_METHOD_CMD_SWITCH) != true)
+		return;
+
+	sc->sc_sme = sysmon_envsys_create();
+
+	sensor[0] = WMI_HP_SWITCH_WLAN;
+	sensor[1] = WMI_HP_SWITCH_BT;
+	sensor[2] = WMI_HP_SWITCH_WWAN;
+
+	CTASSERT(WMI_HP_SENSOR_WLAN == 0);
+	CTASSERT(WMI_HP_SENSOR_BT   == 1);
+	CTASSERT(WMI_HP_SENSOR_WWAN == 2);
+
+	for (i = j = 0; i < 3; i++) {
+
+		if ((sc->sc_val & sensor[i]) == 0)
+			continue;
+
+		(void)strlcpy(sc->sc_sensor[i].desc, desc[i], ENVSYS_DESCLEN);
+
+		sc->sc_sensor[i].state = ENVSYS_SINVALID;
+		sc->sc_sensor[i].units = ENVSYS_INDICATOR;
+
+		if (sysmon_envsys_sensor_attach(sc->sc_sme,
+			&sc->sc_sensor[i]) != 0)
+			goto fail;
+
+		j++;
+	}
+
+	if (j == 0)
+		goto fail;
+
+	sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
+	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
+
+	if (sysmon_envsys_register(sc->sc_sme) != 0)
+		goto fail;
+
+	wmi_hp_sensor_update(sc->sc_dev);
+
+	return;
+
+fail:
+	aprint_debug_dev(sc->sc_dev, "failed to initialize sysmon\n");
+
+	sysmon_envsys_destroy(sc->sc_sme);
+	kmem_free(sc->sc_sensor, WMI_HP_SENSOR_SIZE);
+
+	sc->sc_sme = NULL;
+	sc->sc_sensor = NULL;
+}
+
+static void
+wmi_hp_sensor_update(void *aux)
+{
+	struct wmi_hp_softc *sc;
+	device_t self = aux;
+
+	sc = device_private(self);
+
+	if (sc->sc_sme == NULL || sc->sc_sensor == NULL)
+		return;
+
+	if (wmi_hp_method_read(sc, WMI_HP_METHOD_CMD_SWITCH) != true) {
+		sc->sc_sensor[WMI_HP_SENSOR_WLAN].state = ENVSYS_SINVALID;
+		sc->sc_sensor[WMI_HP_SENSOR_WWAN].state = ENVSYS_SINVALID;
+		sc->sc_sensor[WMI_HP_SENSOR_BT].state = ENVSYS_SINVALID;
+		return;
+	}
+
+	if ((sc->sc_val & WMI_HP_SWITCH_WLAN) != 0) {
+		sc->sc_sensor[WMI_HP_SENSOR_WLAN].value_cur = 0;
+
+		if ((sc->sc_val & WMI_HP_SWITCH_MASK_WLAN_ONAIR) != 0)
+			sc->sc_sensor[WMI_HP_SENSOR_WLAN].value_cur = 1;
+
+		sc->sc_sensor[WMI_HP_SENSOR_WLAN].state = ENVSYS_SVALID;
+	}
+
+	if ((sc->sc_val & WMI_HP_SWITCH_BT) != 0) {
+		sc->sc_sensor[WMI_HP_SENSOR_BT].value_cur = 0;
+
+		if ((sc->sc_val & WMI_HP_SWITCH_MASK_BT_ONAIR) != 0)
+			sc->sc_sensor[WMI_HP_SENSOR_BT].value_cur = 1;
+
+		sc->sc_sensor[WMI_HP_SENSOR_BT].state = ENVSYS_SVALID;
+	}
+
+	if ((sc->sc_val & WMI_HP_SWITCH_WWAN) != 0) {
+		sc->sc_sensor[WMI_HP_SENSOR_WWAN].value_cur = 0;
+
+		if ((sc->sc_val & WMI_HP_SWITCH_MASK_WWAN_ONAIR) != 0)
+			sc->sc_sensor[WMI_HP_SENSOR_WWAN].value_cur = 1;
+
+		sc->sc_sensor[WMI_HP_SENSOR_WWAN].state = ENVSYS_SVALID;
+	}
+}

Reply via email to