I am the happy owner of an Intel NUC dual booting Windows 8.1 and Ubuntu, hooked up to a great-looking Apple LED Cinema Display. The only problem is that the Apple display comes with no physical controls for brightness and Ubuntu doesn't seem to be able to adjust it either. Being a geek I was anything but content with this situation. I finally found a solution to control the brightness using keyboard shortcuts.
Updated December 2020: Using a maintained fork of the acdcontrol tool, removing the need to run acdcontrol with root privileges and a much simpler Bash script for the integration with the desktop environment, documented how to modify acdcontrol to support other monitors.
Step 1 - control the brightness from the command line
We need a way to control the brightness of the display. There's a handy tool called acdcontrol to do that.
Unfortunately, the original version has been unmaintained for over a decade and doesn't support my 27" Apple LED Cinema Display or anything newer than that. Luckily there's a a third party, currently maintained fork of acdcontrol with support for many more monitors. You can clone the repository locally and built this simple tool from source:
git clone https://github.com/yhaenggi/acdcontrol.git
cd acdcontrol
rm acdcontrol
make
After a second or so the acdcontrol binary will have been built.
This tool needs to communicate with the USB Human Interface Device your monitor creates. By default, this is only possible if you are root because the /dev/usb/hiddev* devices are owned by root and are only writeable by root. There are two ways around that. We can either tell our Linux system to change the ownership of the device or have acdcontrol always run as root.
The first alternative is the safest.
First, run lsusb | grep "Apple"
and you will see something like this:
$ lsusb | grep Apple
Bus 001 Device 012: ID 05ac:9226 Apple, Inc. LED Cinema Display
Bus 001 Device 011: ID 05ac:8508 Apple, Inc. iSight in LED Cinema Display
Bus 001 Device 010: ID 05ac:1105 Apple, Inc. Audio in LED Cinema Display
Bus 001 Device 007: ID 05ac:9126 Apple, Inc. USB2.0 Hub
This line in bold is the main USB device that controls the Apple display. Note the ID has two four digit hexadecimal numbers separated by a colon. The first is the USB vendor ID, the second is the USB device ID. Note them down.
Now, create the file /etc/udev/rules.d/50-apple-display.rules
with the following content:
KERNEL=="hiddev*", ATTRS{idVendor}=="05ac", ATTRS{idProduct}=="9226", GROUP="nicholas", OWNER="root", MODE="0660"
You need to replace three things here:
05ac
is the USB vendor ID of your Apple display that you got previously.9226
is the USB device ID of your Apple display that you got previously.nicholas
is your user group. Obviously this will be different for you. If you are not sure what this is runid -gn
on your terminal.
Next up, we tell the kernel that our udev rules have changed:
sudo udevadm control --reload-rules
sudo udevadm trigger
Remember that you may also need to unplug your monitor's USB or Thunderbolt connector from your computer and then plug it right back in for these changes to take effect.
Now copy acdcontrol somewhere in your PATH, e.g. /usr/local/bin:
chmod +x acdcontrol
sudo cp acdcontrol /usr/local/bin
If you are on a multi-user system and your users don't belong in a common group the previous method won't work. In this case you need to use the alternative method, having acdcontrol always run as root:
sudo cp acdcontrol /usr/local/bin sudo chown root:users /usr/local/bin/acdcontrol sudo chmod 0755 /usr/local/bin/acdcontrol sudo chmod +s /usr/local/bin/acdcontrol
Either way, we can now test that acdcontrol works.
Make sure that your display's USB cord is plugged in to your computer. The brightness control, just like the iSight camera and audio input/output, is sent to your display over USB. If you have a Thunderbolt display make sure that it's plugged into a Thunderbolt port. If you have a Thunderbolt display plugged into a Mini DisplayPort only port you're out of luck, sorry. Now run the following:
acdcontrol --detect /dev/usb/hiddev*
It should reply with something like
Apple Cinema and Studio Display Control Program. Please, use --about switch to learn more hiddev driver version is 1.0.4 hiddev driver version is 1.0.4 /dev/usb/hiddev1: USB Monitor - SUPPORTED. Vendor= 0x5ac (Apple), Product=0x9226[Apple Cinema HD Display 27"
See the part I put in bold type, /dev/usb/hiddev1? It may be different for you. If nothing is detected you will not be able to control the monitor brightness.
Part 2 - writing a script to step through the brightness
acdcontrol has a way of doing step changes to your brightness, essentially allowing you to increase and decrease the brightness. However, you need to always give it the hiddev device your monitor uses to talk to your computer which may change on each boot. We need a small script to fix that.
Put the following code into a new file /usr/local/bin/brightness
#!/bin/bash HIDDEV=`acdcontrol --detect /dev/usb/hiddev* | grep -Po "/dev/usb/hiddev[0-9]"` acdcontrol $HIDDEV -- $@ > /dev/null
Now let's make it executable:
$ sudo chmod +x /usr/local/bin/brightness
You can now step the brightness up and down using our script. Let's try it out:
$ brightness +500 # It will make the monitor much brighter $ brightness -500 # It will make the monitor much darker
Step 3 - keyboard shortcuts
Now for the final touch, adding keyboard controls. Assuming that you're using Unity, the default Ubuntu Desktop interface, you just need to open System Settings and click on the Keyboard icon. In there click on the Shortcuts tab.
At the bottom of the list there's a plus (+) button. Click on it. Set:
- Name: Brightness up
- Command: /usr/local/bin/brightness +50
Click on the plus icon a second time and add another entry with:
- Name: Brightness down
- Command: /usr/local/bin/brightness -50
Our custom actions appear under the "Custom..." category and have no keyboard shortcut assignments. Click on the Inactive label to the right of each shortcut and press the key combination you want to use. I use CTRL-SHIFT-ALT-plus and CTRL-SHIFT-ALT-minus for the brightness up and down command respectively. Now try using the shortcuts you specified a few times. You'll see that each time you use the shortcut there's a small brightness change in your display. That was it! Now your Ubuntu Desktop can control the brightness of your display easily through the keyboard.
What about Kubuntu?
You can set up custom shirtcuts from KDE logo, Application, Settings, System Settings, Shortcuts, Custom Shortcuts. You can create a new Command/URL global shortcut and assign the scripts mentioned above. As for the shortcuts, I found that META-F1 and META-F2 work best without causing conflicts. Why F1/F2? This is where brightness down/up can be found on a Mac keyboard :)
Supporting other monitors
As far as I can tell, acdcontrol should work with any monitor which implements the proprietary Apple HID for controlling its brightness (as opposed to using DDC which is what most other monitors do), such as LG UltraFine series of Mac-specific monitors. Please note that I do not have any of these monitors at hand so this section is half speculation, half information I extrapolated from discussions in support forums of other brightness control tools.
You may have to change the acdcontrol.cpp file in two places to add support for other monitors.
First you need to run lsusb to get the USB vendor and device ID of your monitor. Let's say it's vendor ID abcd and device ID 0123.
Edit acdcontrol.cpp and find the Supported vendors line. Add constants for your USB vendor and device ID. Changes in bold:
// Supported vendors
const int APPLE = 0x05ac;
const int SAMSUNG = 0x0419;
const int MYVENDOR = 0xabcd;
// ... more lines here ...
const int CINEMA_DISPLAY_HD_27_2013 = 0x9227;
const int MY_MONITOR = 0x1234;
Then find the void init_device_database()
in the code and add your monitor definition. Changes in bold:
void init_device_database() {
supportedVendors.insert( VendorDesc( SAMSUNG, "Samsung Electronics" ) );
supportedVendors.insert( VendorDesc( APPLE, "Apple" ) );
supportedVendors.insert( VendorDesc( MYVENDOR, "My Vendor's Name" ) );
supportedDevices.insert( DeviceId( MYVENDOR, MY_MONITOR,
"My Monitor's Name" ));
supportedDevices.insert( DeviceId( APPLE, STUDIO_DISPLAY_15,
"Apple Studio Display 15\"" ));
Delete the acdcontrol file and run make again. The recompiled binary will now have support for the device you added.
Pitfalls
The acdcontrol utility has the supported USB vendor and device ID list hard-coded into it. I only have one Apple display to test with. It is possible that different generations of Apple displays may use a different USB device ID. In this case you'll need to modify the source code of the utility yourself as described above.
Brightness control requires a USB connection between your computer and display, obviously. With older Apple displays this is as simple as connecting the USB cord of your display to your computer. With the Thunderbolt display you only have one Thurderbolt cable which transfers both the video signal and the USB data. If your computer has a Thunderbolt port and you connect it there it will work. If your computer has a Mini DisplayPort you will get video output normally but all USB-related features, including brightness control, iSight camera and audio, will not work. There's no workaround for that.
Ubuntu Desktop has brightness controls and options under the Displays section of the system configuration. These will still not work. Ubuntu is not aware of the need to use acdcontrol for Apple displays. That's why we had to go through these steps to get brightness controls working in the first place.
I use two 24" displays on my Shuttle barebone PC where I run Lubuntu 16.04.
Now, I have two things to say. Firstly, in and the following line, there is a root missing.
Secondly, my devices show up, BUT are unsupported. The message I get after is
The 24" monitors seem to have been older than the codebase I was using. Likewise my 27" was too new. To be fair, that code was abandoned years ago. My fork only addressed the one missing monitor I own. I'm glad you found a version with your monitor. I had to go through the C code without knowing enough C :D
git clone https://github.com/warvariuc/acdcontrol
cd acdcontrol
sudo python3 acdcontrol.py /dev/usb/hiddev1 65000
hiddev driver version is 1.0.4
Found supported product 9227 (Apple Cinema HD Display 27" 2013) of vendor 05ac (Apple).
I didn't use any bash wrappers or c code (directly), it uses Python 3, which can be apt-get installed as python3 or similar.
Thanks a lot for this post! Surprisingly enough, it helps also with monitors other than Apple or Samsung. For example, I'm using an LG UltraFine 27MD5KL with Linux.
So now the monitor finally works with one single Thunderbolt, 5k60 and brightness control. \o/
That's great news! I knew about ddcutil but didn't have a monitor that supports the protocol. My only monitor with real brightness control is the Apple Cinema Display. I'm glad that you are trying to get a patch into ddcutil, it will help a lot having native control of the display instead of going through an external tool and scripts every time :)
It would be definitely awesome to have some desktop integration for these brightness controls one day, but it looks like the USB HID protocols are not well documented and differ from model to model and sometimes even change with firmware updates (at least on LG), which is somewhat annoying. At this point I'm happy about any brightness control, because the monitor came with its backlight set so low that it was hard to read. (And it has no control buttons on it, not even a switch.)
Really grateful for this. You're a hero. Worked great in 2023 on Fedora 39. Thanks a billion!
I have an antiquated Apple Cinema 23" display from a 2002 G4 tower, connected to an ACD adapter. This was the *only* thing that worked to dial up the brightness. Thank You for letting me re-use this display!