From fe41e0d039db9482d884bf9074e552f1c2eaf155 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 16 Nov 2020 16:27:34 +0100 Subject: [PATCH 01/26] Add basic driver structure for "new" clevo interface --- Makefile | 2 +- dkms.conf | 4 +++ src/clevo_acpi.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/clevo_acpi.c diff --git a/Makefile b/Makefile index a91b6bf..b8d0363 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := ./src/tuxedo_keyboard.o +obj-m := ./src/tuxedo_keyboard.o ./src/clevo_acpi.o PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/dkms.conf b/dkms.conf index cf3202e..6406f03 100644 --- a/dkms.conf +++ b/dkms.conf @@ -5,6 +5,10 @@ DEST_MODULE_LOCATION[0]="/kernel/lib/" BUILT_MODULE_NAME[0]="tuxedo_keyboard" BUILT_MODULE_LOCATION[0]="src/" +DEST_MODULE_LOCATION[0]="/kernel/lib/" +BUILT_MODULE_NAME[0]="clevo_acpi" +BUILT_MODULE_LOCATION[0]="src/" + MAKE[0]="make KDIR=/lib/modules/${kernelver}/build" CLEAN="make clean" AUTOINSTALL="yes" diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c new file mode 100644 index 0000000..b2cc448 --- /dev/null +++ b/src/clevo_acpi.c @@ -0,0 +1,81 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include + +#define DRIVER_NAME "clevo_acpi" +#define CLEVO_ACPI_RESOURCE_HID "CLV0001" + +struct clevo_acpi_driver_data_t { + struct acpi_device *device; +}; + +static int clevo_acpi_add(struct acpi_device *device) +{ + struct clevo_acpi_driver_data_t *driver_data; + + driver_data = devm_kzalloc(&device->dev, sizeof(*driver_data), GFP_KERNEL); + if (!driver_data) + return -ENOMEM; + + driver_data->device = device; + + pr_debug("acpi add"); + + return 0; +} + +static int clevo_acpi_remove(struct acpi_device *device) +{ + pr_debug("acpi remove"); + return 0; +} + +static void clevo_acpi_notify(struct acpi_device *device, u32 event) +{ + pr_debug("event: %0#10x", event); +} + +#ifdef CONFIG_PM +static int driver_suspend_callb(struct device *dev) +{ + pr_debug("driver suspend\n"); + return 0; +} + +static int driver_resume_callb(struct device *dev) +{ + pr_debug("driver resume\n"); + return 0; +} + +static SIMPLE_DEV_PM_OPS(clevo_driver_pm_ops, driver_suspend_callb, driver_resume_callb); +#endif + +static const struct acpi_device_id clevo_acpi_device_ids[] = { + {CLEVO_ACPI_RESOURCE_HID, 0}, + {"", 0} +}; + +static struct acpi_driver clevo_acpi_driver = { + .name = DRIVER_NAME, + .class = DRIVER_NAME, + .owner = THIS_MODULE, + .ids = clevo_acpi_device_ids, + .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, + .ops = { + .add = clevo_acpi_add, + .remove = clevo_acpi_remove, + .notify = clevo_acpi_notify, + }, +#ifdef CONFIG_PM + .drv.pm = &clevo_driver_pm_ops +#endif +}; + +module_acpi_driver(clevo_acpi_driver); + +MODULE_AUTHOR("TUXEDO Computers GmbH "); +MODULE_DESCRIPTION("Driver for Clevo ACPI interface"); +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL"); From 6d76c68eb49c73a89cae536c976c570b9034efb1 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 17 Nov 2020 17:27:03 +0100 Subject: [PATCH 02/26] clevo_acpi: Add acpi evaluate and event enable functionality --- src/clevo_acpi.c | 62 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index b2cc448..f6a2d11 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -5,11 +5,64 @@ #define DRIVER_NAME "clevo_acpi" #define CLEVO_ACPI_RESOURCE_HID "CLV0001" +#define CLEVO_ACPI_DSM_UUID "93f224e4-fbdc-4bbf-add6-db71bdc0afad" struct clevo_acpi_driver_data_t { struct acpi_device *device; }; +static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg) +{ + u32 status; + u32 result; + acpi_handle handle; + u64 dsm_rev_dummy = 0x00; // Dummy 0 value since not used + u64 dsm_func = cmd; + // Integer package data for argument + union acpi_object dsm_argv4_package_data[] = { + { + .integer.type = ACPI_TYPE_INTEGER, + .integer.value = arg + } + }; + + // Package argument + union acpi_object dsm_argv4 = { + .package.type = ACPI_TYPE_PACKAGE, + .package.count = 1, + .package.elements = dsm_argv4_package_data + }; + + union acpi_object *out_obj; + + guid_t clevo_acpi_dsm_uuid; + + status = guid_parse(CLEVO_ACPI_DSM_UUID, &clevo_acpi_dsm_uuid); + if (status < 0) + return -ENOENT; + + handle = acpi_device_handle(device); + if (handle == NULL) + return -ENODEV; + + out_obj = acpi_evaluate_dsm(handle, &clevo_acpi_dsm_uuid, dsm_rev_dummy, dsm_func, &dsm_argv4); + if (!out_obj) { + pr_err("failed to evaluate _DSM\n"); + result = 0; + } else { + if (out_obj->type == ACPI_TYPE_INTEGER) { + result = (u32) out_obj->integer.value; + } else { + pr_err("unknown output from _DSM\n"); + result = 0; + } + } + + ACPI_FREE(out_obj); + + return result; +} + static int clevo_acpi_add(struct acpi_device *device) { struct clevo_acpi_driver_data_t *driver_data; @@ -20,20 +73,23 @@ static int clevo_acpi_add(struct acpi_device *device) driver_data->device = device; - pr_debug("acpi add"); + pr_debug("acpi add\n"); + + pr_debug("enable acpi events\n"); + clevo_acpi_evaluate(device, 0x46, 0); return 0; } static int clevo_acpi_remove(struct acpi_device *device) { - pr_debug("acpi remove"); + pr_debug("acpi remove\n"); return 0; } static void clevo_acpi_notify(struct acpi_device *device, u32 event) { - pr_debug("event: %0#10x", event); + pr_debug("event: %0#10x\n", event); } #ifdef CONFIG_PM From 6f14b22b33c79588c950a6171645d183754cc97e Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 2 Dec 2020 17:25:43 +0100 Subject: [PATCH 03/26] clevo_keyboard: Basic modularization to allow for multiple interfaces Basic working implementation, WIP - Modularize clevo_keyboard, allowing interfaces to "register" themselves - Add clevo_acpi interface to clevo_keyboard - Prefer acpi interface - Fixed some previously still coupled features on uniwill_keyboard side to allow for the structure change --- src/ck.h | 18 +++ src/clevo_acpi.c | 66 +++++++++-- src/clevo_keyboard.h | 221 +++++++++++++++++++++++++++-------- src/tuxedo_keyboard.c | 72 ++++++++---- src/tuxedo_keyboard.h | 21 ++++ src/tuxedo_keyboard_common.h | 8 +- src/uniwill_keyboard.h | 20 ++-- 7 files changed, 331 insertions(+), 95 deletions(-) create mode 100644 src/ck.h create mode 100644 src/tuxedo_keyboard.h diff --git a/src/ck.h b/src/ck.h new file mode 100644 index 0000000..f5b7977 --- /dev/null +++ b/src/ck.h @@ -0,0 +1,18 @@ +#include +#include + +#ifndef TUXEDO_KEYBOARD_H +#define TUXEDO_KEYBOARD_H + +int clevo_keyboard_init(void); + +struct clevo_interface_t { + char *string_id; + void (*event_callb)(u32); + u32 (*method_call)(u8, u32, u32*); +}; + +u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); +u32 clevo_keyboard_remove_interface(struct clevo_interface_t *new_interface); + +#endif diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index f6a2d11..87f4b30 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -2,19 +2,22 @@ #include #include #include +#include "ck.h" #define DRIVER_NAME "clevo_acpi" #define CLEVO_ACPI_RESOURCE_HID "CLV0001" #define CLEVO_ACPI_DSM_UUID "93f224e4-fbdc-4bbf-add6-db71bdc0afad" struct clevo_acpi_driver_data_t { - struct acpi_device *device; + struct acpi_device *adev; + struct clevo_interface_t *clevo_interface; }; -static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg) +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) { u32 status; - u32 result; acpi_handle handle; u64 dsm_rev_dummy = 0x00; // Dummy 0 value since not used u64 dsm_func = cmd; @@ -45,24 +48,47 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg) if (handle == NULL) return -ENODEV; + pr_debug("evaluate _DSM cmd: %0#4x arg: %0#10x\n", cmd, arg); out_obj = acpi_evaluate_dsm(handle, &clevo_acpi_dsm_uuid, dsm_rev_dummy, dsm_func, &dsm_argv4); if (!out_obj) { pr_err("failed to evaluate _DSM\n"); - result = 0; + status = -1; } else { if (out_obj->type == ACPI_TYPE_INTEGER) { - result = (u32) out_obj->integer.value; + if (!IS_ERR_OR_NULL(result)) + *result = (u32) out_obj->integer.value; } else { pr_err("unknown output from _DSM\n"); - result = 0; + status = -ENODATA; } } ACPI_FREE(out_obj); - return result; + return status; } +u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +{ + u32 status = 0; + + if (!IS_ERR_OR_NULL(active_driver_data)) { + status = clevo_acpi_evaluate(active_driver_data->adev, cmd, arg, result_value); + } else { + pr_err("acpi method call exec, no driver data found\n"); + pr_err("..for method_call: %0#4x arg: %0#10x\n", cmd, arg); + status = -ENODATA; + } + pr_debug("method_call: %0#4x arg: %0#10x result: %0#10x\n", cmd, arg, !IS_ERR_OR_NULL(result_value) ? *result_value : 0); + + return status; +} + +struct clevo_interface_t clevo_acpi_interface = { + .string_id = "clevo_acpi", + .method_call = clevo_acpi_interface_method_call, +}; + static int clevo_acpi_add(struct acpi_device *device) { struct clevo_acpi_driver_data_t *driver_data; @@ -71,12 +97,18 @@ static int clevo_acpi_add(struct acpi_device *device) if (!driver_data) return -ENOMEM; - driver_data->device = device; + driver_data->adev = device; + driver_data->clevo_interface = &clevo_acpi_interface; + + active_driver_data = driver_data; pr_debug("acpi add\n"); - pr_debug("enable acpi events\n"); - clevo_acpi_evaluate(device, 0x46, 0); + // Initiate clevo keyboard, if not already loaded by other interface driver + clevo_keyboard_init(); + + // Add this interface + clevo_keyboard_add_interface(&clevo_acpi_interface); return 0; } @@ -84,12 +116,22 @@ static int clevo_acpi_add(struct acpi_device *device) static int clevo_acpi_remove(struct acpi_device *device) { pr_debug("acpi remove\n"); + clevo_keyboard_remove_interface(&clevo_acpi_interface); + active_driver_data = NULL; return 0; } -static void clevo_acpi_notify(struct acpi_device *device, u32 event) +void clevo_acpi_notify(struct acpi_device *device, u32 event) { + struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; pr_debug("event: %0#10x\n", event); + + // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); + if (!IS_ERR_OR_NULL(clevo_acpi_interface.event_callb)) { + // Execute registered callback + pr_debug("calling event addr\n"); + clevo_acpi_interface.event_callb(event); + } } #ifdef CONFIG_PM @@ -135,3 +177,5 @@ MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Clevo ACPI interface"); MODULE_VERSION("0.0.1"); MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(acpi, clevo_acpi_device_ids); diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 91d938a..8b9f02b 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -18,6 +18,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tuxedo_keyboard_common.h" +#include "tuxedo_keyboard.h" +#include "ck.h" #define CLEVO_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" #define CLEVO_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" @@ -58,6 +60,66 @@ #define WMI_KEYEVENT_CODE_RFKILL1 0x85 #define WMI_KEYEVENT_CODE_RFKILL2 0x86 +static struct clevo_interfaces_t { + struct clevo_interface_t *wmi; + struct clevo_interface_t *acpi; +} clevo_interfaces; + +struct clevo_interface_t *active_clevo_interface; + +void clevo_keyboard_write_state(void); +void clevo_keyboard_event_callb(u32 event); + +u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) +{ + if (strcmp(new_interface->string_id, "clevo_wmi") == 0) { + clevo_interfaces.wmi = new_interface; + clevo_interfaces.wmi->event_callb = clevo_keyboard_event_callb; + + // Only use wmi if there is no other current interface + if (ZERO_OR_NULL_PTR(active_clevo_interface)) { + pr_debug("enable wmi events\n"); + clevo_interfaces.wmi->method_call(0x46, 0, NULL); + + active_clevo_interface = clevo_interfaces.wmi; + } + + } else if (strcmp(new_interface->string_id, "clevo_acpi") == 0) { + clevo_interfaces.acpi = new_interface; + clevo_interfaces.acpi->event_callb = clevo_keyboard_event_callb; + + pr_debug("enable acpi events (takes priority)\n"); + clevo_interfaces.acpi->method_call(0x46, 0, NULL); + active_clevo_interface = clevo_interfaces.acpi; + } else { + // Not recognized interface + pr_err("unrecognized interface\n"); + return -EINVAL; + } + + clevo_keyboard_write_state(); + + return 0; +} +EXPORT_SYMBOL(clevo_keyboard_add_interface); + +u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface) +{ + if (strcmp(interface->string_id, "clevo_wmi") == 0) { + clevo_interfaces.wmi = NULL; + } else if (strcmp(interface->string_id, "clevo_acpi") == 0) { + clevo_interfaces.acpi = NULL; + } else { + return -EINVAL; + } + + if (active_clevo_interface == interface) + active_clevo_interface = NULL; + + return 0; +} +EXPORT_SYMBOL(clevo_keyboard_remove_interface); + struct tuxedo_keyboard_driver clevo_keyboard_driver; static struct key_entry clevo_wmi_keymap[] = { @@ -229,6 +291,16 @@ static ssize_t show_hasextra_fs(struct device *child, return sprintf(buffer, "%d\n", kbd_led_state.has_extra); } +static u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +{ + if (IS_ERR_OR_NULL(active_clevo_interface)) { + pr_err("clevo_keyboard: no active interface\n"); + return -ENODEV; + } + TUXEDO_DEBUG("evaluate method\n"); + return active_clevo_interface->method_call(cmd, arg, result); +} + static int evaluate_wmi_method_clevo(u32 submethod_id, u32 submethod_arg, u32 * retval) { struct acpi_buffer acpi_input = { (acpi_size) sizeof(submethod_arg), &submethod_arg }; @@ -265,10 +337,15 @@ static int evaluate_wmi_method_clevo(u32 submethod_id, u32 submethod_arg, u32 * return 0; } +static u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +{ + return evaluate_wmi_method_clevo(cmd, arg, result_value); +} + static void set_brightness(u8 brightness) { TUXEDO_INFO("Set brightness on %d", brightness); - if (!evaluate_wmi_method_clevo + if (!clevo_evaluate_method (WMI_SUBMETHOD_ID_SET_KB_LEDS, 0xF4000000 | brightness, NULL)) { kbd_led_state.brightness = brightness; } @@ -303,7 +380,7 @@ static int set_enabled_cmd(u8 state) cmd |= 0x07F001; } - return evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_SET_KB_LEDS, cmd, NULL); + return clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, cmd, NULL); } static void set_enabled(u8 state) @@ -339,7 +416,7 @@ static int set_color(u32 region, u32 color) TUXEDO_DEBUG("Set Color '%08x' for region '%08x'", color, region); - return evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_SET_KB_LEDS, wmi_submethod_arg, NULL); + return clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, wmi_submethod_arg, NULL); } static int set_color_code_region(u32 region, u32 colorcode) { @@ -455,7 +532,7 @@ static void set_blinking_pattern(u8 blinkling_pattern) { TUXEDO_INFO("set_mode on %s", blinking_patterns[blinkling_pattern].name); - if (!evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_SET_KB_LEDS, blinking_patterns[blinkling_pattern].value, NULL)) { + if (!clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, blinking_patterns[blinkling_pattern].value, NULL)) { // wmi method was succesfull so update ur internal state struct kbd_led_state.blinking_pattern = blinkling_pattern; } @@ -518,12 +595,13 @@ static int brightness_validator(const char *value, return param_set_int(value, brightness_param); } -static void clevo_wmi_notify(u32 value, void *context) +void clevo_keyboard_event_callb(u32 event) { u32 key_event; + TUXEDO_DEBUG("event callback: (%0#10x)\n", event); - evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_GET_EVENT, 0, &key_event); - TUXEDO_DEBUG("WMI event (%0#6x)\n", key_event); + clevo_evaluate_method(WMI_SUBMETHOD_ID_GET_EVENT, 0, &key_event); + TUXEDO_DEBUG("clevo event (%0#6x)\n", key_event); switch (key_event) { case WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT: @@ -563,16 +641,20 @@ static void clevo_wmi_notify(u32 value, void *context) break; } - if (clevo_keyboard_driver.input_device != NULL) { + if (current_driver != NULL && current_driver->input_device != NULL) { if (!sparse_keymap_report_known_event( - clevo_keyboard_driver.input_device, key_event, 1, - true)) { + current_driver->input_device, key_event, 1, true)) { TUXEDO_DEBUG("Unknown key - %d (%0#6x)\n", key_event, key_event); } } } +static void clevo_wmi_notify(u32 value, void *context) +{ + clevo_keyboard_event_callb(value); +} + // Sysfs attribute file permissions and method linking static DEVICE_ATTR(state, 0644, show_state_fs, set_state_fs); static DEVICE_ATTR(color_left, 0644, show_color_left_fs, set_color_left_fs); @@ -584,44 +666,13 @@ static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); -static int clevo_keyboard_probe(struct platform_device *dev) +struct clevo_interface_t clevo_wmi_interface = { + .string_id = "clevo_wmi", + .method_call = clevo_wmi_interface_method_call +}; + +static void clevo_keyboard_init_device_interface(struct platform_device *dev) { - int status, ret; - - if (!wmi_has_guid(CLEVO_EVENT_GUID)) { - TUXEDO_DEBUG("probe: Clevo event guid missing\n"); - return -ENODEV; - } - - if (!wmi_has_guid(CLEVO_GET_GUID)) { - TUXEDO_DEBUG("probe: Clevo method guid missing\n"); - return -ENODEV; - } - - // Since the WMI GUIDs aren't unique let's (at least) - // check the return of some "known existing general" method - status = evaluate_wmi_method_clevo(0x52, 0, &ret); - if (status < 0) { - TUXEDO_DEBUG("probe: Clevo GUIDs present but method call failed\n"); - return -ENODEV; - } - if (ret == 0xffffffff) { - TUXEDO_DEBUG("probe: Clevo GUIDs present but method returned unexpected value\n"); - return -ENODEV; - } - - status = wmi_install_notify_handler(CLEVO_EVENT_GUID, clevo_wmi_notify, - NULL); - - if (unlikely(ACPI_FAILURE(status))) { - TUXEDO_ERROR("Could not register WMI notify handler (%0#6x)\n", - status); - return -EIO; - } - - // Enable WMI events - evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_GET_AP, 0, NULL); - // Setup sysfs if (device_create_file(&dev->dev, &dev_attr_state) != 0) { TUXEDO_ERROR("Sysfs attribute file creation failed for state\n"); @@ -682,7 +733,10 @@ static int clevo_keyboard_probe(struct platform_device *dev) kbd_led_state.color.center = param_color_center; kbd_led_state.color.right = param_color_right; kbd_led_state.color.extra = param_color_extra; +} +void clevo_keyboard_write_state(void) +{ // Write state set_color(REGION_LEFT, param_color_left); set_color(REGION_CENTER, param_color_center); @@ -692,14 +746,61 @@ static int clevo_keyboard_probe(struct platform_device *dev) if (param_brightness > BRIGHTNESS_MAX) param_brightness = BRIGHTNESS_DEFAULT; set_brightness(param_brightness); set_enabled(param_state); +} + +static int clevo_keyboard_probe(struct platform_device *dev) +{ + int status, ret; + + // *** Clevo ID part *** + if (!wmi_has_guid(CLEVO_EVENT_GUID)) { + TUXEDO_DEBUG("probe: Clevo event guid missing\n"); + return -ENODEV; + } + + if (!wmi_has_guid(CLEVO_GET_GUID)) { + TUXEDO_DEBUG("probe: Clevo method guid missing\n"); + return -ENODEV; + } + + // Since the WMI GUIDs aren't unique let's (at least) + // check the return of some "known existing general" method + status = evaluate_wmi_method_clevo(0x52, 0, &ret); + if (status < 0) { + TUXEDO_DEBUG("probe: Clevo GUIDs present but method call failed\n"); + return -ENODEV; + } + if (ret == 0xffffffff) { + TUXEDO_DEBUG("probe: Clevo GUIDs present but method returned unexpected value\n"); + return -ENODEV; + } + // *** Clevo ID part end *** + + status = wmi_install_notify_handler(CLEVO_EVENT_GUID, clevo_wmi_notify, + NULL); + + if (unlikely(ACPI_FAILURE(status))) { + TUXEDO_ERROR("Could not register WMI notify handler (%0#6x)\n", + status); + return -EIO; + } + + clevo_keyboard_init_device_interface(dev); + + // Add WMI interface (to be done in WMI driver) + clevo_keyboard_add_interface(&clevo_wmi_interface); return 0; } -static int clevo_keyboard_remove(struct platform_device *dev) +static int clevo_keyboard_probe_only_init(struct platform_device *dev) { - wmi_remove_notify_handler(CLEVO_EVENT_GUID); + clevo_keyboard_init_device_interface(dev); + return 0; +} +static void clevo_keyboard_remove_device_interface(struct platform_device *dev) +{ device_remove_file(&dev->dev, &dev_attr_state); device_remove_file(&dev->dev, &dev_attr_color_left); device_remove_file(&dev->dev, &dev_attr_color_center); @@ -711,6 +812,13 @@ static int clevo_keyboard_remove(struct platform_device *dev) if (kbd_led_state.has_extra == 1) { device_remove_file(&dev->dev, &dev_attr_color_extra); } +} + +static int clevo_keyboard_remove(struct platform_device *dev) +{ + wmi_remove_notify_handler(CLEVO_EVENT_GUID); + + clevo_keyboard_remove_device_interface(dev); return 0; } @@ -724,7 +832,7 @@ static int clevo_keyboard_suspend(struct platform_device *dev, pm_message_t stat static int clevo_keyboard_resume(struct platform_device *dev) { - evaluate_wmi_method_clevo(WMI_SUBMETHOD_ID_GET_AP, 0, NULL); + clevo_evaluate_method(WMI_SUBMETHOD_ID_GET_AP, 0, NULL); set_color(REGION_LEFT, kbd_led_state.color.left); set_color(REGION_CENTER, kbd_led_state.color.center); @@ -755,3 +863,16 @@ struct tuxedo_keyboard_driver clevo_keyboard_driver = { .probe = clevo_keyboard_probe, .key_map = clevo_wmi_keymap, }; + +struct tuxedo_keyboard_driver clevo_keyboard_driver_v2 = { + .platform_driver = &platform_driver_clevo, + .probe = clevo_keyboard_probe_only_init, + .key_map = clevo_wmi_keymap, +}; + +int clevo_keyboard_init(void) +{ + tuxedo_keyboard_init_driver(&clevo_keyboard_driver_v2); + return 0; +} +EXPORT_SYMBOL(clevo_keyboard_init); diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index 7035475..b772918 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -20,6 +20,7 @@ #define pr_fmt(fmt) "tuxedo_keyboard" ": " fmt +#include "tuxedo_keyboard.h" #include "tuxedo_keyboard_common.h" #include "clevo_keyboard.h" #include "uniwill_keyboard.h" @@ -80,6 +81,44 @@ err_free_input_device: return err; } +struct platform_device *tuxedo_keyboard_init_driver(struct tuxedo_keyboard_driver *tk_driver) +{ + int err; + TUXEDO_DEBUG("init driver start\n"); + + // If already initiated don't do anything further + if (!IS_ERR_OR_NULL(tuxedo_platform_device)) { + return tuxedo_platform_device; + } + + TUXEDO_DEBUG("create platform bundle\n"); + + tuxedo_platform_device = platform_create_bundle( + tk_driver->platform_driver, tk_driver->probe, NULL, 0, NULL, 0); + + if (IS_ERR_OR_NULL(tuxedo_platform_device)) + return tuxedo_platform_device; + + TUXEDO_DEBUG("platform device created\n"); + + TUXEDO_DEBUG("initialize input device\n"); + if (tk_driver->key_map != NULL) { + err = tuxedo_input_init(tk_driver->key_map); + if (unlikely(err)) { + TUXEDO_ERROR("Could not register input device\n"); + tk_driver->input_device = NULL; + } else { + TUXEDO_DEBUG("input device registered\n"); + tk_driver->input_device = tuxedo_input_device; + } + } + + current_driver = tk_driver; + + return tuxedo_platform_device; +} +EXPORT_SYMBOL(tuxedo_keyboard_init_driver); + static void __exit tuxedo_input_exit(void) { if (unlikely(!tuxedo_input_device)) { @@ -94,7 +133,7 @@ static void __exit tuxedo_input_exit(void) static int __init tuxdeo_keyboard_init(void) { - int i, err; + int i; int num_drivers = sizeof(driver_list) / sizeof(*driver_list); TUXEDO_INFO("Model '%s' found\n", dmi_get_system_info(DMI_PRODUCT_NAME)); @@ -106,25 +145,13 @@ static int __init tuxdeo_keyboard_init(void) i = 0; while (IS_ERR_OR_NULL(tuxedo_platform_device) && i < num_drivers) { current_driver = driver_list[i]; - tuxedo_platform_device = platform_create_bundle( - current_driver->platform_driver, - current_driver->probe, NULL, 0, NULL, 0); + tuxedo_keyboard_init_driver(current_driver); ++i; } if (IS_ERR_OR_NULL(tuxedo_platform_device)) { - TUXEDO_ERROR("No matching hardware found\n"); - return -ENODEV; - } - - if (current_driver->key_map != NULL) { - err = tuxedo_input_init(current_driver->key_map); - if (unlikely(err)) { - TUXEDO_ERROR("Could not register input device\n"); - current_driver->input_device = NULL; - } else { - current_driver->input_device = tuxedo_input_device; - } + TUXEDO_DEBUG("No matching hardware found on init\n"); + current_driver = NULL; } return 0; @@ -132,13 +159,16 @@ static int __init tuxdeo_keyboard_init(void) static void __exit tuxdeo_keyboard_exit(void) { + TUXEDO_DEBUG("tuxedo_input_exit()\n"); tuxedo_input_exit(); + TUXEDO_DEBUG("platform_device_unregister()\n"); + if (!IS_ERR_OR_NULL(tuxedo_platform_device)) + platform_device_unregister(tuxedo_platform_device); + TUXEDO_DEBUG("platform_driver_unregister()\n"); + if (!IS_ERR_OR_NULL(current_driver)) + platform_driver_unregister(current_driver->platform_driver); - platform_device_unregister(tuxedo_platform_device); - - platform_driver_unregister(current_driver->platform_driver); - - TUXEDO_DEBUG("exit"); + TUXEDO_DEBUG("exit\n"); } module_init(tuxdeo_keyboard_init); diff --git a/src/tuxedo_keyboard.h b/src/tuxedo_keyboard.h new file mode 100644 index 0000000..dfc3b20 --- /dev/null +++ b/src/tuxedo_keyboard.h @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include +#include + +#ifndef TUXEDO_KEYBOARD_H +#define TUXEDO_KEYBOARD_H + +struct clevo_interface_t { + char *string_id; + void (*event_callb)(u32); + u32 (*method_call)(u8, u32, u32*); +}; + +u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); + + +#endif \ No newline at end of file diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 3a52b2a..2dec270 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -50,11 +50,13 @@ struct tuxedo_keyboard_driver { }; // Global module devices -static struct platform_device *tuxedo_platform_device; -static struct input_dev *tuxedo_input_device; +static struct platform_device *tuxedo_platform_device = NULL; +static struct input_dev *tuxedo_input_device = NULL; // Currently chosen driver -static struct tuxedo_keyboard_driver *current_driver; +static struct tuxedo_keyboard_driver *current_driver = NULL; + +struct platform_device *tuxedo_keyboard_init_driver(struct tuxedo_keyboard_driver *tk_driver); /** * Basically a copy of the existing report event but doesn't report unknown events diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 5d1a581..8f5cafe 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -89,7 +89,7 @@ static struct key_entry uniwill_wmi_keymap[] = { static void key_event_work(struct work_struct *work) { sparse_keymap_report_known_event( - current_driver->input_device, + uniwill_keyboard_driver.input_device, UNIWILL_OSD_TOUCHPADWORKAROUND, 1, true @@ -244,20 +244,20 @@ static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) if (obj) { if (obj->type == ACPI_TYPE_INTEGER) { code = obj->integer.value; - if (!sparse_keymap_report_known_event(current_driver->input_device, code, 1, true)) { + if (!sparse_keymap_report_known_event(uniwill_keyboard_driver.input_device, code, 1, true)) { TUXEDO_DEBUG("[Ev %d] Unknown key - %d (%0#6x)\n", guid_nr, code, code); } // Special key combination when mode change key is pressed if (code == 0xb0) { - input_report_key(current_driver->input_device, KEY_LEFTMETA, 1); - input_report_key(current_driver->input_device, KEY_LEFTALT, 1); - input_report_key(current_driver->input_device, KEY_F6, 1); - input_sync(current_driver->input_device); - input_report_key(current_driver->input_device, KEY_F6, 0); - input_report_key(current_driver->input_device, KEY_LEFTALT, 0); - input_report_key(current_driver->input_device, KEY_LEFTMETA, 0); - input_sync(current_driver->input_device); + input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 1); + input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTALT, 1); + input_report_key(uniwill_keyboard_driver.input_device, KEY_F6, 1); + input_sync(uniwill_keyboard_driver.input_device); + input_report_key(uniwill_keyboard_driver.input_device, KEY_F6, 0); + input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTALT, 0); + input_report_key(uniwill_keyboard_driver.input_device, KEY_LEFTMETA, 0); + input_sync(uniwill_keyboard_driver.input_device); } // Keyboard backlight brightness toggle From 459a16de007e196c75465d0cbd7be41dde27307f Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 3 Dec 2020 10:15:38 +0100 Subject: [PATCH 04/26] clevo_interfaces: remove/clean up headers --- src/clevo_acpi.c | 3 +-- src/{ck.h => clevo_interfaces.h} | 5 ++--- src/clevo_keyboard.h | 3 +-- src/tuxedo_keyboard.c | 1 - src/tuxedo_keyboard.h | 21 --------------------- 5 files changed, 4 insertions(+), 29 deletions(-) rename src/{ck.h => clevo_interfaces.h} (68%) delete mode 100644 src/tuxedo_keyboard.h diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index 87f4b30..9c1a5a1 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -2,7 +2,7 @@ #include #include #include -#include "ck.h" +#include "clevo_interfaces.h" #define DRIVER_NAME "clevo_acpi" #define CLEVO_ACPI_RESOURCE_HID "CLV0001" @@ -129,7 +129,6 @@ void clevo_acpi_notify(struct acpi_device *device, u32 event) // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); if (!IS_ERR_OR_NULL(clevo_acpi_interface.event_callb)) { // Execute registered callback - pr_debug("calling event addr\n"); clevo_acpi_interface.event_callb(event); } } diff --git a/src/ck.h b/src/clevo_interfaces.h similarity index 68% rename from src/ck.h rename to src/clevo_interfaces.h index f5b7977..418e950 100644 --- a/src/ck.h +++ b/src/clevo_interfaces.h @@ -1,5 +1,4 @@ -#include -#include +#include #ifndef TUXEDO_KEYBOARD_H #define TUXEDO_KEYBOARD_H @@ -13,6 +12,6 @@ struct clevo_interface_t { }; u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); -u32 clevo_keyboard_remove_interface(struct clevo_interface_t *new_interface); +u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface); #endif diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 8b9f02b..20c6c3f 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -18,8 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "tuxedo_keyboard_common.h" -#include "tuxedo_keyboard.h" -#include "ck.h" +#include "clevo_interfaces.h" #define CLEVO_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" #define CLEVO_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index b772918..c4f3872 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -20,7 +20,6 @@ #define pr_fmt(fmt) "tuxedo_keyboard" ": " fmt -#include "tuxedo_keyboard.h" #include "tuxedo_keyboard_common.h" #include "clevo_keyboard.h" #include "uniwill_keyboard.h" diff --git a/src/tuxedo_keyboard.h b/src/tuxedo_keyboard.h deleted file mode 100644 index dfc3b20..0000000 --- a/src/tuxedo_keyboard.h +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#ifndef TUXEDO_KEYBOARD_H -#define TUXEDO_KEYBOARD_H - -struct clevo_interface_t { - char *string_id; - void (*event_callb)(u32); - u32 (*method_call)(u8, u32, u32*); -}; - -u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface); - - -#endif \ No newline at end of file From 2c7eb248b1730950c24d3ad2374801178a9c8283 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 3 Dec 2020 12:10:07 +0100 Subject: [PATCH 05/26] clevo_interfaces: debug modifications & clarifications --- src/clevo_acpi.c | 10 +++++----- src/clevo_keyboard.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index 9c1a5a1..ca7135d 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -48,7 +48,6 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 if (handle == NULL) return -ENODEV; - pr_debug("evaluate _DSM cmd: %0#4x arg: %0#10x\n", cmd, arg); out_obj = acpi_evaluate_dsm(handle, &clevo_acpi_dsm_uuid, dsm_rev_dummy, dsm_func, &dsm_argv4); if (!out_obj) { pr_err("failed to evaluate _DSM\n"); @@ -57,6 +56,7 @@ static u32 clevo_acpi_evaluate(struct acpi_device *device, u8 cmd, u32 arg, u32 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; @@ -79,7 +79,7 @@ u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) pr_err("..for method_call: %0#4x arg: %0#10x\n", cmd, arg); status = -ENODATA; } - pr_debug("method_call: %0#4x arg: %0#10x result: %0#10x\n", cmd, arg, !IS_ERR_OR_NULL(result_value) ? *result_value : 0); + // pr_debug("clevo_acpi method_call: %0#4x arg: %0#10x result: %0#10x\n", cmd, arg, !IS_ERR_OR_NULL(result_value) ? *result_value : 0); return status; } @@ -102,7 +102,7 @@ static int clevo_acpi_add(struct acpi_device *device) active_driver_data = driver_data; - pr_debug("acpi add\n"); + pr_debug("clevo_acpi driver add\n"); // Initiate clevo keyboard, if not already loaded by other interface driver clevo_keyboard_init(); @@ -115,7 +115,7 @@ static int clevo_acpi_add(struct acpi_device *device) static int clevo_acpi_remove(struct acpi_device *device) { - pr_debug("acpi remove\n"); + pr_debug("clevo_acpi driver remove\n"); clevo_keyboard_remove_interface(&clevo_acpi_interface); active_driver_data = NULL; return 0; @@ -124,7 +124,7 @@ static int clevo_acpi_remove(struct acpi_device *device) void clevo_acpi_notify(struct acpi_device *device, u32 event) { struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; - pr_debug("event: %0#10x\n", event); + pr_debug("clevo_acpi event: %0#10x\n", event); // clevo_acpi_driver_data = container_of(&device, struct clevo_acpi_driver_data_t, adev); if (!IS_ERR_OR_NULL(clevo_acpi_interface.event_callb)) { diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 20c6c3f..eabedbf 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -296,7 +296,6 @@ static u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) pr_err("clevo_keyboard: no active interface\n"); return -ENODEV; } - TUXEDO_DEBUG("evaluate method\n"); return active_clevo_interface->method_call(cmd, arg, result); } @@ -308,7 +307,7 @@ static int evaluate_wmi_method_clevo(u32 submethod_id, u32 submethod_arg, u32 * acpi_status status; u32 wmi_output; - TUXEDO_DEBUG("evaluate wmi method: %0#4x IN : %0#6x\n", submethod_id, submethod_arg); + // TUXEDO_DEBUG("evaluate wmi method: %0#4x IN : %0#6x\n", submethod_id, submethod_arg); status = wmi_evaluate_method(CLEVO_GET_GUID, 0x00, submethod_id, &acpi_input, &acpi_output); @@ -597,10 +596,11 @@ static int brightness_validator(const char *value, void clevo_keyboard_event_callb(u32 event) { u32 key_event; - TUXEDO_DEBUG("event callback: (%0#10x)\n", event); clevo_evaluate_method(WMI_SUBMETHOD_ID_GET_EVENT, 0, &key_event); - TUXEDO_DEBUG("clevo event (%0#6x)\n", key_event); + // event = received notification value + // key_event = returned from clevo get event method + TUXEDO_DEBUG("clevo event -> event: %0#6x key_event: %0#6x\n", event, key_event); switch (key_event) { case WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT: From b581e45ee0155934f4be6cbdf4bec09a7d872534 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 3 Dec 2020 13:34:33 +0100 Subject: [PATCH 06/26] clevo_interfaces: add missing licensing headers --- src/clevo_acpi.c | 19 +++++++++++++++++++ src/clevo_interfaces.h | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index ca7135d..7f9b78e 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -1,3 +1,22 @@ +/* +* clevo_acpi.h +* +* Copyright (C) 2020 TUXEDO Computers GmbH +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 418e950..d4ca622 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -1,3 +1,22 @@ +/* +* clevo_interfaces.h +* +* Copyright (C) 2020 TUXEDO Computers GmbH +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ #include #ifndef TUXEDO_KEYBOARD_H From bbc29f39fc2e2e62a5d7b1b4eabfd9311a0807c0 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 12:23:39 +0100 Subject: [PATCH 07/26] clevo_interfaces: Add decoupled clevo_wmi interface --- src/clevo_wmi.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/clevo_wmi.c diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c new file mode 100644 index 0000000..e86a3d3 --- /dev/null +++ b/src/clevo_wmi.c @@ -0,0 +1,165 @@ +/* +* clevo_wmi.h +* +* Copyright (C) 2020 TUXEDO Computers GmbH +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include "clevo_interfaces.h" + +#define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" +#define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" +#define CLEVO_WMI_METHOD_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000" + +static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) +{ + struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg), + &wmi_arg }; + struct acpi_buffer acpi_buffer_out = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *acpi_result; + acpi_status status_acpi; + u32 return_status = 0; + + status_acpi = + wmi_evaluate_method(CLEVO_WMI_METHOD_GUID, 0x00, wmi_method_id, + &acpi_buffer_in, &acpi_buffer_out); + + if (unlikely(ACPI_FAILURE(status_acpi))) { + pr_err("failed to evaluate wmi method\n"); + return -EIO; + } + + acpi_result = (union acpi_object *)acpi_buffer_out.pointer; + 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; + } + } + + kfree(acpi_result); + + return return_status; +} + +u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +{ + return clevo_wmi_evaluate(cmd, arg, result_value); +} + +struct clevo_interface_t clevo_wmi_interface = { + .string_id = "clevo_wmi", + .method_call = clevo_wmi_interface_method_call, +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) +static int clevo_wmi_probe(struct wmi_device *wdev) +#else +static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) +#endif +{ + u32 status, ret; + + pr_debug("clevo_wmi driver probe\n"); + + if (!wmi_has_guid(CLEVO_WMI_EVENT_GUID)) { + pr_debug("probe: Clevo event guid missing\n"); + return -ENODEV; + } + + if (!wmi_has_guid(CLEVO_WMI_METHOD_GUID)) { + pr_debug("probe: Clevo method guid missing\n"); + return -ENODEV; + } + + // 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); + if (status < 0) { + pr_debug("probe: Clevo GUIDs present but method call failed\n"); + return -ENODEV; + } + if (ret == 0xffffffff) { + pr_debug( + "probe: Clevo GUIDs present but method returned unexpected value\n"); + return -ENODEV; + } + + // Initiate clevo keyboard, if not already loaded by other interface driver + clevo_keyboard_init(); + + // Add this interface + clevo_keyboard_add_interface(&clevo_wmi_interface); + + pr_info("clevo_wmi: interface initialized\n"); + + return 0; +} + +static int clevo_wmi_remove(struct wmi_device *wdev) +{ + pr_debug("clevo_wmi driver remove\n"); + return 0; +} + +static void clevo_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) +{ + u32 event_value; + clevo_wmi_evaluate(0x01, 0, &event_value); + pr_debug("clevo_wmi notify\n"); + if (!IS_ERR_OR_NULL(clevo_wmi_interface.event_callb)) { + // Execute registered callback + clevo_wmi_interface.event_callb(event_value); + } +} + +static const struct wmi_device_id clevo_wmi_device_ids[] = { + // Listing one should be enough, for a driver that "takes care of all anyways" + // also prevents probe (and handling) per "device" + { .guid_string = CLEVO_WMI_EVENT_GUID }, + { "" } +}; + +static struct wmi_driver clevo_wmi_driver = { + .driver = { .name = "clevo_wmi", .owner = THIS_MODULE }, + .id_table = clevo_wmi_device_ids, + .probe = clevo_wmi_probe, + .remove = clevo_wmi_remove, + .notify = clevo_wmi_notify, +}; + +module_wmi_driver(clevo_wmi_driver); + +MODULE_AUTHOR("TUXEDO Computers GmbH "); +MODULE_DESCRIPTION("Driver for Clevo WMI interface"); +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(wmi, clevo_wmi_device_ids); From 14c37444e67c880fd9cb6d98a34a60e1ef4d828e Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 13:14:46 +0100 Subject: [PATCH 08/26] clevo_interfaces: Change event handling & use separate wmi module --- src/clevo_acpi.c | 9 +++++++-- src/clevo_keyboard.h | 7 ++----- src/tuxedo_keyboard.c | 1 - 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index 7f9b78e..fbc5b48 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -129,6 +129,8 @@ static int clevo_acpi_add(struct acpi_device *device) // Add this interface clevo_keyboard_add_interface(&clevo_acpi_interface); + pr_info("clevo_acpi: interface initialized\n"); + return 0; } @@ -142,8 +144,11 @@ static int clevo_acpi_remove(struct acpi_device *device) void clevo_acpi_notify(struct acpi_device *device, u32 event) { - struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; - pr_debug("clevo_acpi event: %0#10x\n", event); + u32 event_value; + // struct clevo_acpi_driver_data_t *clevo_acpi_driver_data; + + clevo_acpi_evaluate(device, 0x01, 0, &event_value); + 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); if (!IS_ERR_OR_NULL(clevo_acpi_interface.event_callb)) { diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index eabedbf..8c6c260 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -595,12 +595,9 @@ static int brightness_validator(const char *value, void clevo_keyboard_event_callb(u32 event) { - u32 key_event; + u32 key_event = event; - clevo_evaluate_method(WMI_SUBMETHOD_ID_GET_EVENT, 0, &key_event); - // event = received notification value - // key_event = returned from clevo get event method - TUXEDO_DEBUG("clevo event -> event: %0#6x key_event: %0#6x\n", event, key_event); + // TUXEDO_DEBUG("clevo event: %0#6x\n", event); switch (key_event) { case WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT: diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index c4f3872..891dfba 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -39,7 +39,6 @@ MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); MODULE_SOFTDEP("pre: tuxedo-cc-wmi"); static struct tuxedo_keyboard_driver *driver_list[] = { - &clevo_keyboard_driver, &uniwill_keyboard_driver }; From d1f0a913349e1a29deaf7c155527586e7f43b50b Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 13:18:11 +0100 Subject: [PATCH 09/26] Update build to include clevo_wmi --- Makefile | 2 +- dkms.conf | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index b8d0363..7723023 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := ./src/tuxedo_keyboard.o ./src/clevo_acpi.o +obj-m := ./src/tuxedo_keyboard.o ./src/clevo_wmi.o ./src/clevo_acpi.o PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/dkms.conf b/dkms.conf index 6406f03..f3b5925 100644 --- a/dkms.conf +++ b/dkms.conf @@ -5,9 +5,13 @@ DEST_MODULE_LOCATION[0]="/kernel/lib/" BUILT_MODULE_NAME[0]="tuxedo_keyboard" BUILT_MODULE_LOCATION[0]="src/" -DEST_MODULE_LOCATION[0]="/kernel/lib/" -BUILT_MODULE_NAME[0]="clevo_acpi" -BUILT_MODULE_LOCATION[0]="src/" +DEST_MODULE_LOCATION[1]="/kernel/lib/" +BUILT_MODULE_NAME[1]="clevo_wmi" +BUILT_MODULE_LOCATION[1]="src/" + +DEST_MODULE_LOCATION[2]="/kernel/lib/" +BUILT_MODULE_NAME[2]="clevo_acpi" +BUILT_MODULE_LOCATION[2]="src/" MAKE[0]="make KDIR=/lib/modules/${kernelver}/build" CLEAN="make clean" From 6e3ce9ca6a4e4e805d9eddb8c661e631017d83f0 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 15:20:55 +0100 Subject: [PATCH 10/26] clevo_keyboard: Remove/refactor leftover wmi references --- src/clevo_keyboard.h | 200 ++++++++++-------------------------------- src/tuxedo_keyboard.c | 3 - 2 files changed, 46 insertions(+), 157 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 8c6c260..6ba239d 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -20,10 +20,6 @@ #include "tuxedo_keyboard_common.h" #include "clevo_interfaces.h" -#define CLEVO_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" -#define CLEVO_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" -#define CLEVO_GET_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000" - #define BRIGHTNESS_MIN 0 #define BRIGHTNESS_MAX 255 #define BRIGHTNESS_DEFAULT BRIGHTNESS_MAX @@ -38,26 +34,26 @@ #define KB_COLOR_DEFAULT 0xFFFFFF // White #define DEFAULT_BLINKING_PATTERN 0 -// Submethod IDs for the CLEVO_GET WMI method -#define WMI_SUBMETHOD_ID_GET_EVENT 0x01 -#define WMI_SUBMETHOD_ID_GET_AP 0x46 -#define WMI_SUBMETHOD_ID_SET_KB_LEDS 0x67 /* used to set color, brightness, +// Submethod IDs for the CLEVO_GET interface method +#define CLEVO_METHOD_ID_GET_EVENT 0x01 +#define CLEVO_METHOD_ID_GET_AP 0x46 +#define CLEVO_METHOD_ID_SET_KB_LEDS 0x67 /* used to set color, brightness, blinking pattern, etc. */ -// WMI Event Codes -#define WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT 0x81 -#define WMI_KEYEVENT_CODE_INCREASE_BACKLIGHT 0x82 -#define WMI_KEYEVENT_CODE_NEXT_BLINKING_PATTERN 0x83 -#define WMI_KEYEVENT_CODE_TOGGLE_STATE 0x9F +// Clevo event codes +#define CLEVO_EVENT_DECREASE_BACKLIGHT 0x81 +#define CLEVO_EVENT_INCREASE_BACKLIGHT 0x82 +#define CLEVO_EVENT_NEXT_BLINKING_PATTERN 0x83 +#define CLEVO_EVENT_TOGGLE_STATE 0x9F -#define WMI_KEYEVENT_CODE_CYCLE_BRIGHTNESS 0x8A -#define WMI_KEYEVENT_CODE_TOUCHPAD_TOGGLE 0x5D -#define WMI_KEYEVENT_CODE_TOUCHPAD_OFF 0xFC -#define WMI_KEYEVENT_CODE_TOUCHPAD_ON 0xFD +#define CLEVO_EVENT_CYCLE_BRIGHTNESS 0x8A +#define CLEVO_EVENT_TOUCHPAD_TOGGLE 0x5D +#define CLEVO_EVENT_TOUCHPAD_OFF 0xFC +#define CLEVO_EVENT_TOUCHPAD_ON 0xFD -#define WMI_KEYEVENT_CODE_RFKILL1 0x85 -#define WMI_KEYEVENT_CODE_RFKILL2 0x86 +#define CLEVO_EVENT_RFKILL1 0x85 +#define CLEVO_EVENT_RFKILL2 0x86 static struct clevo_interfaces_t { struct clevo_interface_t *wmi; @@ -121,35 +117,36 @@ EXPORT_SYMBOL(clevo_keyboard_remove_interface); struct tuxedo_keyboard_driver clevo_keyboard_driver; -static struct key_entry clevo_wmi_keymap[] = { +static struct key_entry clevo_keymap[] = { // Keyboard backlight (RGB versions) - { KE_KEY, WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT, { KEY_KBDILLUMDOWN } }, - { KE_KEY, WMI_KEYEVENT_CODE_INCREASE_BACKLIGHT, { KEY_KBDILLUMUP } }, - { KE_KEY, WMI_KEYEVENT_CODE_TOGGLE_STATE, { KEY_KBDILLUMTOGGLE } }, - { KE_KEY, WMI_KEYEVENT_CODE_NEXT_BLINKING_PATTERN, { KEY_LIGHTS_TOGGLE } }, + { KE_KEY, CLEVO_EVENT_DECREASE_BACKLIGHT, { KEY_KBDILLUMDOWN } }, + { KE_KEY, CLEVO_EVENT_INCREASE_BACKLIGHT, { KEY_KBDILLUMUP } }, + { KE_KEY, CLEVO_EVENT_TOGGLE_STATE, { KEY_KBDILLUMTOGGLE } }, + { KE_KEY, CLEVO_EVENT_NEXT_BLINKING_PATTERN, { KEY_LIGHTS_TOGGLE } }, // Single cycle key (white only versions) - { KE_KEY, WMI_KEYEVENT_CODE_CYCLE_BRIGHTNESS, { KEY_KBDILLUMUP } }, + { KE_KEY, CLEVO_EVENT_CYCLE_BRIGHTNESS, { KEY_KBDILLUMUP } }, // Touchpad // The weirdly named touchpad toggle key that is implemented as KEY_F21 "everywhere" // (instead of KEY_TOUCHPAD_TOGGLE or on/off) // Most "new" devices just provide one toggle event - { KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_TOGGLE, { KEY_F21 } }, + { KE_KEY, CLEVO_EVENT_TOUCHPAD_TOGGLE, { KEY_F21 } }, // Some "old" devices produces on/off events - { KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_OFF, { KEY_F21 } }, - { KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_ON, { KEY_F21 } }, + { KE_KEY, CLEVO_EVENT_TOUCHPAD_OFF, { KEY_F21 } }, + { KE_KEY, CLEVO_EVENT_TOUCHPAD_ON, { KEY_F21 } }, // The alternative key events (currently not used) - //{ KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_OFF, { KEY_TOUCHPAD_OFF } }, - //{ KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_ON, { KEY_TOUCHPAD_ON } }, - //{ KE_KEY, WMI_KEYEVENT_CODE_TOUCHPAD_TOGGLE, { KEY_TOUCHPAD_TOGGLE } }, + // { KE_KEY, CLEVO_EVENT_TOUCHPAD_OFF, { KEY_TOUCHPAD_OFF } }, + // { KE_KEY, CLEVO_EVENT_TOUCHPAD_ON, { KEY_TOUCHPAD_ON } }, + // { KE_KEY, CLEVO_EVENT_TOUCHPAD_TOGGLE, { KEY_TOUCHPAD_TOGGLE } }, - { KE_KEY, WMI_KEYEVENT_CODE_RFKILL1, { KEY_RFKILL } }, // Still needed by some devices - { KE_IGNORE, WMI_KEYEVENT_CODE_RFKILL2, { KEY_RFKILL } }, // Older rfkill event + // Rfkill still needed by some devices + { KE_KEY, CLEVO_EVENT_RFKILL1, { KEY_RFKILL } }, + { KE_IGNORE, CLEVO_EVENT_RFKILL2, { KEY_RFKILL } }, // Older rfkill event // Note: Volume events need to be ignored as to not interfere with built-in functionality - { KE_IGNORE, 0xfa, { KEY_UNKNOWN } }, // Appears by volume up/down - { KE_IGNORE, 0xfb, { KEY_UNKNOWN } }, // Appears by mute toggle + { KE_IGNORE, 0xfa, { KEY_UNKNOWN } }, // Appears by volume up/down + { KE_IGNORE, 0xfb, { KEY_UNKNOWN } }, // Appears by mute toggle - { KE_END, 0 } + { KE_END, 0 } }; #define BRIGHTNESS_STEP 25 @@ -299,52 +296,11 @@ static u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) return active_clevo_interface->method_call(cmd, arg, result); } -static int evaluate_wmi_method_clevo(u32 submethod_id, u32 submethod_arg, u32 * retval) -{ - struct acpi_buffer acpi_input = { (acpi_size) sizeof(submethod_arg), &submethod_arg }; - struct acpi_buffer acpi_output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - u32 wmi_output; - - // TUXEDO_DEBUG("evaluate wmi method: %0#4x IN : %0#6x\n", submethod_id, submethod_arg); - - status = wmi_evaluate_method(CLEVO_GET_GUID, 0x00, submethod_id, - &acpi_input, &acpi_output); - - if (unlikely(ACPI_FAILURE(status))) { - TUXEDO_ERROR("evaluate_wmi_method error"); - return -EIO; - } - - obj = (union acpi_object *)acpi_output.pointer; - if (obj && obj->type == ACPI_TYPE_INTEGER) { - wmi_output = (u32) obj->integer.value; - } else { - wmi_output = 0; - } - - TUXEDO_DEBUG("WMI submethod %0#4x output: %0#6x (input: %0#6x)\n", - submethod_id, wmi_output, submethod_arg); - - if (likely(retval)) { /* if no NULL pointer */ - *retval = wmi_output; - } - - kfree(obj); - return 0; -} - -static u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) -{ - return evaluate_wmi_method_clevo(cmd, arg, result_value); -} - static void set_brightness(u8 brightness) { TUXEDO_INFO("Set brightness on %d", brightness); if (!clevo_evaluate_method - (WMI_SUBMETHOD_ID_SET_KB_LEDS, 0xF4000000 | brightness, NULL)) { + (CLEVO_METHOD_ID_SET_KB_LEDS, 0xF4000000 | brightness, NULL)) { kbd_led_state.brightness = brightness; } } @@ -378,7 +334,7 @@ static int set_enabled_cmd(u8 state) cmd |= 0x07F001; } - return clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, cmd, NULL); + return clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, cmd, NULL); } static void set_enabled(u8 state) @@ -410,11 +366,11 @@ static int set_color(u32 region, u32 color) u32 cset = ((color & 0x0000FF) << 16) | ((color & 0xFF0000) >> 8) | ((color & 0x00FF00) >> 8); - u32 wmi_submethod_arg = region | cset; + u32 clevo_submethod_arg = region | cset; TUXEDO_DEBUG("Set Color '%08x' for region '%08x'", color, region); - return clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, wmi_submethod_arg, NULL); + return clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, clevo_submethod_arg, NULL); } static int set_color_code_region(u32 region, u32 colorcode) { @@ -530,8 +486,8 @@ static void set_blinking_pattern(u8 blinkling_pattern) { TUXEDO_INFO("set_mode on %s", blinking_patterns[blinkling_pattern].name); - if (!clevo_evaluate_method(WMI_SUBMETHOD_ID_SET_KB_LEDS, blinking_patterns[blinkling_pattern].value, NULL)) { - // wmi method was succesfull so update ur internal state struct + if (!clevo_evaluate_method(CLEVO_METHOD_ID_SET_KB_LEDS, blinking_patterns[blinkling_pattern].value, NULL)) { + // method was succesfull so update ur internal state struct kbd_led_state.blinking_pattern = blinkling_pattern; } @@ -600,7 +556,7 @@ void clevo_keyboard_event_callb(u32 event) // TUXEDO_DEBUG("clevo event: %0#6x\n", event); switch (key_event) { - case WMI_KEYEVENT_CODE_DECREASE_BACKLIGHT: + case CLEVO_EVENT_DECREASE_BACKLIGHT: if (kbd_led_state.brightness == BRIGHTNESS_MIN || (kbd_led_state.brightness - 25) < BRIGHTNESS_MIN) { set_brightness(BRIGHTNESS_MIN); @@ -610,7 +566,7 @@ void clevo_keyboard_event_callb(u32 event) break; - case WMI_KEYEVENT_CODE_INCREASE_BACKLIGHT: + case CLEVO_EVENT_INCREASE_BACKLIGHT: if (kbd_led_state.brightness == BRIGHTNESS_MAX || (kbd_led_state.brightness + 25) > BRIGHTNESS_MAX) { set_brightness(BRIGHTNESS_MAX); @@ -620,16 +576,16 @@ void clevo_keyboard_event_callb(u32 event) break; -// case WMI_CODE_NEXT_BLINKING_PATTERN: +// case CLEVO_EVENT_NEXT_BLINKING_PATTERN: // set_blinking_pattern((kbd_led_state.blinking_pattern + 1) > // (ARRAY_SIZE(blinking_patterns) - 1) ? 0 : (kbd_led_state.blinking_pattern + 1)); // break; - case WMI_KEYEVENT_CODE_NEXT_BLINKING_PATTERN: + case CLEVO_EVENT_NEXT_BLINKING_PATTERN: set_next_color_whole_kb(); break; - case WMI_KEYEVENT_CODE_TOGGLE_STATE: + case CLEVO_EVENT_TOGGLE_STATE: set_enabled(kbd_led_state.enabled == 0 ? 1 : 0); break; @@ -646,11 +602,6 @@ void clevo_keyboard_event_callb(u32 event) } } -static void clevo_wmi_notify(u32 value, void *context) -{ - clevo_keyboard_event_callb(value); -} - // Sysfs attribute file permissions and method linking static DEVICE_ATTR(state, 0644, show_state_fs, set_state_fs); static DEVICE_ATTR(color_left, 0644, show_color_left_fs, set_color_left_fs); @@ -662,11 +613,6 @@ static DEVICE_ATTR(brightness, 0644, show_brightness_fs, set_brightness_fs); static DEVICE_ATTR(mode, 0644, show_blinking_patterns_fs, set_blinking_pattern_fs); static DEVICE_ATTR(extra, 0444, show_hasextra_fs, NULL); -struct clevo_interface_t clevo_wmi_interface = { - .string_id = "clevo_wmi", - .method_call = clevo_wmi_interface_method_call -}; - static void clevo_keyboard_init_device_interface(struct platform_device *dev) { // Setup sysfs @@ -744,51 +690,6 @@ void clevo_keyboard_write_state(void) set_enabled(param_state); } -static int clevo_keyboard_probe(struct platform_device *dev) -{ - int status, ret; - - // *** Clevo ID part *** - if (!wmi_has_guid(CLEVO_EVENT_GUID)) { - TUXEDO_DEBUG("probe: Clevo event guid missing\n"); - return -ENODEV; - } - - if (!wmi_has_guid(CLEVO_GET_GUID)) { - TUXEDO_DEBUG("probe: Clevo method guid missing\n"); - return -ENODEV; - } - - // Since the WMI GUIDs aren't unique let's (at least) - // check the return of some "known existing general" method - status = evaluate_wmi_method_clevo(0x52, 0, &ret); - if (status < 0) { - TUXEDO_DEBUG("probe: Clevo GUIDs present but method call failed\n"); - return -ENODEV; - } - if (ret == 0xffffffff) { - TUXEDO_DEBUG("probe: Clevo GUIDs present but method returned unexpected value\n"); - return -ENODEV; - } - // *** Clevo ID part end *** - - status = wmi_install_notify_handler(CLEVO_EVENT_GUID, clevo_wmi_notify, - NULL); - - if (unlikely(ACPI_FAILURE(status))) { - TUXEDO_ERROR("Could not register WMI notify handler (%0#6x)\n", - status); - return -EIO; - } - - clevo_keyboard_init_device_interface(dev); - - // Add WMI interface (to be done in WMI driver) - clevo_keyboard_add_interface(&clevo_wmi_interface); - - return 0; -} - static int clevo_keyboard_probe_only_init(struct platform_device *dev) { clevo_keyboard_init_device_interface(dev); @@ -812,10 +713,7 @@ static void clevo_keyboard_remove_device_interface(struct platform_device *dev) static int clevo_keyboard_remove(struct platform_device *dev) { - wmi_remove_notify_handler(CLEVO_EVENT_GUID); - clevo_keyboard_remove_device_interface(dev); - return 0; } @@ -828,7 +726,7 @@ static int clevo_keyboard_suspend(struct platform_device *dev, pm_message_t stat static int clevo_keyboard_resume(struct platform_device *dev) { - clevo_evaluate_method(WMI_SUBMETHOD_ID_GET_AP, 0, NULL); + clevo_evaluate_method(CLEVO_METHOD_ID_GET_AP, 0, NULL); set_color(REGION_LEFT, kbd_led_state.color.left); set_color(REGION_CENTER, kbd_led_state.color.center); @@ -854,16 +752,10 @@ static struct platform_driver platform_driver_clevo = { }, }; -struct tuxedo_keyboard_driver clevo_keyboard_driver = { - .platform_driver = &platform_driver_clevo, - .probe = clevo_keyboard_probe, - .key_map = clevo_wmi_keymap, -}; - struct tuxedo_keyboard_driver clevo_keyboard_driver_v2 = { .platform_driver = &platform_driver_clevo, .probe = clevo_keyboard_probe_only_init, - .key_map = clevo_wmi_keymap, + .key_map = clevo_keymap, }; int clevo_keyboard_init(void) diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index 891dfba..323e674 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -29,9 +29,6 @@ MODULE_DESCRIPTION("TUXEDO Computers keyboard & keyboard backlight Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("2.1.0"); -MODULE_ALIAS("wmi:" CLEVO_EVENT_GUID); -MODULE_ALIAS("wmi:" CLEVO_GET_GUID); - MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_0); MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_1); MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); From 21c65b40b08d5aa1e0aac1875e4465802480f73f Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 15:50:48 +0100 Subject: [PATCH 11/26] clevo_wmi: Fix device list end --- src/clevo_wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index e86a3d3..0e8b055 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -144,7 +144,7 @@ static const struct wmi_device_id clevo_wmi_device_ids[] = { // Listing one should be enough, for a driver that "takes care of all anyways" // also prevents probe (and handling) per "device" { .guid_string = CLEVO_WMI_EVENT_GUID }, - { "" } + { } }; static struct wmi_driver clevo_wmi_driver = { From b484e47de063e3b4a395f13277fbc14e3283af0d Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 4 Dec 2020 16:11:47 +0100 Subject: [PATCH 12/26] clevo_wmi: Add explicit module alias "for older kernels" --- src/clevo_wmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 0e8b055..c945ae8 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -163,3 +163,4 @@ MODULE_VERSION("0.0.1"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(wmi, clevo_wmi_device_ids); +MODULE_ALIAS("wmi:" CLEVO_WMI_EVENT_GUID); From 8667006c4a48290fc1358856ab7be3e746ad1744 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 09:37:53 +0100 Subject: [PATCH 13/26] clevo_interfaces: Add clevo cmd defines - Fix incl. guard "typo" --- src/clevo_interfaces.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index d4ca622..0bf06ac 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -17,10 +17,27 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef TUXEDO_INTERFACES_H +#define TUXEDO_INTERFACES_H + #include -#ifndef TUXEDO_KEYBOARD_H -#define TUXEDO_KEYBOARD_H +// The clevo get commands expect no parameters +#define CLEVO_CMD_GET_FANINFO1 0x63 +#define CLEVO_CMD_GET_FANINFO2 0x64 +#define CLEVO_CMD_GET_FANINFO3 0x6e + +#define CLEVO_CMD_GET_WEBCAM_SW 0x06 +#define CLEVO_CMD_GET_FLIGHTMODE_SW 0x07 +#define CLEVO_CMD_GET_TOUCHPAD_SW 0x09 + +// The clevo set commands expect a parameter +#define CLEVO_CMD_SET_FANSPEED_VALUE 0x68 +#define CLEVO_CMD_SET_FANSPEED_AUTO 0x69 + +#define CLEVO_CMD_SET_WEBCAM_SW 0x22 +#define CLEVO_CMD_SET_FLIGHTMODE_SW 0x20 +#define CLEVO_CMD_SET_TOUCHPAD_SW 0x2a int clevo_keyboard_init(void); From 1f8b5a66b35305623b97a8a514d2ca0443721ded Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 10:59:10 +0100 Subject: [PATCH 14/26] clevo_interfaces: Move resource ID defs --- src/clevo_acpi.c | 2 -- src/clevo_interfaces.h | 7 +++++++ src/clevo_wmi.c | 4 ---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index fbc5b48..b278298 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -24,8 +24,6 @@ #include "clevo_interfaces.h" #define DRIVER_NAME "clevo_acpi" -#define CLEVO_ACPI_RESOURCE_HID "CLV0001" -#define CLEVO_ACPI_DSM_UUID "93f224e4-fbdc-4bbf-add6-db71bdc0afad" struct clevo_acpi_driver_data_t { struct acpi_device *adev; diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 0bf06ac..2011f5f 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -22,6 +22,13 @@ #include +#define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" +#define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" +#define CLEVO_WMI_METHOD_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000" + +#define CLEVO_ACPI_RESOURCE_HID "CLV0001" +#define CLEVO_ACPI_DSM_UUID "93f224e4-fbdc-4bbf-add6-db71bdc0afad" + // The clevo get commands expect no parameters #define CLEVO_CMD_GET_FANINFO1 0x63 #define CLEVO_CMD_GET_FANINFO2 0x64 diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index c945ae8..20f6585 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -24,10 +24,6 @@ #include #include "clevo_interfaces.h" -#define CLEVO_WMI_EVENT_GUID "ABBC0F6B-8EA1-11D1-00A0-C90629100000" -#define CLEVO_WMI_EMAIL_GUID "ABBC0F6C-8EA1-11D1-00A0-C90629100000" -#define CLEVO_WMI_METHOD_GUID "ABBC0F6D-8EA1-11D1-00A0-C90629100000" - static int clevo_wmi_evaluate(u32 wmi_method_id, u32 wmi_arg, u32 *result) { struct acpi_buffer acpi_buffer_in = { (acpi_size)sizeof(wmi_arg), From bea8621bdbe96791fe920731cd6640cadce84398 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 12:19:36 +0100 Subject: [PATCH 15/26] clevo_interfaces: Export method and ID interface --- src/clevo_interfaces.h | 2 ++ src/clevo_keyboard.h | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 2011f5f..dfb4483 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -56,5 +56,7 @@ struct clevo_interface_t { 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_get_active_interface_id(char **id_str); #endif diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 6ba239d..158a41a 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -287,7 +287,7 @@ static ssize_t show_hasextra_fs(struct device *child, return sprintf(buffer, "%d\n", kbd_led_state.has_extra); } -static u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) +u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) { if (IS_ERR_OR_NULL(active_clevo_interface)) { pr_err("clevo_keyboard: no active interface\n"); @@ -295,6 +295,21 @@ static u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result) } return active_clevo_interface->method_call(cmd, arg, result); } +EXPORT_SYMBOL(clevo_evaluate_method); + +u32 clevo_get_active_interface_id(char **id_str) +{ + if (IS_ERR_OR_NULL(active_clevo_interface)) { + pr_err("clevo_keyboard: no active interface\n"); + return -ENODEV; + } + + if (!IS_ERR_OR_NULL(id_str)) + *id_str = active_clevo_interface->string_id; + + return 0; +} +EXPORT_SYMBOL(clevo_get_active_interface_id); static void set_brightness(u8 brightness) { From 597902a808da2e0cc6971ce8dc144f68f61f4581 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 16:37:26 +0100 Subject: [PATCH 16/26] clevo_interfaces: Move module alias defines --- src/clevo_interfaces.h | 11 +++++++++++ src/clevo_wmi.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index dfb4483..40905ed 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -59,4 +59,15 @@ u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface); u32 clevo_evaluate_method(u8 cmd, u32 arg, u32 *result); u32 clevo_get_active_interface_id(char **id_str); +#define MODULE_ALIAS_CLEVO_WMI() \ + MODULE_ALIAS("wmi:" CLEVO_WMI_EVENT_GUID); \ + MODULE_ALIAS("wmi:" CLEVO_WMI_METHOD_GUID); + +#define MODULE_ALIAS_CLEVO_ACPI() \ + MODULE_ALIAS("acpi*:" CLEVO_ACPI_RESOURCE_HID ":*"); + +#define MODULE_ALIAS_CLEVO_INTERFACES() \ + MODULE_ALIAS_CLEVO_WMI(); \ + MODULE_ALIAS_CLEVO_ACPI(); + #endif diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 20f6585..a229915 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -159,4 +159,4 @@ MODULE_VERSION("0.0.1"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(wmi, clevo_wmi_device_ids); -MODULE_ALIAS("wmi:" CLEVO_WMI_EVENT_GUID); +MODULE_ALIAS_CLEVO_WMI(); From 596212e17aad7811125bebfd175dc4372a55a8a9 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 16:47:34 +0100 Subject: [PATCH 17/26] tuxedo_io: include tuxedo_cc_wmi as tuxedo_io - Clevo part now using exported interface from clevo_interfaces - Uniwill part still works as previously - Additional module alias for ACPI interface needed and added --- Makefile | 5 +- dkms.conf | 4 + src/tuxedo_io/tongfang_wmi.h | 291 ++++++++++++++++++++++++++ src/tuxedo_io/tuxedo_io.c | 351 ++++++++++++++++++++++++++++++++ src/tuxedo_io/tuxedo_io_ioctl.h | 86 ++++++++ 5 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 src/tuxedo_io/tongfang_wmi.h create mode 100644 src/tuxedo_io/tuxedo_io.c create mode 100644 src/tuxedo_io/tuxedo_io_ioctl.h diff --git a/Makefile b/Makefile index 7723023..8d031d9 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,10 @@ # You should have received a copy of the GNU General Public License # along with this software. If not, see . # -obj-m := ./src/tuxedo_keyboard.o ./src/clevo_wmi.o ./src/clevo_acpi.o +obj-m := ./src/tuxedo_keyboard.o \ + ./src/clevo_wmi.o \ + ./src/clevo_acpi.o \ + ./src/tuxedo_io/tuxedo_io.o PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/dkms.conf b/dkms.conf index f3b5925..7e8238e 100644 --- a/dkms.conf +++ b/dkms.conf @@ -13,6 +13,10 @@ DEST_MODULE_LOCATION[2]="/kernel/lib/" BUILT_MODULE_NAME[2]="clevo_acpi" BUILT_MODULE_LOCATION[2]="src/" +DEST_MODULE_LOCATION[3]="/kernel/lib/" +BUILT_MODULE_NAME[3]="tuxedo_io" +BUILT_MODULE_LOCATION[3]="src/tuxedo_io" + MAKE[0]="make KDIR=/lib/modules/${kernelver}/build" CLEAN="make clean" AUTOINSTALL="yes" diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h new file mode 100644 index 0000000..cfabbb3 --- /dev/null +++ b/src/tuxedo_io/tongfang_wmi.h @@ -0,0 +1,291 @@ +/*! + * Copyright (c) 2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-cc-wmi. + * + * tuxedo-cc-wmi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. If not, see . + */ +#include +#include +#include +#include + +#define UNIWILL_WMI_MGMT_GUID_BA "ABBC0F6D-8EA1-11D1-00A0-C90629100000" +#define UNIWILL_WMI_MGMT_GUID_BB "ABBC0F6E-8EA1-11D1-00A0-C90629100000" +#define UNIWILL_WMI_MGMT_GUID_BC "ABBC0F6F-8EA1-11D1-00A0-C90629100000" + +#define UNIWILL_WMI_EVENT_GUID_0 "ABBC0F70-8EA1-11D1-00A0-C90629100000" +#define UNIWILL_WMI_EVENT_GUID_1 "ABBC0F71-8EA1-11D1-00A0-C90629100000" +#define UNIWILL_WMI_EVENT_GUID_2 "ABBC0F72-8EA1-11D1-00A0-C90629100000" + +#define UNIWILL_EC_REG_LDAT 0x8a +#define UNIWILL_EC_REG_HDAT 0x8b +#define UNIWILL_EC_REG_FLAGS 0x8c +#define UNIWILL_EC_REG_CMDL 0x8d +#define UNIWILL_EC_REG_CMDH 0x8e + +#define UNIWILL_EC_BIT_RFLG 0 +#define UNIWILL_EC_BIT_WFLG 1 +#define UNIWILL_EC_BIT_BFLG 2 +#define UNIWILL_EC_BIT_CFLG 3 +#define UNIWILL_EC_BIT_DRDY 7 + +#define UW_EC_WAIT_CYCLES 0x50 + +union uw_ec_read_return { + u32 dword; + struct { + u8 data_low; + u8 data_high; + } bytes; +}; + +union uw_ec_write_return { + u32 dword; + struct { + u8 addr_low; + u8 addr_high; + u8 data_low; + u8 data_high; + } bytes; +}; + +static bool uniwill_ec_direct = true; + +DEFINE_MUTEX(uniwill_ec_lock); + +static u32 uw_wmi_ec_evaluate(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, u8 read_flag, u32 *return_buffer) +{ + acpi_status status; + union acpi_object *out_acpi; + u32 e_result = 0; + + // Kernel buffer for input argument + u32 *wmi_arg = (u32 *) kmalloc(sizeof(u32)*10, GFP_KERNEL); + // Byte reference to the input buffer + u8 *wmi_arg_bytes = (u8 *) wmi_arg; + + u8 wmi_instance = 0x00; + u32 wmi_method_id = 0x04; + struct acpi_buffer wmi_in = { (acpi_size) sizeof(wmi_arg), wmi_arg}; + struct acpi_buffer wmi_out = { ACPI_ALLOCATE_BUFFER, NULL }; + + mutex_lock(&uniwill_ec_lock); + + // Zero input buffer + memset(wmi_arg, 0x00, 10 * sizeof(u32)); + + // Configure the input buffer + wmi_arg_bytes[0] = addr_low; + wmi_arg_bytes[1] = addr_high; + wmi_arg_bytes[2] = data_low; + wmi_arg_bytes[3] = data_high; + + if (read_flag != 0) { + wmi_arg_bytes[5] = 0x01; + } + + status = wmi_evaluate_method(UNIWILL_WMI_MGMT_GUID_BC, wmi_instance, wmi_method_id, &wmi_in, &wmi_out); + out_acpi = (union acpi_object *) wmi_out.pointer; + + if (out_acpi && out_acpi->type == ACPI_TYPE_BUFFER) { + memcpy(return_buffer, out_acpi->buffer.pointer, out_acpi->buffer.length); + } /* else if (out_acpi && out_acpi->type == ACPI_TYPE_INTEGER) { + e_result = (u32) out_acpi->integer.value; + }*/ + if (ACPI_FAILURE(status)) { + pr_err("uniwill_wmi.h: Error evaluating method\n"); + e_result = -EIO; + } + + kfree(out_acpi); + kfree(wmi_arg); + + mutex_unlock(&uniwill_ec_lock); + + return e_result; +} + +/** + * EC address read through WMI + */ +static u32 uw_ec_read_addr_wmi(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) +{ + u32 uw_data[10]; + u32 ret = uw_wmi_ec_evaluate(addr_low, addr_high, 0x00, 0x00, 1, uw_data); + output->dword = uw_data[0]; + pr_debug("addr: 0x%02x%02x value: %0#4x (high: %0#4x) result: %d\n", addr_high, addr_low, output->bytes.data_low, output->bytes.data_high, ret); + return ret; +} + +/** + * EC address write through WMI + */ +static u32 uw_ec_write_addr_wmi(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) +{ + u32 uw_data[10]; + u32 ret = uw_wmi_ec_evaluate(addr_low, addr_high, data_low, data_high, 0, uw_data); + output->dword = uw_data[0]; + return ret; +} + +/** + * Direct EC address read + */ +static u32 uw_ec_read_addr_direct(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) +{ + u32 result; + u8 tmp, count, flags; + + mutex_lock(&uniwill_ec_lock); + + ec_write(UNIWILL_EC_REG_LDAT, addr_low); + ec_write(UNIWILL_EC_REG_HDAT, addr_high); + + flags = (0 << UNIWILL_EC_BIT_DRDY) | (1 << UNIWILL_EC_BIT_RFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + + // Wait for ready flag + count = UW_EC_WAIT_CYCLES; + ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { + msleep(1); + ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + count -= 1; + } + + if (count != 0) { + output->dword = 0; + ec_read(UNIWILL_EC_REG_CMDL, &tmp); + output->bytes.data_low = tmp; + ec_read(UNIWILL_EC_REG_CMDH, &tmp); + output->bytes.data_high = tmp; + result = 0; + } else { + output->dword = 0xfefefefe; + result = -EIO; + } + + ec_write(UNIWILL_EC_REG_FLAGS, 0x00); + + mutex_unlock(&uniwill_ec_lock); + + pr_debug("addr: 0x%02x%02x value: %0#4x result: %d\n", addr_high, addr_low, output->bytes.data_low, result); + + return result; +} + +static u32 uw_ec_write_addr_direct(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) +{ + u32 result = 0; + u8 tmp, count, flags; + + mutex_lock(&uniwill_ec_lock); + + ec_write(UNIWILL_EC_REG_LDAT, addr_low); + ec_write(UNIWILL_EC_REG_HDAT, addr_high); + ec_write(UNIWILL_EC_REG_CMDL, data_low); + ec_write(UNIWILL_EC_REG_CMDH, data_high); + + flags = (0 << UNIWILL_EC_BIT_DRDY) | (1 << UNIWILL_EC_BIT_WFLG); + ec_write(UNIWILL_EC_REG_FLAGS, flags); + + // Wait for ready flag + count = UW_EC_WAIT_CYCLES; + ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + while (((tmp & (1 << UNIWILL_EC_BIT_DRDY)) == 0) && count != 0) { + msleep(1); + ec_read(UNIWILL_EC_REG_FLAGS, &tmp); + count -= 1; + } + + // Replicate wmi output depending on success + if (count != 0) { + output->bytes.addr_low = addr_low; + output->bytes.addr_high = addr_high; + output->bytes.data_low = data_low; + output->bytes.data_high = data_high; + result = 0; + } else { + output->dword = 0xfefefefe; + result = -EIO; + } + + ec_write(UNIWILL_EC_REG_FLAGS, 0x00); + + mutex_unlock(&uniwill_ec_lock); + + return result; +} + +u32 uw_ec_read_addr(u8 addr_low, u8 addr_high, union uw_ec_read_return *output) +{ + if (uniwill_ec_direct) { + return uw_ec_read_addr_direct(addr_low, addr_high, output); + } else { + return uw_ec_read_addr_wmi(addr_low, addr_high, output); + } +} +EXPORT_SYMBOL(uw_ec_read_addr); + +u32 uw_ec_write_addr(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union uw_ec_write_return *output) +{ + if (uniwill_ec_direct) { + return uw_ec_write_addr_direct(addr_low, addr_high, data_low, data_high, output); + } else { + return uw_ec_write_addr_wmi(addr_low, addr_high, data_low, data_high, output); + } +} +EXPORT_SYMBOL(uw_ec_write_addr); + +static u32 uniwill_identify(void) +{ + int status; + + // Look for for GUIDs used on uniwill devices + status = + wmi_has_guid(UNIWILL_WMI_EVENT_GUID_0) && + wmi_has_guid(UNIWILL_WMI_EVENT_GUID_1) && + wmi_has_guid(UNIWILL_WMI_EVENT_GUID_2) && + wmi_has_guid(UNIWILL_WMI_MGMT_GUID_BA) && + wmi_has_guid(UNIWILL_WMI_MGMT_GUID_BB) && + wmi_has_guid(UNIWILL_WMI_MGMT_GUID_BC); + + if (!status) + { + pr_debug("probe: At least one Uniwill GUID missing\n"); + return -ENODEV; + } + + return 0; +} + +static void uniwill_init(void) +{ + union uw_ec_write_return reg_write_return; + + // Enable manual mode + uw_ec_write_addr(0x41, 0x07, 0x01, 0x00, ®_write_return); + + // Zero second fan temp for detection + uw_ec_write_addr(0x4f, 0x04, 0x00, 0x00, ®_write_return); +} + +static void uniwill_exit(void) +{ + union uw_ec_write_return reg_write_return; + + // Disable manual mode + uw_ec_write_addr(0x41, 0x07, 0x00, 0x00, ®_write_return); +} diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c new file mode 100644 index 0000000..c83cba6 --- /dev/null +++ b/src/tuxedo_io/tuxedo_io.c @@ -0,0 +1,351 @@ +/*! + * Copyright (c) 2019-2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-cc-wmi. + * + * tuxedo-cc-wmi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. If not, see . + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../clevo_interfaces.h" +#include "tongfang_wmi.h" +#include "tuxedo_io_ioctl.h" + +MODULE_DESCRIPTION("Hardware interface for TUXEDO laptops"); +MODULE_AUTHOR("TUXEDO Computers GmbH "); +MODULE_VERSION("0.1.7"); +MODULE_LICENSE("GPL"); + +MODULE_ALIAS_CLEVO_INTERFACES(); +MODULE_ALIAS("wmi:" CLEVO_WMI_METHOD_GUID); +MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BA); +MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BB); +MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BC); + +// Initialized in module init, global for ioctl interface +static u32 id_check_clevo; +static u32 id_check_uniwill; + +static u32 clevo_identify(void) +{ + return clevo_get_active_interface_id(&dummy) == 0 ? 1 : 0; +} + +/*static int fop_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int fop_release(struct inode *inode, struct file *file) +{ + return 0; +}*/ + +static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned long arg) +{ + u32 result = 0, status; + u32 copy_result; + u32 argument = (u32) arg; + + switch (cmd) { + case R_FANINFO1: + status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO1, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + case R_FANINFO2: + status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO2, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + case R_FANINFO3: + status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO3, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + /*case R_FANINFO4: + status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO4, 0); + copy_to_user((int32_t *) arg, &result, sizeof(result)); + break;*/ + case R_WEBCAM_SW: + status = clevo_evaluate_method(CLEVO_CMD_GET_WEBCAM_SW, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + case R_FLIGHTMODE_SW: + status = clevo_evaluate_method(CLEVO_CMD_GET_FLIGHTMODE_SW, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + case R_TOUCHPAD_SW: + status = clevo_evaluate_method(CLEVO_CMD_GET_TOUCHPAD_SW, 0, &result); + copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); + break; + } + + switch (cmd) { + case W_FANSPEED: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + clevo_evaluate_method(CLEVO_CMD_SET_FANSPEED_VALUE, argument, &result); + // Note: Delay needed to let hardware catch up with the written value. + // No known ready flag. If the value is read too soon, the old value + // will still be read out. + // (Theoretically needed for other methods as well.) + // Can it be lower? 50ms is too low + msleep(100); + break; + case W_FANAUTO: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + clevo_evaluate_method(CLEVO_CMD_SET_FANSPEED_AUTO, argument, &result); + break; + case W_WEBCAM_SW: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + status = clevo_evaluate_method(CLEVO_CMD_GET_WEBCAM_SW, 0, &result); + // Only set status if it isn't already the right value + // (workaround for old and/or buggy WMI interfaces that toggle on write) + if ((argument & 0x01) != (result & 0x01)) { + clevo_evaluate_method(CLEVO_CMD_SET_WEBCAM_SW, argument, &result); + } + break; + case W_FLIGHTMODE_SW: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + clevo_evaluate_method(CLEVO_CMD_SET_FLIGHTMODE_SW, argument, &result); + break; + case W_TOUCHPAD_SW: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + clevo_evaluate_method(CLEVO_CMD_SET_TOUCHPAD_SW, argument, &result); + break; + } + + return 0; +} + +static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigned long arg) +{ + u32 result = 0; + u32 copy_result; + u32 argument; + union uw_ec_read_return reg_read_return; + union uw_ec_write_return reg_write_return; + +#ifdef DEBUG + u32 uw_arg[10]; + u32 uw_result[10]; + int i; + for (i = 0; i < 10; ++i) { + uw_result[i] = 0xdeadbeef; + } +#endif + + switch (cmd) { + case R_UW_FANSPEED: + uw_ec_read_addr(0x04, 0x18, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_FANSPEED2: + uw_ec_read_addr(0x09, 0x18, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_FAN_TEMP: + uw_ec_read_addr(0x3e, 0x04, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_FAN_TEMP2: + uw_ec_read_addr(0x4f, 0x04, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_MODE: + uw_ec_read_addr(0x51, 0x07, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; + case R_UW_MODE_ENABLE: + uw_ec_read_addr(0x41, 0x07, ®_read_return); + result = reg_read_return.bytes.data_low; + copy_result = copy_to_user((void *) arg, &result, sizeof(result)); + break; +#ifdef DEBUG + case R_TF_BC: + copy_result = copy_from_user(&uw_arg, (void *) arg, sizeof(uw_arg)); + pr_info("R_TF_BC args [%0#2x, %0#2x, %0#2x, %0#2x]\n", uw_arg[0], uw_arg[1], uw_arg[2], uw_arg[3]); + if (uniwill_ec_direct) { + result = uw_ec_read_addr_direct(uw_arg[0], uw_arg[1], ®_read_return); + copy_result = copy_to_user((void *) arg, ®_read_return.dword, sizeof(reg_read_return.dword)); + } else { + result = uw_wmi_ec_evaluate(uw_arg[0], uw_arg[1], uw_arg[2], uw_arg[3], 1, uw_result); + copy_result = copy_to_user((void *) arg, &uw_result, sizeof(uw_result)); + } + break; +#endif + } + + switch (cmd) { + case W_UW_FANSPEED: + // Get fan speed argument + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + + // Check current mode + uw_ec_read_addr(0x51, 0x07, ®_read_return); + if (reg_read_return.bytes.data_low != 0x40) { + // If not "full fan mode" (ie. 0x40) switch to it (required for fancontrol) + uw_ec_write_addr(0x51, 0x07, 0x40, 0x00, ®_write_return); + } + // Set speed + uw_ec_write_addr(0x04, 0x18, argument & 0xff, 0x00, ®_write_return); + break; + case W_UW_FANSPEED2: + // Get fan speed argument + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + + // Check current mode + uw_ec_read_addr(0x51, 0x07, ®_read_return); + if (reg_read_return.bytes.data_low != 0x40) { + // If not "full fan mode" (ie. 0x40) switch to it (required for fancontrol) + uw_ec_write_addr(0x51, 0x07, 0x40, 0x00, ®_write_return); + } + // Set speed + uw_ec_write_addr(0x09, 0x18, argument & 0xff, 0x00, ®_write_return); + break; + case W_UW_MODE: + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + uw_ec_write_addr(0x51, 0x07, argument & 0xff, 0x00, ®_write_return); + break; + case W_UW_MODE_ENABLE: + // Note: Is for the moment set and cleared on init/exit of module (uniwill mode) + /* + copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); + uw_ec_write_addr(0x41, 0x07, argument & 0x01, 0x00, ®_write_return); + */ + break; +#ifdef DEBUG + case W_TF_BC: + copy_result = copy_from_user(&uw_arg, (void *) arg, sizeof(uw_arg)); + if (uniwill_ec_direct) { + result = uw_ec_write_addr_direct(uw_arg[0], uw_arg[1], uw_arg[2], uw_arg[3], ®_write_return); + copy_result = copy_to_user((void *) arg, ®_write_return.dword, sizeof(reg_write_return.dword)); + } else { + result = uw_wmi_ec_evaluate(uw_arg[0], uw_arg[1], uw_arg[2], uw_arg[3], 0, uw_result); + copy_result = copy_to_user((void *) arg, &uw_result, sizeof(uw_result)); + reg_write_return.dword = uw_result[0]; + } + /*pr_info("data_high %0#2x\n", reg_write_return.bytes.data_high); + pr_info("data_low %0#2x\n", reg_write_return.bytes.data_low); + pr_info("addr_high %0#2x\n", reg_write_return.bytes.addr_high); + pr_info("addr_low %0#2x\n", reg_write_return.bytes.addr_low);*/ + break; +#endif + } + + return 0; +} + +static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + u32 status; + // u32 result = 0; + u32 copy_result; + + const char *module_version = THIS_MODULE->version; + switch (cmd) { + case R_MOD_VERSION: + copy_result = copy_to_user((char *) arg, module_version, strlen(module_version) + 1); + break; + // Hardware id checks, 1 = positive, 0 = negative + case R_HWCHECK_CL: + id_check_clevo = clevo_identify(); + copy_result = copy_to_user((void *) arg, (void *) &id_check_clevo, sizeof(id_check_clevo)); + break; + case R_HWCHECK_UW: + copy_result = copy_to_user((void *) arg, (void *) &id_check_uniwill, sizeof(id_check_uniwill)); + break; + } + + status = clevo_ioctl_interface(file, cmd, arg); + if (status != 0) return status; + status = uniwill_ioctl_interface(file, cmd, arg); + if (status != 0) return status; + + return 0; +} + +static struct file_operations fops_dev = { + .owner = THIS_MODULE, + .unlocked_ioctl = fop_ioctl +// .open = fop_open, +// .release = fop_release +}; + +struct class *tuxedo_io_device_class; +dev_t tuxedo_io_device_handle; + +static struct cdev tuxedo_io_cdev; + +static int __init tuxedo_io_init(void) +{ + int err; + + // Hardware identification + id_check_clevo = clevo_identify(); + id_check_uniwill = uniwill_identify() == 0 ? 1 : 0; + + if (id_check_uniwill == 1) { + uniwill_init(); + } + +#ifdef DEBUG + if (id_check_clevo == 0 && id_check_uniwill == 0) { + pr_debug("No matching hardware found\n"); + } +#endif + + err = alloc_chrdev_region(&tuxedo_io_device_handle, 0, 1, "tuxedo_io_cdev"); + if (err != 0) { + pr_err("Failed to allocate chrdev region\n"); + return err; + } + cdev_init(&tuxedo_io_cdev, &fops_dev); + err = (cdev_add(&tuxedo_io_cdev, tuxedo_io_device_handle, 1)); + if (err < 0) { + pr_err("Failed to add cdev\n"); + unregister_chrdev_region(tuxedo_io_device_handle, 1); + } + tuxedo_io_device_class = class_create(THIS_MODULE, "tuxedo_io"); + device_create(tuxedo_io_device_class, NULL, tuxedo_io_device_handle, NULL, "tuxedo_io"); + pr_debug("Module init successful\n"); + + return 0; +} + +static void __exit tuxedo_io_exit(void) +{ + if (id_check_uniwill == 1) { + uniwill_exit(); + } + + device_destroy(tuxedo_io_device_class, tuxedo_io_device_handle); + class_destroy(tuxedo_io_device_class); + cdev_del(&tuxedo_io_cdev); + unregister_chrdev_region(tuxedo_io_device_handle, 1); + pr_debug("Module exit\n"); +} + +module_init(tuxedo_io_init); +module_exit(tuxedo_io_exit); diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h new file mode 100644 index 0000000..c97b228 --- /dev/null +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -0,0 +1,86 @@ +/*! + * Copyright (c) 2019-2020 TUXEDO Computers GmbH + * + * This file is part of tuxedo-cc-wmi. + * + * tuxedo-cc-wmi is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. If not, see . + */ +#ifndef TUXEDO_IO_IOCTL_H +#define TUXEDO_IO_IOCTL_H + +#define IOCTL_MAGIC 0xEC + +#define MAGIC_READ_CL IOCTL_MAGIC +#define MAGIC_WRITE_CL IOCTL_MAGIC + 1 + +#define MAGIC_READ_UW IOCTL_MAGIC + 2 +#define MAGIC_WRITE_UW IOCTL_MAGIC + 3 + + +// General +#define R_MOD_VERSION _IOR(IOCTL_MAGIC, 0x00, char*) + +#define R_HWCHECK_CL _IOR(IOCTL_MAGIC, 0x05, char*) +#define R_HWCHECK_UW _IOR(IOCTL_MAGIC, 0x06, char*) + +/** + * Clevo interface + */ + +// Read +#define R_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) +#define R_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) +#define R_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) +// #define R_FANINFO4 _IOR(MAGIC_READ_CL, 0x04, int32_t*) + +#define R_WEBCAM_SW _IOR(MAGIC_READ_CL, 0x13, int32_t*) +#define R_FLIGHTMODE_SW _IOR(MAGIC_READ_CL, 0x14, int32_t*) +#define R_TOUCHPAD_SW _IOR(MAGIC_READ_CL, 0x15, int32_t*) + +#ifdef DEBUG +#define R_TF_BC _IOW(MAGIC_READ_CL, 0x91, uint32_t*) +#endif + +// Write +#define W_FANSPEED _IOW(MAGIC_WRITE_CL, 0x10, int32_t*) +#define W_FANAUTO _IOW(MAGIC_WRITE_CL, 0x11, int32_t*) + +#define W_WEBCAM_SW _IOW(MAGIC_WRITE_CL, 0x12, int32_t*) +#define W_FLIGHTMODE_SW _IOW(MAGIC_WRITE_CL, 0x13, int32_t*) +#define W_TOUCHPAD_SW _IOW(MAGIC_WRITE_CL, 0x14, int32_t*) + +#ifdef DEBUG +#define W_TF_BC _IOW(MAGIC_WRITE_CL, 0x91, uint32_t*) +#endif + +/** + * Uniwill interface + */ + +// Read +#define R_UW_FANSPEED _IOR(MAGIC_READ_UW, 0x10, int32_t*) +#define R_UW_FANSPEED2 _IOR(MAGIC_READ_UW, 0x11, int32_t*) +#define R_UW_FAN_TEMP _IOR(MAGIC_READ_UW, 0x12, int32_t*) +#define R_UW_FAN_TEMP2 _IOR(MAGIC_READ_UW, 0x13, int32_t*) + +#define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) +#define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) + +// Write +#define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) +#define W_UW_FANSPEED2 _IOW(MAGIC_WRITE_UW, 0x11, int32_t*) +#define W_UW_MODE _IOW(MAGIC_WRITE_UW, 0x12, int32_t*) +#define W_UW_MODE_ENABLE _IOW(MAGIC_WRITE_UW, 0x13, int32_t*) + +#endif From a8230d47f6e0fd60cfc75e0b16f8f1f5a9b73765 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 7 Dec 2020 16:58:05 +0100 Subject: [PATCH 18/26] packaging: Add module restart/install logic - For clevo interfaces - For tuxedo_io from tuxedo_cc_wmi --- deb/module-name/DEBIAN/control | 4 +- deb/module-name/DEBIAN/postinst | 82 ++++++++++++++++++++++----------- src_pkg/rpm_pkg.spec | 36 ++++++++++++++- 3 files changed, 91 insertions(+), 31 deletions(-) diff --git a/deb/module-name/DEBIAN/control b/deb/module-name/DEBIAN/control index 8b66a0c..a819e20 100644 --- a/deb/module-name/DEBIAN/control +++ b/deb/module-name/DEBIAN/control @@ -3,8 +3,8 @@ Version: x.x.x Section: admin Priority: optional Depends: dkms (>= 1.95) -Conflicts: tuxedo-keyboard-dkms (<= 2.0.0), tuxedo-wmi-dkms (<= 1.5.1), tuxedo-xp-xc-touchpad-key-fix, tuxedo-touchpad-fix (<= 1.0.8), tuxedo-xp-xc-airplane-mode-fix (<= 0.6) -Replaces: tuxedo-keyboard-dkms (<= 2.0.0), tuxedo-wmi-dkms (<= 1.5.1), tuxedo-xp-xc-touchpad-key-fix, tuxedo-touchpad-fix (<= 1.0.8), tuxedo-xp-xc-airplane-mode-fix (<= 0.6) +Conflicts: tuxedo-keyboard-dkms (<= 2.0.0), tuxedo-wmi-dkms (<= 1.5.1), tuxedo-xp-xc-touchpad-key-fix, tuxedo-touchpad-fix (<= 1.0.8), tuxedo-xp-xc-airplane-mode-fix (<= 0.6), tuxedo-cc-wmi +Replaces: tuxedo-keyboard-dkms (<= 2.0.0), tuxedo-wmi-dkms (<= 1.5.1), tuxedo-xp-xc-touchpad-key-fix, tuxedo-touchpad-fix (<= 1.0.8), tuxedo-xp-xc-airplane-mode-fix (<= 0.6), tuxedo-cc-wmi Maintainer: TUXEDO Computers GmbH Homepage: https://www.tuxedocomputers.com Architecture: all diff --git a/deb/module-name/DEBIAN/postinst b/deb/module-name/DEBIAN/postinst index d943585..8f1fe6b 100755 --- a/deb/module-name/DEBIAN/postinst +++ b/deb/module-name/DEBIAN/postinst @@ -20,45 +20,73 @@ CVERSION=`dpkg-query -W -f='${Version}' $DEB_NAME | awk -F "-" '{print $1}' | cu ARCH=`dpkg --print-architecture` dkms_configure () { - for POSTINST in /usr/lib/dkms/common.postinst "/usr/share/$PACKAGE_NAME/postinst"; do - if [ -f "$POSTINST" ]; then - "$POSTINST" "$NAME" "$CVERSION" "/usr/share/$PACKAGE_NAME" "$ARCH" "$2" - return $? - fi - echo "WARNING: $POSTINST does not exist." >&2 - done - echo "ERROR: DKMS version is too old and $PACKAGE_NAME was not" >&2 - echo "built with legacy DKMS support." >&2 - echo "You must either rebuild $PACKAGE_NAME with legacy postinst" >&2 - echo "support or upgrade DKMS to a more current version." >&2 - return 1 + for POSTINST in /usr/lib/dkms/common.postinst "/usr/share/$PACKAGE_NAME/postinst"; do + if [ -f "$POSTINST" ]; then + "$POSTINST" "$NAME" "$CVERSION" "/usr/share/$PACKAGE_NAME" "$ARCH" "$2" + return $? + fi + echo "WARNING: $POSTINST does not exist." >&2 + done + echo "ERROR: DKMS version is too old and $PACKAGE_NAME was not" >&2 + echo "built with legacy DKMS support." >&2 + echo "You must either rebuild $PACKAGE_NAME with legacy postinst" >&2 + echo "support or upgrade DKMS to a more current version." >&2 + return 1 } # End dkms standard postinst case "$1" in configure) - # Run standard dkms build/install for all kernels with headers installed + # Run standard dkms build/install for all kernels with headers installed dkms_configure - # Attempt to (re-)load module immediately, fail silently if not possible at this stage - rmmod ${module} > /dev/null 2>&1 || true - modprobe ${module} > /dev/null 2>&1 || true + # Attempt to (re-)load module immediately, fail silently if not possible at this stage - # Install default config if none exist already - if [ ! -f "/etc/modprobe.d/tuxedo_keyboard.conf" ]; then - cp -f /usr/share/tuxedo-keyboard/tuxedo_keyboard.conf /etc/modprobe.d/tuxedo_keyboard.conf - fi + # Also stop tccd service if running before + echo "Check tccd running status" + if systemctl is-active --quiet tccd.service; then + TCCD_RUNNING=true + else + TCCD_RUNNING=false + fi - ;; + if $TCCD_RUNNING; then + echo "Stop tccd temporarily" + systemctl stop tccd 2>&1 || true + fi - abort-upgrade|abort-remove|abort-deconfigure) - ;; + echo "(Re)load modules if possible" + rmmod tuxedo_io > /dev/null 2>&1 || true + rmmod clevo_wmi > /dev/null 2>&1 || true + rmmod clevo_acpi > /dev/null 2>&1 || true + rmmod tuxedo_keyboard > /dev/null 2>&1 || true + + modprobe tuxedo_keyboard > /dev/null 2>&1 || true + modprobe clevo_wmi > /dev/null 2>&1 || true + modprobe clevo_acpi > /dev/null 2>&1 || true + modprobe tuxedo_io > /dev/null 2>&1 || true - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; + # Restart tccd after reload if it was running + if $TCCD_RUNNING; then + echo "Start tccd again" + systemctl start tccd 2>&1 || true + fi + + # Install default config if none exist already + if [ ! -f "/etc/modprobe.d/tuxedo_keyboard.conf" ]; then + cp -f /usr/share/tuxedo-keyboard/tuxedo_keyboard.conf /etc/modprobe.d/tuxedo_keyboard.conf + fi + + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; esac exit 0 diff --git a/src_pkg/rpm_pkg.spec b/src_pkg/rpm_pkg.spec index c365dac..8559855 100644 --- a/src_pkg/rpm_pkg.spec +++ b/src_pkg/rpm_pkg.spec @@ -31,6 +31,7 @@ Provides: tuxedo_keyboard = %{version}-%{release} Obsoletes: tuxedo_keyboard < %{version}-%{release} Obsoletes: tuxedo-xp-xc-touchpad-key-fix Obsoletes: tuxedo-touchpad-fix <= 1.0.1 +Obsoletes: tuxedo-cc-wmi Requires: dkms >= 1.95 BuildRoot: %{_tmppath} Packager: Tomte @@ -71,14 +72,45 @@ for POSTINST in /usr/lib/dkms/common.postinst /usr/share/%{module}/postinst; do if [ -f $POSTINST ]; then $POSTINST %{module} %{version} /usr/share/%{module} RET=$? - rmmod %{module} > /dev/null 2>&1 || true - modprobe %{module} > /dev/null 2>&1 || true + + # Attempt to (re-)load module immediately, fail silently if not possible at this stage + + # Also stop tccd service if running before + echo "Check tccd running status" + if systemctl is-active --quiet tccd.service; then + TCCD_RUNNING=true + else + TCCD_RUNNING=false + fi + + if $TCCD_RUNNING; then + echo "Stop tccd temporarily" + systemctl stop tccd 2>&1 || true + fi + + echo "(Re)load modules if possible" + + rmmod tuxedo_io > /dev/null 2>&1 || true + rmmod clevo_wmi > /dev/null 2>&1 || true + rmmod clevo_acpi > /dev/null 2>&1 || true + rmmod tuxedo_keyboard > /dev/null 2>&1 || true + + modprobe tuxedo_keyboard > /dev/null 2>&1 || true + modprobe clevo_wmi > /dev/null 2>&1 || true + modprobe clevo_acpi > /dev/null 2>&1 || true + modprobe tuxedo_io > /dev/null 2>&1 || true # Install default config if none exist already if [ ! -f "/etc/modprobe.d/tuxedo_keyboard.conf" ]; then cp -f /usr/share/tuxedo-keyboard/tuxedo_keyboard.conf /etc/modprobe.d/tuxedo_keyboard.conf fi + # Restart tccd after reload if it was running + if $TCCD_RUNNING; then + echo "Start tccd again" + systemctl start tccd 2>&1 || true + fi + exit $RET fi echo "WARNING: $POSTINST does not exist." From 15cb908351f3358b25cdd5e834f75835801a0092 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 09:30:27 +0100 Subject: [PATCH 19/26] tuxedo_io: Fix build, remove leftover dummy variable --- src/tuxedo_io/tuxedo_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index c83cba6..4bd84bc 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -47,7 +47,7 @@ static u32 id_check_uniwill; static u32 clevo_identify(void) { - return clevo_get_active_interface_id(&dummy) == 0 ? 1 : 0; + return clevo_get_active_interface_id(NULL) == 0 ? 1 : 0; } /*static int fop_open(struct inode *inode, struct file *file) From 4aa71e4ef0951b5d919a5f517337abd0d809d867 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 10:25:06 +0100 Subject: [PATCH 20/26] clevo_keyboard: Remove non-error "error" output --- src/clevo_keyboard.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index 158a41a..11aec25 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -299,10 +299,8 @@ EXPORT_SYMBOL(clevo_evaluate_method); u32 clevo_get_active_interface_id(char **id_str) { - if (IS_ERR_OR_NULL(active_clevo_interface)) { - pr_err("clevo_keyboard: no active interface\n"); + if (IS_ERR_OR_NULL(active_clevo_interface)) return -ENODEV; - } if (!IS_ERR_OR_NULL(id_str)) *id_str = active_clevo_interface->string_id; From 3100646b69177df835fb0d32bf5efef812d608c1 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 10:46:11 +0100 Subject: [PATCH 21/26] packaging: Fix: explicitly unload old tuxedo_cc_wmi at rpm install --- src_pkg/rpm_pkg.spec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src_pkg/rpm_pkg.spec b/src_pkg/rpm_pkg.spec index 8559855..e3487e7 100644 --- a/src_pkg/rpm_pkg.spec +++ b/src_pkg/rpm_pkg.spec @@ -88,6 +88,9 @@ for POSTINST in /usr/lib/dkms/common.postinst /usr/share/%{module}/postinst; do systemctl stop tccd 2>&1 || true fi + % Explicitly unload old tuxedo_cc_wmi if loaded at this point + rmmod tuxedo_cc_wmi > /dev/null 2>&1 || true + echo "(Re)load modules if possible" rmmod tuxedo_io > /dev/null 2>&1 || true From 423e515121c2e8f93773e70ed1597a738b4f03fd Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 10:51:45 +0100 Subject: [PATCH 22/26] Increase module versions --- src/tuxedo_io/tuxedo_io.c | 2 +- src/tuxedo_keyboard.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 4bd84bc..d03befe 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -32,7 +32,7 @@ MODULE_DESCRIPTION("Hardware interface for TUXEDO laptops"); MODULE_AUTHOR("TUXEDO Computers GmbH "); -MODULE_VERSION("0.1.7"); +MODULE_VERSION("0.2.0"); MODULE_LICENSE("GPL"); MODULE_ALIAS_CLEVO_INTERFACES(); diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index 323e674..285f291 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -27,7 +27,7 @@ MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("TUXEDO Computers keyboard & keyboard backlight Driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("2.1.0"); +MODULE_VERSION("3.0.0"); MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_0); MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_1); From 95a8097b0fb998d4f8a6dc03e01054f691e9b48f Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 11:46:13 +0100 Subject: [PATCH 23/26] clevo_interfaces: Minor text clean-ups --- src/clevo_acpi.c | 2 +- src/clevo_wmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index b278298..b187e34 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -127,7 +127,7 @@ static int clevo_acpi_add(struct acpi_device *device) // Add this interface clevo_keyboard_add_interface(&clevo_acpi_interface); - pr_info("clevo_acpi: interface initialized\n"); + pr_info("interface initialized\n"); return 0; } diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index a229915..46b5604 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -114,7 +114,7 @@ static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) // Add this interface clevo_keyboard_add_interface(&clevo_wmi_interface); - pr_info("clevo_wmi: interface initialized\n"); + pr_info("interface initialized\n"); return 0; } From 51741558ed72b77ee3db61471273c49bcb513ca9 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 15:48:18 +0100 Subject: [PATCH 24/26] tuxedo_io: Add clevo interface string read ioctl --- src/tuxedo_io/tuxedo_io.c | 10 ++++++++++ src/tuxedo_io/tuxedo_io_ioctl.h | 17 +++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index d03befe..11d7ab1 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -65,8 +65,18 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned u32 result = 0, status; u32 copy_result; u32 argument = (u32) arg; + + const char str_no_if[] = ""; + char *str_clevo_if; switch (cmd) { + case R_HW_IF_STR: + if (clevo_get_active_interface_id(&str_clevo_if) == 0) { + copy_result = copy_to_user((char *) arg, str_clevo_if, strlen(str_clevo_if) + 1); + } else { + copy_result = copy_to_user((char *) arg, str_no_if, strlen(str_no_if) + 1); + } + break; case R_FANINFO1: status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO1, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index c97b228..22ab9d2 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -1,9 +1,9 @@ /*! * Copyright (c) 2019-2020 TUXEDO Computers GmbH * - * This file is part of tuxedo-cc-wmi. + * This file is part of tuxedo-io. * - * tuxedo-cc-wmi is free software: you can redistribute it and/or modify + * tuxedo-io is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -21,24 +21,25 @@ #define IOCTL_MAGIC 0xEC -#define MAGIC_READ_CL IOCTL_MAGIC -#define MAGIC_WRITE_CL IOCTL_MAGIC + 1 +#define MAGIC_READ_CL IOCTL_MAGIC + 1 +#define MAGIC_WRITE_CL IOCTL_MAGIC + 2 -#define MAGIC_READ_UW IOCTL_MAGIC + 2 -#define MAGIC_WRITE_UW IOCTL_MAGIC + 3 +#define MAGIC_READ_UW IOCTL_MAGIC + 3 +#define MAGIC_WRITE_UW IOCTL_MAGIC + 4 // General #define R_MOD_VERSION _IOR(IOCTL_MAGIC, 0x00, char*) -#define R_HWCHECK_CL _IOR(IOCTL_MAGIC, 0x05, char*) -#define R_HWCHECK_UW _IOR(IOCTL_MAGIC, 0x06, char*) +#define R_HWCHECK_CL _IOR(IOCTL_MAGIC, 0x05, int32_t*) +#define R_HWCHECK_UW _IOR(IOCTL_MAGIC, 0x06, int32_t*) /** * Clevo interface */ // Read +#define R_HW_IF_STR _IOR(MAGIC_READ_CL, 0x00, char*) #define R_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) #define R_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) #define R_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) From 2c32684ee85e6dd3dee44dfef10d566ea9d7a5dc Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 15:50:25 +0100 Subject: [PATCH 25/26] tuxedo_io: Prefix the clevo ioctls with CL for clarity --- src/tuxedo_io/tuxedo_io.c | 26 +++++++++++++------------- src/tuxedo_io/tuxedo_io_ioctl.h | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 11d7ab1..068466a 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -70,45 +70,45 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned char *str_clevo_if; switch (cmd) { - case R_HW_IF_STR: + case R_CL_HW_IF_STR: if (clevo_get_active_interface_id(&str_clevo_if) == 0) { copy_result = copy_to_user((char *) arg, str_clevo_if, strlen(str_clevo_if) + 1); } else { copy_result = copy_to_user((char *) arg, str_no_if, strlen(str_no_if) + 1); } break; - case R_FANINFO1: + case R_CL_FANINFO1: status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO1, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; - case R_FANINFO2: + case R_CL_FANINFO2: status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO2, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; - case R_FANINFO3: + case R_CL_FANINFO3: status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO3, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; - /*case R_FANINFO4: + /*case R_CL_FANINFO4: status = clevo_evaluate_method(CLEVO_CMD_GET_FANINFO4, 0); copy_to_user((int32_t *) arg, &result, sizeof(result)); break;*/ - case R_WEBCAM_SW: + case R_CL_WEBCAM_SW: status = clevo_evaluate_method(CLEVO_CMD_GET_WEBCAM_SW, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; - case R_FLIGHTMODE_SW: + case R_CL_FLIGHTMODE_SW: status = clevo_evaluate_method(CLEVO_CMD_GET_FLIGHTMODE_SW, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; - case R_TOUCHPAD_SW: + case R_CL_TOUCHPAD_SW: status = clevo_evaluate_method(CLEVO_CMD_GET_TOUCHPAD_SW, 0, &result); copy_result = copy_to_user((int32_t *) arg, &result, sizeof(result)); break; } switch (cmd) { - case W_FANSPEED: + case W_CL_FANSPEED: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); clevo_evaluate_method(CLEVO_CMD_SET_FANSPEED_VALUE, argument, &result); // Note: Delay needed to let hardware catch up with the written value. @@ -118,11 +118,11 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned // Can it be lower? 50ms is too low msleep(100); break; - case W_FANAUTO: + case W_CL_FANAUTO: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); clevo_evaluate_method(CLEVO_CMD_SET_FANSPEED_AUTO, argument, &result); break; - case W_WEBCAM_SW: + case W_CL_WEBCAM_SW: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); status = clevo_evaluate_method(CLEVO_CMD_GET_WEBCAM_SW, 0, &result); // Only set status if it isn't already the right value @@ -131,11 +131,11 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned clevo_evaluate_method(CLEVO_CMD_SET_WEBCAM_SW, argument, &result); } break; - case W_FLIGHTMODE_SW: + case W_CL_FLIGHTMODE_SW: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); clevo_evaluate_method(CLEVO_CMD_SET_FLIGHTMODE_SW, argument, &result); break; - case W_TOUCHPAD_SW: + case W_CL_TOUCHPAD_SW: copy_result = copy_from_user(&argument, (int32_t *) arg, sizeof(argument)); clevo_evaluate_method(CLEVO_CMD_SET_TOUCHPAD_SW, argument, &result); break; diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index 22ab9d2..e907be1 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -39,27 +39,27 @@ */ // Read -#define R_HW_IF_STR _IOR(MAGIC_READ_CL, 0x00, char*) -#define R_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) -#define R_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) -#define R_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) +#define R_CL_HW_IF_STR _IOR(MAGIC_READ_CL, 0x00, char*) +#define R_CL_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) +#define R_CL_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) +#define R_CL_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) // #define R_FANINFO4 _IOR(MAGIC_READ_CL, 0x04, int32_t*) -#define R_WEBCAM_SW _IOR(MAGIC_READ_CL, 0x13, int32_t*) -#define R_FLIGHTMODE_SW _IOR(MAGIC_READ_CL, 0x14, int32_t*) -#define R_TOUCHPAD_SW _IOR(MAGIC_READ_CL, 0x15, int32_t*) +#define R_CL_WEBCAM_SW _IOR(MAGIC_READ_CL, 0x13, int32_t*) +#define R_CL_FLIGHTMODE_SW _IOR(MAGIC_READ_CL, 0x14, int32_t*) +#define R_CL_TOUCHPAD_SW _IOR(MAGIC_READ_CL, 0x15, int32_t*) #ifdef DEBUG #define R_TF_BC _IOW(MAGIC_READ_CL, 0x91, uint32_t*) #endif // Write -#define W_FANSPEED _IOW(MAGIC_WRITE_CL, 0x10, int32_t*) -#define W_FANAUTO _IOW(MAGIC_WRITE_CL, 0x11, int32_t*) +#define W_CL_FANSPEED _IOW(MAGIC_WRITE_CL, 0x10, int32_t*) +#define W_CL_FANAUTO _IOW(MAGIC_WRITE_CL, 0x11, int32_t*) -#define W_WEBCAM_SW _IOW(MAGIC_WRITE_CL, 0x12, int32_t*) -#define W_FLIGHTMODE_SW _IOW(MAGIC_WRITE_CL, 0x13, int32_t*) -#define W_TOUCHPAD_SW _IOW(MAGIC_WRITE_CL, 0x14, int32_t*) +#define W_CL_WEBCAM_SW _IOW(MAGIC_WRITE_CL, 0x12, int32_t*) +#define W_CL_FLIGHTMODE_SW _IOW(MAGIC_WRITE_CL, 0x13, int32_t*) +#define W_CL_TOUCHPAD_SW _IOW(MAGIC_WRITE_CL, 0x14, int32_t*) #ifdef DEBUG #define W_TF_BC _IOW(MAGIC_WRITE_CL, 0x91, uint32_t*) From 4bbc290a8d300d1887096e5085d99d4ed60496fe Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 8 Dec 2020 15:54:51 +0100 Subject: [PATCH 26/26] tuxedo_io: Convert ioctl spaces to tabs for consistency --- src/tuxedo_io/tuxedo_io_ioctl.h | 64 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index e907be1..ccef035 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -21,48 +21,48 @@ #define IOCTL_MAGIC 0xEC -#define MAGIC_READ_CL IOCTL_MAGIC + 1 -#define MAGIC_WRITE_CL IOCTL_MAGIC + 2 +#define MAGIC_READ_CL IOCTL_MAGIC + 1 +#define MAGIC_WRITE_CL IOCTL_MAGIC + 2 -#define MAGIC_READ_UW IOCTL_MAGIC + 3 -#define MAGIC_WRITE_UW IOCTL_MAGIC + 4 +#define MAGIC_READ_UW IOCTL_MAGIC + 3 +#define MAGIC_WRITE_UW IOCTL_MAGIC + 4 // General -#define R_MOD_VERSION _IOR(IOCTL_MAGIC, 0x00, char*) +#define R_MOD_VERSION _IOR(IOCTL_MAGIC, 0x00, char*) -#define R_HWCHECK_CL _IOR(IOCTL_MAGIC, 0x05, int32_t*) -#define R_HWCHECK_UW _IOR(IOCTL_MAGIC, 0x06, int32_t*) +#define R_HWCHECK_CL _IOR(IOCTL_MAGIC, 0x05, int32_t*) +#define R_HWCHECK_UW _IOR(IOCTL_MAGIC, 0x06, int32_t*) /** * Clevo interface */ // Read -#define R_CL_HW_IF_STR _IOR(MAGIC_READ_CL, 0x00, char*) -#define R_CL_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) -#define R_CL_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) -#define R_CL_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) -// #define R_FANINFO4 _IOR(MAGIC_READ_CL, 0x04, int32_t*) +#define R_CL_HW_IF_STR _IOR(MAGIC_READ_CL, 0x00, char*) +#define R_CL_FANINFO1 _IOR(MAGIC_READ_CL, 0x10, int32_t*) +#define R_CL_FANINFO2 _IOR(MAGIC_READ_CL, 0x11, int32_t*) +#define R_CL_FANINFO3 _IOR(MAGIC_READ_CL, 0x12, int32_t*) +// #define R_FANINFO4 _IOR(MAGIC_READ_CL, 0x04, int32_t*) -#define R_CL_WEBCAM_SW _IOR(MAGIC_READ_CL, 0x13, int32_t*) -#define R_CL_FLIGHTMODE_SW _IOR(MAGIC_READ_CL, 0x14, int32_t*) -#define R_CL_TOUCHPAD_SW _IOR(MAGIC_READ_CL, 0x15, int32_t*) +#define R_CL_WEBCAM_SW _IOR(MAGIC_READ_CL, 0x13, int32_t*) +#define R_CL_FLIGHTMODE_SW _IOR(MAGIC_READ_CL, 0x14, int32_t*) +#define R_CL_TOUCHPAD_SW _IOR(MAGIC_READ_CL, 0x15, int32_t*) #ifdef DEBUG -#define R_TF_BC _IOW(MAGIC_READ_CL, 0x91, uint32_t*) +#define R_TF_BC _IOW(MAGIC_READ_CL, 0x91, uint32_t*) #endif // Write -#define W_CL_FANSPEED _IOW(MAGIC_WRITE_CL, 0x10, int32_t*) -#define W_CL_FANAUTO _IOW(MAGIC_WRITE_CL, 0x11, int32_t*) +#define W_CL_FANSPEED _IOW(MAGIC_WRITE_CL, 0x10, int32_t*) +#define W_CL_FANAUTO _IOW(MAGIC_WRITE_CL, 0x11, int32_t*) -#define W_CL_WEBCAM_SW _IOW(MAGIC_WRITE_CL, 0x12, int32_t*) -#define W_CL_FLIGHTMODE_SW _IOW(MAGIC_WRITE_CL, 0x13, int32_t*) -#define W_CL_TOUCHPAD_SW _IOW(MAGIC_WRITE_CL, 0x14, int32_t*) +#define W_CL_WEBCAM_SW _IOW(MAGIC_WRITE_CL, 0x12, int32_t*) +#define W_CL_FLIGHTMODE_SW _IOW(MAGIC_WRITE_CL, 0x13, int32_t*) +#define W_CL_TOUCHPAD_SW _IOW(MAGIC_WRITE_CL, 0x14, int32_t*) #ifdef DEBUG -#define W_TF_BC _IOW(MAGIC_WRITE_CL, 0x91, uint32_t*) +#define W_TF_BC _IOW(MAGIC_WRITE_CL, 0x91, uint32_t*) #endif /** @@ -70,18 +70,18 @@ */ // Read -#define R_UW_FANSPEED _IOR(MAGIC_READ_UW, 0x10, int32_t*) -#define R_UW_FANSPEED2 _IOR(MAGIC_READ_UW, 0x11, int32_t*) -#define R_UW_FAN_TEMP _IOR(MAGIC_READ_UW, 0x12, int32_t*) -#define R_UW_FAN_TEMP2 _IOR(MAGIC_READ_UW, 0x13, int32_t*) +#define R_UW_FANSPEED _IOR(MAGIC_READ_UW, 0x10, int32_t*) +#define R_UW_FANSPEED2 _IOR(MAGIC_READ_UW, 0x11, int32_t*) +#define R_UW_FAN_TEMP _IOR(MAGIC_READ_UW, 0x12, int32_t*) +#define R_UW_FAN_TEMP2 _IOR(MAGIC_READ_UW, 0x13, int32_t*) -#define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) -#define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) +#define R_UW_MODE _IOR(MAGIC_READ_UW, 0x14, int32_t*) +#define R_UW_MODE_ENABLE _IOR(MAGIC_READ_UW, 0x15, int32_t*) // Write -#define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) -#define W_UW_FANSPEED2 _IOW(MAGIC_WRITE_UW, 0x11, int32_t*) -#define W_UW_MODE _IOW(MAGIC_WRITE_UW, 0x12, int32_t*) -#define W_UW_MODE_ENABLE _IOW(MAGIC_WRITE_UW, 0x13, int32_t*) +#define W_UW_FANSPEED _IOW(MAGIC_WRITE_UW, 0x10, int32_t*) +#define W_UW_FANSPEED2 _IOW(MAGIC_WRITE_UW, 0x11, int32_t*) +#define W_UW_MODE _IOW(MAGIC_WRITE_UW, 0x12, int32_t*) +#define W_UW_MODE_ENABLE _IOW(MAGIC_WRITE_UW, 0x13, int32_t*) #endif