更新:

更新:

在我的 上Dell latitude e6540,WMI 热键Fn+UpFn+Down不起作用。我已在内核中编译了所有必需的模块:

CONFIG_DELL_LAPTOP=m
CONFIG_DELL_WMI=m
CONFIG_DELL_WMI_AIO=m

在前代型号 (Latitude e6520) 上,一切正常,无需任何额外设置。我在两台笔记本电脑上使用相同的(自定义构建)内核 3.16.6。在 e6520 上 wmi 可以工作,在 e6540 上则不行。

我仍然可以通过以下方式更改亮度echo

echo 35 > /sys/class/backlight/acpi_video0/brightness

root但显然,只是作为。

Fn+UpFn+Down不会更改 中的值/sys/class/backlight/acpi_video0/brightness。在以前的模型上,它确实改变了值。

我注意到的一件事是,在旧型号上,最大值是15。在新型号上是这样95。看起来这个机制内部可能发生了一些变化。

因此我的问题是:如何让 WMI 热键在我的新笔记本电脑上工作?

我正在使用带有自定义内核 3.16.6 的 Debian wheezy。我还尝试过发行版内核 3.16(来自 Wheezy-backports 的 linux-image-3.16-0.bpo.2-amd64),并且 wmi 键也不起作用。

更新:

我刚刚注意到,当我在 BIOS 中时,WMI 热键工作正常!令人惊讶的是,当我启动到 Linux 时它们不起作用。

以下是 dmesg 的输出。提到的dell_wmi: Received unknown WMI event看起来与我的问题相关,但我在旧笔记本电脑上收到相同的消息,其中 wmi 热键正在工作。因此,仅此一点似乎并不是问题所在。

dmesg | egrep -i '(dell|wmi)'
[Tue Apr 15 22:04:30 2014] DMI: Dell Inc. Latitude E6540/05V0V4, BIOS A05 09/03/2013
[Tue Apr 15 22:04:30 2014] ACPI: RSDP 00000000000eee60 00024 (v02 DELL  )
[Tue Apr 15 22:04:30 2014] ACPI: XSDT 00000000d8fe0080 0007C (v01 DELL    CBX3    01072009 AMI  00010013)
[Tue Apr 15 22:04:30 2014] ACPI: FACP 00000000d8fed7e8 0010C (v05 DELL    CBX3    01072009 AMI  00010013)
[Tue Apr 15 22:04:30 2014] ACPI: DSDT 00000000d8fe0188 0D659 (v02 DELL    CBX3    00000014 INTL 20091112)
[Tue Apr 15 22:04:30 2014] ACPI: APIC 00000000d8fed8f8 00072 (v03 DELL    CBX3    01072009 AMI  00010013)
[Tue Apr 15 22:04:30 2014] ACPI: FPDT 00000000d8fed970 00044 (v01 DELL    CBX3    01072009 AMI  00010013)
[Tue Apr 15 22:04:30 2014] ACPI: HPET 00000000d8feed38 00038 (v01 DELL    CBX3    01072009 AMI. 00000005)
[Tue Apr 15 22:04:30 2014] ACPI: MCFG 00000000d8fef148 0003C (v01 DELL    CBX3    01072009 MSFT 00000097)
[Tue Apr 15 22:04:38 2014] dcdbas dcdbas: Dell Systems Management Base Driver (version 5.6.0-3.2)
[Tue Apr 15 22:04:39 2014] wmi: Mapper loaded
[Tue Apr 15 22:04:39 2014] input: Dell WMI hotkeys as /devices/virtual/input/input10
[Wed Apr 16 18:30:04 2014] dell_wmi: Received unknown WMI event (0x0)
[Fri Apr 18 17:09:41 2014] dell_wmi: Received unknown WMI event (0x0)
[Fri Apr 18 17:09:41 2014] dell_wmi: Received unknown WMI event (0x0)
[Fri Apr 18 17:09:49 2014] dell_wmi: Received unknown WMI event (0x0)

更新2

修补 WMI 模块后,我收到以下Fn+UpFn+消息Down

2014-04-18 19:00:49  kernel: [  120.731480] dell_wmi: WMBU = 0002 0010 0048
2014-04-18 19:00:49  kernel: [  120.731496] wmi: DEBUG Event GUID: 9DBB5994-A997-11DA-B012-B622A1EF5492

2014-04-18 19:00:53  kernel: [  123.935400] dell_wmi: WMBU = 0002 0010 0050
2014-04-18 19:00:53  kernel: [  123.935415] wmi: DEBUG Event GUID: 9DBB5994-A997-11DA-B012-B622A1EF5492

更新3

另外有趣的是,笔记本电脑预装了 Ubuntu 12.04,并且 wmi 键可以在 Ubuntu 中使用。

