在我的 上Dell latitude e6540
,WMI 热键Fn+Up和Fn+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+Up和Fn+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+Up和Fn+消息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
。返回值现在取决于 的值WMEV
。WVPT
在返回的缓冲区中设置 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_event
WMI 模块的选项
# 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
。