Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

screen brightness #1

Open
s-light opened this issue Dec 7, 2019 · 50 comments
Open

screen brightness #1

s-light opened this issue Dec 7, 2019 · 50 comments
Labels
bug Something isn't working enhancement New feature or request

Comments

@s-light
Copy link
Owner

s-light commented Dec 7, 2019

research how screenbrightness is handled by windows..
then implement for linux.

@s-light s-light added bug Something isn't working enhancement New feature or request labels Dec 7, 2019
@T-Grave
Copy link

T-Grave commented Dec 16, 2019

I saw you managed to make brightness control work using icc-brightness; how did you set it up for both displays?

After running the tool I only managed to change the brightness of the second display, which even on maximum seems rather dim in comparison to the main display (which is probably at full brightness, so that could be why).

It's also a bit buggy, when I change the brightness, it is like the display is flickering to max brightness for a split second first.

Any pointers on this?

Thanks for all of your investigation so far, it's been really helpful!

@s-light
Copy link
Owner Author

s-light commented Dec 17, 2019

hello @T-Grave ,
great you found the information :-)

i have setup icc-brightness just as in the orig. repository readme.
and with this it is working for me for the main screen (the top one = OLED)
(but i loose the color-resolution of course....)
sometimes icc-brightness gets buggy. then not every brightness step is working.
if this happens i just do a $ icc-brightness clean this deletes the automatically generated profiles.
and then it is working again..

i dont see any flickering..

for the bottom screen i have currently no way to dim it.
i experimented a little bit with DDC (Display Data Channel) and the I2C devices i found..
but did not get any results yet..
i think / hope that is the way it is done undder windows...

there are some basic information out there:

for me that is what i tried so far:

$ i2cdetect -l
i2c-3   i2c             i915 gmbus dpb                          I2C adapter
i2c-10  i2c             DPDDC-D                                 I2C adapter
i2c-1   smbus           SMBus I801 adapter at efa0              SMBus adapter
i2c-8   i2c             DPDDC-A                                 I2C adapter
i2c-6   i2c             i915 gmbus dpd                          I2C adapter
i2c-13  i2c             NVIDIA i2c adapter 1 at 1:00.0          I2C adapter
i2c-4   i2c             i915 gmbus dpc                          I2C adapter
i2c-11  i2c             Synopsys DesignWare I2C adapter         I2C adapter
i2c-2   i2c             Synopsys DesignWare I2C adapter         I2C adapter
i2c-0   i2c             NVIDIA GPU I2C adapter                  I2C adapter
i2c-9   i2c             DPDDC-B                                 I2C adapter
i2c-7   i2c             Synopsys DesignWare I2C adapter         I2C adapter
i2c-14  i2c             NVIDIA i2c adapter 7 at 1:00.0          I2C adapter
i2c-5   i2c             i915 gmbus misc                         I2C adapter
i2c-12  i2c             Synopsys DesignWare I2C adapter         I2C adapter

but ddcutil detect only partly works:

$ ddcutil detect
Failure getting EDID for /dev/i2c-0: status code=EOPNOTSUPP(-95): Operation not supported
Invalid display
   I2C bus:             /dev/i2c-8
   EDID synopsis:
      Mfg id:           SDC
      Model:            Unspecified
      Serial number:    Unspecified
      Manufacture year: 2019
      EDID version:     1.4
   DDC communication failed

Invalid display
   I2C bus:             /dev/i2c-10
   EDID synopsis:
      Mfg id:           BOE
      Model:            Unspecified
      Serial number:    Unspecified
      Manufacture year: 2019
      EDID version:     1.4
   DDC communication failed

i had no time to try the fix mentioned for nvidia cards yet..
and i don't tried ddccontrol

the other idea i had was to start windows and try to get som traces with wireshark - hopefully finding if the system is doing the brightness changes per i2c...

@T-Grave
Copy link

T-Grave commented Dec 17, 2019

I also checked out ddcutil and gave it a try with the verbose option.

This appears to be a laptop display. Laptop displays do not support DDC/CI.

So I guess DDC won't be an option 😞

Below the full output of ddcutil detect --verbose gave me the following output:

Output level:               Verbose
Reporting DDC data errors:  false
Trace groups active:        none
Traced functions:           none
Traced files:               none
Force I2C slave address:    false

Invalid display
   I2C bus:             /dev/i2c-7
      I2C address 0x30 (EDID block#)  present: false
      I2C address 0x37 (DDC)          present: false
      I2C address 0x50 (EDID)         present: true 
      /sys/bus/i2c/devices/i2c-7/name: DPDDC-A
   EDID synopsis:
      Mfg id:           SDC
      Model:            Unspecified
      Serial number:    Unspecified
      Manufacture year: 2019
      EDID version:     1.4
      Product code:     41001
      Extra descriptor: Unspecified
      Video input definition: 0xb5 - Digital Input (DisplayPort)
      Supported features:
         Digital display type: RGB 4:4:4
         Standard sRGB color space: False
      White x,y:        0.312, 0.329
      Red   x,y:        0.685, 0.312
      Green x,y:        0.243, 0.707
      Blue  x,y:        0.139, 0.055
      Extension blocks: 1
   EDID source: 
   EDID hex dump:
              +0          +4          +8          +c            0   4   8   c   
      +0000   00 ff ff ff ff ff ff 00 4c 83 29 a0 00 00 00 00   ........L.).....
      +0010   08 1d 01 04 b5 22 13 78 02 44 81 af 50 3e b5 23   .....".x.D..P>.#
      +0020   0e 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01   .PT.............
      +0030   01 01 01 01 01 01 fd df 00 30 f2 70 0c 80 30 20   .........0.p..0 
      +0040   44 00 58 c2 10 00 00 1b fd df 00 30 f2 70 0c 80   D.X........0.p..
      +0050   30 20 44 00 58 c2 10 00 00 1b 00 00 00 0f 00 ff   0 D.X...........
      +0060   09 3c ff 09 3c 2c 80 00 00 00 00 00 00 00 00 10   .<..<,..........
      +0070   00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 4a   ...............J
   DDC communication failed
   This appears to be a laptop display. Laptop displays do not support DDC/CI.