答案1

这篇文章描述了我如何基于 acpidump 中的 DSDT 进行 WMI 调试(SSDT 此处不包含相关详细信息)。

\_SB.AMW0是 Dell ACPI 固件中的 WMI 设备。该\EV4方法调用的\WMNF是在设备上调用的唯一方法\_SB.AMW0(函数SWEV= Set?WMI 事件)。\EV4是嵌入式/键盘控制器调用的方法。

现在,SWEV是Set WMI Event,CMEV很可能是Clear WMI Event。调用后SWEV,变量中的位WMEV(“WMI 事件”?)被设置。 WMI 通过调用该方法并检查其返回值来检查事件代码_WED。在此_WED方法中,确实可见已WMEV检查并被CMEV调用:

Method (_WED, 1, NotSerialized)  // _Wxx: Wake Event
{
    WVSP ()
    If (LNotEqual (Arg0, 0xD0))
    {
        WVCU ()
        Return (WMBU) /* \_SB_.AMW0.WMBU */
    }

    If (LEqual (ECD0, Zero))
    {
        WVCU ()
        Return (WMBU) /* \_SB_.AMW0.WMBU */
    }

    If (And (WMEV, 0x0200))
    {
        CWEV (0x0200)
        // WMBU = { 0x0002, 0x0000, 0xE045 }
        WVPT (0x02)
        WVPT (Zero)
        WVPT (0xE045)
    }
    Else
    {
        If (And (WMEV, 0x0100))
        {
            CWEV (0x0100)
            If (ECG4 ())
            {
                WVPT (0x02)
                WVPT (Zero)
                WVPT (0xE043)
            }
            Else
            {
                WVPT (0x02)
                WVPT (Zero)
                WVPT (0xE044)
            }
        }
        Else
        {
            If (And (WMEV, 0x0800))
            {
                Store (EC0A (WMBU), WMBU) /* \_SB_.AMW0.WMBU */
                CWEV (0x0800)
            }
        }
    }

    WVCU ()
    Return (WMBU) /* \_SB_.AMW0.WMBU */
}

但请注意,有两种情况可能会阻止返回事件代码(但此处不适用):

  • 如果 Arg0(通知 ID)不是 0xD0。从 WMI 描述的解释中可以看出,情况并非如此:

    9DBB5994-A997-11DA-B012-B622A1EF5492:
        object_id: � [D0 00]
        notify_id: D0
        reserved: 00
        instance_count: 1
        flags: 0x8 ACPI_WMI_EVENT 
    
  • 如果\_SB.AMW0.ECD0等于0.由于 Dell WMI 代码侦听 WMI 事件,因此使用非零参数调用WED0(WMI Event ),这也不成立。D0

那么,我们继续来解读一下_WED。返回值现在取决于 的值WMEVWVPT在返回的缓冲区中设置 16 位字WMBU(并为下一次调用提前指针WVPT)。我们可以建立下表:

WMEV                returned WMBU   guessed key (see dell-wmi)
0200                0002 0000 E045  KEY_PROG1 or NumLock
0100 (ECG4())       0002 0000 E043  ??
0100 (not ECG4())   0002 0000 E044  ??
0800                ?? (value depends on EC registers)

现在,dell-wmi 代码期望第二个单词是0x0010,而不是0x0000。为了进一步调试此问题,您应该启用debug_eventWMI 模块的选项

# remove all dependencies of WMI and WMI itself:
modprobe -vr dell-wmi
modprobe wmi debug_event
modprobe dell-wmi

现在按热键并观察内核日志。您需要找出确切的格式是什么WMBU,我猜您会得到 WMEV 0x0800 最有趣的密钥,您需要仔细看看。也许将其添加到dell_wmi_notify(之后u16 *buffer_entry = (u16 *)obj->buffer.pointer;)以进行调试:

pr_info("WMBU = %04x %04x %04x\n", buffer_entry[0], buffer_entry[1], buffer_entry[2]);

答案2

你可以安装x背光,一个用于管理亮度的实用程序兰德R。然后,要激活它,请使用一个简单的脚本,绑定到您的两个键:

#!/usr/bin/env bash
up() {
    xbacklight -inc 10
}

down() {
    xbacklight -dec 10
}

notify() {
    bright=$(</sys/class/backlight/acpi_video0/actual_brightness)
    if [[ "$bright" -eq 95 ]]; then
        score="100%"
    else score="$(( $bright * 100 / 95 ))"
    fi
    printf '%s\n' "Backlight set to ${score}%" | dzen2 -p 3
}

if [[ $1 = up ]]; then
    up && notify
elif [[ $1 = down ]]; then
    down && notify
fi

将您的通知方法替换为您在正常设置中使用的任何方法,例如notify-send

相关内容