I like to use a GNU/Linux machine than a Windows machine for at least two reasons:
In this post, I will tell you how an OS upgrade broke a functionality on my machine and how I fixed it (which was a fun experience).
Update 1: zerosk8 says in a comment that the command
Update 2: The technique described in this post worked on my Lenovo laptop (with an ATI graphics card). It didn’t, however, work on my Samsung N150 laptop (which has an Intel graphics card). Check this blog post of mine to see what works on the Samsung machine.
Original post:
My upgrade to Kubuntu Gutsy broke the functionality of Fn+Home and Fn+End keys on my ThinkPad. (If you use Sony Vaio, look at Daniel’s comment. Thanks Daniel for the information!) These keys are used to control the brightness of the LCD screen. When I was Googling around to find a solution, I learned that the LCD screen driver provides a file system-like interface for controlling it. The file
In case you didn’t know exactly how to install this program, or too lazy to type commands, use these commands:
Chose the keyboard shortcut Ctrl+Alt+=.
For command, I gave the path to
Likewise, I assigned Ctrl+Alt+- to
- GNU/Linux user environment (especially KDE) is customizable.
- You get to see how things are implemented, which is kinda fun.
In this post, I will tell you how an OS upgrade broke a functionality on my machine and how I fixed it (which was a fun experience).
Update 1: zerosk8 says in a comment that the command
xbacklight
can be used to control screen brightness from the command line. On Ubuntu machines, run sudo apt-get install xbacklight
to install the command on your machine. Thank you zerosk8! (Near the end of this post I am discussing how I set up keyboard shortcuts for adjusting brightness. This part might be useful even if you use xbacklight
command.)Update 2: The technique described in this post worked on my Lenovo laptop (with an ATI graphics card). It didn’t, however, work on my Samsung N150 laptop (which has an Intel graphics card). Check this blog post of mine to see what works on the Samsung machine.
Original post:
My upgrade to Kubuntu Gutsy broke the functionality of Fn+Home and Fn+End keys on my ThinkPad. (If you use Sony Vaio, look at Daniel’s comment. Thanks Daniel for the information!) These keys are used to control the brightness of the LCD screen. When I was Googling around to find a solution, I learned that the LCD screen driver provides a file system-like interface for controlling it. The file
/sys/class/backlight/acpi_video0/brightness
acts as the interface for adjusting screen brightness. So I wrote the following shell script to adjust screen brightness:#!/bin/sh
#
# Adjust LCD brightness of ThinkPad laptops.
CTRL_FILE=/sys/class/backlight/acpi_video0/brightness
usage() {
echo >&2 Usage: lcd-brightness [value]
}
case $# in
0)
cat $CTRL_FILE
;;
1)
echo $1 >$CTRL_FILE
;;
*)
usage
esac
The code feels right when looking at it. Let’s try it out.So this problem looks like a permission issue. Just to make sure:$ ./lcd-brightness 80 $ ./lcd-brightness 70 ./lcd-brightness: line 16: /sys/class/backlight/acpi_video0/brightness: Permission denied
$ sudo ./lcd-brightness # sudo runs the command as root. 80 $ sudo ./lcd-brightness 70 # This worked -- screen brightness changed.
So only root can change the screen brightness. But I don’t want to$ ls -l
/sys/class/backlight/acpi_video0/brightness -rw-r--r-- 1 root root 4.0K Jan 17 16:47 /sys/class/backlight/acpi_video0/brightness
sudo
all the time to adjust screen brightness. I said to myself, “I know how to handle this.” And I installed my script like this:Time to test this newly installed script.$ sudo cp ./lcd-brightness /usr/local/bin/ $ sudo chmod 755 /usr/local/bin/lcd-brightness $ sudo chmod +s
/usr/local/bin/lcd-brightness $ ls -l
/usr/local/bin/lcd-brightness -rwsr-sr-x 1 root root 7.3K Jan 17 08:21 /usr/local/bin/lcd-brightness
Looks like setuid bit is not working as I expected. Some more Googling around gave me the answer. Wikipedia article on setuid says: “Due to the increased likelihood of security flaws, many operating systems ignore the setuid attribute when applied to executable shell scripts.“ That explains everything. So my next option is to write it as a C program. I translated this shell script into C as follows:$ type lcd-brightness lcd-brightness is /usr/local/bin/lcd-brightness $ lcd-brightness 70 $ lcd-brightness 80
/usr/local/bin/lcd-brightness: line 16: /sys/class/backlight/acpi_video0/brightness: Permission denied
# Huh? Let’s try again as root?$ sudo lcd-brightness 80 # This changes the brightness
/*
* Change/query the brightness of LCD screen.
*/
#include <stdio.h>
void usage()
{
fprintf(stderr, "Usage: lcd-brightness [value]\n");
}
int main(int argc, char *argv[])
{
FILE *fp;
int bright = 0;
const char *kFileName =
"/sys/class/backlight/acpi_video0/brightness";
switch (argc) {
case 1:
fp = fopen(kFileName, "r");
fscanf(fp, "%d", &bright);
printf("%d\n", bright);
break;
case 2:
fp = fopen(kFileName, "w");
bright = atoi(argv[1]);
fprintf(fp, "%d\n", bright);
break;
default:
usage();
return -1;
}
fclose(fp);
return 0;
}
Compiling this file and installing the binary like earlier does the job. Cool :-)In case you didn’t know exactly how to install this program, or too lazy to type commands, use these commands:
But this is not the end of story. Later I found a usability problem with this program. I use this program only when I want to either increase or decrease the screen brightness. That is a two-step process — first I have to run the program and find the screen brightness. Then run it again with appropriate brightness argument. This is not an optimal way to use a program like this. So I decided to write two more shell scripts on top of$ gcc lcd-brightness.c $ sudo cp ./a.out /usr/local/bin/lcd-brightness $ sudo chmod +s
/usr/local/bin/lcd-brightness $ ls -l /usr/local/bin/lcd-brightness -rwsr-sr-x 1 root root 7.3K Jun 7 21:47 /usr/local/bin/lcd-brightness
lcd-brightness
command. Here are those scripts:$ cat increase-lcd-brightness
#/bin/bash
#
# Increase LCD brightness by 10.
# Assumes that lcd-brightness command is on $PATH.
lcd-brightness $(expr $(lcd-brightness) + 10)
$ cat decrease-lcd-brightness
#/bin/bash
#
# Decrease LCD brightness by 10.
# Assumes that lcd-brightness command is on $PATH.
lcd-brightness $(expr $(lcd-brightness) - 10)
The scripts are very simple, aren’t they? But there’s still another usability issue: I have to switch to a terminal to invoke these commands, which might be a distraction when I am coding or reading some document. Correct approach would be to use shortcut keys for this. So I went ahead and defined two new global shortcut keys on my machine. On KDE it’s done from Control Center. I opened the corresponding applet by selecting K Menu > System Settings > Accessibility > Input Actions. Added a new action called “Increase LCD Brightness” with type as “Keyboard Shortcut -> Command/URL (simple)”.Chose the keyboard shortcut Ctrl+Alt+=.
For command, I gave the path to
increase-lcd-brightness
script.Likewise, I assigned Ctrl+Alt+- to
decrease-lcd-brightness
script. And that’s about it. Now I can use shortcut keys for adjusting screen brightness. Now you understand when I say “Linux is customizable,” don’t you? ;-)
I was having trouble with my LCD until I read your page. Thanks for the incredibly clear and detailed explanation. I will now experiment with more customizations in Linux!
ReplyDeleteThank you very much. I did the same thing with my Sony Vaio, with the following changes:
ReplyDelete1) The path is /sys/class/backlight/sony/brightness
2) The brightness steps from 1 to 7 by increments of 1, so I modified the shell scripts to use 1 instead of 10.
3) I use gnome, so I set shortcut keys using gconf-editor
Thanks for pointing the way!
I have been frustrated for a while trying to get screen brightness to work in my Dell Inspiron e1705. Your blog inspired me, and after locating the brightness file (for me it was /proc/acpi/video/VID/LCD/brightness), I wrote a simple script in C++ that had to look at the current value and modify it accordingly (my brightness file starts at 12 and goes in increments of 12 up to 84, then jumps to 100), assigned shortcuts, and voila! I couldn't be happier. Thanks for the idea!
ReplyDeleteThis post helped me immensely. Thanks a ton for your code examples. I'm on a Gateway ML6721, which has irregular brightness settings.(12,25,37,50,62,75,87, and 100)
ReplyDeleteI built a pair of scripts to replace yours to use these variables. If there's anyone out there who would like such things, just send me an email or reply to this. I'll also upload the "lcd-brightness" all compiled, if that's all right with the author.
Thanks a lot for the insight.
ReplyDeleteI compiled the C program on my system. To change brightness level, it will only work sudo'ed, becaue the file it has to modify requires root privileges. How did you achieve making the C program work for a regular user (without sudo)?
Thanks in advance.
Daniel
Ok, after installing the C program like you instructed, it worked.
ReplyDeleteOnly thing is that to compile I had to include stdlib.h
and that's because of the atoi() function.
Thanks again.
"Only thing is that to compile I had to include stdlib.h"
ReplyDeleteAh, good catch. I didn't have all warnings enabled; so I didn't see the warning when I compiled. 'gcc -Wall' shows me the warning about atoi. Thanks Daniel!
To avoid the prickly setuid business you can take advantage of the fact that the acpid daemon runs as root. Just create an event file at /etc/acpi/events/Fn-PgUp that contains the following:
ReplyDeleteevent=ibm/hotkey HKEY 00000080 00001012
action=/etc/acpi/Fn-PgUp.sh
And have your Fn-PgUp.sh change the brighness.
When you hit Fn-PgUp the acpi event "HKEY 00000080 00001012" is generated which is picked up and acted upon by acpid.
There is very nice application in Ubuntu, which is connected to these values in /sys filesystem and which show nice "progress bar" when user change its brightness.
ReplyDeleteDoes someone know its name? I'd like to install that on my Debian. If you know, please let me know on my e-mail address, thanks.
OK, it's name is gnome-power-manager... if everyone would like to know. Very nice app :)
ReplyDeleteHi Manki, Guys
ReplyDeleteI have the same problem, but with Redhat 2.6.9, what confuses me now is that I couldn't find this brightness file in my system, I already tried sys/class/... but nothing there!, I also tried proc/acpi/... path; have read this in a comment posted above, but still nothing, any suggestion to solve this!:(
I only need to know the path of the brightness file in Redhat filesystem.
Suhib
Hi Suhib,
ReplyDeleteIs "/proc/acpi/video/VGA/LCD/brightness" what you're looking for? (I don't have a RedHat machine; a quick Google search seems to suggest this path. Hope this helps.)
I see, but the problem is I don't have the video directory in "/proc/acpi/.." path!!?
ReplyDelete@Suhib Rawshdeh:
ReplyDeleteIt sounds very simple, but have you tried a "locate brightness"? It might just return what you're looking for. (If you haven't used locate before, be sure to run "sudo updatedb" first.
I think my problem is that I'm using an older version of redhat which didn't support acpi.
ReplyDeleteThanks any way guys,
Hi!!! mankikannan.blogspot.com is one of the best innovative websites of its kind. I enjoy reading it every day. I will be back.
ReplyDelete@Anonymous: whoa, you've made my day. Thank You!
ReplyDeleteI consider, that you are mistaken. I can defend the position. Write to me in PM.
ReplyDeleteI was looking for a way to change the LCD brightness on startup with my script, and google showed me this post.
ReplyDeleteFirst, I tryed to modify /sys/class/backlight/acpi_video0/brightness, but it was so annoying to sudo echa time.
Finally, just discovered an app for CLI that lets you change the brightness in a very easy way (and no need of superuser permissions!).
The app is: xbacklight
Using it: xbacklight -set number
number, an integer between 0 and 100
;)
Awesome post dude!
ReplyDeleteIt just works perfectly! :D
You have no idea how badly I have been asking for something like this for ages! :D
Thanks a ton. :D
Thanks Royzz. Thanks zerosk8. :)
ReplyDeleteThanks, it work's great.
ReplyDeleteYou can modify your C source code to:
/*
* Change/query the brightness of LCD screen.
*/
#include
int main(int argc, char *argv[])
{
FILE *fp;
int bright = 0;
const char *kFileName = "/sys/class/backlight/dell_backlight/brightness";
fp = fopen(kFileName, "r");
fscanf(fp, "%d", &bright);
fclose(fp);
switch (argc) {
case 1:
printf("%d\n", bright);
break;
case 2:
fp = fopen(kFileName, "w");
bright += atoi(argv[1]);
fprintf(fp, "%d\n", bright);
fclose(fp);
break;
default:
fprintf(stderr, "Usage: lcd-brightness [value]\n");
return -1;
}
return 0;
}
Now, you don't have to create 2 more scripts to increase/decrease - just type:
lcd-brigthness +[number] - to increase by number
lcd-brigthness -[number] - to decrease by number
lcd-brigthness - to print the current number
(Of course correct the path to the brightness file so it will match yours and make sure to set the write chmode)
I`m with Lubuntu (kernel 3.0.x) on Vostro 3350 w hybrid GFX(ATI+Sandy). So i have: /sys/class/backlight/acpi_video1/brightness - for SandyBr. GFX and
ReplyDelete/sys/class/backlight/acpi_video0/brightness - for ATI
and /sys/class/backlight/intel_backlight/brightness - which does nothing.
Since I didn`t manage to setup GFX switching properly(yet), I use acpi_call module to disable ATI on startup to save power & fan noise.
I checked the scripts - it works, when i change acpi_video0 to acpi_video1, thanks - it gives me idea how it works, but xbacklight utility mentioned above is the general solution for me.