Invalid display
   I2C bus:             /dev/i2c-9
      I2C address 0x30 (EDID block#)  present: false
      I2C address 0x37 (DDC)          present: false
      I2C address 0x50 (EDID)         present: true 
      /sys/bus/i2c/devices/i2c-9/name: DPDDC-D
   EDID synopsis:
      Mfg id:           BOE
      Model:            Unspecified
      Serial number:    Unspecified
      Manufacture year: 2019
      EDID version:     1.4
      Product code:     2143
      Extra descriptor: Unspecified
      Video input definition: 0xa5 - Digital Input (DisplayPort)
      Supported features:
         Digital display type: RGB 4:4:4
         Standard sRGB color space: False
      White x,y:        0.312, 0.328
      Red   x,y:        0.640, 0.329
      Green x,y:        0.300, 0.600
      Blue  x,y:        0.149, 0.060
      Extension blocks: 0
   EDID source: 
   EDID hex dump:
              +0          +4          +8          +c            0   4   8   c   
      +0000   00 ff ff ff ff ff ff 00 09 e5 5f 08 00 00 00 00   .........._.....
      +0010   01 1d 01 04 a5 22 0a 78 02 de 50 a3 54 4c 99 26   .....".x..P.TL.&
      +0020   0f 50 54 00 00 00 01 01 01 01 01 01 01 01 01 01   .PT.............
      +0030   01 01 01 01 01 01 a8 6b 00 a0 f0 4c 30 40 30 20   .......k...L0@0 
      +0040   35 00 58 63 10 00 00 1a 22 56 00 a0 f0 4c 30 40   5.Xc...."V...L0@
      +0050   30 20 35 00 58 63 10 00 00 1a 2e 1d 80 a0 70 26   0 5.Xc........p&
      +0060   30 20 30 20 35 00 58 63 10 00 00 1a 5c 17 80 a0   0 0 5.Xc....\...
      +0070   70 26 30 20 30 20 35 00 58 63 10 00 00 1a 00 bb   p&0 0 5.Xc......
   DDC communication failed
   This appears to be a laptop display. Laptop displays do not support DDC/CI.

@T-Grave
Copy link

T-Grave commented Dec 17, 2019

An update on using icc-brightness: after using the clean command, it now controls my main display instead of the ScreenPad Plus. But I still have the flicker. Since you're not experiencing the flicker I suspect it has something to do with GNOME (I'm using PopOS).

With the main display it is even clearer; the flicker is really the panel changing to max brightness for a split second right before it drops to the new requested value. I suspect the display (or gnome) is responding to me pressing the brightness button (but just setting max brightness because it doesn't know better) right before the icc-brightness watch kicks in.

When I have time I will see how it behaves when I use the command line instead of the buttons to confirm my suspicions.

Also, while reading this I think using ICC or xrandr is probably the only existing solution we will be able to use for the main display, as it would be related to the panel being OLED.

There is multiple threads on "why doesn't linux kernel support brightness controls on OLED panels yet" and one of them actually mentions a laptop from System76, shipping with PopOS that has an OLED panel and the brightness control works out of the box on it. We might find some clues there as well.

If I can find out how, I will try and figure out how windows is setting the brightness. But I have not got a lot of experience with WireShark apart from actual network diagnostics and I have trouble finding guides on how to apply it for something else then network readings :)

Edit:

After another reboot and icc brightness is changing the brightness of my bottom screen again.
So it's definitely possible to target the screen with the techniques the tool uses.

Using the cli directly instead of the watch/service causes no flicker, so my assumptions about something else (probably GNOME related) trying to adjust brightness (and failing) when I use the buttons right before icc-brightness does its thing is probably correct.

@s-light
Copy link
Owner Author

s-light commented Dec 18, 2019

i had tested the xrandr thing to dim the bottom screen and - yes this works -
but not really:
icc-brightness and also xrandr --brightness *value*

Multiply the gamma values on the crtc currently attached to the output to specified floating value. Useful for overly bright or overly dim outputs. However, this is a software only modification, if your hardware has support to actually change the brightness, you will probably prefer to use xbacklight.

→ you loose color-quality / color-resolution if you dim this way...

and

$ xbacklight -display DP-1-2 -get
RANDR Query Version returned error -1
$ xbacklight -display eDP-1-1 -get
RANDR Query Version returned error -1

also does not work...

and if you dim the bottom screen to 0% and are in a dark place you will see that the background is still brightly shining...
same happens if you 'switch off' the screens with sleep 1s; xset dpms force off
(i have configured this as a shortcut action for Meta + C - is sometimes helpful if my screen is distracting me to much from something else ;-) )

