From 45a240f5f2c96ecba15b12e0386ff742a14dbfa0 Mon Sep 17 00:00:00 2001 From: Werner Sembach Date: Sat, 16 Jul 2022 17:08:15 +0200 Subject: [PATCH] Add debug on wmi call 13 output for testing Fix wrong pointer dereferentiation Add debug output for clevo_acpi Create more flexible clevo_evaluate_method2() --- src/clevo_acpi.c | 30 ++++++++++++++++------------- src/clevo_interfaces.h | 4 +++- src/clevo_keyboard.h | 26 ++++++++++++++++++++++++- src/clevo_wmi.c | 43 +++++++++++++++++++++++------------------- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index 9b246eb..eb734b0 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -31,7 +31,7 @@ struct clevo_acpi_driver_data_t { static struct clevo_acpi_driver_data_t *active_driver_data = NULL; -static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 *result) +static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, union acpi_object **result) { u32 status; acpi_handle handle; @@ -68,23 +68,17 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 if (!out_obj) { pr_err("failed to evaluate _DSM\n"); status = -1; - } else { - if (out_obj->type == ACPI_TYPE_INTEGER) { - if (!IS_ERR_OR_NULL(result)) - *result = (u32) out_obj->integer.value; - // pr_debug("evaluate _DSM cmd: %0#4x arg: %0#10x\n", cmd, arg); - } else { - pr_err("unknown output from _DSM\n"); - status = -ENODATA; + } + else { + if (!IS_ERR_OR_NULL(result)) { + *result = out_obj; } } - ACPI_FREE(out_obj); - return status; } -u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value) { u32 status = 0; @@ -139,9 +133,19 @@ static int clevo_acpi_remove(struct acpi_device *device) void clevo_acpi_notify(struct acpi_device *device, u32 event) { u32 event_value; + union acpi_object *out_obj; + u32 status; // struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; - clevo_acpi_evaluate(device, 0x01, 0, &event_value); + status = clevo_acpi_evaluate(device, 0x01, 0, &out_obj); + if (!status) { + if (out_obj->type == ACPI_TYPE_INTEGER) { + event_value = (u32)out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + } + ACPI_FREE(out_obj); + } pr_debug("clevo_acpi event: %0#6x, clevo event value: %0#6x\n", event, event_value); // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index e8f2bd5..c3226cd 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -20,6 +20,7 @@ #define CLEVO_INTERFACES_H #include +#include #define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" #define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" @@ -51,12 +52,13 @@ struct clevo_interface_t { char *string_id; void (*event_callb)(u32); - u32 (*method_call)(u8, u32, u32*); + u32 (*method_call)(u8, u32, union acpi_object **); }; u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface); u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result); +u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result); u32 clevo_get_active_interface_id(char **id_str); #define MODULE_ALIAS_CLEVO_WMI() \ diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 8f52d22..d7712ee 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -307,7 +307,7 @@ static ssize_t show_hasextra_fs(struct device *child, return sprintf(buffer, "%d\n", kbd_led_state.has_extra); } -u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +u32 clevo_evaluate_method2(u8 cmd, u32 arg, union acpi_object **result) { if (IS_ERR_OR_NULL(active_clevo_interface)) { pr_err("clevo_keyboard: no active interface while attempting cmd %02x arg %08x\n", cmd, arg); @@ -315,6 +315,30 @@ u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) } return active_clevo_interface->method_call(cmd, arg, result); } +EXPORT_SYMBOL(clevo_evaluate_method2); + +u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +{ + u32 status = 0; + union acpi_object *out_obj; + + status = clevo_evaluate_method2(cmd, arg, &out_obj); + if (status) { + return status; + } + else { + if (out_obj->type == ACPI_TYPE_INTEGER) { + if (!IS_ERR_OR_NULL(result)) + *result = (u32) out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + status = -ENODATA; + } + ACPI_FREE(out_obj); + } + + return status; +} EXPORT_SYMBOL(clevo_evaluate_method); u32 clevo_get_active_interface_id(char **id_str) diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 14320f4..22623a6 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -23,7 +23,7 @@ #include #include "clevo_interfaces.h" -static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) +static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, union acpi_object **result) { struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg), &wmi_arg }; @@ -45,26 +45,17 @@ static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) if (!acpi_result) { pr_err("failed to evaluate WMI method\n"); return_status = -1; - } else { - if (acpi_result->type == ACPI_TYPE_INTEGER) { - if (!IS_ERR_OR_NULL(result)) { - *result = (u32)acpi_result->integer.value; - /*pr_debug( - "evaluate wmi cmd: %0#4x arg: %0#10x\n", - wmi_method_id, wmi_arg);*/ - } - } else { - pr_err("unknown output from wmi method\n"); - return_status = -EIO; + } + else { + if (!IS_ERR_OR_NULL(result)) { + *result = acpi_result; } } - kfree(acpi_result); - return return_status; } -u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, union acpi_object **result_value) { return clevo_wmi_evaluate(cmd, arg, result_value); } @@ -80,7 +71,8 @@ static int clevo_wmi_probe(struct wmi_device *wdev) static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) #endif { - u32 status, ret; + u32 status; + union acpi_object *out_obj; pr_debug("clevo_wmi driver probe\n"); @@ -96,16 +88,18 @@ static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) // Since the WMI GUIDs aren't unique let's (at least) // check the return of some "known existing general" method - status = clevo_wmi_evaluate(0x52, 0, &ret); + status = clevo_wmi_evaluate(0x52, 0, &out_obj); if (status < 0) { pr_debug("probe: Clevo GUIDs present but method call failed\n"); return -ENODEV; } - if (ret == 0xffffffff) { + if (out_obj->type != ACPI_TYPE_INTEGER || (out_obj->type == ACPI_TYPE_INTEGER && (u32)out_obj->integer.value == 0xffffffff)) { pr_debug( "probe: Clevo GUIDs present but method returned unexpected value\n"); + ACPI_FREE(out_obj); return -ENODEV; } + ACPI_FREE(out_obj); // Add this interface clevo_keyboard_add_interface(&clevo_wmi_interface); @@ -131,7 +125,18 @@ static void clevo_wmi_remove(struct wmi_device *wdev) static void clevo_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) { u32 event_value; - clevo_wmi_evaluate(0x01, 0, &event_value); + union acpi_object *out_obj; + u32 status; + + status = clevo_wmi_evaluate(0x01, 0, &out_obj); + if (!status) { + if (out_obj->type == ACPI_TYPE_INTEGER) { + event_value = (u32)out_obj->integer.value; + } else { + pr_err("return type not integer, use clevo_evaluate_method2\n"); + } + ACPI_FREE(out_obj); + } pr_debug("clevo_wmi notify\n"); if (!IS_ERR_OR_NULL(clevo_wmi_interface.event_callb)) { // Execute registered callback