From 821c502823d5438cf9f171009b3b6618e9bdc0b6 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 1 Sep 2020 18:54:07 +0200 Subject: [PATCH 01/10] Initial classdev lightbar support --- src/uniwill_keyboard.h | 117 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 6b5dcdc..4eb58ef 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -24,6 +24,7 @@ #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" @@ -585,9 +586,113 @@ static int uw_kbd_bl_init(struct platform_device *dev) return status; } -static int uniwill_keyboard_probe(struct platform_device *dev) +#define UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS 0x24 + +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 (__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); + + return status; +} + +static int lightbar_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) +{ + u8 red = 0xff, green = 0xff, blue = 0xff; + if (strpbrk(led_cdev->name, "red") != 0) { + red = brightness; + } else if (strpbrk(led_cdev->name, "green") != 0) { + green = brightness; + } else if (strpbrk(led_cdev->name, "blue") != 0) { + blue = brightness; + } + uniwill_write_lightbar_rgb(red, green, blue); + return 0; +} + +static enum led_brightness lightbar_get(struct led_classdev *led_cdev) +{ + u8 red, green, blue; + uniwill_read_lightbar_rgb(&red, &green, &blue); + if (strpbrk(led_cdev->name, "red") != 0) { + return red; + } else if (strpbrk(led_cdev->name, "green") != 0) { + return green; + } else if (strpbrk(led_cdev->name, "blue") != 0) { + return blue; + } + + return 0; +} + +static struct led_classdev lightbar_led_classdevs[] = { + { + .name = "tuxedo:red:lightbar", + .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, + .brightness_set_blocking = &lightbar_set_blocking, + .brightness_get = &lightbar_get + }, + { + .name = "tuxedo:green:lightbar", + .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, + .brightness_set_blocking = &lightbar_set_blocking, + .brightness_get = &lightbar_get + }, + { + .name = "tuxedo:blue:lightbar", + .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, + .brightness_set_blocking = &lightbar_set_blocking, + .brightness_get = &lightbar_get + } +}; + +static int uniwill_keyboard_probe(struct platform_device *dev) +{ + int status, i; // Look for for GUIDs used on uniwill devices status = @@ -626,6 +731,10 @@ static int uniwill_keyboard_probe(struct platform_device *dev) uw_kbd_bl_init(dev); + for (i = 0; i < 3; ++i) { + led_classdev_register(&dev->dev, &lightbar_led_classdevs[i]); + } + return 0; err_remove_notifiers: @@ -638,6 +747,8 @@ err_remove_notifiers: static int uniwill_keyboard_remove(struct platform_device *dev) { + int i; + // Restore previous backlight enable state if (uniwill_kbd_bl_enable_state_on_start != 0xff) { if (uniwill_kbd_bl_type_rgb_single_color) @@ -652,6 +763,10 @@ static int uniwill_keyboard_remove(struct platform_device *dev) del_timer(&uw_kbd_bl_init_timer); + for (i = 0; i < 3; ++i) { + led_classdev_unregister(&lightbar_led_classdevs[i]); + } + return 0; } From 839f13b350c113f9cd5a6655f65bedfb1dbfb5dc Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 2 Sep 2020 10:18:33 +0200 Subject: [PATCH 02/10] Fix uw lightbar color comparison --- src/uniwill_keyboard.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 4eb58ef..c4bb112 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -25,6 +25,7 @@ #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" @@ -643,11 +644,11 @@ static int uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) static int lightbar_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { u8 red = 0xff, green = 0xff, blue = 0xff; - if (strpbrk(led_cdev->name, "red") != 0) { + if (strstr(led_cdev->name, "red") != NULL) { red = brightness; - } else if (strpbrk(led_cdev->name, "green") != 0) { + } else if (strstr(led_cdev->name, "green") != NULL) { green = brightness; - } else if (strpbrk(led_cdev->name, "blue") != 0) { + } else if (strstr(led_cdev->name, "blue") != NULL) { blue = brightness; } uniwill_write_lightbar_rgb(red, green, blue); @@ -658,11 +659,11 @@ static enum led_brightness lightbar_get(struct led_classdev *led_cdev) { u8 red, green, blue; uniwill_read_lightbar_rgb(&red, &green, &blue); - if (strpbrk(led_cdev->name, "red") != 0) { + if (strstr(led_cdev->name, "red") != NULL) { return red; - } else if (strpbrk(led_cdev->name, "green") != 0) { + } else if (strstr(led_cdev->name, "green") != NULL) { return green; - } else if (strpbrk(led_cdev->name, "blue") != 0) { + } else if (strstr(led_cdev->name, "blue") != NULL) { return blue; } From 8db1b16c790d251fd0f5c2a4b91bb36f4f7b0a21 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 2 Sep 2020 10:21:04 +0200 Subject: [PATCH 03/10] Fix uw kbd bl rgb sysfs removal --- src/uniwill_keyboard.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index c4bb112..1597a34 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -750,10 +750,12 @@ static int uniwill_keyboard_remove(struct platform_device *dev) { int i; + if (uniwill_kbd_bl_type_rgb_single_color) { + sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); + } + // Restore previous backlight enable state if (uniwill_kbd_bl_enable_state_on_start != 0xff) { - if (uniwill_kbd_bl_type_rgb_single_color) - sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); uniwill_write_kbd_bl_enable(uniwill_kbd_bl_enable_state_on_start); } From a3e69ca8f9f63e453a0bfb6fe47804b96854e37e Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 2 Sep 2020 10:59:03 +0200 Subject: [PATCH 04/10] Change uw lightbar led names for possible future compliance --- src/uniwill_keyboard.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 1597a34..88b3495 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -644,11 +644,11 @@ static int uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) static int lightbar_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { u8 red = 0xff, green = 0xff, blue = 0xff; - if (strstr(led_cdev->name, "red") != NULL) { + if (strstr(led_cdev->name, ":1:") != NULL) { red = brightness; - } else if (strstr(led_cdev->name, "green") != NULL) { + } else if (strstr(led_cdev->name, ":2:") != NULL) { green = brightness; - } else if (strstr(led_cdev->name, "blue") != NULL) { + } else if (strstr(led_cdev->name, ":3:") != NULL) { blue = brightness; } uniwill_write_lightbar_rgb(red, green, blue); @@ -659,11 +659,11 @@ static enum led_brightness lightbar_get(struct led_classdev *led_cdev) { u8 red, green, blue; uniwill_read_lightbar_rgb(&red, &green, &blue); - if (strstr(led_cdev->name, "red") != NULL) { + if (strstr(led_cdev->name, ":1:") != NULL) { return red; - } else if (strstr(led_cdev->name, "green") != NULL) { + } else if (strstr(led_cdev->name, ":2:") != NULL) { return green; - } else if (strstr(led_cdev->name, "blue") != NULL) { + } else if (strstr(led_cdev->name, ":3:") != NULL) { return blue; } @@ -672,19 +672,19 @@ static enum led_brightness lightbar_get(struct led_classdev *led_cdev) static struct led_classdev lightbar_led_classdevs[] = { { - .name = "tuxedo:red:lightbar", + .name = "tuxedo_lightbar:1:status", .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get }, { - .name = "tuxedo:green:lightbar", + .name = "tuxedo_lightbar:2:status", .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get }, { - .name = "tuxedo:blue:lightbar", + .name = "tuxedo_lightbar:3:status", .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get From 50f8afdf75b1d30736f8e73905a146802a0d5e41 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 2 Sep 2020 14:14:03 +0200 Subject: [PATCH 05/10] Add uw lightbar "animation led" --- src/uniwill_keyboard.h | 127 +++++++++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 19 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 88b3495..76760e7 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -588,6 +588,10 @@ static int uw_kbd_bl_init(struct platform_device *dev) } #define UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS 0x24 +#define UNIWILL_LIGHTBAR_LED_NAME_RGB_RED "lightbar_rgb:1:status" +#define UNIWILL_LIGHTBAR_LED_NAME_RGB_GREEN "lightbar_rgb:2:status" +#define UNIWILL_LIGHTBAR_LED_NAME_RGB_BLUE "lightbar_rgb:3:status" +#define UNIWILL_LIGHTBAR_LED_NAME_ANIMATION "lightbar_animation::status" static void uniwill_write_lightbar_rgb(u8 red, u8 green, u8 blue) { @@ -641,30 +645,109 @@ static int uniwill_read_lightbar_rgb(u8 *red, u8 *green, u8 *blue) 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); + } else { + TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); + } + + if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); + if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); +} + +static int uniwill_read_lightbar_animation(bool *animation_status) +{ + 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(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); + + return status; +} + static int lightbar_set_blocking(struct led_classdev *led_cdev, enum led_brightness brightness) { u8 red = 0xff, green = 0xff, blue = 0xff; - if (strstr(led_cdev->name, ":1:") != NULL) { - red = brightness; - } else if (strstr(led_cdev->name, ":2:") != NULL) { - green = brightness; - } else if (strstr(led_cdev->name, ":3:") != NULL) { - blue = brightness; + bool led_red = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_RED) != NULL; + bool led_green = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_GREEN) != NULL; + bool led_blue = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_BLUE) != NULL; + bool led_animation = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_ANIMATION) != NULL; + + if (led_red || led_green || led_blue) { + if (led_red) { + red = brightness; + } else if (led_green) { + green = brightness; + } else if (led_blue) { + blue = brightness; + } + uniwill_write_lightbar_rgb(red, green, blue); + // Also make sure the animation is off + uniwill_write_lightbar_animation(false); + } else if (led_animation) { + if (brightness == 1) { + uniwill_write_lightbar_animation(true); + } else { + uniwill_write_lightbar_animation(false); + } } - uniwill_write_lightbar_rgb(red, green, blue); return 0; } static enum led_brightness lightbar_get(struct led_classdev *led_cdev) { u8 red, green, blue; - uniwill_read_lightbar_rgb(&red, &green, &blue); - if (strstr(led_cdev->name, ":1:") != NULL) { - return red; - } else if (strstr(led_cdev->name, ":2:") != NULL) { - return green; - } else if (strstr(led_cdev->name, ":3:") != NULL) { - return blue; + bool animation_status; + bool led_red = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_RED) != NULL; + bool led_green = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_GREEN) != NULL; + bool led_blue = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_RGB_BLUE) != NULL; + bool led_animation = strstr(led_cdev->name, UNIWILL_LIGHTBAR_LED_NAME_ANIMATION) != NULL; + + if (led_red || led_green || led_blue) { + uniwill_read_lightbar_rgb(&red, &green, &blue); + if (led_red) { + return red; + } else if (led_green) { + return green; + } else if (led_blue) { + return blue; + } + } else if (led_animation) { + uniwill_read_lightbar_animation(&animation_status); + return animation_status ? 1 : 0; } return 0; @@ -672,22 +755,28 @@ static enum led_brightness lightbar_get(struct led_classdev *led_cdev) static struct led_classdev lightbar_led_classdevs[] = { { - .name = "tuxedo_lightbar:1:status", + .name = UNIWILL_LIGHTBAR_LED_NAME_RGB_RED, .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get }, { - .name = "tuxedo_lightbar:2:status", + .name = UNIWILL_LIGHTBAR_LED_NAME_RGB_GREEN, .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get }, { - .name = "tuxedo_lightbar:3:status", + .name = UNIWILL_LIGHTBAR_LED_NAME_RGB_BLUE, .max_brightness = UNIWILL_LIGHTBAR_LED_MAX_BRIGHTNESS, .brightness_set_blocking = &lightbar_set_blocking, .brightness_get = &lightbar_get + }, + { + .name = UNIWILL_LIGHTBAR_LED_NAME_ANIMATION, + .max_brightness = 1, + .brightness_set_blocking = &lightbar_set_blocking, + .brightness_get = &lightbar_get } }; @@ -732,7 +821,7 @@ static int uniwill_keyboard_probe(struct platform_device *dev) uw_kbd_bl_init(dev); - for (i = 0; i < 3; ++i) { + for (i = 0; i < 4; ++i) { led_classdev_register(&dev->dev, &lightbar_led_classdevs[i]); } @@ -766,7 +855,7 @@ static int uniwill_keyboard_remove(struct platform_device *dev) del_timer(&uw_kbd_bl_init_timer); - for (i = 0; i < 3; ++i) { + for (i = 0; i < 4; ++i) { led_classdev_unregister(&lightbar_led_classdevs[i]); } From 0d954602b59b6fa91f067bb3186246fdc91fa831 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 28 Oct 2020 17:08:32 +0100 Subject: [PATCH 06/10] uw_lightbar: Fix init structure --- src/uniwill_keyboard.h | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 76760e7..33201c4 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -753,6 +753,7 @@ static enum led_brightness lightbar_get(struct led_classdev *led_cdev) return 0; } +static bool uw_lightbar_loaded; static struct led_classdev lightbar_led_classdevs[] = { { .name = UNIWILL_LIGHTBAR_LED_NAME_RGB_RED, @@ -780,9 +781,33 @@ static struct led_classdev lightbar_led_classdevs[] = { } }; +static int uw_lightbar_init(struct platform_device *dev) +{ + int i, j, status; + for (i = 0; i < ARRAY_SIZE(lightbar_led_classdevs); ++i) { + status = led_classdev_register(&dev->dev, &lightbar_led_classdevs[i]); + if (status < 0) { + for (j = 0; j < i; j++) + led_classdev_unregister(&lightbar_led_classdevs[j]); + return status; + } + } + + return 0; +} + +static int uw_lightbar_remove(struct platform_device *dev) +{ + int i; + for (i = 0; i < ARRAY_SIZE(lightbar_led_classdevs); ++i) { + led_classdev_unregister(&lightbar_led_classdevs[i]); + } + return 0; +} + static int uniwill_keyboard_probe(struct platform_device *dev) { - int status, i; + int status; // Look for for GUIDs used on uniwill devices status = @@ -821,9 +846,8 @@ static int uniwill_keyboard_probe(struct platform_device *dev) uw_kbd_bl_init(dev); - for (i = 0; i < 4; ++i) { - led_classdev_register(&dev->dev, &lightbar_led_classdevs[i]); - } + status = uw_lightbar_init(dev); + uw_lightbar_loaded = (status >= 0); return 0; @@ -837,7 +861,6 @@ err_remove_notifiers: static int uniwill_keyboard_remove(struct platform_device *dev) { - int i; if (uniwill_kbd_bl_type_rgb_single_color) { sysfs_remove_group(&dev->dev.kobj, &uw_kbd_bl_color_attr_group); @@ -855,9 +878,8 @@ static int uniwill_keyboard_remove(struct platform_device *dev) del_timer(&uw_kbd_bl_init_timer); - for (i = 0; i < 4; ++i) { - led_classdev_unregister(&lightbar_led_classdevs[i]); - } + if (uw_lightbar_loaded) + uw_lightbar_remove(dev); return 0; } From a28f8858ac059f43d87e5d557c7c6aa40061cb93 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 29 Oct 2020 12:09:48 +0100 Subject: [PATCH 07/10] uw_lightbar: Add compatible device check --- src/uniwill_keyboard.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 33201c4..922af27 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -784,6 +784,14 @@ static struct led_classdev lightbar_led_classdevs[] = { static int uw_lightbar_init(struct platform_device *dev) { int i, j, status; + + bool lightbar_supported = false + || dmi_match(DMI_BOARD_NAME, "LAPQC71A") + || dmi_match(DMI_BOARD_NAME, "LAPQC71B") + ; + if (!lightbar_supported) + return -ENODEV; + for (i = 0; i < ARRAY_SIZE(lightbar_led_classdevs); ++i) { status = led_classdev_register(&dev->dev, &lightbar_led_classdevs[i]); if (status < 0) { From d035d7afb08228fac84cfebb64fe3f84526b559e Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Fri, 30 Oct 2020 12:17:17 +0100 Subject: [PATCH 08/10] uniwill: Refactor and simplify external symbol handling tuxedo-cc-mwi symbols now used in many places. Until further aggregation some wrappers are needed for clarity. --- src/uniwill_keyboard.h | 149 ++++++++--------------------------------- src/uw_io.h | 102 ++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 122 deletions(-) create mode 100644 src/uw_io.h diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index 922af27..c87b8fb 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -26,6 +26,7 @@ #include #include #include +#include "uw_io.h" #define UNIWILL_WMI_MGMT_GUID_BA "ABBC0F6D-8EA1-11D1-00A0-C90629100000" #define UNIWILL_WMI_MGMT_GUID_BB "ABBC0F6E-8EA1-11D1-00A0-C90629100000" @@ -53,30 +54,6 @@ #define UNIWILL_BRIGHTNESS_DEFAULT UNIWILL_BRIGHTNESS_MAX * 0.30 #define UNIWILL_COLOR_DEFAULT 0xffffff -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; - struct tuxedo_keyboard_driver uniwill_keyboard_driver; struct kbd_led_state_uw_t { @@ -152,22 +129,11 @@ static struct notifier_block keyboard_notifier_block = { static u8 uniwill_read_kbd_bl_enabled(void) { union uw_ec_read_return reg_read_return; - - uw_ec_read_func *__uw_ec_read_addr; - u8 enabled = 0xff; - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - - if (__uw_ec_read_addr) { - __uw_ec_read_addr(0x8c, 0x07, ®_read_return); - enabled = (reg_read_return.bytes.data_low >> 1) & 0x01; - enabled = !enabled; - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); + __uw_ec_read_addr(0x8c, 0x07, ®_read_return); + enabled = (reg_read_return.bytes.data_low >> 1) & 0x01; + enabled = !enabled; return enabled; } @@ -176,27 +142,13 @@ 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; - - uw_ec_read_func *__uw_ec_read_addr; - uw_ec_write_func *__uw_ec_write_addr; - u8 write_value = 0; enable = enable & 0x01; - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - __uw_ec_write_addr = symbol_get(uw_ec_write_addr); - - if (__uw_ec_read_addr && __uw_ec_write_addr) { - __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); - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); - if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); + __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); } /*static u32 uniwill_read_kbd_bl_br_state(u8 *brightness_state) @@ -204,18 +156,9 @@ static void uniwill_write_kbd_bl_enable(u8 enable) union uw_ec_read_return reg_read_return; u32 result; - 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(0x8c, 0x07, ®_read_return); - *brightness_state = (reg_read_return.bytes.data_low & 0xf0) >> 4; - result = 0; - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - result = -EIO; - } + __uw_ec_read_addr(0x8c, 0x07, ®_read_return); + *brightness_state = (reg_read_return.bytes.data_low & 0xf0) >> 4; + result = 0; return result; }*/ @@ -225,24 +168,13 @@ 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_func *__uw_ec_read_addr; - - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - - if (__uw_ec_read_addr) { - __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; - result = 0; - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - result = -EIO; - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); + __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; + result = 0; return result; } @@ -251,27 +183,14 @@ static void uniwill_write_kbd_bl_rgb(u8 red, u8 green, u8 blue) { union uw_ec_write_return reg_write_return; - uw_ec_read_func *__uw_ec_read_addr; - uw_ec_write_func *__uw_ec_write_addr; - - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - __uw_ec_write_addr = symbol_get(uw_ec_write_addr); - - if (__uw_ec_read_addr && __uw_ec_write_addr) { - // 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); - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); - if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); + // 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); } static void uniwill_write_kbd_bl_state(void) { @@ -298,22 +217,8 @@ static void uniwill_write_kbd_bl_state(void) { static void uniwill_write_kbd_bl_reset(void) { union uw_ec_write_return reg_write_return; - union uw_ec_read_return reg_read_return; - uw_ec_read_func *__uw_ec_read_addr; - uw_ec_write_func *__uw_ec_write_addr; - - __uw_ec_read_addr = symbol_get(uw_ec_read_addr); - __uw_ec_write_addr = symbol_get(uw_ec_write_addr); - - if (__uw_ec_read_addr && __uw_ec_write_addr) { - __uw_ec_write_addr(0x8c, 0x07, 0x10, 0x00, ®_write_return); - } else { - TUXEDO_DEBUG("tuxedo-cc-wmi symbols not found\n"); - } - - if (__uw_ec_read_addr) symbol_put(uw_ec_read_addr); - if (__uw_ec_write_addr) symbol_put(uw_ec_write_addr); + __uw_ec_write_addr(0x8c, 0x07, 0x10, 0x00, ®_write_return); } static void uniwill_wmi_handle_event(u32 value, void *context, u32 guid_nr) diff --git a/src/uw_io.h b/src/uw_io.h new file mode 100644 index 0000000..ea4b639 --- /dev/null +++ b/src/uw_io.h @@ -0,0 +1,102 @@ +/* +* uw_io.h +* +* Copyright (C) 2018-2020 TUXEDO Computers GmbH +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#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 eea83c3a37836e302003f1fb051d64e34cb84bc1 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Wed, 11 Nov 2020 15:55:45 +0100 Subject: [PATCH 09/10] uw: Fix touchpad toggle Actually only returning notify stop on last key messes up some platforms leading to that next toggle does not register. Should either stop all or none. From now stopping none. --- src/uniwill_keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index c87b8fb..a5fe5b9 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -110,7 +110,7 @@ static int keyboard_notifier_callb(struct notifier_block *nb, unsigned long code if (prevprev_key == 85 && prev_key == 29) { TUXEDO_DEBUG("Touchpad Toggle\n"); schedule_work(&uniwill_key_event_work); - ret = NOTIFY_STOP; + ret = NOTIFY_OK; } break; } From a95d0ecdd5c7d694343f585d901cb95ea286bebd Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Thu, 12 Nov 2020 10:57:45 +0100 Subject: [PATCH 10/10] uw: Add keyboard brightness up/down mapping --- src/uniwill_keyboard.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/uniwill_keyboard.h b/src/uniwill_keyboard.h index a5fe5b9..5d1a581 100644 --- a/src/uniwill_keyboard.h +++ b/src/uniwill_keyboard.h @@ -46,6 +46,8 @@ #define UNIWILL_OSD_DC_ADAPTER_CHANGE 0x0AB #define UNIWILL_KEY_RFKILL 0x0A4 +#define UNIWILL_KEY_KBDILLUMDOWN 0x0B1 +#define UNIWILL_KEY_KBDILLUMUP 0x0B2 #define UNIWILL_OSD_TOUCHPADWORKAROUND 0xFFF @@ -74,6 +76,9 @@ static struct key_entry uniwill_wmi_keymap[] = { // Manual mode rfkill { KE_KEY, UNIWILL_KEY_RFKILL, { KEY_RFKILL }}, { KE_KEY, UNIWILL_OSD_TOUCHPADWORKAROUND, { KEY_F21 } }, + // Keyboard brightness + { KE_KEY, UNIWILL_KEY_KBDILLUMDOWN, { KEY_KBDILLUMDOWN } }, + { KE_KEY, UNIWILL_KEY_KBDILLUMUP, { KEY_KBDILLUMUP } }, // Only used to put ev bits { KE_KEY, 0xffff, { KEY_F6 } }, { KE_KEY, 0xffff, { KEY_LEFTALT } },