regarding WireShark - i just have looked up - and it is not possible out of the box to capture i2c. :-(
my next idea is to try if the python smbus2 package is working on windows.....
but currently i have no time to test... :-(

@s-light
Copy link
Owner Author

s-light commented Dec 18, 2019

just scrolled through the arch-wiki backlight page:

Note: Since OLED screens have no backlight, brightness cannot be controlled by changing backlight power on laptops equipped with an OLED screen. In this case see, perceived screen brightness can only be adjusted via software color correction.

I think this is partly wrong!
it is correct that OLEDs are the light-sources themselves...
and so have no discrete backlight.
but from a controll-point-of-view i think most of the panels have some additonal way to control the overall brightness - i will have to check this again -
but iam very confident in this ;-)

there are reports about pwm-flickering problems with dimmed oled-panels..
(that could be a hint to a panel-wide pwm-dimming..)

@T-Grave
Copy link

T-Grave commented Dec 18, 2019

there are reports about pwm-flickering problems with dimmed oled-panels..
(that could be a hint to a panel-wide pwm-dimming..)

I just noticed your comment in this thread as well on someone who did have luck with PWM based brightness control on their OLED display.

https://www.reddit.com/r/linux/comments/cmf0vi/the_state_of_oled_brightness_on_linux/

I really do hope you are right tho!

For now I'll be going with the xrandr option, at least for the main display, since icc-brightness is rather buggy and the end result is about the same (they both have the color degradation issue as well at low brightness). Found the following script which could be used to hook up the brightness keys to xrandr automatically.

#!/bin/sh

path=/sys/class/backlight/intel_backlight

luminance() {
    read -r level < "$path"/actual_brightness
    factor=$((max))
    new_brightness="$(bc -l <<< "scale = 2; $level / $factor")"
    echo "${new_brightness}"
}

read -r max < "$path"/max_brightness

xrandr --output eDP1 --brightness "$(luminance)"

inotifywait -me modify "$path"/actual_brightness | while read; do
    xrandr --output eDP1 --brightness "$(luminance)"
done

@T-Grave
Copy link

T-Grave commented Dec 18, 2019

i had tested the xrandr thing to dim the bottom screen and - yes this works -

This is already helpful for me to brighten up the bottom screen; seems like it's set to 0.75 by default (at least for me) which is not bright enough in daylight conditions at the office.

While the top screen is at least already consuming less energy using this method (because of how OLED works), the bottom screen will still consume full energy when using xrandr/icc-brightness since it's a LED/LCD display.

It being a LED/LCD display however, means it should be controllable through ACPI just like any other display I think. The problem is the linux kernel doesn't expect two internal displays, so it's not available by default.

I've come across similar issues with another Asus notebook from 2014, the Taichi31. It was slightly different, because it had a second screen on the back, which could be used as a tablet and thus they already had issues with having them both turned on at the same time. But I think the way it was hooked up was very similar: both using eDPI1 for main and DPI1 for second.

https://bugs.freedesktop.org/show_bug.cgi?id=73156
https://bugzilla.kernel.org/show_bug.cgi?id=68631

Which also led me to this:
https://github.com/torvalds/linux/blob/master/drivers/platform/x86/asus-nb-wmi.c

Have you tried enabling that kernel module? Also seems like it contains specific mappers for specific Asus devices and while it's mainly something to make the hotkeys work better, I think there's also more specific brightness control tools in there. at least, going off the following comment in one of those bug reports:

What happens if you change backlight using the asus-nb-wmi interface directly, i.e. sudo sh -c "echo N > /sys/class/backlight/asus-nb-wmi/brightness" where N is a value between 0 and cat /sys/class/backlight/asus-nb-wmi/max_brightness?

As for an alternative to wireshark monitoring:

I might have found something interesting in the following bug report:

If anyone can enable CONFIG_DRM_DP_AUX_CHARDEV=y and dump the DPCD using the
aux chardev (IIRC should pop up somewhere under /sys/class/drm/card0-eDP-1),
it might give some clues.

I'm definitely no expert on these things, but I already came across DP aux channel monitoring before when I was trying to find out how the interface might be potentially used to communicate back-light control, so this looks interesting.

All tho it might not be all to useful, since the goal is probably to record whatever is happening in there when we're actually changing the back-light in windows and this is linux specific. It is part of the kernel tho and some parts of the linux kernel are available in windows, so there's a slim chance we could get something like that setup in there.

@s-light
Copy link
Owner Author

s-light commented Dec 18, 2019

wow - that looks promising!

i don't think i have enabled the asus_nb_wmi module... have to check..
i hope i get some time in one or two weeks to test and experiment with this a little more!
thanks for reporting your finds!

@T-Grave
Copy link

T-Grave commented Dec 18, 2019

Just setup the automatic xrandr script, only to find out it also causes flickering. I suspect the hotkeys are actually triggering something somewhere to reset the brightness to 1.

update
So, since you weren't having the issue using KDE and I do using GNOME, I went looking what parts of GNOME also control brightness (it's about 2 or 3 different services).

Sooo instead of disabling parts of those 3 services I thought I might try a GNOME Extension I came across while looking into the issue: OLED Dimmer

