From 821c502823d5438cf9f171009b3b6618e9bdc0b6 Mon Sep 17 00:00:00 2001 From: Christoffer Sandberg Date: Tue, 1 Sep 2020 18:54:07 +0200 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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) {