#!/bin/sh # This software is released into the public domain. # It is provided "as is", without warranties or conditions of any kind. # Anyone is free to use, modify, redistribute and do anything with this software. # backlight brightness configuration utility # # Requirements: POSIX sh, backlight in /sys/class/backlight/*, # write permission for $BACKLIGHT/brightness set -eu sys_backlight="/sys/class/backlight" sys_leds="/sys/class/leds" find_backlight() { for f in "$sys_backlight"/*; do if [ "$f" = "$sys_backlight/*" ]; then printf "cannot find a backlight in %s\n" "$sys_backlight" >&2 exit 1 elif [ -n "$bldir" ]; then printf "multiple backlights found, choose one with \$BACKLIGHT\n" >&2 exit 1 fi bldir="$f" done } is_backlight() { [ -d "$1" ] && [ -f "$1/brightness" ] && [ -f "$1/max_brightness" ] } list_backlights() { for f in "$sys_backlight"/* "$sys_leds"/*; do if is_backlight "$f"; then printf "%s\n" "${f##*/}" fi done } get_bldir() { bldir= case "${BACKLIGHT:-}" in /*) bldir="$BACKLIGHT" ;; "") find_backlight ;; *) if is_backlight "$sys_backlight/$BACKLIGHT"; then bldir="$sys_backlight/$BACKLIGHT" elif is_backlight "$sys_leds/$BACKLIGHT"; then bldir="$sys_leds/$BACKLIGHT" else printf "no such backlight found: '%s'\n" "$BACKLIGHT" >&2 exit 1 fi ;; esac blname="${bldir##*/}" } read_num() { read -r num <"$1" if ! is_num "$num"; then printf "expected a number reading '%s', but got '%s'\n" "$1" "$num" >&2 exit 1 fi } is_num() { case "$1" in [0-9]) return 0 ;; [0-9][0-9]) return 0 ;; [0-9][0-9][0-9]) return 0 ;; [0-9][0-9][0-9][0-9]) return 0 ;; [0-9][0-9][0-9][0-9][0-9]) return 0 ;; [0-9][0-9][0-9][0-9][0-9][0-9][0-9]) return 0 ;; [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) return 0 ;; [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]) return 0 ;; # hopefully it's not a >2^32 number esac return 1 } get_brightness() { read_num "$bldir/max_brightness" raw_max="$num" read_num "$bldir/brightness" raw_curr="$num" max=100 curr=$(( (raw_curr + (raw_max / 2 / max)) * max / raw_max )) # brightness 0 tends to completely turn off the backlight raw_min=1 case "$blname" in nvidia_[0-9]*) raw_min=0 ;; # nvidia_0 at 0 is still not off esac } get_raw_new() { op="$1" val="$2" raw_new= new= if ! is_num "$val"; then printf "expected a number for brightness, but got '%s'\n" "$val" >&2 exit 2 fi case "$op" in +) : $(( new = curr + val )) ;; -) : $(( new = curr - val )) ;; "") : $(( new = val )) ;; =+) : $(( raw_new = raw_curr + val )) ;; =-) : $(( raw_new = raw_curr - val )) ;; =) : $(( raw_new = val )) ;; *) printf "invalid operator '%s'\n" "$op" >&2 exit 2 ;; esac if [ -n "$new" ]; then : $(( raw_new = new * raw_max / max )) if [ "$new" -lt "$curr" ] && [ "$raw_new" -ge "$raw_curr" ]; then : $(( raw_new = raw_curr - 1 )) elif [ "$new" -gt "$curr" ] && [ "$raw_new" -le "$raw_curr" ]; then : $(( raw_new = raw_curr + 1 )) fi fi if [ -n "$raw_new" ]; then if [ "$raw_new" -gt "$raw_max" ]; then raw_new="$raw_max" fi if [ "$raw_new" -lt "$raw_min" ]; then raw_new="$raw_min" fi fi } set_brightness() { get_raw_new "$1" "$2" printf %d "$raw_new" > "$bldir/brightness" } usage() { prog="$(basename "$0")" printf "%s: usage: %s OPERATOR\n" "$prog" "$prog" printf "\n" printf "Operators:\n" printf " (none) print current brightness in percentages\n" printf " PERC set brightness to PERC percentages of max\n" printf " +PERC increase brightness by PERC percentage points\n" printf " -PERC decrease brightness by PERC percentage points\n" printf " = print current brightness raw value\n" printf " VAL set brightness to VAL raw value\n" printf " =+VAL increase brightness by VAL raw value\n" printf " =-VAL decrease brightness by VAL raw value\n" printf " -L, --list list all found backlights\n" printf "\n" printf "Environment variables:\n" printf " BACKLIGHT the backlight to use (absolute path or a folder\n" printf " in %s or %s)\n" "$sys_backlight" "$sys_leds" } main() { if [ $# -gt 1 ]; then usage >&2 exit 2 fi if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then usage exit fi if [ "${1:-}" = "-L" ] || [ "${1:-}" = "--list" ]; then list_backlights exit fi get_bldir get_brightness op="${1:-}" case "$op" in "") printf "%d\n" "$curr" ;; +[0-9]*) set_brightness + "${op#+}" ;; -[0-9]*) set_brightness - "${op#-}" ;; [0-9]*) set_brightness "" "$op" ;; =) printf "%d\n" "$raw_curr" ;; =+[0-9]*) set_brightness "=+" "${op#=+}" ;; #+=[0-9]*) set_brightness "=+" "${op#+=}" ;; =-[0-9]*) set_brightness "=-" "${op#=-}" ;; #-=[0-9]*) set_brightness "=-" "${op#-=}" ;; =[0-9]*) set_brightness "=" "${op#=}" ;; *) printf "invalid operator: '%s'\n" "$op" >&2 exit 2 esac } main "$@"