And it worked out of the box, without the flickering, which is great.
Interesting to note: it actually adjusts both screens at the same time, I'm going to check out how it works underneath the hood, so I can hopefully adjust it a bit to control both screens separately.

It's not ideal yet for the Screenpad Plus, since I'd rather have the ability to actually control the backlight instead of faking it, but definitely the best quick fix until now when using GNOME.

@s-light
Copy link
Owner Author

s-light commented Dec 18, 2019

i currently have the nvidia drivers installed.

graphic: 
	product: NVIDIA TU106M [GeForce RTX 2060 Mobile]
	driver version: 435.21
	product: Intel UHD Graphics 630 (Mobile)
	driver version:

there is a newer version on the nvidia site - currently the ubuntu official ppa is installed..
the open driver did work some sort of - if i remember correctly...
but i think i read that is is slower in some aspects - and i use my system for 3d rendering - so currently need the full performance..
i also did not try to switch cards to save power...

good you have found a working solution!
i think in the issues of the icc-brightness repo there was a request to enable multi-monitor setting...

@T-Grave
Copy link

T-Grave commented Dec 18, 2019

For reference, I came across these, they look interesting for the main display:

https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1831587
https://bugs.launchpad.net/ubuntu/+source/linux-oem/+bug/1844798

Also, I quickly went over the OLED dimmer code, it's a Gnome only approach and it's about 60 lines of javascript. It applies an effect on top of the entire UI so it's not screen specific either. Looking at the xrandr outputs, the effect it applies translates into the brightness values in xrandr being updated as well, causing my "max brightness" on the secondary panel to be 0.85 :(

It does play nicely with the Night Light GNOME provides by default, so I'll keep it until we figure out a decent way to control the backlights.

@moshemalawach
Copy link

Just bought the UX481FA, which is a lower end (full hd and not oled) version of the zenbook duo.

What is the recommended way to handle brightness? Normal brightness controls work well for main screen, but do nothing for the keyboard one

@s-light
Copy link
Owner Author

s-light commented Mar 1, 2020

we currently do not have any working solution as far as i know!

under windows asus has a custom tool/ui for the second screen brightness.
you could try and experiment / search for set brightness for external monitor -
maybe that is how it is possible..
i currently have no time left to experiment on this - so my second screen is 'stuck' on the brightness it is set to (i don't know for sure if this is 100% could be less).

if you find any additional information please let us know!

@T-Grave
Copy link

T-Grave commented Mar 2, 2020

Until someone figures out how to actually drive the second display's backlight, you can always setup a xrandr cli script to fake the brightness down. This does cause washed out colors at lower values and still uses the exact same amount of power as full brightness for all values. But it does help a bit for the eyes at night :)

You could even go as far as setting up keybindings for it.

@moshemalawach
Copy link

moshemalawach commented Mar 2, 2020 via email

@T-Grave
Copy link

T-Grave commented Mar 6, 2020

@moshemalawach I had the same issue, the default screen brightness was set to 0.75 for the second screen. Setting it to 1 (using xrandr) makes it use full brightness.

@moshemalawach
Copy link

Issue is base brightness of second display is low on my computer and I don't have windows installed anymore to bring it higher :/

@moshemalawach
Copy link

It's already at 1

@rayperea
Copy link

rayperea commented May 3, 2020

I've been able to get my screen brightness on both screens to work for me. I've created a new repository with my code so feel free to check it out and use it:
https://github.com/rayperea/asusZenBookProDuoScreenBrightnessService

My solution takes care of the issue that the bottom display is dimmer than the top display. I was able to get the 2 displays to be pretty much the same brightness

I haven't done any testing on any other systems, only mine:
Arch Linux / Gnome Desktop / Xorg Window System.
However, if you have a different distro, you should be able to modify it to work on your system

Also, here is a demo video of it working on my system:
https://player.vimeo.com/video/414545766

@T-Grave
Copy link

T-Grave commented May 8, 2020

@rayperea Thanks for sharing!

Does it work well with Night Light enabled inside Gnome?

@rayperea
Copy link

@T-Grave
Unfortunately, it doesn't currently work with Night Light at all. As soon as night light is enabled, within a second or two, it reverts back to the non-warm version.

Good news though... getting it work work with Night Light should be easy peasy. We just have to take the current Night Light setting into consideration when setting the brightness using xrandr. When I get a minute or two, I'll update the repo... or, if someone wants to write the code, pull requests are welcome

@Plippo
Copy link

Plippo commented May 22, 2020

Hi there,

I bought the 14 inch model (UX481) last week and while those two are fairly different (for instance my main screen is LCD, not OLED, and brightness control for the main screen worked out of the box) the problem with the brightness of the lower screen is quite similar: under Linux, it was stuck at around 50% brightness and I couldn't control it (or turn it off). So I did some digging through the DSTS code and also watched the behavior of the ASUS Windows software and finally found a way to control the bottom screen brightness in Linux. Using it is quite hack-ish at the moment (it will have to be built into the kernel to work nicely), but it's usable and I think there is a good chance that it also works at the UX581 – I don't see why ASUS should use a different method as the driver software used in Windows is identical for both models.

So, here is how I managed to control bottom screen brightness on my device (use at your own risk):

  • install the acpi_call kernel module using the package from your distribution. In Debian, Ubuntu etc. the package is called acpi-call-dkms
  • load the module using sudo modprobe acpi_call
  • use the following commands to control the bottom screen (they all have to be executed as root - instead of using sudo, you can of course also use a root shell):
    • Change Brightness of the screen:
      echo '\_SB.ATKD.WMNB 0x0 0x53564544 b32000500xx000000' | sudo tee /proc/acpi/call
      where xx is a value between 00 and FF (00 being darkest, FF brightest, 77 in between etc.)
      So for maximum brightness, use:
      echo '\_SB.ATKD.WMNB 0x0 0x53564544 b32000500FF000000' | sudo tee /proc/acpi/call
    • Turn off the screen:
      echo '\_SB.ATKD.WMNB 0x0 0x53564544 b3100050000000000' | sudo tee /proc/acpi/call
    • To turn the screen back on again, just send a brightness command.

I added the acpi_call module to my /etc/modules file so it is loaded at system startup and added the following line to /etc/rc.local in order to turn the screen to full brightness at system start:
echo '\_SB.ATKD.WMNB 0x0 0x53564544 b32000500FF000000' > /proc/acpi/call

I hope it also works for you!

@s-light
Copy link
Owner Author

s-light commented May 22, 2020

Wow!!
Thanks @Plippo for the research & digging!!
i will test this on my device next week and report back!

for the integration: could this be something to go into the asus-nb-wmi module mentioned by T-Grave?

@moshemalawach
Copy link

moshemalawach commented May 22, 2020 via email

@Plippo
Copy link

Plippo commented May 22, 2020

for the integration: could this be something to go into the asus-nb-wmi module mentioned by T-Grave?

I suppose that's the best place, but I didn't have time yet to look into where exactly to put it... as userspace most likely isn't prepared for having two backlight devices, it'll probably have to be as an LED device or something like that.

@s-light
Copy link
Owner Author

s-light commented May 23, 2020

just checked - it works for me :-)
(UX581GV)
thanks @Plippo 👍 🎉

@Plippo
Copy link

Plippo commented May 24, 2020

I've added support for brightness control to the asus-wmi kernel module. To test it, you can build and load the module using DKMS. I've described the process here: https://github.com/Plippo/asus-wmi-screenpad/blob/master/README.md
It would be great if you could try it out and look if the module (and the instructions) work for you!
Setting the brightness still requires the command line at the moment, but with the kernel module, the commands are much more user friendly.

@s-light
Copy link
Owner Author

s-light commented May 24, 2020

looks great!!
i will test your patched asus-wmi tomorrow!

just a side note:
the minimum value that switches the backligt on for me is 04
echo '\_SB.ATKD.WMNB 0x0 0x53564544 b3200050004000000' | sudo tee /proc/acpi/call

out of interesst: could you describe a bit more in detail what you have done to find these calls?!
i would like to dig into the oled brigntess control if i find time..

@s-light
Copy link
Owner Author

s-light commented May 24, 2020

my curiosity was to big - so i tried it direclt - but it failed during compile time:

stefan@stefan-Zen:~/mydata/github$ git clone https://github.com/Plippo/asus-wmi-screenpad.git
Cloning into 'asus-wmi-screenpad'...
remote: Enumerating objects: 32, done.
remote: Counting objects: 100% (32/32), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 32 (delta 11), reused 17 (delta 3), pack-reused 0
Unpacking objects: 100% (32/32), done.
stefan@stefan-Zen:~/mydata/github$ sudo ln -sf ~/mydata/github/asus-wmi-screenpad/ /usr/src/asus-wmi-1.0
stefan@stefan-Zen:~/mydata/github$ ll /usr/src/asus*
lrwxrwxrwx 1 root root 46 2020-05-24 23:20:06.270 /usr/src/asus-wmi-1.0 -> /home/stefan/mydata/github/asus-wmi-screenpad//
stefan@stefan-Zen:~/mydata/github$ sudo lsudo dkms add -m asus-wmi -v 1.0

Creating symlink /var/lib/dkms/asus-wmi/1.0/source ->
                 /usr/src/asus-wmi-1.0

