From 36372473514f47b20b97683503fa1e96b710bb1e Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 3 Sep 2021 22:07:13 +0200 Subject: [PATCH 01/23] Add basic uniwill-wmi module - Add separate uniwill-wmi module - Add uniwill interfaces header --- Makefile | 3 +- dkms.conf | 4 ++ src/uniwill_interfaces.h | 29 +++++++++++ src/uniwill_wmi.c | 110 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/uniwill_interfaces.h create mode 100644 src/uniwill_wmi.c diff --git a/Makefile b/Makefile index 8d031d9..c60cf4d 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,8 @@ obj-m := ./src/tuxedo_keyboard.o \ ./src/clevo_wmi.o \ ./src/clevo_acpi.o \ - ./src/tuxedo_io/tuxedo_io.o + ./src/tuxedo_io/tuxedo_io.o \ + ./src/uniwill_wmi.o PWD := $(shell pwd) KDIR := /lib/modules/$(shell uname -r)/build diff --git a/dkms.conf b/dkms.conf index 2d3424c..54db155 100644 --- a/dkms.conf +++ b/dkms.conf @@ -17,6 +17,10 @@ DEST_MODULE_LOCATION[3]="/kernel/lib/" BUILT_MODULE_NAME[3]="tuxedo_io" BUILT_MODULE_LOCATION[3]="src/tuxedo_io" +DEST_MODULE_LOCATION[4]="/kernel/lib/" +BUILT_MODULE_NAME[4]="uniwill_wmi" +BUILT_MODULE_LOCATION[4]="src/" + MAKE[0]="make KDIR=/lib/modules/${kernelver}/build" CLEAN="make clean" AUTOINSTALL="yes" diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h new file mode 100644 index 0000000..a167be9 --- /dev/null +++ b/src/uniwill_interfaces.h @@ -0,0 +1,29 @@ +/*! + * Copyright (c) 2021 TUXEDO Computers GmbH + * + * This file is part of tuxedo-keyboard. + * + * tuxedo-keyboard 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 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 MODULE_ALIAS_UNIWILL_WMI() \ + MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); \ + MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BC); diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c new file mode 100644 index 0000000..f3a839a --- /dev/null +++ b/src/uniwill_wmi.c @@ -0,0 +1,110 @@ +/*! + * Copyright (c) 2021 TUXEDO Computers GmbH + * + * This file is part of tuxedo-keyboard. + * + * tuxedo-keyboard 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 "uniwill_interfaces.h" + +/*u32 uniwill_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) +{ + return uniwill_wmi_evaluate(cmd, arg, result_value); +} + +struct uniwill_interface_t uniwill_wmi_interface = { + .string_id = "uniwill_wmi", + .method_call = uniwill_wmi_interface_method_call, +};*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) +static int uniwill_wmi_probe(struct wmi_device *wdev) +#else +static int uniwill_wmi_probe(struct wmi_device *wdev, const void *dummy_context) +#endif +{ + 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; + } + + // TODO: Add interface and init + + pr_info("interface initialized\n"); + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) +static int uniwill_wmi_remove(struct wmi_device *wdev) +#else +static void uniwill_wmi_remove(struct wmi_device *wdev) +#endif +{ + pr_debug("uniwill_wmi driver remove\n"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) + return 0; +#endif +} + +static void uniwill_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) +{ + //u32 event_value; + pr_debug("uniwill_wmi notify\n"); + /*if (!IS_ERR_OR_NULL(uniwill_wmi_interface.event_callb)) { + // Execute registered callback + // TODO + }*/ +} + +static const struct wmi_device_id uniwill_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 = UNIWILL_WMI_EVENT_GUID_2 }, + { } +}; + +static struct wmi_driver uniwill_wmi_driver = { + .driver = { .name = "uniwill_wmi", .owner = THIS_MODULE }, + .id_table = uniwill_wmi_device_ids, + .probe = uniwill_wmi_probe, + .remove = uniwill_wmi_remove, + .notify = uniwill_wmi_notify, +}; + +module_wmi_driver(uniwill_wmi_driver); + +MODULE_AUTHOR("TUXEDO Computers GmbH "); +MODULE_DESCRIPTION("Driver for Uniwill WMI interface"); +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(wmi, uniwill_wmi_device_ids); +MODULE_ALIAS_UNIWILL_WMI(); From 9db498b8368ba91bd17ad741cdf5c775c042a0d3 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 7 Sep 2021 19:47:31 +0200 Subject: [PATCH 02/23] Add/correct interface include guards --- src/clevo_interfaces.h | 4 ++-- src/uniwill_interfaces.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index f2fe0f1..1b384e6 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this software. If not, see . */ -#ifndef TUXEDO_INTERFACES_H -#define TUXEDO_INTERFACES_H +#ifndef CLEVO_INTERFACES_H +#define CLEVO_INTERFACES_H #include diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index a167be9..b2184bf 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with this software. If not, see . */ +#ifndef UNIWILL_INTERFACES_H +#define UNIWILL_INTERFACES_H + #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" @@ -27,3 +30,5 @@ #define MODULE_ALIAS_UNIWILL_WMI() \ MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); \ MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BC); + +#endif From 54c6da280e217be05f22e75e8b7bb2fe85ef50fe Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 7 Sep 2021 21:44:00 +0200 Subject: [PATCH 03/23] Add uniwill interface methods --- src/uniwill_interfaces.h | 20 +++++ src/uniwill_keyboard.h | 161 ++++++++++++++++++++++++++++----------- src/uniwill_wmi.c | 5 +- 3 files changed, 139 insertions(+), 47 deletions(-) diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index b2184bf..d222d52 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -19,6 +19,8 @@ #ifndef UNIWILL_INTERFACES_H #define UNIWILL_INTERFACES_H +#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" @@ -31,4 +33,22 @@ MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); \ MODULE_ALIAS("wmi:" UNIWILL_WMI_MGMT_GUID_BC); +#define UNIWILL_INTERFACE_WMI_STRID "uniwill_wmi" + +typedef u32 (uniwill_read_ec_ram_t)(u16, u8*); +typedef u32 (uniwill_write_ec_ram_t)(u16, u8); +typedef void (uniwill_event_callb_t)(u32); + +struct uniwill_interface_t { + char *string_id; + uniwill_event_callb_t *event_callb; + uniwill_read_ec_ram_t *read_ec_ram; + uniwill_write_ec_ram_t *write_ec_ram; +}; + +u32 uniwill_add_interface(struct uniwill_interface_t *new_interface); +u32 uniwill_remove_interface(struct uniwill_interface_t *interface); +uniwill_read_ec_ram_t uniwill_read_ec_ram; +uniwill_write_ec_ram_t uniwill_write_ec_ram; + #endif diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 39c04a0..1a25b79 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -1,5 +1,5 @@ /*! - * Copyright (c) 2020 TUXEDO Computers GmbH + * Copyright (c) 2020-2021 TUXEDO Computers GmbH * * This file is part of tuxedo-keyboard. * @@ -27,6 +27,7 @@ #include #include #include "uw_io.h" +#include "uniwill_interfaces.h" #define UNIWILL_WMI_MGMT_GUID_BA "ABBC0F6D-8EA1-11D1-00A0-C90629100000" #define UNIWILL_WMI_MGMT_GUID_BB "ABBC0F6E-8EA1-11D1-00A0-C90629100000" @@ -88,6 +89,69 @@ static struct key_entry uniwill_wmi_keymap[] = { { KE_END, 0 } }; +static struct uniwill_interfaces_t { + struct uniwill_interface_t *wmi; +} uniwill_interfaces; + +uniwill_event_callb_t uniwill_event_callb; + +u32 uniwill_read_ec_ram(u16 address, u8 *data) +{ + if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) + uniwill_interfaces.wmi->read_ec_ram(address, data); + else + return -EIO; + + return 0; +} +EXPORT_SYMBOL(uniwill_read_ec_ram); + +u32 uniwill_write_ec_ram(u16 address, u8 data) +{ + if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) + uniwill_interfaces.wmi->write_ec_ram(address, data); + else + return -EIO; + + return 0; +} +EXPORT_SYMBOL(uniwill_write_ec_ram); + +static DEFINE_MUTEX(uniwill_interface_modification_lock); + +u32 uniwill_add_interface(struct uniwill_interface_t *interface) +{ + mutex_lock(&uniwill_interface_modification_lock); + + if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID)) + uniwill_interfaces.wmi = interface; + else { + mutex_unlock(&uniwill_interface_modification_lock); + return -EINVAL; + + interface->event_callb = uniwill_event_callb; + + mutex_unlock(&uniwill_interface_modification_lock); + return 0; +} +EXPORT_SYMBOL(uniwill_add_interface); + +u32 uniwill_remove_interface(struct uniwill_interface_t *interface) +{ + mutex_lock(&uniwill_interface_modification_lock); + + if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID)) + uniwill_interfaces.wmi = NULL; + else { + mutex_unlock(&uniwill_interface_modification_lock); + return -EINVAL; + } + + mutex_unlock(&uniwill_interface_modification_lock); + return 0; +} +EXPORT_SYMBOL(uniwill_remove_interface); + static void key_event_work(struct work_struct *work) { sparse_keymap_report_known_event( @@ -228,6 +292,55 @@ static void uniwill_write_kbd_bl_reset(void) __uw_ec_write_addr(0x8c, 0x07, 0x10, 0x00, ®_write_return); } +void uniwill_event_callb(u32 code) +{ + if (!sparse_keymap_report_known_event(uniwill_keyboard_driver.input_device, code, 1, true)) { + TUXEDO_DEBUG("Unknown code - %d (%0#6x)\n", code, code); + } + + // Special key combination when mode change key is pressed + if (code == 0xb0) { + 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 + if (uniwill_kbd_bl_type_rgb_single_color) { + switch (code) { + case UNIWILL_OSD_KB_LED_LEVEL0: + kbd_led_state_uw.brightness = 0x00; + uniwill_write_kbd_bl_state(); + break; + case UNIWILL_OSD_KB_LED_LEVEL1: + kbd_led_state_uw.brightness = 0x20; + uniwill_write_kbd_bl_state(); + break; + case UNIWILL_OSD_KB_LED_LEVEL2: + kbd_led_state_uw.brightness = 0x50; + uniwill_write_kbd_bl_state(); + break; + case UNIWILL_OSD_KB_LED_LEVEL3: + kbd_led_state_uw.brightness = 0x80; + uniwill_write_kbd_bl_state(); + break; + case UNIWILL_OSD_KB_LED_LEVEL4: + kbd_led_state_uw.brightness = 0xc8; + uniwill_write_kbd_bl_state(); + break; + // Also refresh keyboard state on cable switch event + case UNIWILL_OSD_DC_ADAPTER_CHANGE: + uniwill_write_kbd_bl_state(); + break; + } + } +} + static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -246,51 +359,7 @@ 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(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(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 - if (uniwill_kbd_bl_type_rgb_single_color) { - switch (code) { - case UNIWILL_OSD_KB_LED_LEVEL0: - kbd_led_state_uw.brightness = 0x00; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL1: - kbd_led_state_uw.brightness = 0x20; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL2: - kbd_led_state_uw.brightness = 0x50; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL3: - kbd_led_state_uw.brightness = 0x80; - uniwill_write_kbd_bl_state(); - break; - case UNIWILL_OSD_KB_LED_LEVEL4: - kbd_led_state_uw.brightness = 0xc8; - uniwill_write_kbd_bl_state(); - break; - // Also refresh keyboard state on cable switch event - case UNIWILL_OSD_DC_ADAPTER_CHANGE: - uniwill_write_kbd_bl_state(); - break; - } - } + uniwill_event_callb(code); } else { TUXEDO_DEBUG("[Ev %d] Unknown event type - %d (%0#6x)\n", guid_nr, obj->type, obj->type); } diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index f3a839a..c775a07 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -92,7 +92,10 @@ static const struct wmi_device_id uniwill_wmi_device_ids[] = { }; static struct wmi_driver uniwill_wmi_driver = { - .driver = { .name = "uniwill_wmi", .owner = THIS_MODULE }, + .driver = { + .name = UNIWILL_INTERFACE_WMI_STRID, + .owner = THIS_MODULE + }, .id_table = uniwill_wmi_device_ids, .probe = uniwill_wmi_probe, .remove = uniwill_wmi_remove, From 13510d6fc21123b7a429e91caad502d2abe6c053 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 10 Sep 2021 00:15:10 +0200 Subject: [PATCH 04/23] Fix missing bracket --- src/uniwill_keyboard.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 1a25b79..da75588 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -128,9 +128,9 @@ u32 uniwill_add_interface(struct uniwill_interface_t *interface) else { mutex_unlock(&uniwill_interface_modification_lock); return -EINVAL; - + } interface->event_callb = uniwill_event_callb; - + mutex_unlock(&uniwill_interface_modification_lock); return 0; } From 0da37ce0caf4f115a148b55a97389068ceb29200 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 10 Sep 2021 22:57:43 +0200 Subject: [PATCH 05/23] Add uniwill wmi event callb hooks and handling - Event/notify handling - Actually adding interface --- src/uniwill_keyboard.h | 3 ++- src/uniwill_wmi.c | 40 ++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index da75588..133d69e 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -123,9 +123,10 @@ u32 uniwill_add_interface(struct uniwill_interface_t *interface) { mutex_lock(&uniwill_interface_modification_lock); - if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID)) + if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID) == 0) uniwill_interfaces.wmi = interface; else { + TUXEDO_DEBUG("trying to add unknown interface\n"); mutex_unlock(&uniwill_interface_modification_lock); return -EINVAL; } diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index c775a07..622cce9 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -23,15 +23,11 @@ #include #include "uniwill_interfaces.h" -/*u32 uniwill_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) -{ - return uniwill_wmi_evaluate(cmd, arg, result_value); -} - struct uniwill_interface_t uniwill_wmi_interface = { - .string_id = "uniwill_wmi", - .method_call = uniwill_wmi_interface_method_call, -};*/ + .string_id = UNIWILL_INTERFACE_WMI_STRID, + .read_ec_ram = NULL, //uw_wmi_read_ec_ram, + .write_ec_ram = NULL //uw_wmi_write_ec_ram +}; #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) static int uniwill_wmi_probe(struct wmi_device *wdev) @@ -55,7 +51,7 @@ static int uniwill_wmi_probe(struct wmi_device *wdev, const void *dummy_context) return -ENODEV; } - // TODO: Add interface and init + uniwill_add_interface(&uniwill_wmi_interface); pr_info("interface initialized\n"); @@ -69,19 +65,31 @@ static void uniwill_wmi_remove(struct wmi_device *wdev) #endif { pr_debug("uniwill_wmi driver remove\n"); + uniwill_remove_interface(&uniwill_wmi_interface); #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) return 0; #endif } -static void uniwill_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy) +static void uniwill_wmi_notify(struct wmi_device *wdev, union acpi_object *obj) { - //u32 event_value; - pr_debug("uniwill_wmi notify\n"); - /*if (!IS_ERR_OR_NULL(uniwill_wmi_interface.event_callb)) { - // Execute registered callback - // TODO - }*/ + u32 code; + + if (!IS_ERR_OR_NULL(uniwill_wmi_interface.event_callb)) { + if (obj) { + if (obj->type == ACPI_TYPE_INTEGER) { + code = obj->integer.value; + // Execute registered callback + uniwill_wmi_interface.event_callb(code); + } else { + pr_debug("unknown event type - %d (%0#6x)\n", obj->type, obj->type); + } + } else { + pr_debug("expected ACPI object doesn't exist\n"); + } + } else { + pr_debug("no registered callback\n"); + } } static const struct wmi_device_id uniwill_wmi_device_ids[] = { From 57ebb3a9fe68e1bd2b6bc240702c131a3956488b Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Sep 2021 21:26:12 +0200 Subject: [PATCH 06/23] Move and include mem read/write functions --- src/uniwill_wmi.c | 246 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 2 deletions(-) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 622cce9..7884304 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -21,12 +21,254 @@ #include #include #include +#include #include "uniwill_interfaces.h" +#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_wmi_read_ec_ram(u16 addr, u8 *data) +{ + u32 result; + u8 addr_low, addr_high; + union uw_ec_read_return output; + + if (IS_ERR_OR_NULL(data)) + return -EINVAL; + + addr_low = addr & 0xff; + addr_high = (addr >> 8) & 0xff; + + if (uniwill_ec_direct) { + result = uw_ec_read_addr_direct(addr_low, addr_high, &output); + } else { + result = uw_ec_read_addr_wmi(addr_low, addr_high, &output); + } + + *data = output.bytes.data_low; + return result; +} + +u32 uw_wmi_write_ec_ram(u16 addr, u8 data) +{ + u32 result; + u8 addr_low, addr_high, data_low, data_high; + union uw_ec_write_return output; + + addr_low = addr & 0xff; + addr_high = (addr >> 8) & 0xff; + data_low = data; + data_high = 0x00; + + if (uniwill_ec_direct) + result = uw_ec_write_addr_direct(addr_low, addr_high, data_low, data_high, &output); + else + result = uw_ec_write_addr_wmi(addr_low, addr_high, data_low, data_high, &output); + + return result; +} + struct uniwill_interface_t uniwill_wmi_interface = { .string_id = UNIWILL_INTERFACE_WMI_STRID, - .read_ec_ram = NULL, //uw_wmi_read_ec_ram, - .write_ec_ram = NULL //uw_wmi_write_ec_ram + .read_ec_ram = uw_wmi_read_ec_ram, + .write_ec_ram = uw_wmi_write_ec_ram }; #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 0) From b855a8ff6da59a610a8be579bb139dc6b939a556 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Mon, 13 Sep 2021 23:58:08 +0200 Subject: [PATCH 07/23] Packaging: Include module reload for uniwill_wmi --- deb/module-name/DEBIAN/postinst | 2 ++ src_pkg/rpm_pkg.spec | 2 ++ 2 files changed, 4 insertions(+) diff --git a/deb/module-name/DEBIAN/postinst b/deb/module-name/DEBIAN/postinst index 8f1fe6b..149a019 100755 --- a/deb/module-name/DEBIAN/postinst +++ b/deb/module-name/DEBIAN/postinst @@ -58,11 +58,13 @@ case "$1" in echo "(Re)load modules if possible" rmmod tuxedo_io > /dev/null 2>&1 || true + rmmod uniwill_wmi > /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 uniwill_wmi > /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 diff --git a/src_pkg/rpm_pkg.spec b/src_pkg/rpm_pkg.spec index 7b52fd3..934236d 100644 --- a/src_pkg/rpm_pkg.spec +++ b/src_pkg/rpm_pkg.spec @@ -96,11 +96,13 @@ for POSTINST in /usr/lib/dkms/common.postinst /usr/share/%{module}/postinst; do echo "(Re)load modules if possible" rmmod tuxedo_io > /dev/null 2>&1 || true + rmmod uniwill_wmi > /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 uniwill_wmi > /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 From 9ec3dc927abec4588f65ea741d708ee9fec2179f Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 15 Sep 2021 17:58:06 +0200 Subject: [PATCH 08/23] Reorder uniwill driver init and remove --- src/tuxedo_keyboard.c | 62 +++++++++++++++++------------------- src/tuxedo_keyboard_common.h | 1 + src/uniwill_keyboard.h | 59 ++++++++++++++++++++++++++++------ 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/src/tuxedo_keyboard.c b/src/tuxedo_keyboard.c index 829d1d2..c6bbef6 100644 --- a/src/tuxedo_keyboard.c +++ b/src/tuxedo_keyboard.c @@ -28,15 +28,9 @@ MODULE_DESCRIPTION("TUXEDO Computers keyboard & keyboard backlight Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("3.0.8"); -MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_0); -MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_1); -MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); - static DEFINE_MUTEX(tuxedo_keyboard_init_driver_lock); -static struct tuxedo_keyboard_driver *driver_list[] = { - &uniwill_keyboard_driver -}; +// static struct tuxedo_keyboard_driver *driver_list[] = { }; static int tuxedo_input_init(const struct key_entry key_map[]) { @@ -134,44 +128,48 @@ static void __exit tuxedo_input_exit(void) } } -static int __init tuxedo_keyboard_init(void) +void tuxedo_keyboard_remove_driver(struct tuxedo_keyboard_driver *tk_driver) { - int i; - int num_drivers = sizeof(driver_list) / sizeof(*driver_list); - TUXEDO_INFO("Model '%s' found\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); + bool specified_driver_differ_from_used = + tk_driver != NULL && + ( + strcmp( + tk_driver->platform_driver->driver.name, + current_driver->platform_driver->driver.name + ) != 0 + ); - // Attempt to load each available driver - // Associated probe decides if it fits - // Driver from first successful probe is used + if (specified_driver_differ_from_used) + return; - i = 0; - while (IS_ERR_OR_NULL(tuxedo_platform_device) && i < num_drivers) { - current_driver = driver_list[i]; - tuxedo_keyboard_init_driver(current_driver); - ++i; + 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_platform_device = NULL; } - - if (IS_ERR_OR_NULL(tuxedo_platform_device)) { - TUXEDO_DEBUG("No matching hardware found on init\n"); + TUXEDO_DEBUG("platform_driver_unregister()\n"); + if (!IS_ERR_OR_NULL(current_driver)) { + platform_driver_unregister(current_driver->platform_driver); current_driver = NULL; } +} +EXPORT_SYMBOL(tuxedo_keyboard_remove_driver); + +static int __init tuxedo_keyboard_init(void) +{ + TUXEDO_INFO("module init\n"); return 0; } static void __exit tuxedo_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); + TUXEDO_INFO("module exit\n"); - TUXEDO_DEBUG("exit\n"); + if (tuxedo_platform_device != NULL) + tuxedo_keyboard_remove_driver(NULL); } module_init(tuxedo_keyboard_init); diff --git a/src/tuxedo_keyboard_common.h b/src/tuxedo_keyboard_common.h index 49651b4..84f6059 100644 --- a/src/tuxedo_keyboard_common.h +++ b/src/tuxedo_keyboard_common.h @@ -56,6 +56,7 @@ static struct input_dev *tuxedo_input_device = NULL; static struct tuxedo_keyboard_driver *current_driver = NULL; struct platform_device *tuxedo_keyboard_init_driver(struct tuxedo_keyboard_driver *tk_driver); +void tuxedo_keyboard_remove_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 133d69e..16243b2 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -133,6 +133,10 @@ u32 uniwill_add_interface(struct uniwill_interface_t *interface) interface->event_callb = uniwill_event_callb; mutex_unlock(&uniwill_interface_modification_lock); + + // Initialize driver if not already present + tuxedo_keyboard_init_driver(&uniwill_keyboard_driver); + return 0; } EXPORT_SYMBOL(uniwill_add_interface); @@ -141,14 +145,18 @@ u32 uniwill_remove_interface(struct uniwill_interface_t *interface) { mutex_lock(&uniwill_interface_modification_lock); - if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID)) + if (strcmp(interface->string_id, UNIWILL_INTERFACE_WMI_STRID) == 0) { + // Remove driver if last interface is removed + tuxedo_keyboard_remove_driver(&uniwill_keyboard_driver); + uniwill_interfaces.wmi = NULL; - else { + } else { mutex_unlock(&uniwill_interface_modification_lock); return -EINVAL; } mutex_unlock(&uniwill_interface_modification_lock); + return 0; } EXPORT_SYMBOL(uniwill_remove_interface); @@ -342,7 +350,7 @@ void uniwill_event_callb(u32 code) } } -static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) +/*static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -367,9 +375,9 @@ static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) } kfree(obj); -} +}*/ -static void uniwill_wmi_notify0(u32 value, void *context) +/*static void uniwill_wmi_notify0(u32 value, void *context) { uniwill_wmi_handle_event(value, context, 0); } @@ -382,7 +390,7 @@ static void uniwill_wmi_notify1(u32 value, void *context) static void uniwill_wmi_notify2(u32 value, void *context) { uniwill_wmi_handle_event(value, context, 2); -} +}*/ static ssize_t uw_brightness_show(struct device *child, struct device_attribute *attr, char *buffer) @@ -820,7 +828,7 @@ static int uw_lightbar_remove(struct platform_device *dev) return 0; } -static int uniwill_keyboard_probe(struct platform_device *dev) +/*static int uniwill_keyboard_probe(struct platform_device *dev) { int status; @@ -872,6 +880,40 @@ err_remove_notifiers: wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_2); return -ENODEV; +}*/ + +static int uniwill_keyboard_probe(struct platform_device *dev) +{ + u32 i; + u8 data; + int status; + + // FIXME Hard set balanced profile until we have implemented a way to + // switch it while tuxedo_io is loaded + // uw_ec_write_addr(0x51, 0x07, 0x00, 0x00, ®_write_return); + uniwill_write_ec_ram(0x0751, 0x00); + + // Set manual-mode fan-curve in 0x0743 - 0x0747 + // Some kind of default fan-curve is stored in 0x0786 - 0x078a: Using it to initialize manual-mode fan-curve + for (i = 0; i < 5; ++i) { + uniwill_read_ec_ram(0x0786 + i, &data); + uniwill_write_ec_ram(0x0743 + i, data); + } + + // Enable manual mode + uniwill_write_ec_ram(0x0741, 0x01); + + // Zero second fan temp for detection + uniwill_write_ec_ram(0x044f, 0x00); + + status = register_keyboard_notifier(&keyboard_notifier_block); + + uw_kbd_bl_init(dev); + + status = uw_lightbar_init(dev); + uw_lightbar_loaded = (status >= 0); + + return 0; } static int uniwill_keyboard_remove(struct platform_device *dev) @@ -887,9 +929,6 @@ static int uniwill_keyboard_remove(struct platform_device *dev) } unregister_keyboard_notifier(&keyboard_notifier_block); - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_0); - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_1); - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_2); del_timer(&uw_kbd_bl_init_timer); From 16f7c246dddb0b3380d9a908b85a6553c656a84c Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Sep 2021 00:14:39 +0200 Subject: [PATCH 09/23] Adjust clevo driver init and remove accordingly --- src/clevo_acpi.c | 7 +- src/clevo_interfaces.h | 5 +- src/clevo_keyboard.h | 142 +++++++++++++++++++++-------------------- src/clevo_wmi.c | 13 ++-- 4 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/clevo_acpi.c b/src/clevo_acpi.c index ffba014..9b246eb 100644 --- a/src/clevo_acpi.c +++ b/src/clevo_acpi.c @@ -101,7 +101,7 @@ u32 clevo_acpi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) } struct clevo_interface_t clevo_acpi_interface = { - .string_id = "clevo_acpi", + .string_id = CLEVO_INTERFACE_ACPI_STRID, .method_call = clevo_acpi_interface_method_call, }; @@ -123,9 +123,6 @@ static int clevo_acpi_add(struct acpi_device *device) // Add this interface clevo_keyboard_add_interface(&clevo_acpi_interface); - // Initiate clevo keyboard, if not already loaded by other interface driver - clevo_keyboard_init(); - pr_info("interface initialized\n"); return 0; @@ -195,7 +192,7 @@ module_acpi_driver(clevo_acpi_driver); MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Clevo ACPI interface"); -MODULE_VERSION("0.0.2"); +MODULE_VERSION("0.0.3"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(acpi, clevo_acpi_device_ids); diff --git a/src/clevo_interfaces.h b/src/clevo_interfaces.h index 1b384e6..e8f2bd5 100644 --- a/src/clevo_interfaces.h +++ b/src/clevo_interfaces.h @@ -48,8 +48,6 @@ #define CLEVO_CMD_OPT 0x79 #define CLEVO_OPT_SUBCMD_SET_PERF_PROF 0x19 -int clevo_keyboard_init(void); - struct clevo_interface_t { char *string_id; void (*event_callb)(u32); @@ -65,6 +63,9 @@ u32 clevo_get_active_interface_id(char **id_str); MODULE_ALIAS("wmi:" CLEVO_WMI_EVENT_GUID); \ MODULE_ALIAS("wmi:" CLEVO_WMI_METHOD_GUID); +#define CLEVO_INTERFACE_WMI_STRID "clevo_wmi" +#define CLEVO_INTERFACE_ACPI_STRID "clevo_acpi" + #define MODULE_ALIAS_CLEVO_ACPI() \ MODULE_ALIAS("acpi*:" CLEVO_ACPI_RESOURCE_HID ":*"); diff --git a/src/clevo_keyboard.h b/src/clevo_keyboard.h index ef6c61e..9906389 100644 --- a/src/clevo_keyboard.h +++ b/src/clevo_keyboard.h @@ -54,6 +54,8 @@ #define CLEVO_EVENT_RFKILL1 0x85 #define CLEVO_EVENT_RFKILL2 0x86 +struct tuxedo_keyboard_driver clevo_keyboard_driver; + static struct clevo_interfaces_t { struct clevo_interface_t *wmi; struct clevo_interface_t *acpi; @@ -70,7 +72,7 @@ u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) { mutex_lock(&clevo_keyboard_interface_modification_lock); - if (strcmp(new_interface->string_id, "clevo_wmi") == 0) { + if (strcmp(new_interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { clevo_interfaces.wmi = new_interface; clevo_interfaces.wmi->event_callb = clevo_keyboard_event_callb; @@ -82,7 +84,7 @@ u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) active_clevo_interface = clevo_interfaces.wmi; } - } else if (strcmp(new_interface->string_id, "clevo_acpi") == 0) { + } else if (strcmp(new_interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { clevo_interfaces.acpi = new_interface; clevo_interfaces.acpi->event_callb = clevo_keyboard_event_callb; @@ -98,6 +100,9 @@ u32 clevo_keyboard_add_interface(struct clevo_interface_t *new_interface) mutex_unlock(&clevo_keyboard_interface_modification_lock); + if (active_clevo_interface != NULL) + tuxedo_keyboard_init_driver(&clevo_keyboard_driver); + return 0; } EXPORT_SYMBOL(clevo_keyboard_add_interface); @@ -106,17 +111,20 @@ u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface) { mutex_lock(&clevo_keyboard_interface_modification_lock); - if (strcmp(interface->string_id, "clevo_wmi") == 0) { + if (strcmp(interface->string_id, CLEVO_INTERFACE_WMI_STRID) == 0) { clevo_interfaces.wmi = NULL; - } else if (strcmp(interface->string_id, "clevo_acpi") == 0) { + } else if (strcmp(interface->string_id, CLEVO_INTERFACE_ACPI_STRID) == 0) { clevo_interfaces.acpi = NULL; } else { mutex_unlock(&clevo_keyboard_interface_modification_lock); return -EINVAL; } - if (active_clevo_interface == interface) + if (active_clevo_interface == interface) { + tuxedo_keyboard_remove_driver(&clevo_keyboard_driver); active_clevo_interface = NULL; + } + mutex_unlock(&clevo_keyboard_interface_modification_lock); @@ -124,8 +132,6 @@ u32 clevo_keyboard_remove_interface(struct clevo_interface_t *interface) } EXPORT_SYMBOL(clevo_keyboard_remove_interface); -struct tuxedo_keyboard_driver clevo_keyboard_driver; - static struct key_entry clevo_keymap[] = { // Keyboard backlight (RGB versions) { KE_KEY, CLEVO_EVENT_DECREASE_BACKLIGHT, { KEY_KBDILLUMDOWN } }, @@ -299,7 +305,7 @@ static ssize_t show_hasextra_fs(struct device *child, 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"); + pr_err("clevo_keyboard: no active interface while attempting cmd %02x arg %08x\n", cmd, arg); return -ENODEV; } return active_clevo_interface->method_call(cmd, arg, result); @@ -705,9 +711,65 @@ void clevo_keyboard_write_state(void) set_enabled(kbd_led_state.enabled); } -static int clevo_keyboard_probe_only_init(struct platform_device *dev) +/** + * strstr version of dmi_match + */ +static bool dmi_string_in(enum dmi_field f, const char *str) +{ + const char *info = dmi_get_system_info(f); + + if (info == NULL || str == NULL) + return info == str; + + return strstr(info, str) != NULL; +} + +int clevo_keyboard_init(void) +{ + bool performance_profile_set_workaround; + + // Init state from params + kbd_led_state.color.left = param_color_left; + kbd_led_state.color.center = param_color_center; + kbd_led_state.color.right = param_color_right; + kbd_led_state.color.extra = param_color_extra; + + kbd_led_state.blinking_pattern = param_blinking_pattern; + + if (param_brightness > BRIGHTNESS_MAX) param_brightness = BRIGHTNESS_DEFAULT; + kbd_led_state.brightness = param_brightness; + + kbd_led_state.enabled = param_state; + + clevo_keyboard_write_state(); + + // Workaround for firmware issue not setting selected performance profile. + // Explicitly set "performance" perf. profile on init regardless of what is chosen + // for these devices (Aura, XP14, IBS14v5) + performance_profile_set_workaround = false + || dmi_string_in(DMI_BOARD_NAME, "AURA1501") + || dmi_string_in(DMI_BOARD_NAME, "EDUBOOK1502") + || dmi_string_in(DMI_BOARD_NAME, "NL5xRU") + || dmi_string_in(DMI_BOARD_NAME, "NV4XMB,ME,MZ") + || dmi_string_in(DMI_BOARD_NAME, "L140CU") + || dmi_string_in(DMI_BOARD_NAME, "NS50MU") + || dmi_string_in(DMI_BOARD_NAME, "PCX0DX") + || dmi_string_in(DMI_BOARD_NAME, "PCx0Dx_GN20") + || dmi_string_in(DMI_BOARD_NAME, "L14xMU") + ; + if (performance_profile_set_workaround) { + TUXEDO_INFO("Performance profile 'performance' set workaround applied\n"); + clevo_evaluate_method(0x79, 0x19000002, NULL); + } + + return 0; +} + +static int clevo_keyboard_probe(struct platform_device *dev) { clevo_keyboard_init_device_interface(dev); + clevo_keyboard_init(); + return 0; } @@ -759,66 +821,8 @@ static struct platform_driver platform_driver_clevo = { }, }; -struct tuxedo_keyboard_driver clevo_keyboard_driver_v2 = { +struct tuxedo_keyboard_driver clevo_keyboard_driver = { .platform_driver = &platform_driver_clevo, - .probe = clevo_keyboard_probe_only_init, + .probe = clevo_keyboard_probe, .key_map = clevo_keymap, }; - -/** - * strstr version of dmi_match - */ -static bool dmi_string_in(enum dmi_field f, const char *str) -{ - const char *info = dmi_get_system_info(f); - - if (info == NULL || str == NULL) - return info == str; - - return strstr(info, str) != NULL; -} - -int clevo_keyboard_init(void) -{ - bool performance_profile_set_workaround; - - if (IS_ERR_OR_NULL(tuxedo_keyboard_init_driver(&clevo_keyboard_driver_v2))) - return -EEXIST; - - // Init state from params - kbd_led_state.color.left = param_color_left; - kbd_led_state.color.center = param_color_center; - kbd_led_state.color.right = param_color_right; - kbd_led_state.color.extra = param_color_extra; - - kbd_led_state.blinking_pattern = param_blinking_pattern; - - if (param_brightness > BRIGHTNESS_MAX) param_brightness = BRIGHTNESS_DEFAULT; - kbd_led_state.brightness = param_brightness; - - kbd_led_state.enabled = param_state; - - clevo_keyboard_write_state(); - - // Workaround for firmware issue not setting selected performance profile. - // Explicitly set "performance" perf. profile on init regardless of what is chosen - // for these devices (Aura, XP14, IBS14v5) - performance_profile_set_workaround = false - || dmi_string_in(DMI_BOARD_NAME, "AURA1501") - || dmi_string_in(DMI_BOARD_NAME, "EDUBOOK1502") - || dmi_string_in(DMI_BOARD_NAME, "NL5xRU") - || dmi_string_in(DMI_BOARD_NAME, "NV4XMB,ME,MZ") - || dmi_string_in(DMI_BOARD_NAME, "L140CU") - || dmi_string_in(DMI_BOARD_NAME, "NS50MU") - || dmi_string_in(DMI_BOARD_NAME, "PCX0DX") - || dmi_string_in(DMI_BOARD_NAME, "PCx0Dx_GN20") - || dmi_string_in(DMI_BOARD_NAME, "L14xMU") - ; - if (performance_profile_set_workaround) { - TUXEDO_INFO("Performance profile 'performance' set workaround applied\n"); - clevo_evaluate_method(0x79, 0x19000002, NULL); - } - - return 0; -} -EXPORT_SYMBOL(clevo_keyboard_init); diff --git a/src/clevo_wmi.c b/src/clevo_wmi.c index 919ce6d..14320f4 100644 --- a/src/clevo_wmi.c +++ b/src/clevo_wmi.c @@ -70,7 +70,7 @@ u32 clevo_wmi_interface_method_call(u8 cmd, u32 arg, u32 *result_value) } struct clevo_interface_t clevo_wmi_interface = { - .string_id = "clevo_wmi", + .string_id = CLEVO_INTERFACE_WMI_STRID, .method_call = clevo_wmi_interface_method_call, }; @@ -110,9 +110,6 @@ static int clevo_wmi_probe(struct wmi_device *wdev, const void *dummy_context) // Add this interface clevo_keyboard_add_interface(&clevo_wmi_interface); - // Initiate clevo keyboard, if not already loaded by other interface driver - clevo_keyboard_init(); - pr_info("interface initialized\n"); return 0; @@ -125,6 +122,7 @@ static void clevo_wmi_remove(struct wmi_device *wdev) #endif { pr_debug("clevo_wmi driver remove\n"); + clevo_keyboard_remove_interface(&clevo_wmi_interface); #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) return 0; #endif @@ -149,7 +147,10 @@ static const struct wmi_device_id clevo_wmi_device_ids[] = { }; static struct wmi_driver clevo_wmi_driver = { - .driver = { .name = "clevo_wmi", .owner = THIS_MODULE }, + .driver = { + .name = CLEVO_INTERFACE_WMI_STRID, + .owner = THIS_MODULE + }, .id_table = clevo_wmi_device_ids, .probe = clevo_wmi_probe, .remove = clevo_wmi_remove, @@ -160,7 +161,7 @@ module_wmi_driver(clevo_wmi_driver); MODULE_AUTHOR("TUXEDO Computers GmbH "); MODULE_DESCRIPTION("Driver for Clevo WMI interface"); -MODULE_VERSION("0.0.3"); +MODULE_VERSION("0.0.4"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(wmi, clevo_wmi_device_ids); From 931d3c7f30cec21962ba14746767b0b021fb9051 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Sep 2021 20:33:05 +0200 Subject: [PATCH 10/23] Add visible error on missing uw interface read/write attempt --- src/uniwill_keyboard.h | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 16243b2..db89606 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -97,23 +97,31 @@ uniwill_event_callb_t uniwill_event_callb; u32 uniwill_read_ec_ram(u16 address, u8 *data) { - if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) - uniwill_interfaces.wmi->read_ec_ram(address, data); - else - return -EIO; + u32 status; - return 0; + if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) + status = uniwill_interfaces.wmi->read_ec_ram(address, data); + else { + pr_err("no active interface while read addr 0x%04x\n", address); + status = -EIO; + } + + return status; } EXPORT_SYMBOL(uniwill_read_ec_ram); u32 uniwill_write_ec_ram(u16 address, u8 data) { - if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) - uniwill_interfaces.wmi->write_ec_ram(address, data); - else - return -EIO; + u32 status; - return 0; + if (!IS_ERR_OR_NULL(uniwill_interfaces.wmi)) + status = uniwill_interfaces.wmi->write_ec_ram(address, data); + else { + pr_err("no active interface while write addr 0x%04x data 0x%02x\n", address, data); + status = -EIO; + } + + return status; } EXPORT_SYMBOL(uniwill_write_ec_ram); From 64c47a69430b73b95a943b493329c1184a44d001 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 16 Sep 2021 20:45:13 +0200 Subject: [PATCH 11/23] Change use of uw if read/write to new ones - For uniwill_keyboard part - Remove now unused uw_io.h --- src/uniwill_keyboard.h | 147 +++++++++++------------------------------ src/uw_io.h | 101 ---------------------------- 2 files changed, 40 insertions(+), 208 deletions(-) delete mode 100644 src/uw_io.h diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index db89606..52891a5 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -26,7 +26,6 @@ #include #include #include -#include "uw_io.h" #include "uniwill_interfaces.h" #define UNIWILL_WMI_MGMT_GUID_BA "ABBC0F6D-8EA1-11D1-00A0-C90629100000" @@ -216,11 +215,11 @@ static struct notifier_block keyboard_notifier_block = { static u8 uniwill_read_kbd_bl_enabled(void) { - union uw_ec_read_return reg_read_return; + u8 backlight_data; u8 enabled = 0xff; - __uw_ec_read_addr(0x8c, 0x07, ®_read_return); - enabled = (reg_read_return.bytes.data_low >> 1) & 0x01; + uniwill_read_ec_ram(0x078c, &backlight_data); + enabled = (backlight_data >> 1) & 0x01; enabled = !enabled; return enabled; @@ -228,24 +227,22 @@ static u8 uniwill_read_kbd_bl_enabled(void) static void uniwill_write_kbd_bl_enable(u8 enable) { - union uw_ec_read_return reg_read_return; - union uw_ec_write_return reg_write_return; - u8 write_value = 0; + u8 backlight_data; enable = enable & 0x01; - __uw_ec_read_addr(0x8c, 0x07, ®_read_return); - write_value = reg_read_return.bytes.data_low & ~(1 << 1); - write_value |= (!enable << 1); - __uw_ec_write_addr(0x8c, 0x07, write_value, 0x00, ®_write_return); + uniwill_read_ec_ram(0x078c, &backlight_data); + backlight_data = backlight_data & ~(1 << 1); + backlight_data |= (!enable << 1); + uniwill_write_ec_ram(0x078c, backlight_data); } /*static u32 uniwill_read_kbd_bl_br_state(u8 *brightness_state) { - union uw_ec_read_return reg_read_return; + u8 backlight_data; u32 result; - __uw_ec_read_addr(0x8c, 0x07, ®_read_return); - *brightness_state = (reg_read_return.bytes.data_low & 0xf0) >> 4; + uniwill_read_ec_ram(0x078c, &backlight_data); + *brightness_state = (backlight_data & 0xf0) >> 4; result = 0; return result; @@ -253,15 +250,12 @@ static void uniwill_write_kbd_bl_enable(u8 enable) static u32 uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) { - union uw_ec_read_return reg_read_return; u32 result; - __uw_ec_read_addr(0x03, 0x18, ®_read_return); - *red = reg_read_return.bytes.data_low; - __uw_ec_read_addr(0x05, 0x18, ®_read_return); - *green = reg_read_return.bytes.data_low; - __uw_ec_read_addr(0x08, 0x18, ®_read_return); - *blue = reg_read_return.bytes.data_low; + uniwill_read_ec_ram(0x1803, red); + uniwill_read_ec_ram(0x1805, green); + uniwill_read_ec_ram(0x1808, blue); + result = 0; return result; @@ -269,16 +263,13 @@ static u32 uniwill_read_kbd_bl_rgb(u8 *red, u8 *green, u8 *blue) static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) { - union uw_ec_write_return reg_write_return; - - // Write the colors if (red > 0xc8) red = 0xc8; if (green > 0xc8) green = 0xc8; if (blue > 0xc8) blue = 0xc8; - __uw_ec_write_addr(0x03, 0x18, red, 0x00, ®_write_return); - __uw_ec_write_addr(0x05, 0x18, green, 0x00, ®_write_return); - __uw_ec_write_addr(0x08, 0x18, blue, 0x00, ®_write_return); - TUXEDO_DEBUG("Wrote color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); + uniwill_write_ec_ram(0x1803, red); + uniwill_write_ec_ram(0x1805, green); + uniwill_write_ec_ram(0x1808, blue); + TUXEDO_DEBUG("Wrote kbd color [%0#4x, %0#4x, %0#4x]\n", red, green, blue); } static void uniwill_write_kbd_bl_state(void) { @@ -304,9 +295,7 @@ static void uniwill_write_kbd_bl_state(void) { static void uniwill_write_kbd_bl_reset(void) { - union uw_ec_write_return reg_write_return; - - __uw_ec_write_addr(0x8c, 0x07, 0x10, 0x00, ®_write_return); + uniwill_write_ec_ram(0x078c, 0x10); } void uniwill_event_callb(u32 code) @@ -604,105 +593,49 @@ static int uw_kbd_bl_init(struct platform_device *dev) static void uniwill_write_lightbar_rgb(u8 red, u8 green, u8 blue) { - union uw_ec_write_return reg_write_return; - - uw_ec_write_func *__uw_ec_write_addr; - - __uw_ec_write_addr = symbol_get(uw_ec_write_addr); - - if (__uw_ec_write_addr) { - if (red <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { - __uw_ec_write_addr(0x49, 0x07, red, 0x00, ®_write_return); - } - if (green <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { - __uw_ec_write_addr(0x4a, 0x07, green, 0x00, ®_write_return); - } - if (blue <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { - __uw_ec_write_addr(0x4b, 0x07, blue, 0x00, ®_write_return); - } - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); + if (red <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { + uniwill_write_ec_ram(0x0749, red); + } + if (green <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { + uniwill_write_ec_ram(0x074a, green); + } + if (blue <= UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS) { + uniwill_write_ec_ram(0x074b, blue); } - - if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); } static int uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) { int status; - union uw_ec_read_return reg_read_return; - uw_ec_read_func *__uw_ec_read_addr; - - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - - if (__uw_ec_read_addr) { - __uw_ec_read_addr(0x49, 0x07, ®_read_return); - *red = reg_read_return.bytes.data_low; - __uw_ec_read_addr(0x4a, 0x07, ®_read_return); - *green = reg_read_return.bytes.data_low; - __uw_ec_read_addr(0x4b, 0x07, ®_read_return); - *blue = reg_read_return.bytes.data_low; - status = 0; - } else { - status = -EIO; - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); + uniwill_read_ec_ram(0x0749, red); + uniwill_read_ec_ram(0x074a, green); + uniwill_read_ec_ram(0x074b, blue); + status = 0; return status; } static void uniwill_write_lightbar_animation(bool animation_status) { - union uw_ec_write_return reg_write_return; - union uw_ec_read_return reg_read_return; - u8 value; - uw_ec_write_func *__uw_ec_write_addr; - uw_ec_read_func *__uw_ec_read_addr; - - __uw_ec_write_addr = symbol_get(uw_ec_write_addr); - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - - if (__uw_ec_write_addr && __uw_ec_read_addr) { - __uw_ec_read_addr(0x48, 0x07, ®_read_return); - value = reg_read_return.bytes.data_low; - if (animation_status) { - value |= 0x80; - } else { - value &= ~0x80; - } - __uw_ec_write_addr(0x48, 0x07, value, 0x00, ®_write_return); + uniwill_read_ec_ram(0x0748, &value); + if (animation_status) { + value |= 0x80; } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); + value &= ~0x80; } - - if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); + uniwill_write_ec_ram(0x0748, value); } static int uniwill_read_lightbar_animation(bool *animation_status) { int status; - union uw_ec_read_return reg_read_return; + u8 lightbar_animation_data; - uw_ec_read_func *__uw_ec_read_addr; - - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - - if (__uw_ec_read_addr) { - __uw_ec_read_addr(0x48, 0x07, ®_read_return); - *animation_status = (reg_read_return.bytes.data_low & 0x80) > 0; - status = 0; - } else { - status = -EIO; - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); + status = uniwill_read_ec_ram(0x0748, &lightbar_animation_data); + *animation_status = (lightbar_animation_data & 0x80) > 0; return status; } diff --git a/src/uw_io.h b/src/uw_io.h deleted file mode 100644 index 4d80df9..0000000 --- a/src/uw_io.h +++ /dev/null @@ -1,101 +0,0 @@ -/*! - * Copyright (c) 2020 TUXEDO Computers GmbH - * - * This file is part of tuxedo-keyboard. - * - * tuxedo-keyboard 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 UW_IO_H -#define UW_IO_H - -#include -#include - -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; -}; - -typedef u32 (uw_ec_read_func)(u8, u8, union uw_ec_read_return *); -typedef u32 (uw_ec_write_func)(u8, u8, u8, u8, union uw_ec_write_return *); - -extern uw_ec_read_func uw_ec_read_addr; -extern uw_ec_write_func uw_ec_write_addr; - -/** - * uw ec read from tccwmi for now stuffed in this wrapper for simplification - * - * @returns The result of the tccwmi function, or -ENOENT - * if tccwmi symbol is not accessible - */ -static u32 __uw_ec_read_addr(u8 addr_low, u8 addr_high, - union uw_ec_read_return *output) -{ - uw_ec_read_func *symbol_uw_ec_read_addr; - u32 result = 0; - symbol_uw_ec_read_addr = symbol_get(uw_ec_read_addr); - if (symbol_uw_ec_read_addr) { - result = symbol_uw_ec_read_addr(addr_low, addr_high, output); - } else { - pr_debug("tuxedo-cc-wmi symbols not found\n"); - result = -ENOENT; - } - - if (symbol_uw_ec_read_addr) - symbol_put(uw_ec_read_addr); - - return result; -} - -/** - * uw ec write from tccwmi for now stuffed in this wrapper for simplification - * - * @returns The result of the tccwmi function, or -ENOENT - * if tccwmi symbol is not accessible - */ -static u32 __uw_ec_write_addr(u8 addr_low, u8 addr_high, u8 data_low, - u8 data_high, union uw_ec_write_return *output) -{ - uw_ec_write_func *symbol_uw_ec_write_addr; - u32 result = 0; - symbol_uw_ec_write_addr = symbol_get(uw_ec_write_addr); - - if (symbol_uw_ec_write_addr) { - result = symbol_uw_ec_write_addr(addr_low, addr_high, data_low, - data_high, output); - } else { - pr_debug("tuxedo-cc-wmi symbols not found\n"); - result = -ENOENT; - } - - if (symbol_uw_ec_write_addr) - symbol_put(uw_ec_write_addr); - - return result; -} - -#endif From 56b5c5461d3b9a087e22f90049d5285f94168d2a Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Sep 2021 19:15:11 +0200 Subject: [PATCH 12/23] Move uw manual mode set/remove --- src/tuxedo_io/tongfang_wmi.h | 5 ----- src/uniwill_keyboard.h | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index c331062..db35f64 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -291,9 +291,6 @@ static void uniwill_init(void) uw_ec_write_addr(0x43 + i, 0x07, reg_read_return.bytes.data_low, 0x00, ®_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); } @@ -302,8 +299,6 @@ 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); } static u32 uw_set_fan(u32 fan_index, u8 fan_speed) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 52891a5..ae6f1eb 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -876,6 +876,9 @@ static int uniwill_keyboard_remove(struct platform_device *dev) if (uw_lightbar_loaded) uw_lightbar_remove(dev); + // Disable manual mode + uniwill_write_ec_ram(0x0741, 0x00); + return 0; } From cf4d9967b71493b403167ec9ea6f5d687f4a6434 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Sep 2021 20:16:39 +0200 Subject: [PATCH 13/23] tuxedo_io: Add new uw interfaces header --- src/tuxedo_io/tuxedo_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 2eb1e2a..905c424 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -27,6 +27,7 @@ #include #include #include "../clevo_interfaces.h" +#include "../uniwill_interfaces.h" #include "tongfang_wmi.h" #include "tuxedo_io_ioctl.h" From de124948ab444739bda53c769bfcedf8f53f04cf Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Sep 2021 20:19:58 +0200 Subject: [PATCH 14/23] Change use of uw if read/write to new ones - For fan control --- src/tuxedo_io/tongfang_wmi.h | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index db35f64..0b5a31f 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -303,36 +303,35 @@ static void uniwill_exit(void) static u32 uw_set_fan(u32 fan_index, u8 fan_speed) { - u8 reg_low, reg_high = 0x18; u32 i; - union uw_ec_read_return reg_read_return; - union uw_ec_write_return reg_write_return; - u8 low_reg_fan0 = 0x04; - u8 low_reg_fan1 = 0x09; + u8 mode_data; + u16 addr_fan0 = 0x1804; + u16 addr_fan1 = 0x1809; + u16 addr_for_fan; if (fan_index == 0) - reg_low = low_reg_fan0; + addr_for_fan = addr_fan0; else if (fan_index == 1) - reg_low = low_reg_fan1; + addr_for_fan = addr_fan1; else return -EINVAL; // Check current mode - uw_ec_read_addr(0x51, 0x07, ®_read_return); - if (!(reg_read_return.bytes.data_low & 0x40)) { + uniwill_read_ec_ram(0x0751, &mode_data); + if (!(mode_data & 0x40)) { // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) - uw_ec_write_addr(0x51, 0x07, reg_read_return.bytes.data_low | 0x40, 0x00, ®_write_return); + uniwill_write_ec_ram(0x0751, mode_data | 0x40); // Attempt to write both fans as quick as possible before complete ramp-up pr_debug("prevent ramp-up start\n"); for (i = 0; i < 10; ++i) { - uw_ec_write_addr(low_reg_fan0, reg_high, fan_speed & 0xff, 0x00, ®_write_return); - uw_ec_write_addr(low_reg_fan1, reg_high, fan_speed & 0xff, 0x00, ®_write_return); + uniwill_write_ec_ram(addr_fan0, fan_speed & 0xff); + uniwill_write_ec_ram(addr_fan1, fan_speed & 0xff); msleep(10); } pr_debug("prevent ramp-up done\n"); } else { // Otherwise just set the chosen fan - uw_ec_write_addr(reg_low, reg_high, fan_speed & 0xff, 0x00, ®_write_return); + uniwill_write_ec_ram(addr_for_fan, fan_speed & 0xff); } return 0; @@ -340,13 +339,11 @@ static u32 uw_set_fan(u32 fan_index, u8 fan_speed) static u32 uw_set_fan_auto(void) { - union uw_ec_read_return reg_read_return; - union uw_ec_write_return reg_write_return; - + u8 mode_data; // Get current mode - uw_ec_read_addr(0x51, 0x07, ®_read_return); + uniwill_read_ec_ram(0x0751, &mode_data); // Switch off "full fan mode" (i.e. unset 0x40 bit) - uw_ec_write_addr(0x51, 0x07, reg_read_return.bytes.data_low & 0xbf, 0x00, ®_write_return); + uniwill_write_ec_ram(0x0751, mode_data & 0xbf); return 0; } From 4fa915fcc322922b1fa17463d691b444bd405fb5 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Sep 2021 22:06:37 +0200 Subject: [PATCH 15/23] Change use of uw if read/write to new ones - For tuxedo_io --- src/tuxedo_io/tongfang_wmi.h | 5 +++-- src/tuxedo_io/tuxedo_io.c | 43 +++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index 0b5a31f..9ee56e1 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -276,7 +276,7 @@ static u32 uniwill_identify(void) static void uniwill_init(void) { - u32 i; +/* u32 i; union uw_ec_read_return reg_read_return; union uw_ec_write_return reg_write_return; @@ -293,11 +293,12 @@ static void uniwill_init(void) // 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; + // union uw_ec_write_return reg_write_return; } diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 905c424..33415b7 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -157,6 +157,7 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne u32 result = 0; u32 copy_result; u32 argument; + u8 byte_data; union uw_ec_read_return reg_read_return; union uw_ec_write_return reg_write_return; @@ -171,46 +172,49 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne switch (cmd) { case R_UW_FANSPEED: - uw_ec_read_addr(0x04, 0x18, ®_read_return); - result = reg_read_return.bytes.data_low; + uniwill_read_ec_ram(0x1804, &byte_data); + result = byte_data; 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; + uniwill_read_ec_ram(0x1809, &byte_data); + result = byte_data; 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; + uniwill_read_ec_ram(0x043e, &byte_data); + result = byte_data; 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; + uniwill_read_ec_ram(0x044f, &byte_data); + result = byte_data; 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; + uniwill_read_ec_ram(0x0751, &byte_data); + result = byte_data; 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; + uniwill_read_ec_ram(0x0741, &byte_data); + result = byte_data; 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)); + reg_read_return.dword = 0; + result = uniwill_read_ec_ram((uw_arg[1] << 8) | uw_arg[0], ®_read_return.bytes.data_low); + copy_result = copy_to_user((void *) arg, ®_read_return.dword, sizeof(reg_read_return.dword)); // 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) { + /*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 } @@ -228,13 +232,13 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne 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); + uniwill_write_ec_ram(0x0751, argument & 0xff); 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); + uniwill_write_ec_ram(0x0741, argument & 0x01); */ break; case W_UW_FANAUTO: @@ -242,15 +246,18 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne break; #ifdef DEBUG case W_TF_BC: + reg_write_return.dword = 0; copy_result = copy_from_user(&uw_arg, (void *) arg, sizeof(uw_arg)); - if (uniwill_ec_direct) { + uniwill_write_ec_ram((uw_arg[1] << 8) | uw_arg[0], uw_arg[2]); + copy_result = copy_to_user((void *) arg, ®_write_return.dword, sizeof(reg_write_return.dword)); + /*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); From da31d09aad835766467d6a971fae1e3a208b0451 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 17 Sep 2021 23:53:42 +0200 Subject: [PATCH 16/23] Check input device reference before using --- src/uniwill_keyboard.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index ae6f1eb..895350c 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -300,9 +300,10 @@ static void uniwill_write_kbd_bl_reset(void) void uniwill_event_callb(u32 code) { - if (!sparse_keymap_report_known_event(uniwill_keyboard_driver.input_device, code, 1, true)) { - TUXEDO_DEBUG("Unknown code - %d (%0#6x)\n", code, code); - } + if (uniwill_keyboard_driver.input_device != NULL) + if (!sparse_keymap_report_known_event(uniwill_keyboard_driver.input_device, code, 1, true)) { + TUXEDO_DEBUG("Unknown code - %d (%0#6x)\n", code, code); + } // Special key combination when mode change key is pressed if (code == 0xb0) { From f8bd16ca6885a7c821a26aae3ad513c95ebe7fe2 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Sat, 18 Sep 2021 00:03:49 +0200 Subject: [PATCH 17/23] Move uw fan ctrl helper funcs --- src/tuxedo_io/tongfang_wmi.h | 47 ------------------------------------ src/tuxedo_io/tuxedo_io.c | 47 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index 9ee56e1..703a348 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -302,51 +302,4 @@ static void uniwill_exit(void) } -static u32 uw_set_fan(u32 fan_index, u8 fan_speed) -{ - u32 i; - u8 mode_data; - u16 addr_fan0 = 0x1804; - u16 addr_fan1 = 0x1809; - u16 addr_for_fan; - - if (fan_index == 0) - addr_for_fan = addr_fan0; - else if (fan_index == 1) - addr_for_fan = addr_fan1; - else - return -EINVAL; - - // Check current mode - uniwill_read_ec_ram(0x0751, &mode_data); - if (!(mode_data & 0x40)) { - // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) - uniwill_write_ec_ram(0x0751, mode_data | 0x40); - // Attempt to write both fans as quick as possible before complete ramp-up - pr_debug("prevent ramp-up start\n"); - for (i = 0; i < 10; ++i) { - uniwill_write_ec_ram(addr_fan0, fan_speed & 0xff); - uniwill_write_ec_ram(addr_fan1, fan_speed & 0xff); - msleep(10); - } - pr_debug("prevent ramp-up done\n"); - } else { - // Otherwise just set the chosen fan - uniwill_write_ec_ram(addr_for_fan, fan_speed & 0xff); - } - - return 0; -} - -static u32 uw_set_fan_auto(void) -{ - u8 mode_data; - // Get current mode - uniwill_read_ec_ram(0x0751, &mode_data); - // Switch off "full fan mode" (i.e. unset 0x40 bit) - uniwill_write_ec_ram(0x0751, mode_data & 0xbf); - - return 0; -} - #endif diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 33415b7..fb20372 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -152,6 +152,53 @@ static long clevo_ioctl_interface(struct file *file, unsigned int cmd, unsigned return 0; } +static u32 uw_set_fan(u32 fan_index, u8 fan_speed) +{ + u32 i; + u8 mode_data; + u16 addr_fan0 = 0x1804; + u16 addr_fan1 = 0x1809; + u16 addr_for_fan; + + if (fan_index == 0) + addr_for_fan = addr_fan0; + else if (fan_index == 1) + addr_for_fan = addr_fan1; + else + return -EINVAL; + + // Check current mode + uniwill_read_ec_ram(0x0751, &mode_data); + if (!(mode_data & 0x40)) { + // If not "full fan mode" (i.e. 0x40 bit set) switch to it (required for fancontrol) + uniwill_write_ec_ram(0x0751, mode_data | 0x40); + // Attempt to write both fans as quick as possible before complete ramp-up + pr_debug("prevent ramp-up start\n"); + for (i = 0; i < 10; ++i) { + uniwill_write_ec_ram(addr_fan0, fan_speed & 0xff); + uniwill_write_ec_ram(addr_fan1, fan_speed & 0xff); + msleep(10); + } + pr_debug("prevent ramp-up done\n"); + } else { + // Otherwise just set the chosen fan + uniwill_write_ec_ram(addr_for_fan, fan_speed & 0xff); + } + + return 0; +} + +static u32 uw_set_fan_auto(void) +{ + u8 mode_data; + // Get current mode + uniwill_read_ec_ram(0x0751, &mode_data); + // Switch off "full fan mode" (i.e. unset 0x40 bit) + uniwill_write_ec_ram(0x0751, mode_data & 0xbf); + + return 0; +} + static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigned long arg) { u32 result = 0; From ea720826e808cb25dcbb1b0d9e727e724ecc2ced Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Sat, 18 Sep 2021 00:13:42 +0200 Subject: [PATCH 18/23] Fix some whitespace format issues --- src/tuxedo_io/tuxedo_io.c | 6 +++--- src/uniwill_interfaces.h | 12 ++++++------ src/uniwill_keyboard.h | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index fb20372..8fb8088 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -288,7 +288,7 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne uniwill_write_ec_ram(0x0741, argument & 0x01); */ break; - case W_UW_FANAUTO: + case W_UW_FANAUTO: uw_set_fan_auto(); break; #ifdef DEBUG @@ -348,8 +348,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static struct file_operations fops_dev = { .owner = THIS_MODULE, .unlocked_ioctl = fop_ioctl -// .open = fop_open, -// .release = fop_release +// .open = fop_open, +// .release = fop_release }; struct class *tuxedo_io_device_class; diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index d222d52..e66bff2 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -21,13 +21,13 @@ #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_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_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 MODULE_ALIAS_UNIWILL_WMI() \ MODULE_ALIAS("wmi:" UNIWILL_WMI_EVENT_GUID_2); \ diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 895350c..e03b569 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -210,7 +210,7 @@ static int keyboard_notifier_callb(struct notifier_block *nb, unsigned long code } static struct notifier_block keyboard_notifier_block = { - .notifier_call = keyboard_notifier_callb + .notifier_call = keyboard_notifier_callb }; static u8 uniwill_read_kbd_bl_enabled(void) @@ -736,7 +736,7 @@ static int uw_lightbar_init(struct platform_device *dev) || dmi_match(DMI_PRODUCT_NAME, "A60 MUV") #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) || dmi_match(DMI_PRODUCT_SKU, "STELLARIS1XI03") - || dmi_match(DMI_PRODUCT_SKU, "STELLARIS1XA03") + || dmi_match(DMI_PRODUCT_SKU, "STELLARIS1XA03") #endif ; From d2ff4e4b839b1937ae7ddd0615b710a64e8b9c7a Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Sat, 18 Sep 2021 00:30:00 +0200 Subject: [PATCH 19/23] Add uniwill interface str id and read for tuxedo_io --- src/tuxedo_io/tongfang_wmi.h | 22 ---------------------- src/tuxedo_io/tuxedo_io.c | 20 +++++++++++++++----- src/tuxedo_io/tuxedo_io_ioctl.h | 1 + src/uniwill_interfaces.h | 1 + src/uniwill_keyboard.h | 14 +++++++++++++- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h index 703a348..98ebdf4 100644 --- a/src/tuxedo_io/tongfang_wmi.h +++ b/src/tuxedo_io/tongfang_wmi.h @@ -252,28 +252,6 @@ u32 uw_ec_write_addr(u8 addr_low, u8 addr_high, u8 data_low, u8 data_high, union } 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) { /* u32 i; diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 8fb8088..9b61dfc 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -51,6 +51,11 @@ static u32 clevo_identify(void) return clevo_get_active_interface_id(NULL) == 0 ? 1 : 0; } +static u32 uniwill_identify(void) +{ + return uniwill_get_active_interface_id(NULL) == 0 ? 1 : 0; +} + /*static int fop_open(struct inode *inode, struct file *file) { return 0; @@ -205,6 +210,8 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne u32 copy_result; u32 argument; u8 byte_data; + const char str_no_if[] = ""; + char *str_uniwill_if; union uw_ec_read_return reg_read_return; union uw_ec_write_return reg_write_return; @@ -218,6 +225,13 @@ static long uniwill_ioctl_interface(struct file *file, unsigned int cmd, unsigne #endif switch (cmd) { + case R_UW_HW_IF_STR: + if (uniwill_get_active_interface_id(&str_uniwill_if) == 0) { + copy_result = copy_to_user((char *) arg, str_uniwill_if, strlen(str_uniwill_if) + 1); + } else { + copy_result = copy_to_user((char *) arg, str_no_if, strlen(str_no_if) + 1); + } + break; case R_UW_FANSPEED: uniwill_read_ec_ram(0x1804, &byte_data); result = byte_data; @@ -363,11 +377,7 @@ static int __init tuxedo_io_init(void) // Hardware identification id_check_clevo = clevo_identify(); - id_check_uniwill = uniwill_identify() == 0 ? 1 : 0; - - if (id_check_uniwill == 1) { - uniwill_init(); - } + id_check_uniwill = uniwill_identify(); #ifdef DEBUG if (id_check_clevo == 0 && id_check_uniwill == 0) { diff --git a/src/tuxedo_io/tuxedo_io_ioctl.h b/src/tuxedo_io/tuxedo_io_ioctl.h index 8a6a22c..f271707 100644 --- a/src/tuxedo_io/tuxedo_io_ioctl.h +++ b/src/tuxedo_io/tuxedo_io_ioctl.h @@ -71,6 +71,7 @@ */ // Read +#define R_UW_HW_IF_STR _IOR(MAGIC_READ_UW, 0x00, char*) #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*) diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index e66bff2..835fb87 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -50,5 +50,6 @@ u32 uniwill_add_interface(struct uniwill_interface_t *new_interface); u32 uniwill_remove_interface(struct uniwill_interface_t *interface); uniwill_read_ec_ram_t uniwill_read_ec_ram; uniwill_write_ec_ram_t uniwill_write_ec_ram; +u32 uniwill_get_active_interface_id(char **id_str); #endif diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index e03b569..f2bf3d3 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -90,7 +90,7 @@ static struct key_entry uniwill_wmi_keymap[] = { static struct uniwill_interfaces_t { struct uniwill_interface_t *wmi; -} uniwill_interfaces; +} uniwill_interfaces = { .wmi = NULL }; uniwill_event_callb_t uniwill_event_callb; @@ -168,6 +168,18 @@ u32 uniwill_remove_interface(struct uniwill_interface_t *interface) } EXPORT_SYMBOL(uniwill_remove_interface); +u32 uniwill_get_active_interface_id(char **id_str) +{ + if (IS_ERR_OR_NULL(uniwill_interfaces.wmi)) + return -ENODEV; + + if (!IS_ERR_OR_NULL(id_str)) + *id_str = uniwill_interfaces.wmi->string_id; + + return 0; +} +EXPORT_SYMBOL(uniwill_get_active_interface_id); + static void key_event_work(struct work_struct *work) { sparse_keymap_report_known_event( From df3df09c10938cd9703bf9b57a808007f9fa99e9 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Sat, 18 Sep 2021 00:37:46 +0200 Subject: [PATCH 20/23] Remove rest of tongfang_wmi.h - Reference includes - Move remaining unions to interfaces - Remove remaining uniwill_exit from tuxedo_io --- src/tuxedo_io/tongfang_wmi.h | 283 ----------------------------------- src/tuxedo_io/tuxedo_io.c | 5 - src/uniwill_interfaces.h | 18 +++ src/uniwill_wmi.c | 18 --- 4 files changed, 18 insertions(+), 306 deletions(-) delete mode 100644 src/tuxedo_io/tongfang_wmi.h diff --git a/src/tuxedo_io/tongfang_wmi.h b/src/tuxedo_io/tongfang_wmi.h deleted file mode 100644 index 98ebdf4..0000000 --- a/src/tuxedo_io/tongfang_wmi.h +++ /dev/null @@ -1,283 +0,0 @@ -/*! - * Copyright (c) 2020 TUXEDO Computers GmbH - * - * This file is part of tuxedo-io. - * - * 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. - * - * 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 TONGFANG_WMI_H -#define TONGFANG_WMI_H - -#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 void uniwill_init(void) -{ -/* u32 i; - union uw_ec_read_return reg_read_return; - union uw_ec_write_return reg_write_return; - - // FIXME Hard set balanced profile until we have implemented a way to - // switch it while tuxedo_io is loaded - uw_ec_write_addr(0x51, 0x07, 0x00, 0x00, ®_write_return); - - // Set manual-mode fan-curve in 0x0743 - 0x0747 - // Some kind of default fan-curve is stored in 0x0786 - 0x078a: Using it to initialize manual-mode fan-curve - for (i = 0; i < 5; ++i) { - uw_ec_read_addr(0x86 + i, 0x07, ®_read_return); - uw_ec_write_addr(0x43 + i, 0x07, reg_read_return.bytes.data_low, 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; - -} - -#endif diff --git a/src/tuxedo_io/tuxedo_io.c b/src/tuxedo_io/tuxedo_io.c index 9b61dfc..80c968d 100644 --- a/src/tuxedo_io/tuxedo_io.c +++ b/src/tuxedo_io/tuxedo_io.c @@ -28,7 +28,6 @@ #include #include "../clevo_interfaces.h" #include "../uniwill_interfaces.h" -#include "tongfang_wmi.h" #include "tuxedo_io_ioctl.h" MODULE_DESCRIPTION("Hardware interface for TUXEDO laptops"); @@ -405,10 +404,6 @@ static int __init tuxedo_io_init(void) 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); diff --git a/src/uniwill_interfaces.h b/src/uniwill_interfaces.h index 835fb87..3c1bf45 100644 --- a/src/uniwill_interfaces.h +++ b/src/uniwill_interfaces.h @@ -52,4 +52,22 @@ uniwill_read_ec_ram_t uniwill_read_ec_ram; uniwill_write_ec_ram_t uniwill_write_ec_ram; u32 uniwill_get_active_interface_id(char **id_str); +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; +}; + #endif diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index 7884304..b3dab9a 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -38,24 +38,6 @@ #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); From 2440ed47b5a6be2bfab2f1a99496b4a2db75fc06 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 22 Sep 2021 00:02:49 +0200 Subject: [PATCH 21/23] Remove old uw probe, notifys and event handlers --- src/uniwill_keyboard.h | 96 ------------------------------------------ 1 file changed, 96 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index f2bf3d3..71daba8 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -360,48 +360,6 @@ void uniwill_event_callb(u32 code) } } -/*static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) -{ - struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - - acpi_status status; - int code; - - status = wmi_get_event_data(value, &response); - if (status != AE_OK) { - TUXEDO_ERROR("uniwill handle event -> bad event status\n"); - return; - } - - obj = (union acpi_object *) response.pointer; - if (obj) { - if (obj->type == ACPI_TYPE_INTEGER) { - code = obj->integer.value; - uniwill_event_callb(code); - } else { - TUXEDO_DEBUG("[Ev %d] Unknown event type - %d (%0#6x)\n", guid_nr, obj->type, obj->type); - } - } - - kfree(obj); -}*/ - -/*static void uniwill_wmi_notify0(u32 value, void *context) -{ - uniwill_wmi_handle_event(value, context, 0); -} - -static void uniwill_wmi_notify1(u32 value, void *context) -{ - uniwill_wmi_handle_event(value, context, 1); -} - -static void uniwill_wmi_notify2(u32 value, void *context) -{ - uniwill_wmi_handle_event(value, context, 2); -}*/ - static ssize_t uw_brightness_show(struct device *child, struct device_attribute *attr, char *buffer) { @@ -782,60 +740,6 @@ static int uw_lightbar_remove(struct platform_device *dev) return 0; } -/*static int uniwill_keyboard_probe(struct platform_device *dev) -{ - 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) { - TUXEDO_DEBUG("probe: At least one Uniwill GUID missing\n"); - return -ENODEV; - } - - // Attempt to add event handlers - status = wmi_install_notify_handler(UNIWILL_WMI_EVENT_GUID_0, uniwill_wmi_notify0, NULL); - if (ACPI_FAILURE(status)) { - TUXEDO_ERROR("probe: Failed to install uniwill notify handler 0\n"); - goto err_remove_notifiers; - } - - status = wmi_install_notify_handler(UNIWILL_WMI_EVENT_GUID_1, uniwill_wmi_notify1, NULL); - if (ACPI_FAILURE(status)) { - TUXEDO_ERROR("probe: Failed to install uniwill notify handler 1\n"); - goto err_remove_notifiers; - } - - status = wmi_install_notify_handler(UNIWILL_WMI_EVENT_GUID_2, uniwill_wmi_notify2, NULL); - if (ACPI_FAILURE(status)) { - TUXEDO_ERROR("probe: Failed to install uniwill notify handler 2\n"); - goto err_remove_notifiers; - } - - status = register_keyboard_notifier(&keyboard_notifier_block); - - uw_kbd_bl_init(dev); - - status = uw_lightbar_init(dev); - uw_lightbar_loaded = (status >= 0); - - return 0; - -err_remove_notifiers: - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_0); - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_1); - wmi_remove_notify_handler(UNIWILL_WMI_EVENT_GUID_2); - - return -ENODEV; -}*/ - static int uniwill_keyboard_probe(struct platform_device *dev) { u32 i; From f6226ac07a1f04638b922425bb2046374127da04 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 22 Sep 2021 00:44:51 +0200 Subject: [PATCH 22/23] Expose and clarify uw WMI read/write method as parameter --- src/uniwill_wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/uniwill_wmi.c b/src/uniwill_wmi.c index b3dab9a..40dbc38 100644 --- a/src/uniwill_wmi.c +++ b/src/uniwill_wmi.c @@ -341,5 +341,14 @@ MODULE_DESCRIPTION("Driver for Uniwill WMI interface"); MODULE_VERSION("0.0.1"); MODULE_LICENSE("GPL"); +/* + * If set to true, the module will use the replicated WMI functions + * (direct ec_read/ec_write) to read and write to the EC RAM instead + * of the original. Since the original functions, in all observed cases, + * use excessive delays, they are not preferred. + */ +module_param_cb(ec_direct_io, ¶m_ops_bool, &uniwill_ec_direct, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(ec_direct_io, "Do not use WMI methods to read/write EC RAM (default: true)."); + MODULE_DEVICE_TABLE(wmi, uniwill_wmi_device_ids); MODULE_ALIAS_UNIWILL_WMI(); From 5b57ddbec1ac73997b782f346c3bd22c64f26b18 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 22 Sep 2021 01:39:02 +0200 Subject: [PATCH 23/23] Remove unused return statuses --- src/uniwill_keyboard.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 71daba8..37b2a12 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -575,16 +575,11 @@ static void uniwill_write_lightbar_rgb(u8 red, u8 green, u8 blue) } } -static int uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) +static void uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) { - int status; - uniwill_read_ec_ram(0x0749, red); uniwill_read_ec_ram(0x074a, green); uniwill_read_ec_ram(0x074b, blue); - status = 0; - - return status; } static void uniwill_write_lightbar_animation(bool animation_status) @@ -600,15 +595,11 @@ static void uniwill_write_lightbar_animation(bool animation_status) uniwill_write_ec_ram(0x0748, value); } -static int uniwill_read_lightbar_animation(bool *animation_status) +static void uniwill_read_lightbar_animation(bool *animation_status) { - int status; u8 lightbar_animation_data; - - status = uniwill_read_ec_ram(0x0748, &lightbar_animation_data); + uniwill_read_ec_ram(0x0748, &lightbar_animation_data); *animation_status = (lightbar_animation_data & 0x80) > 0; - - return status; } static int lightbar_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness)