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]);