DKMS: add completed.
stefan@stefan-Zen:~/mydata/github$ sudo dkms build -m asus-wmi -v 1.0

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area...
make -j16 KERNELRELEASE=5.3.0-55-generic -C /lib/modules/5.3.0-55-generic/build M=/var/lib/dkms/asus-wmi/1.0/build...(bad exit status: 2)
ERROR (dkms apport): binary package for asus-wmi: 1.0 not found
Error! Bad return status for module build on kernel: 5.3.0-55-generic (x86_64)
Consult /var/lib/dkms/asus-wmi/1.0/build/make.log for more information.
stefan@stefan-Zen:~/mydata/github$ cat /var/lib/dkms/asus-wmi/1.0/build/make.log
DKMS make.log for asus-wmi-1.0 for kernel 5.3.0-55-generic (x86_64)
So 24. Mai 23:20:52 CEST 2020
make: Entering directory '/usr/src/linux-headers-5.3.0-55-generic'
  CC [M]  /var/lib/dkms/asus-wmi/1.0/build/asus-wmi.o
  CC [M]  /var/lib/dkms/asus-wmi/1.0/build/asus-nb-wmi.o
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘charge_control_end_threshold_store’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:398:30: error: ‘ASUS_WMI_DEVID_RSOC’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_UWB’?
  398 |  ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, value, &rv);
      |                              ^~~~~~~~~~~~~~~~~~~
      |                              ASUS_WMI_DEVID_UWB
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:398:30: note: each undeclared identifier is reported only once for each function it appears in
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘asus_wmi_battery_add’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:437:24: error: ‘ASUS_WMI_DEVID_RSOC’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_UWB’?
  437 |  asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, 100, NULL);
      |                        ^~~~~~~~~~~~~~~~~~~
      |                        ASUS_WMI_DEVID_UWB
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘asus_wmi_battery_init’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:459:36: error: ‘ASUS_WMI_DEVID_RSOC’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_UWB’?
  459 |  if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_RSOC)) {
      |                                    ^~~~~~~~~~~~~~~~~~~
      |                                    ASUS_WMI_DEVID_UWB
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘asus_fan_set_auto’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:1387:34: error: ‘ASUS_WMI_DEVID_CPU_FAN_CTRL’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_FAN_CTRL’?
 1387 |   status = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,
      |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                  ASUS_WMI_DEVID_FAN_CTRL
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘fan1_input_show’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:1479:37: error: ‘ASUS_WMI_DEVID_CPU_FAN_CTRL’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_FAN_CTRL’?
 1479 |   ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL,
      |                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                     ASUS_WMI_DEVID_FAN_CTRL
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘pwm1_enable_store’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:1551:31: error: ‘ASUS_WMI_DEVID_CPU_FAN_CTRL’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_FAN_CTRL’?
 1551 |   ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,
      |                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                               ASUS_WMI_DEVID_FAN_CTRL
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c: In function ‘asus_wmi_fan_init’:
/var/lib/dkms/asus-wmi/1.0/build/asus-wmi.c:1681:36: error: ‘ASUS_WMI_DEVID_CPU_FAN_CTRL’ undeclared (first use in this function); did you mean ‘ASUS_WMI_DEVID_FAN_CTRL’?
 1681 |  if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL))
      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                    ASUS_WMI_DEVID_FAN_CTRL
make[1]: *** [scripts/Makefile.build:288: /var/lib/dkms/asus-wmi/1.0/build/asus-wmi.o] Error 1
make: *** [Makefile:1656: _module_/var/lib/dkms/asus-wmi/1.0/build] Error 2
make: Leaving directory '/usr/src/linux-headers-5.3.0-55-generic'
stefan@stefan-Zen:~/mydata/github$

did not dig deeper for now... maybe you have an idea what i have missed...

@Plippo
Copy link

Plippo commented May 24, 2020

Oh the problem is probably that I based the module on kernel 5.4 and it is using some symbols that aren't there yet in 5.3. I'll try to create a version for 5.3 tomorrow.
For me, the lowest value turning on the backlight is 3, so I guess it depends on the model.
Regarding the calls, I was mainly going through the devices in the WMI section of the DSDT and looking for ones that were not yet used in the kernel module. I'll try to describe it a bit better tomorrow.

@moshemalawach
Copy link

moshemalawach commented May 24, 2020 via email

@s-light
Copy link
Owner Author

s-light commented May 25, 2020

@Plippo thanks - but don't invest to much time into 5.3 ...
i think i will upgrade my system to kubuntu 20.04 later this week anyway....

@Plippo
Copy link

Plippo commented May 25, 2020

@Plippo thanks - but don't invest to much time into 5.3 ...
i think i will upgrade my system to kubuntu 20.04 later this week anyway....

No worries, didn't have to invest much - I created a branch for 5.3 which you find here: https://github.com/Plippo/asus-wmi-screenpad/tree/5.3
I couldn't test it though as I don't have 5.3 ready

@Plippo
Copy link

Plippo commented May 25, 2020

Could it provide a backlight class interface too?

I plan on trying that too, but I don't have much hope that it'll work well. We'll see...

@Plippo
Copy link

Plippo commented May 25, 2020

out of interesst: could you describe a bit more in detail what you have done to find these calls?!
i would like to dig into the oled brigntess control if i find time..

Basically what I did is the following:

  • First of all, I read this article because I didn't now anything about DSDT, WMI or ACPI programming before :) This helped a lot.
  • I extracted and decompiled the DSDT according to the article
  • Looking at the source code of the asus_wmi module, I found that reading other brightness values happened in method DSTS (0x53545344) and writing brightness values in DEVS (0x53564544). So I searched through my DSDT.dsl for these values and found the section where these methods are handled.
  • Looking through the code, I realized that IIA0 probably determines the device that is accessed. So I compared the values of IIA0 in the DSDT with those from /include/linux/platform_data/x86/asus-wmi.h in the kernel sources. I ruled out every value that already was in asus-wmi.h, because those had to be for other devices (otherwise it would have already worked). So I looked at all the devices that were NOT in asus-wmi.h. As there would probably be methods for reading AND writing the brightness, I looked at which devices appear both under DSTS as well as DEVS. Devices that only appeared under one of them could be ruled out.
  • I also ruled out devices that always returned a fixed value or a few fixed values in DSTS as the backlight is dynamic, so they had to return dynamic values.
  • So the first device ID that matched these criteria was 0x00050032. It didn't appear in asus-wmi.h, returned a dynamic value and existed in DSTS as well as in DEVS. So I decided to give it a try and after determining the correct format to call these methods (you have to put the device id and the parameter into one buffer and invert the order of the bytes while doing this - so 0x00050032 becomes b32000500) and much trial and error, I managed to successfully call the method to get the current value using acpi_call.
  • At first the returned value looked completely random (0x01FF80), but from the DSTS code it was obvious that the interesting part is the last byte, as the code always puts 0x01FF before whatever it reads. But of course as I couldn't change the backlight, I didn't know if this value really reflected the current brightness or maybe something completely different. So I decided to brave and try calling the DEVS code to set the value. As I didn't know which value to use, I called it using the value 0 and to my big excitement, the screen went off. Well of course it could have been that it was broken now, so I called the method again using the last byte from the value I had obtained before (80) and was relieved that the screen went back to its original brightness. So well from now on, it was only trial and error to find out which was the maximum value (well more trial and less error, as I knew it was two bytes and all values in this range worked).
  • later I also looked at device 0x00050031 and found out that it read the same register as 0x00050032 but only returned either 0x10001 or 0x10000, so I figured that it could be used to turn the screen on and off without changing the current value.

