Esta postagem descreve como abordo a depuração da WMI com base no DSDT do seu acpidump (o SSDT não contém detalhes relevantes aqui).
\_SB.AMW0
é o dispositivo WMI no firmware do ACPI da Dell. O método \EV4
chama \WMNF
, que é o único método que chama o dispositivo \_SB.AMW0
(função SWEV
= Set? Evento WMI). \EV4
é o método que é chamado pelo controlador incorporado / teclado.
Agora, SWEV
é Definir Evento WMI, CMEV
é provável Limpar Evento WMI. Ao chamar SWEV
, os bits na variável WMEV
("Evento WMI"?) São definidos. O WMI verifica os códigos de evento chamando o método _WED
e verificando seu valor de retorno. Neste método _WED
, é realmente visível que WMEV
está marcado e CMEV
é chamado:
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 */
}
Observe, no entanto, que há duas condições que podem impedir que um código de evento seja retornado (não aplicável aqui):
-
Se Arg0 (o ID de notificação) não for 0xD0. Este não é o caso, como pode ser visto nesta interpretação da descrição do WMI:
9DBB5994-A997-11DA-B012-B622A1EF5492:
object_id: � [D0 00]
notify_id: D0
reserved: 00
instance_count: 1
flags: 0x8 ACPI_WMI_EVENT
- Se
\_SB.AMW0.ECD0
for igual a 0
. Como o código do Dell WMI escuta eventos WMI, o WED0
(evento% WMID0
) foi chamado com um argumento diferente de zero e isso também não é válido.
Então, vamos continuar com a interpretação de _WED
. O valor de retorno agora depende do valor de WMEV
. WVPT
define a palavra de 16 bits no buffer retornado WMBU
(e avança o ponteiro para a próxima chamada WVPT
). Podemos construir a seguinte tabela:
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)
Agora, o código dell-wmi espera que a segunda palavra seja 0x0010
, não 0x0000
. Para depurar ainda mais isso, você deve ativar a opção debug_event
para o módulo WMI
# remove all dependencies of WMI and WMI itself:
modprobe -vr dell-wmi
modprobe wmi debug_event
modprobe dell-wmi
Agora pressione as teclas de atalho e observe seus registros do kernel. Você precisa descobrir qual é o formato exato de WMBU
, eu acho que você obtém as chaves mais interessantes para o WMEV 0x0800, você precisa dar uma olhada nisso. Talvez adicione isso a dell_wmi_notify
(após u16 *buffer_entry = (u16 *)obj->buffer.pointer;
) para depuração:
pr_info("WMBU = %04x %04x %04x\n", buffer_entry[0], buffer_entry[1], buffer_entry[2]);