NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/46870
The following reply was made to PR kern/46870; it has been noted by GNATS.
From: Nat Sloss <nathanialsloss%yahoo.com.au@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc:
Subject: Re: kern/46870
Date: Wed, 29 Aug 2012 18:40:38 +1000
Hi.
Here are the files:
--- /dev/null 2012-08-29 17:38:04.000000000 +1000
+++ ../../sys/dev/acpi/panasonic_acpi.c 2012-08-29 16:55:51.000000000
+1000
@@ -0,0 +1,626 @@
+/*-
+ * Copyright (c) 2006-2012 Nathanial Sloss
<nathanialsloss%yahoo.com.au@localhost>
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 2003 OGAWA Takaya <t-ogawa%triaez.kaisei.org@localhost>
+ * Copyright (c) 2004 Yoshihiro TAKAHASHI <nyan%FreeBSD.org@localhost>
+ * 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>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/callout.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/pmf.h>
+#include <sys/sysctl.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpireg.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <sys/fcntl.h>
+
+typedef struct panasonic_softc {
+ device_t sc_dev;
+ struct acpi_devnode *sc_node;
+
+ int sc_brightness;
+ int sc_brightness_min;
+ int sc_brightness_max;
+
+#define PANASONIC_PSW_SLEEP 0
+#define PANASONIC_PSW_HIBERNATE 1
+#define PANASONIC_PSW_DISPLAY_CYCLE 2
+#define PANASONIC_PSW_BATTERY_INFO 3
+#define PANASONIC_PSW_LAST 4
+
+ struct sysmon_pswitch sc_smpsw[PANASONIC_PSW_LAST];
+ bool sc_smpsw_valid;
+
+ struct sysctllog *sc_log;
+ int sc_brightness_mib;
+
+} panasonic_softc_t;
+
+/* Hotkey buttons (HKEY) */
+#define PANASONIC_NOTIFY_BrightnessDownPRESSED 0x81
+#define PANASONIC_NOTIFY_BrightnessDownRELEASED 0x01
+
+#define PANASONIC_NOTIFY_BrightnessUpPRESSED 0x82
+#define PANASONIC_NOTIFY_BrightnessUpRELEASED 0x02
+
+#define PANASONIC_NOTIFY_DisplayCyclePRESSED 0x83
+#define PANASONIC_NOTIFY_DisplayCycleRELEASED 0x03
+
+#define PANASONIC_NOTIFY_VolumeMutePRESSED 0x84
+#define PANASONIC_NOTIFY_VolumeMuteRELEASED 0x04
+
+#define PANASONIC_NOTIFY_VolumeDownPRESSED 0x85
+#define PANASONIC_NOTIFY_VolumeDownRELEASED 0x05
+
+#define PANASONIC_NOTIFY_VolumeUpPRESSED 0x86
+#define PANASONIC_NOTIFY_VolumeUpRELEASED 0x06
+
+#define PANASONIC_NOTIFY_SuspendToRamPRESSED 0x07
+
+#define PANASONIC_NOTIFY_BatteryInfoPRESSED 0x89
+#define PANASONIC_NOTIFY_BatteryInfoRELEASED 0x09
+
+#define PANASONIC_NOTIFY_SuspendToHddPRESSED 0x0A
+
+#define ACPI_SERIAL_BEGIN(x)
+#define ACPI_SERIAL_END(x)
+#define ACPI_SERIAL_ASSERT(x)
+
+#define HKEY_SET 0
+#define HKEY_GET 1
+
+/* Registers */
+#define HKEY_REG_LCD_BRIGHTNESS_MAX_AC 0x02
+#define HKEY_REG_LCD_BRIGHTNESS_MIN_AC 0x03
+#define HKEY_REG_LCD_BRIGHTNESS_AC 0x04
+#define HKEY_REG_LCD_BRIGHTNESS_MAX_DC 0x05
+#define HKEY_REG_LCD_BRIGHTNESS_MIN_DC 0x06
+#define HKEY_REG_LCD_BRIGHTNESS_DC 0x07
+#define HKEY_REG_SOUND_MUTE 0x08
+
+/* Field definitions */
+#define HKEY_LCD_BRIGHTNESS_BITS 4
+#define HKEY_LCD_BRIGHTNESS_DIV ((1 << HKEY_LCD_BRIGHTNESS_BITS) - 1)
+
+#define LCD_BRIGHTNESS_DOWN 0
+#define LCD_BRIGHTNESS_UP 1
+
+#define LCD_BRIGHTNESS_MIN 0
+#define LCD_BRIGHTNESS_MAX 1
+
+#define HARDWARE_UNMUTE 0
+#define HARDWARE_MUTE 1
+
+static int panasonic_match(device_t, cfdata_t, void *);
+static void panasonic_attach(device_t, device_t, void *);
+static int panasonic_detach(device_t, int);
+
+static void panasonic_notify_handler(ACPI_HANDLE, UINT32, void *);
+
+static void panasonic_init(struct panasonic_softc *);
+static void panasonic_sysctl_setup(struct panasonic_softc *);
+
+static int
+acpi_panasonic_hkey_event(device_t, ACPI_INTEGER *);
+
+static void
+acpi_panasonic_hkey_action(device_t, ACPI_INTEGER);
+
+static void panasonic_acpi_brightness_up(device_t);
+
+static void panasonic_acpi_brightness_down(device_t);
+
+static void hkey_lcd_brightness_action(struct panasonic_softc *, int);
+
+static int
+hkey_lcd_brightness(struct panasonic_softc *, int, ACPI_INTEGER *);
+
+static ACPI_INTEGER
+acpi_panasonic_sinf(ACPI_HANDLE, ACPI_INTEGER);
+
+static void
+acpi_panasonic_sset(ACPI_HANDLE, ACPI_INTEGER, ACPI_INTEGER);
+
+static int
+hkey_sound_mute(ACPI_HANDLE, int, ACPI_INTEGER *);
+
+CFATTACH_DECL_NEW(panasonic, sizeof(panasonic_softc_t),
+ panasonic_match, panasonic_attach, panasonic_detach, NULL);
+
+static const char * const panasonic_ids[] = {
+ "MAT0019",
+ NULL
+};
+
+static int
+panasonic_match(device_t parent, cfdata_t match, void *opaque)
+{
+ struct acpi_attach_args *aa = opaque;
+
+ if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+ return 0;
+
+ return acpi_match_hid(aa->aa_node->ad_devinfo, panasonic_ids);
+}
+
+static void
+panasonic_attach(device_t parent, device_t self, void *opaque)
+{
+ panasonic_softc_t *sc = device_private(self);
+ struct acpi_attach_args *aa = opaque;
+ struct sysmon_pswitch *psw;
+ ACPI_STATUS rv;
+
+ sc->sc_node = aa->aa_node;
+ sc->sc_dev = self;
+
+ aprint_naive(": Panasonic Hotkeys\n");
+ aprint_normal(": Panasonic Hotkeys\n");
+
+ rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, ACPI_ALL_NOTIFY,
+ panasonic_notify_handler, sc);
+ if (ACPI_FAILURE(rv))
+ aprint_error_dev(self, "couldn't install notify handler: %s\n",
+ AcpiFormatException(rv));
+
+ /* Register power switches with sysmon */
+ psw = sc->sc_smpsw;
+ sc->sc_smpsw_valid = true;
+
+ psw[PANASONIC_PSW_SLEEP].smpsw_name = device_xname(self);
+ psw[PANASONIC_PSW_SLEEP].smpsw_type = PSWITCH_TYPE_SLEEP;
+#if notyet
+ psw[PANASONIC_PSW_HIBERNATE].smpsw_name = device_xname(self);
+ mpsw[PANASONIC_PSW_HIBERNATE].smpsw_type = PSWITCH_TYPE_HIBERNATE;
+#endif
+ int i;
+ for (i = PANASONIC_PSW_DISPLAY_CYCLE; i < PANASONIC_PSW_LAST; i++)
+ psw[i].smpsw_type = PSWITCH_TYPE_HOTKEY;
+ psw[PANASONIC_PSW_DISPLAY_CYCLE].smpsw_name = PSWITCH_HK_DISPLAY_CYCLE;
+ psw[PANASONIC_PSW_BATTERY_INFO].smpsw_name = PSWITCH_HK_BATTERY_INFO;
+
+ for (i = 0; i < PANASONIC_PSW_LAST; i++) {
+ if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) {
+ aprint_error_dev(self,
+ "couldn't register with sysmon\n");
+ sc->sc_smpsw_valid = false;
+ break;
+ }
+ }
+ if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
+ panasonic_acpi_brightness_up, true))
+ aprint_error_dev(self,
+ "couldn't register BRIGHTNESS UP handler\n");
+
+ if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
+ panasonic_acpi_brightness_down, true))
+ aprint_error_dev(self,
+ "couldn't register BRIGHTNESS DOWN handler\n");
+
+ if (!pmf_device_register(self, NULL, NULL))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+
+ panasonic_init(sc);
+ panasonic_sysctl_setup(sc);
+}
+
+static int
+panasonic_detach(device_t self, int flags)
+{
+ struct panasonic_softc *sc = device_private(self);
+ int i;
+
+ if (sc->sc_smpsw_valid)
+ for (i = 0; i < PANASONIC_PSW_LAST; i++)
+ sysmon_pswitch_unregister(&sc->sc_smpsw[i]);
+
+ if (sc->sc_log)
+ sysctl_teardown(&sc->sc_log);
+ pmf_device_deregister(self);
+
+ return 0;
+}
+
+static void
+panasonic_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque)
+{
+ panasonic_softc_t *sc = opaque;
+
+ ACPI_INTEGER key;
+ key = 0;
+
+ switch (notify) {
+ case 0x80:
+ ACPI_SERIAL_BEGIN(panasonic);
+ if (acpi_panasonic_hkey_event(sc->sc_dev, &key) == 0) {
+ acpi_panasonic_hkey_action(sc->sc_dev, key);
+ }
+
+ ACPI_SERIAL_END(panasonic);
+ break;
+ default:
+ aprint_debug_dev(sc->sc_dev, "unknown notify: %#x\n", notify);
+ break;
+ }
+}
+
+static void
+panasonic_init(struct panasonic_softc *sc)
+{
+ ACPI_INTEGER val;
+ ACPI_HANDLE hdl;
+
+ hdl = sc->sc_node->ad_handle;
+ val = HARDWARE_UNMUTE;
+
+ /* Unmute the speaker - Hardware */
+ hkey_sound_mute(hdl, HKEY_SET, &val);
+
+ /* Initialise variables */
+ sc->sc_brightness_min = acpi_panasonic_sinf(hdl,
+ HKEY_REG_LCD_BRIGHTNESS_MIN_AC);
+ sc->sc_brightness_max = acpi_panasonic_sinf(hdl,
+ HKEY_REG_LCD_BRIGHTNESS_MAX_AC);
+ if (sc->sc_brightness_max <= 0)
+ sc->sc_brightness_max = 100;
+ sc->sc_brightness = (acpi_panasonic_sinf(hdl,
+ HKEY_REG_LCD_BRIGHTNESS_AC) * 100) / sc->sc_brightness_max;
+}
+
+static int
+panasonic_sysctl_verify(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node;
+ struct panasonic_softc *sc;
+ ACPI_INTEGER val;
+ int err, tmp;
+
+ node = *rnode;
+ sc = rnode->sysctl_data;
+
+ if (node.sysctl_num == sc->sc_brightness_mib) {
+ err = hkey_lcd_brightness(sc, HKEY_GET, &val);
+ if (err)
+ val = sc->sc_brightness_min;
+ tmp = (val * 100) / sc->sc_brightness_max;
+ node.sysctl_data = &tmp;
+ err = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (err || newp == NULL)
+ return err;
+
+ if (tmp < 0 || tmp > 100)
+ return EINVAL;
+ val = (tmp * sc->sc_brightness_max) / 100;
+ if (val == 0)
+ val = sc->sc_brightness_min;
+ err = hkey_lcd_brightness(sc, HKEY_SET, &val);
+ if (err)
+ return err;
+ tmp = (val * 100) / sc->sc_brightness_max;
+ sc->sc_brightness = tmp;
+ }
+
+ return 0;
+}
+
+static void
+panasonic_sysctl_setup(struct panasonic_softc *sc)
+{
+ const struct sysctlnode *node, *node_brightness;
+ int err;
+
+ err = sysctl_createv(&sc->sc_log, 0, NULL, NULL, 0,
+ CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+
+ err = sysctl_createv(&sc->sc_log, 0, NULL, &node, 0,
+ CTLTYPE_NODE, "panasonic",
+ SYSCTL_DESCR("Toughbook controls"), NULL, 0,
+ NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+
+ err = sysctl_createv(&sc->sc_log, 0, &node, &node_brightness,
+ CTLFLAG_READWRITE | CTLFLAG_ANYWRITE, CTLTYPE_INT, "brightness",
+ SYSCTL_DESCR("Screen brightness (Percent)"),
+ panasonic_sysctl_verify, 0, sc, 0,
+ CTL_CREATE, CTL_EOL);
+ if (err)
+ goto sysctl_err;
+ sc->sc_brightness_mib = node_brightness->sysctl_num;
+
+ return;
+sysctl_err:
+ aprint_error_dev(sc->sc_dev, "failed to add sysctl nodes. (%d)\n", err);
+}
+
+static int
+acpi_panasonic_hkey_event(device_t self, ACPI_INTEGER *arg) {
+
+ struct panasonic_softc *sc = device_private(self);
+
+ ACPI_BUFFER buf;
+ ACPI_OBJECT *res;
+ ACPI_INTEGER val;
+ int status;
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ status = ENXIO;
+
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ buf.Pointer = NULL;
+ AcpiEvaluateObject(sc->sc_node->ad_handle, "HINF", NULL, &buf);
+ res = (ACPI_OBJECT *)buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ aprint_error_dev(self, "HINF returned non-integer\n");
+ goto end;
+ }
+ val = res->Integer.Value;
+
+ *arg = val;
+ status = 0;
+end:
+ if (buf.Pointer)
+ AcpiOsFree(buf.Pointer);
+
+ return (status);
+}
+
+static void
+acpi_panasonic_hkey_action(device_t self, ACPI_INTEGER key)
+{
+
+ struct panasonic_softc *sc = device_private(self);
+
+ ACPI_SERIAL_ASSERT(panasonic);
+
+ switch (key) {
+ case PANASONIC_NOTIFY_BrightnessDownPRESSED:
+ pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_DOWN);
+ break;
+ case PANASONIC_NOTIFY_BrightnessDownRELEASED:
+ break;
+ case PANASONIC_NOTIFY_BrightnessUpPRESSED:
+ pmf_event_inject(NULL, PMFE_DISPLAY_BRIGHTNESS_UP);
+ break;
+ case PANASONIC_NOTIFY_BrightnessUpRELEASED:
+ break;
+ case PANASONIC_NOTIFY_DisplayCyclePRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_DISPLAY_CYCLE],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_DisplayCycleRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_DISPLAY_CYCLE],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ case PANASONIC_NOTIFY_VolumeMutePRESSED:
+ pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_TOGGLE);
+ break;
+ case PANASONIC_NOTIFY_VolumeMuteRELEASED:
+ break;
+ case PANASONIC_NOTIFY_VolumeDownPRESSED:
+ pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN);
+ break;
+ case PANASONIC_NOTIFY_VolumeDownRELEASED:
+ break;
+ case PANASONIC_NOTIFY_VolumeUpPRESSED:
+ pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP);
+ break;
+ case PANASONIC_NOTIFY_VolumeUpRELEASED:
+ break;
+ case PANASONIC_NOTIFY_SuspendToRamPRESSED:
+ /* Suspend. */
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_SLEEP],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_BatteryInfoPRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_BATTERY_INFO],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_BatteryInfoRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_BATTERY_INFO],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ case PANASONIC_NOTIFY_SuspendToHddPRESSED:
+#if notyet
+ /* Hibernate. */
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_HIBERNATE],
+ PSWITCH_EVENT_PRESSED);
+#endif
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev, "Unknown Key 0x%X\n", (int)key);
+ break;
+ }
+}
+
+static void
+panasonic_acpi_brightness_up(device_t self){
+
+ struct panasonic_softc *sc = device_private(self);
+
+ hkey_lcd_brightness_action(sc, LCD_BRIGHTNESS_UP);
+
+}
+
+static void
+panasonic_acpi_brightness_down(device_t self){
+
+ struct panasonic_softc *sc = device_private(self);
+
+ hkey_lcd_brightness_action(sc, LCD_BRIGHTNESS_DOWN);
+
+}
+
+static void
+hkey_lcd_brightness_action(struct panasonic_softc *sc, int direction){
+
+ ACPI_INTEGER arg;
+
+ hkey_lcd_brightness(sc, HKEY_GET, &arg);
+
+ if (direction == LCD_BRIGHTNESS_UP)
+ arg += sc->sc_brightness_max / HKEY_LCD_BRIGHTNESS_DIV;
+ else
+ arg -= sc->sc_brightness_max / HKEY_LCD_BRIGHTNESS_DIV;
+
+ if (arg < sc->sc_brightness_min)
+ arg = sc->sc_brightness_min;
+ else if (arg > sc->sc_brightness_max)
+ arg = sc->sc_brightness_max;
+
+ hkey_lcd_brightness(sc, HKEY_SET, &arg);
+
+}
+
+static int
+hkey_lcd_brightness(struct panasonic_softc *sc, int op, ACPI_INTEGER *val)
+{
+ ACPI_HANDLE hdl;
+ ACPI_INTEGER reg;
+
+ hdl = sc->sc_node->ad_handle;
+
+ reg = HKEY_REG_LCD_BRIGHTNESS_AC;
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ switch (op) {
+ case HKEY_SET:
+ if (*val < sc->sc_brightness_min ||
+ *val > sc->sc_brightness_max)
+ return (EINVAL);
+ acpi_panasonic_sset(hdl, reg, *val);
+ break;
+ case HKEY_GET:
+ *val = acpi_panasonic_sinf(hdl, reg);
+ break;
+ }
+
+ return (0);
+}
+
+static ACPI_INTEGER
+acpi_panasonic_sinf(ACPI_HANDLE hdl, ACPI_INTEGER index)
+{
+ ACPI_BUFFER buf;
+ ACPI_OBJECT *res;
+ ACPI_INTEGER ret;
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ ret = -1;
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ buf.Pointer = NULL;
+ AcpiEvaluateObject(hdl, "SINF", NULL, &buf);
+ res = (ACPI_OBJECT *)buf.Pointer;
+ if (res->Type == ACPI_TYPE_PACKAGE)
+ ret = res->Package.Elements[index].Integer.Value;
+ AcpiOsFree(buf.Pointer);
+
+ return (ret);
+}
+
+static void
+acpi_panasonic_sset(ACPI_HANDLE hdl, ACPI_INTEGER index, ACPI_INTEGER val)
+{
+ ACPI_OBJECT_LIST args;
+ ACPI_OBJECT obj[2];
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ obj[0].Type = ACPI_TYPE_INTEGER;
+ obj[0].Integer.Value = index;
+ obj[1].Type = ACPI_TYPE_INTEGER;
+ obj[1].Integer.Value = val;
+ args.Count = 2;
+ args.Pointer = obj;
+ AcpiEvaluateObject(hdl, "SSET", &args, NULL);
+}
+
+static int
+hkey_sound_mute(ACPI_HANDLE hdl, int op, ACPI_INTEGER *val)
+{
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ switch (op) {
+ case HKEY_SET:
+ if (*val != 0 && *val != 1)
+ return (EINVAL);
+ acpi_panasonic_sset(hdl, HKEY_REG_SOUND_MUTE, *val);
+ break;
+ case HKEY_GET:
+ *val = acpi_panasonic_sinf(hdl, HKEY_REG_SOUND_MUTE);
+ break;
+ }
+
+ return (0);
+}
+
--- /dev/null 2012-08-29 17:38:04.000000000 +1000
+++ man4/panasonic.4 2012-08-29 18:04:06.000000000 +1000
@@ -0,0 +1,74 @@
+.\"
+.\" Copyright (c) 2012 Nathanial Sloss <nathanialsloss%yahoo.com.au@localhost>
+.\" 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+.\"
+.Dd August 29, 2012
+.Dt PANASONIC 4
+.Os
+.Sh NAME
+.Nm panasonic
+.Nd Panasonic TOUGHBOOK laptop features support
+.Sh SYNOPSIS
+.Cd "panasonic* at acpi?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for hotkey handling and screen brightness found on
+Panasonic TOUGHBOOK laptop computers.
+.Pp
+The
+.Nm
+driver provides support for modifying the screen brightness via the
+.Xr sysctl 8
+interface.
+.Pp
+The following
+.Xr sysctl 8
+variables are available:
+.Pp
+.Bl -tag -width "hw.panasonic.brightness [R/W]" -compact
+.It Em hw.panasonic.brightness Bq R/W
+Controls current LCD brightness.
+Range [0-100].
+.El
+.Sh SEE ALSO
+.Xr acpi 4 ,
+.Xr acpivga 4 ,
+.Xr pmf 9 ,
+.Xr sysmon_envsys 9 ,
+.Xr toughbook_hbtn 4
+.Sh HISTORY
+The
+.Nm
+device driver appeared in FreeBSD and was extended and ported to
+.Nx 3.0.1 by Nathanial Sloss.
+.Sh AUTHORS
+.An OGAWA Takaya Aq t-ogawa%triaez.kaisei.org@localhost
+.An Yoshihiro TAKAHASHI Aq nyan%FreeBSD.org@localhost
+.An Nathanial Sloss
+.Sh BUGS
+If the computer is fully supported by
+.Xr acpivga 4 then a different method
+for controlling the screen brightness is used and the above mentioned
+.Xr sysctl 8 variable may not work.
--- /dev/null 2012-08-29 17:38:04.000000000 +1000
+++ ../../sys/dev/acpi/toughbook_hbtn_acpi.c 2012-07-02 19:34:35.000000000
+1000
@@ -0,0 +1,287 @@
+/*-
+ * Copyright (c)2008 - 2012 Nathanial Sloss
<nathanialsloss%yahoo.com.au@localhost>
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/* Panasonic Toughbook CF-18/19 (and possibly others) tablet button driver.
*/
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/pmf.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpireg.h>
+
+typedef struct toughbook_hbtn_softc {
+ device_t sc_dev;
+ struct acpi_devnode *sc_node;
+
+#define PANASONIC_PSW_SECURITY 0
+#define PANASONIC_PSW_ROTATION 1
+#define PANASONIC_PSW_ENTER 2
+#define PANASONIC_PSW_INPUT_PANEL 3
+#define PANASONIC_PSW_LAST 4
+
+ struct sysmon_pswitch sc_smpsw[PANASONIC_PSW_LAST];
+ bool sc_smpsw_valid;
+
+} toughbook_hbtn_softc_t;
+
+/* Tablet buttons (HBTN) */
+#define PANASONIC_NOTIFY_SecurityPRESSED 0x34
+#define PANASONIC_NOTIFY_SecurityRELEASED 0x35
+
+#define PANASONIC_NOTIFY_RotationPRESSED 0x36
+#define PANASONIC_NOTIFY_RotationRELEASED 0x37
+
+#define PANASONIC_NOTIFY_EnterPRESSED 0x38
+#define PANASONIC_NOTIFY_EnterRELEASED 0x39
+
+#define PANASONIC_NOTIFY_InputPanelPRESSED 0x3A
+#define PANASONIC_NOTIFY_InputPanelRELEASED 0x3B
+
+#define ACPI_SERIAL_BEGIN(x)
+#define ACPI_SERIAL_END(x)
+#define ACPI_SERIAL_ASSERT(x)
+
+#define HKEY_SET 0
+#define HKEY_GET 1
+
+static int hbtn_match(device_t, cfdata_t, void *);
+static void hbtn_attach(device_t, device_t, void *);
+static int hbtn_detach(device_t, int);
+
+static void hbtn_notify_handler(ACPI_HANDLE, UINT32, void *);
+
+static int
+acpi_hbtn_event(device_t, ACPI_INTEGER *);
+
+static void
+acpi_hbtn_action(device_t, ACPI_INTEGER);
+
+CFATTACH_DECL_NEW(toughbook_hbtn, sizeof(toughbook_hbtn_softc_t),
+ hbtn_match, hbtn_attach, hbtn_detach, NULL);
+
+static const char * const toughbook_hbtn_ids[] = {
+ "MAT001F",
+ "MAT0020",
+ NULL
+};
+
+static int
+hbtn_match(device_t parent, cfdata_t match, void *opaque)
+{
+ struct acpi_attach_args *aa = opaque;
+
+ if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+ return 0;
+
+ return acpi_match_hid(aa->aa_node->ad_devinfo, toughbook_hbtn_ids);
+}
+
+static void
+hbtn_attach(device_t parent, device_t self, void *opaque)
+{
+ toughbook_hbtn_softc_t *sc = device_private(self);
+ struct acpi_attach_args *aa = opaque;
+ struct sysmon_pswitch *psw;
+ ACPI_STATUS rv;
+
+ sc->sc_node = aa->aa_node;
+ sc->sc_dev = self;
+
+ aprint_naive(": Toughbook tablet buttons\n");
+ aprint_normal(": Toughbook tablet buttons\n");
+
+ rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, ACPI_ALL_NOTIFY,
+ hbtn_notify_handler, sc);
+ if (ACPI_FAILURE(rv))
+ aprint_error_dev(self, "couldn't install notify handler: %s\n",
+ AcpiFormatException(rv));
+
+ /* Register power switches with sysmon */
+ psw = sc->sc_smpsw;
+ sc->sc_smpsw_valid = true;
+
+ int i;
+ for (i = PANASONIC_PSW_SECURITY; i < PANASONIC_PSW_LAST; i++)
+ psw[i].smpsw_type = PSWITCH_TYPE_HOTKEY;
+ psw[PANASONIC_PSW_SECURITY].smpsw_name = "security";
+ psw[PANASONIC_PSW_ROTATION].smpsw_name = "rotation-button";
+ psw[PANASONIC_PSW_ENTER].smpsw_name = "enter-button";
+ psw[PANASONIC_PSW_INPUT_PANEL].smpsw_name = "input_panel-button";
+
+ for (i = 0; i < PANASONIC_PSW_LAST; i++) {
+ if (sysmon_pswitch_register(&sc->sc_smpsw[i]) != 0) {
+ aprint_error_dev(self,
+ "couldn't register with sysmon\n");
+ sc->sc_smpsw_valid = false;
+ break;
+ }
+ }
+
+ if (!pmf_device_register(self, NULL, NULL))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+
+}
+
+static int
+hbtn_detach(device_t self, int flags)
+{
+ toughbook_hbtn_softc_t *sc = device_private(self);
+ int i;
+
+ if (sc->sc_smpsw_valid)
+ for (i = 0; i < PANASONIC_PSW_LAST; i++)
+ sysmon_pswitch_unregister(&sc->sc_smpsw[i]);
+
+ pmf_device_deregister(self);
+
+ return 0;
+}
+
+static void
+hbtn_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque)
+{
+ toughbook_hbtn_softc_t *sc = opaque;
+
+ ACPI_INTEGER key;
+ key = 0;
+
+ switch (notify) {
+ case 0x80:
+ ACPI_SERIAL_BEGIN(panasonic);
+ if (acpi_hbtn_event(sc->sc_dev, &key) == 0) {
+ acpi_hbtn_action(sc->sc_dev, key);
+ }
+
+ ACPI_SERIAL_END(panasonic);
+ break;
+ default:
+ aprint_debug_dev(sc->sc_dev, "unknown notify: %#x\n", notify);
+ break;
+ }
+
+}
+
+static int
+acpi_hbtn_event(device_t self, ACPI_INTEGER *arg) {
+
+ toughbook_hbtn_softc_t *sc = device_private(self);
+
+ ACPI_BUFFER buf;
+ ACPI_OBJECT *res;
+ ACPI_INTEGER val;
+ int status;
+
+ ACPI_SERIAL_ASSERT(panasonic);
+ status = ENXIO;
+
+ buf.Length = ACPI_ALLOCATE_BUFFER;
+ buf.Pointer = NULL;
+ AcpiEvaluateObject(sc->sc_node->ad_handle, "HINF", NULL, &buf);
+ res = (ACPI_OBJECT *)buf.Pointer;
+ if (res->Type != ACPI_TYPE_INTEGER) {
+ aprint_error_dev(self, "HINF returned non-integer\n");
+ goto end;
+ }
+ val = res->Integer.Value;
+
+ *arg = val;
+ status = 0;
+end:
+ if (buf.Pointer)
+ AcpiOsFree(buf.Pointer);
+
+ return status;
+}
+
+static void
+acpi_hbtn_action(device_t self, ACPI_INTEGER key)
+{
+
+ toughbook_hbtn_softc_t *sc = device_private(self);
+
+ ACPI_SERIAL_ASSERT(panasonic);
+
+ switch (key) {
+ case PANASONIC_NOTIFY_SecurityPRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_SECURITY],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_SecurityRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_SECURITY],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ case PANASONIC_NOTIFY_RotationPRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_ROTATION],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_RotationRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_ROTATION],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ case PANASONIC_NOTIFY_EnterPRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_ENTER],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_EnterRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_ENTER],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ case PANASONIC_NOTIFY_InputPanelPRESSED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_INPUT_PANEL],
+ PSWITCH_EVENT_PRESSED);
+ break;
+ case PANASONIC_NOTIFY_InputPanelRELEASED:
+ if (sc->sc_smpsw_valid == false)
+ break;
+ sysmon_pswitch_event(&sc->sc_smpsw[PANASONIC_PSW_INPUT_PANEL],
+ PSWITCH_EVENT_RELEASED);
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev, "Unknown Key 0x%X\n", (int)key);
+ }
+}
+
--- /dev/null 2012-08-29 17:38:04.000000000 +1000
+++ ./man4/toughbook_hbtn.4 2012-07-02 20:39:29.000000000 +1000
@@ -0,0 +1,63 @@
+.\"
+.\" Copyright (c) 2012 Nathanial Sloss <nathanialsloss%yahoo.com.au@localhost>
+.\" 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+.\"
+.Dd July 2, 2012
+.Dt TOUGHBOOK_HBTN 4
+.Os
+.Sh NAME
+.Nm toughbook_hbtn
+.Nd Panasonic Toughbook CF-18/19 Tablet Buttons
+.Sh SYNOPSIS
+.Cd "toughbook_hbtn* at acpi?"
+.Sh DESCRIPTION
+The
+.Nm
+driver supports the tablet buttons found on CF-18/19 Toughbook computers:
+.Bl -column -offset indent "Button " "/etc/powerd/actions/button"
+.It Sy Button Ta Sy Script
+.It Li Input (Keyboard) Ta Pa /etc/powerd/actions/input_panel-button
+.It Li Enter (Target) Ta Pa /etc/powerd/actions/enter-button
+.It Li Rotation Ta Pa /etc/powerd/actions/rotation-button
+.It Li Security (Key) Ta Pa /etc/powerd/actions/security
+.El
+.Pp
+When a button is pressed, the
+.Xr powerd 8
+daemon, if running,
+will execute the corresponding script.
+.Sh SEE ALSO
+.Xr acpi 4 ,
+.Xr panasonic 4 ,
+.Xr powerd 8
+.Sh AUTHORS
+Software and manual page written by Nathanial Sloss
+.Sh HISTORY
+The
+.Nm
+driver
+was an addition to
+.Xr panasonic 4
+which was ported to
+.Nx 3.0.1 but was never released .
I hope this software is useful.
Regards,
Nat.
Home |
Main Index |
Thread Index |
Old Index