git: d5bf6a7245cc - main - acpi_asus_wmi(4): Add support for WMI event queue
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 17 Mar 2025 15:46:59 UTC
The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=d5bf6a7245cc7825d17ebb00d1e7f07ae6dc32e6 commit d5bf6a7245cc7825d17ebb00d1e7f07ae6dc32e6 Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2025-03-17 15:45:14 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2025-03-17 15:45:14 +0000 acpi_asus_wmi(4): Add support for WMI event queue Event codes are expected to be retrieved from a queue on at least some models. Specifically, very likely the ACPI WMI devices with _UID ATK are queued whereas those with ASUSWMI are not. Sponsored by: Future Crew LLC MFC after: 1 month Reviewed by: mav Differential Revision: https://reviews.freebsd.org/D48984 --- sys/dev/acpi_support/acpi_asus_wmi.c | 89 ++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 13 deletions(-) diff --git a/sys/dev/acpi_support/acpi_asus_wmi.c b/sys/dev/acpi_support/acpi_asus_wmi.c index 968de5fe5e87..e3d16b9345ee 100644 --- a/sys/dev/acpi_support/acpi_asus_wmi.c +++ b/sys/dev/acpi_support/acpi_asus_wmi.c @@ -112,6 +112,12 @@ ACPI_MODULE_NAME("ASUS-WMI") #define ASUS_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF #define ASUS_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00 +/* Events */ +#define ASUS_WMI_EVENT_QUEUE_SIZE 0x10 +#define ASUS_WMI_EVENT_QUEUE_END 0x1 +#define ASUS_WMI_EVENT_MASK 0xFFFF +#define ASUS_WMI_EVENT_VALUE_ATK 0xFF + struct acpi_asus_wmi_softc { device_t dev; device_t wmi_dev; @@ -120,6 +126,7 @@ struct acpi_asus_wmi_softc { struct sysctl_oid *sysctl_tree; int dsts_id; int handle_keys; + bool event_queue; struct cdev *kbd_bkl; uint32_t kbd_bkl_level; #ifdef EVDEV_SUPPORT @@ -363,6 +370,8 @@ static int acpi_wpi_asus_get_devstate(struct acpi_asus_wmi_softc *sc, UINT32 dev_id, UINT32 *retval); static int acpi_wpi_asus_set_devstate(struct acpi_asus_wmi_softc *sc, UINT32 dev_id, UINT32 ctrl_param, UINT32 *retval); +static int acpi_asus_wmi_get_event_code(device_t wmi_dev, UINT32 notify, + int *code); static void acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_asus_wmi_backlight_update_status(device_t dev, struct backlight_props *props); @@ -463,7 +472,7 @@ acpi_asus_wmi_attach(device_t dev) { struct acpi_asus_wmi_softc *sc; UINT32 val; - int dev_id, i; + int dev_id, i, code; bool have_kbd_bkl = false; ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); @@ -577,6 +586,23 @@ next: } ACPI_SERIAL_END(asus_wmi); + /* Detect and flush event queue */ + if (sc->dsts_id == ASUS_WMI_METHODID_DSTS2) { + for (i = 0; i <= ASUS_WMI_EVENT_QUEUE_SIZE; i++) { + if (acpi_asus_wmi_get_event_code(sc->wmi_dev, + ASUS_WMI_EVENT_VALUE_ATK, &code) != 0) { + device_printf(dev, + "Can not flush event queue\n"); + break; + } + if (code == ASUS_WMI_EVENT_QUEUE_END || + code == ASUS_WMI_EVENT_MASK) { + sc->event_queue = true; + break; + } + } + } + #ifdef EVDEV_SUPPORT if (sc->notify_guid != NULL) { sc->evdev = evdev_alloc(); @@ -746,6 +772,24 @@ acpi_asus_wmi_free_buffer(ACPI_BUFFER* buf) { } } +static int +acpi_asus_wmi_get_event_code(device_t wmi_dev, UINT32 notify, int *code) +{ + ACPI_BUFFER response = { ACPI_ALLOCATE_BUFFER, NULL }; + ACPI_OBJECT *obj; + int error = 0; + + if (ACPI_FAILURE(ACPI_WMI_GET_EVENT_DATA(wmi_dev, notify, &response))) + return (EIO); + obj = (ACPI_OBJECT*) response.Pointer; + if (obj && obj->Type == ACPI_TYPE_INTEGER) + *code = obj->Integer.Value & ASUS_WMI_EVENT_MASK; + else + error = EINVAL; + acpi_asus_wmi_free_buffer(&response); + return (error); +} + #ifdef EVDEV_SUPPORT static void acpi_asus_wmi_push_evdev_event(struct evdev_dev *evdev, UINT32 notify) @@ -768,20 +812,11 @@ acpi_asus_wmi_push_evdev_event(struct evdev_dev *evdev, UINT32 notify) #endif static void -acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context) +acpi_asus_wmi_handle_event(struct acpi_asus_wmi_softc *sc, int code) { - device_t dev = context; - ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); UINT32 val; - int code = 0; - struct acpi_asus_wmi_softc *sc = device_get_softc(dev); - ACPI_BUFFER response = { ACPI_ALLOCATE_BUFFER, NULL }; - ACPI_OBJECT *obj; - ACPI_WMI_GET_EVENT_DATA(sc->wmi_dev, notify, &response); - obj = (ACPI_OBJECT*) response.Pointer; - if (obj && obj->Type == ACPI_TYPE_INTEGER) { - code = obj->Integer.Value; + if (code != 0) { acpi_UserNotify("ASUS", ACPI_ROOT_OBJECT, code); #ifdef EVDEV_SUPPORT @@ -814,7 +849,35 @@ acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context) ASUS_WMI_DEVID_TOUCHPAD, val, NULL); } } - acpi_asus_wmi_free_buffer(&response); +} + +static void +acpi_asus_wmi_notify(ACPI_HANDLE h, UINT32 notify, void *context) +{ + device_t dev = context; + struct acpi_asus_wmi_softc *sc = device_get_softc(dev); + int code = 0, i = 1; + + ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); + + if (sc->event_queue) + i += ASUS_WMI_EVENT_QUEUE_SIZE; + do { + if (acpi_asus_wmi_get_event_code(sc->wmi_dev, notify, &code) + != 0) { + device_printf(dev, "Failed to get event code\n"); + return; + } + if (code == ASUS_WMI_EVENT_QUEUE_END || + code == ASUS_WMI_EVENT_MASK) + return; + acpi_asus_wmi_handle_event(sc, code); + if (notify != ASUS_WMI_EVENT_VALUE_ATK) + return; + } while (--i != 0); + if (sc->event_queue) + device_printf(dev, "Can not read event queue, " + "last code: 0x%x\n", code); } static int