Well, that's all. I hope this helps you find out more about your main screen backlight!

@Plippo
Copy link

Plippo commented May 25, 2020

Could it provide a backlight class interface too?

I tried it out, but as I feared, userspace doesn't go along well with having two backlight devices. At least Gnome can only control one, and I don't think you can pick which - I was no longer able to control the main screen using the backlight keys, only the screenpad. If you want you can try it out, I added a "backlight" branch to my repository. Just remove the module using `sudo dkms remove asus-wmi/1.0 --all', remove the /usr/src/asus-wmi-1.0 folder and then follow the instructions from the backlight branch

@moshemalawach
Copy link

Could it provide a backlight class interface too?

I tried it out, but as I feared, userspace doesn't go along well with having two backlight devices. At least Gnome can only control one, and I don't think you can pick which - I was no longer able to control the main screen using the backlight keys, only the screenpad. If you want you can try it out, I added a "backlight" branch to my repository. Just remove the module using `sudo dkms remove asus-wmi/1.0 --all', remove the /usr/src/asus-wmi-1.0 folder and then follow the instructions from the backlight branch

I will open a bug about it in gnome shell, we need to fix this upstream :)

In the meantime we can make a gnome extension to support it correctly.

@moshemalawach
Copy link

Cross referencing issue in gnome shell:
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2836

@Plippo
Copy link

Plippo commented May 26, 2020

Thanks for creating that issue!
In the meantime, I've created a script to facilitate changing the brightness using keyboard shortcuts: https://github.com/Plippo/screenpad-tools
So for me, it works quite perfectly now even without the backlight class interface.
I plan on adding more tools, maybe even an gnome shell extension, in the future.

@s-light
Copy link
Owner Author

s-light commented May 30, 2020

@Plippo thanks for your detailed description!!
i will read into this some more!

i can not test the 5.3 branch anymore -
(did forget to test it before i updated my system yesterday.. sorry!)

today i tested your backlight branch -
for my Kubuntu it is working nicely out of the box for the bottom screen!
and yes - the main screen (oled in my case) does not work react any longer..
but for it i also needed a 'fake' workaround - it never worked out of the box!
i used icc-brightness (its a 'color-correction' workaround)
manually setting brightness with icc-brightness 10 100 (brightness, max)
is working.

i searched a bit regarding multi-screen-brightness control -
this are things i found that could be interesting...

@s-light
Copy link
Owner Author

s-light commented May 31, 2020

tested your script today :-)
thanks for creating it!
it is working great for me!
🎂
i added global shortcuts for
Ctrl + Fn + F4 / F5 for bottom screen brightness down / up
and also added the shortcut for the screen toggle key :-)
working really nicely!

@antonvino
Copy link

Tested the bottom screen backlight adjustment on my machine as well UX581GV Ubuntu 20.04. Works great. Thank you for figuring it out.

@SacDin
Copy link

SacDin commented Jun 5, 2020

Great discovery @Plippo . Working perfectly. Thank you for your efforts. I am planning to make some UI tool for screenpad similar to windows for adjusting brightness and managing app windows in efficient manner. Any suggestions on what stack should be used ? I am thinking to do it with electron. Also, should it be integrated with any desktop environment like KDE or GNOME or independent programme ?

@s-light
Copy link
Owner Author

s-light commented Jun 6, 2020

i understand your idea to use electron as it is a nice environment to work with...
but i also thing that it is to resource hungry for something basic/nice to have.....
→ just my personal feeling!

for KDE you don't need any fancy tools for the window screen management i thinkg -
as the desktop already offers keyboard options to move the current window from one to the other screen.
i have added the 'toggle screen' key to Window to next Screen
this results in toggle if only the two screens are active - and moves the window through all screens if an 3 external screen is attached...
image
i don't know if gnome has similar things out of the box..

for the brightness i hope that i find some time in the next weeks to test and read some deeper what it needs to include the second screen into the normal brightness-management.
currently the script is working fine with the shortcuts - but the power management things like dimming the screen automatically after x sec of no use are missing ;-)

@Plippo
Copy link

Plippo commented Jun 6, 2020

In Gnome there's a component called gnome-settings-daemon that is responsible for things like backlight control. I've already looked into it and unfortunately it is not at all prepared for handling multiple backlight devices, so probably needs to be changed quite a bit. I suppose there's a similar component in KDE. Unfortunately, I don't have much time at the moment to work on this.

@chrislemaire
Copy link

