Re: [PATCH 2/2] platform/x86: msi-wmi: Add MSI Claw M-Center keys
From: Derek John Clark
Date: Fri Jun 12 2026 - 14:30:43 EST
On Fri, Jun 12, 2026 at 10:54 AM Armin Wolf <W_Armin@xxxxxx> wrote:
>
> Am 12.06.26 um 00:39 schrieb Derek J. Clark:
>
> > MSI Claw devices produce WMI events through the MSI WMI hotkeys GUID for
> > some of their buttons. When pressed, these cause spam in the kernel. For
> > the majority of devices these events can be safely ignored as they are
> > duplicated by the AT Translated Set 2 Keyboard device exposed as an
> > evdev. For the MSI Claw A8 BZ2EM model's M-Center Menu button (left of
> > the screen) there is no associated keyboard event, so this event must be
> > exposed. Map this button to the same scancode produced by the AT
> > Keyboard device on other models. This does cause double F15 events on
> > the A1M, 7 AI+ A2VM, and 8 AI+ A2VM, but it appears to be harmless in my
> > testing.
> >
> > Signed-off-by: Derek J. Clark <derekjohn.clark@xxxxxxxxx>
> > ---
> > drivers/platform/x86/msi-wmi.c | 22 ++++++++++++++++++++++
> > 1 file changed, 22 insertions(+)
> >
> > diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
> > index d00ced756581..73a4f0d2dc04 100644
> > --- a/drivers/platform/x86/msi-wmi.c
> > +++ b/drivers/platform/x86/msi-wmi.c
> > @@ -46,6 +46,12 @@ enum msi_scancodes {
> > WIND_KEY_WLAN = 0x5f, /* Fn+F11 Wi-Fi toggle */
> > WIND_KEY_TURBO, /* Fn+F10 turbo mode toggle */
> > WIND_KEY_ECO = 0x69, /* Fn+F10 ECO mode toggle */
> > + /* MSI Claw keys */
> > + CLAW_KEY_VOLUMEDOWN = 0x21,
> > + CLAW_KEY_CENTER = 0x29, /* MSI M-Center main menu */
> > + CLAW_KEY_QUICK_LONG = 0x2a, /* MSI M-Center quick access long hold */
> > + CLAW_KEY_VOLUMEUP = 0x32,
> > + CLAW_KEY_QUICK_SHORT = 0x58, /* MSI M-Center quick access short press */
> > };
> > static struct key_entry msi_wmi_keymap[] = {
> > { KE_KEY, MSI_KEY_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
> > @@ -69,6 +75,15 @@ static struct key_entry msi_wmi_keymap[] = {
> > { KE_KEY, WIND_KEY_TURBO, {KEY_PROG1} },
> > { KE_KEY, WIND_KEY_ECO, {KEY_PROG2} },
> >
> > + /* These are MSI Claw keys, used for MSI M-Center in Windows */
> > + { KE_KEY, CLAW_KEY_CENTER, {KEY_F15} },
> > +
> > + /* These MSI Claw keys work without WMI. Ignore them to avoid double keycodes */
> > + { KE_IGNORE, CLAW_KEY_QUICK_SHORT },
> > + { KE_IGNORE, CLAW_KEY_QUICK_LONG },
> > + { KE_IGNORE, CLAW_KEY_VOLUMEUP },
> > + { KE_IGNORE, CLAW_KEY_VOLUMEDOWN },
> > +
> > { KE_END, 0 }
> > };
> >
> > @@ -183,6 +198,13 @@ static void msi_wmi_notify(union acpi_object *obj, void *context)
> > eventcode = obj->integer.value;
> > pr_debug("Eventcode: 0x%x\n", eventcode);
> > break;
> > + case ACPI_TYPE_BUFFER:
> > + if (!obj->buffer.length)
> > + return;
> > +
> > + eventcode = obj->buffer.pointer[0];
> > + pr_debug("Eventcode: 0x%x\n", eventcode);
>
> Can you share the BMOF associated with this event? I suspect that the buffer should
> contain a u32.
The GUID's don't appear to contain any bmof data:
$ lsmod | grep bmof
wmi_bmof 12288 0
wmi 32768 4 video,wmi_bmof,msi_wmi,msi_wmi_platform
$ tree -l -L 2
.
├── 1E2A0DA0-2B9E-424F-9C87-B1DAC3F4E9DA-3 ->
../../../devices/pci0000:00/0000:00:02.3/0000:c3:00.0/PNP0C14:01/wmi_bus/wmi_bus-PNP0C14:01/1E2A0DA0-2B9E-424F-9C87-B1DAC3F4E9DA-3
│ ├── driver_override
│ ├── expensive
│ ├── guid
│ ├── instance_count
│ ├── modalias
│ ├── notify_id
│ ├── power
│ ├── subsystem -> ../../../../../../../../bus/wmi
│ └── uevent
├── 5B3CC38A-40D9-7245-8AE6-1145B751BE3F-1 ->
../../../devices/pci0000:00/0000:00:14.3/PNP0C09:00/PNP0C14:00/wmi_bus/wmi_bus-PNP0C14:00/5B3CC38A-40D9-7245-8AE6-1145B751BE3F-1
│ ├── driver_override
│ ├── expensive
│ ├── guid
│ ├── instance_count
│ ├── modalias
│ ├── notify_id
│ ├── power
│ ├── subsystem -> ../../../../../../../../bus/wmi
│ └── uevent
├── ABBC0F6E-8EA1-11D1-00A0-C90629100000-0 ->
../../../devices/pci0000:00/0000:00:14.3/PNP0C09:00/PNP0C14:00/wmi_bus/wmi_bus-PNP0C14:00/ABBC0F6E-8EA1-11D1-00A0-C90629100000-0
│ ├── driver -> ../../../../../../../../bus/wmi/drivers/msi-wmi-platform
│ ├── driver_override
│ ├── expensive
│ ├── guid
│ ├── hwmon
│ ├── instance_count
│ ├── modalias
│ ├── object_id
│ ├── platform-profile
│ ├── power
│ ├── subsystem -> ../../../../../../../../bus/wmi
│ └── uevent
└── B2526ED4-CB45-49FA-9230-8D2FE8AFB8EC-2 ->
../../../devices/pci0000:00/0000:00:02.3/0000:c3:00.0/PNP0C14:01/wmi_bus/wmi_bus-PNP0C14:01/B2526ED4-CB45-49FA-9230-8D2FE8AFB8EC-2
├── driver_override
├── expensive
├── guid
├── instance_count
├── modalias
├── object_id
├── power
├── subsystem -> ../../../../../../../../bus/wmi
└── uevent
16 directories, 28 files
I extracted the _WED event method from the DSDT. I don't have a lot of
experience with interpreting ACPI, but my understanding is that it
returns u8[2] with index 0 being the keycode and index 1 being the
state. Since we don't get events on release, that is essentially
unused. I can do a .length != 2 in the validation step before I
extract the keycode if desired.
Method (_WED, 1, NotSerialized) // _Wxx: Wake Event, xx=0x00-0xFF
{
If ((Arg0 == 0xC0))
{
Name (EVRT, Buffer (0x02)
{
0x00, 0x00 // ..
})
Name (TMPB, Zero)
TMPB = WMRD (0xD8)
EVRT [Zero] = TMPB /* \_SB_.PCI0.SBRG.EC__.SCM0._WED.TMPB */
If ((TMPB == 0x08))
{
EVRT [One] = ((WMRD (0xE4) >> 0x03) & 0x1F
)
}
If ((TMPB == 0x56))
{
EVRT [One] = WMRD (0x2E)
}
If ((TMPB == 0x57))
{
EVRT [One] = WMRD (0x2E)
}
If ((TMPB == 0x5F))
{
EVRT [One] = WMRD (0x2E)
}
If ((TMPB == 0x60))
{
EVRT [One] = (WMRD (0xE4) & 0x07)
}
If ((TMPB == 0x62))
{
EVRT [One] = WMRD (0xD1)
}
If ((TMPB == 0x63))
{
EVRT [One] = WMRD (0xD1)
}
If ((TMPB == 0x73))
{
EVRT [One] = ((WMRD (0xE4) >> 0x03) & 0x1F
)
}
If ((TMPB == 0x79))
{
EVRT [One] = ((WMRD (0xE4) >> 0x03) & 0x1F
)
}
If ((TMPB == 0x7B))
{
EVRT [One] = WMRD (0x2E)
}
If ((TMPB == 0x84))
{
EVRT [One] = WMRD (0x2E)
}
If ((TMPB == 0x02))
{
EVRT [One] = ((WMRD (0xE4) >> 0x03) & 0x1F
)
}
WMWT (0xD8, Zero)
Return (EVRT) /* \_SB_.PCI0.SBRG.EC__.SCM0._WED.EVRT */
}
Return (Zero)
}
Also the _WDG that points the Wind GUID to arg 0xC0:
Name (_WDG, Buffer (0x64)
{
/* 0000 */ 0x6A, 0x0F, 0xBC, 0xAB, 0xA1, 0x8E, 0xD1,
0x11, // j.......
/* 0008 */ 0x00, 0xA0, 0xC9, 0x06, 0x29, 0x10, 0x00,
0x00, // ....)...
/* 0010 */ 0x41, 0x4B, 0x01, 0x01, 0x6B, 0x0F, 0xBC,
0xAB, // AK..k...
/* 0018 */ 0xA1, 0x8E, 0xD1, 0x11, 0x00, 0xA0, 0xC9,
0x06, // ........
/* 0020 */ 0x29, 0x10, 0x00, 0x00, 0x41, 0x4C, 0x01,
0x01, // )...AL..
/* 0028 */ 0x6D, 0x0F, 0xBC, 0xAB, 0xA1, 0x8E, 0xD1,
0x11, // m.......
/* 0030 */ 0x00, 0xA0, 0xC9, 0x06, 0x29, 0x10, 0x00,
0x00, // ....)...
/* 0038 */ 0x41, 0x4A, 0x01, 0x02, 0x6E, 0x0F, 0xBC,
0xAB, // AJ..n...
/* 0040 */ 0xA1, 0x8E, 0xD1, 0x11, 0x00, 0xA0, 0xC9,
0x06, // ........
/* 0048 */ 0x29, 0x10, 0x00, 0x00, 0x41, 0x4D, 0x01,
0x02, // )...AM..
/* 0050 */ 0x8A, 0xC3, 0x3C, 0x5B, 0xD9, 0x40, 0x45,
0x72, // ..<[.@Er
/* 0058 */ 0x8A, 0xE6, 0x11, 0x45, 0xB7, 0x51, 0xBE,
0x3F, // ...E.Q.?
/* 0060 */ 0xC0, 0x00, 0x01, 0x09
// ....
})
...
Thanks,
Derek
> Thanks,
> Armin Wolf
>
> > + break;
> > default:
> > pr_info("Unknown event received\n");
> > return;