For KDE I came up with a script to do the brightness control. Thought I'd post it here for anyone that might find such a thing useful. I bound the brightness up/down keys to execute /../step.sh 1//../step.sh -1 to get it working decently smoothly.

step.sh
#!/bin/sh

# Check whether the steps parameter is entered
STEPS=$1
if [ -z $STEPS ]; then
	echo "Usage: step.sh <nsteps>"
	exit 1
fi

# Gets the brightness, max brightness and brightness steps setting from KDE
BRIGHTNESS=$(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightness)
MAX_BRIGHTNESS=$(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightnessMax)

BRIGHTNESS_STEPS=$(qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.brightnessSteps)
BRIGHTNESS_STEP_SIZE=$(($MAX_BRIGHTNESS / $BRIGHTNESS_STEPS))

# Check whether the KDE parameters could be retrieved
if [ -z $BRIGHTNESS ] || [ -z $MAX_BRIGHTNESS ] || [ -z $BRIGHTNESS_STEP_SIZE ]; then
	echo "Missing a parameter from KDE"
	exit 1
fi

# Calculate new brightness after applying x steps
BRIGHTNESS=$(($BRIGHTNESS + $STEPS * $BRIGHTNESS_STEP_SIZE))
if [ 0 -gt $BRIGHTNESS ]; then
	BRIGHTNESS=0
elif [ $BRIGHTNESS -gt $MAX_BRIGHTNESS ]; then
	BRIGHTNESS=$MAX_BRIGHTNESS
fi

echo "Setting brightness through a step to $BRIGHTNESS"

# Set the KDE brightness value
qdbus org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement/Actions/BrightnessControl org.kde.Solid.PowerManagement.Actions.BrightnessControl.setBrightness $BRIGHTNESS

# Calculate the brightness as a percentage
PERC=$(echo "scale=2;$BRIGHTNESS / $MAX_BRIGHTNESS" | bc)
echo "Setting brightness to $BRIGHTNESS/$MAX_BRIGHTNESS: $PERC"

# Set the brightness of both laptop screens
xrandr --output "DP-2" --brightness $PERC
xrandr --output "eDP-1" --brightness $PERC

@SacDin
Copy link

SacDin commented Jun 17, 2020

@chrislemaire Your script is using software based approach. Try hardware based approach provided by @Plippo and you will notice how much quality difference it makes.

@SacDin
Copy link

SacDin commented Jun 17, 2020

@s-light I appreciate your views and agree on electron is too heavy for such a simple use case. I am using script provided by @Plippo : https://github.com/Plippo/screenpad-tools and it works quite perfectly well to satisfy the need with keyboard shortcuts. So I have dropped idea of making dedicated UI. Thank you once again for your efforts @Plippo .

Natrinicle added a commit to Natrinicle/ASUS-ZenBook-Pro-Duo-UX581GV that referenced this issue Jan 7, 2021
The script ux581_brightness.sh reads the currently requested brightness
and the maximum brightness and generates a percent representation. There
is a min/max percent brightness for both the OLED and Screenpad displays
and the percentage is scaled accordingly. The Screenpad brightness is
then scaled to 0-255 (0x00-0xFF) for the /proc/acpi/call request that
Plippo documented in
s-light#1

The path and service files have been included for SystemD to set up
inotifywatch on the brightness file and an INSTALL text file has been
included to show where to place the files and what to run to enable them
on startup.
Natrinicle added a commit to Natrinicle/ASUS-ZenBook-Pro-Duo-UX581GV that referenced this issue Jan 7, 2021
The script ux581_brightness.sh reads the currently requested brightness
and the maximum brightness and generates a percent representation. There
is a min/max percent brightness for both the OLED and Screenpad displays
and the percentage is scaled accordingly. The Screenpad brightness is
then scaled to 0-255 (0x00-0xFF) for the /proc/acpi/call request that
Plippo documented in
s-light#1

The path and service files have been included for SystemD to set up
inotifywatch on the brightness file and an INSTALL text file has been
included to show where to place the files and what to run to enable them
on startup.
@lyubomyr-shaydariv
Copy link

@Plippo
Thank you for the detailed story and hints how to make it all work. Fortunately, your 3 years-old instructions are perfect to make my secondary monitor get disabled on my ASUS UX582ZM, and it was really fantastic to get it done since I uninstalled Windows that was originally installed on the machine. So I just have a simple script to control the brightness:

#!/bin/bash

set -euxo pipefail

BASE_DIR="$(dirname -- "$(readlink -f -- "$0")")"

BRIGHTNESS="${1?no brightness, 00..FF}"

if [[ ! "$BRIGHTNESS" =~ ^[0-9A-F]{2}$ ]]; then
	echo "$0: fatal: brightness must be a hexadecimal two-digit number" >&2
	exit 1
fi

bash "$BASE_DIR"/ensure-acpi-call.sh
echo "\\_SB.ATKD.WMNB 0x0 0x53564544 b32000500${BRIGHTNESS}000000" \
	| sudo tee /proc/acpi/call

Since it's now three years since the original discussion, I don't want bother @Plippo or anybody else here, but could anybody please tell, how should I read the current brightness value from /proc/acpi/call (I guess this is where the value can be read from, right)? The reason I'm wondering is that the brightness is not preserved between sleeps/wakeups therefore I need to script it in my /lib/systemd/system-sleep/. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

9 participants