setbrightness.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. setbrightness - sets your laptop's screen brightness (backlight) from the
  3. command-line.
  4. This program does nothing more than open a file and write some specific
  5. numerical value to it, obtained from the command-line.
  6. Only that this file will be the backlight brightness file, thus allowing us
  7. to set it with sudo, or even without it via setuid ;)
  8. Copyright 2022 kzimmermann - https://tilde.town/~kzimmermann/
  9. This program is Free Software licensed under the GNU GPLv3 or later.
  10. For more information, please see https://www.gnu.org/licenses
  11. */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. // Alpine Linux with intel chips sets this file here. Change as needed.
  16. const char *BRIGHTFILE = "/sys/class/backlight/intel_backlight/brightness";
  17. // Likewise, this is the location of the file indicating max value for it:
  18. const char *MAX_BRIGHTFILE = "/sys/class/backlight/intel_backlight/max_brightness";
  19. void
  20. helper(char *progname) {
  21. printf("%s - utility to set the laptop's display brightness (backlight) from the command-line\n", progname);
  22. printf("Usage: %s BRIGHTNESS [+BRIGHTNESS] [-BRIGHTNESS]\n", progname);
  23. printf("Where BRIGHTNESS is an absolute value between 1 and 100, or a 'step' value preceeded by a + (increase) or a - (decrease) sign.\n");
  24. printf("Examples:\n");
  25. printf("%s 50 # sets the display brightness to 50%%\n", progname);
  26. printf("%s +10 # sets the brightness 10%% brighter\n", progname);
  27. printf("%s -15 # sets the brightness 15%% dimmer\n", progname);
  28. }
  29. // datatype of a "tuple" containing a leading character and a numerical value:
  30. struct
  31. argtuple {
  32. char sign;
  33. int value;
  34. };
  35. // this function will process a token like "+83239" and identify the parts:
  36. struct argtuple
  37. parseArg(char token[])
  38. {
  39. struct argtuple t;
  40. sscanf(token, "%1c%d", &t.sign, &t.value);
  41. if (!(t.sign == '+' || t.sign == '-')) {
  42. // parsing error. Let's use the (!,0) tuple as an error code
  43. t.sign = '!';
  44. t.value = 0;
  45. }
  46. return t;
  47. }
  48. int
  49. main(int argc, char *argv[])
  50. {
  51. int status = 0;
  52. int maxbrightness = 0;
  53. int brightness = 0;
  54. int is_absolute = 0;
  55. int multiplier = 1;
  56. struct argtuple at;
  57. FILE *fp;
  58. // parse -h or --help argument:
  59. if (argc == 2) {
  60. if (strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--help", 6) == 0) {
  61. helper(argv[0]);
  62. return 0;
  63. }
  64. }
  65. fp = fopen(BRIGHTFILE, "r");
  66. if (fp == NULL) {
  67. printf("Error: brightness file does not exist.\n");
  68. printf("Make sure some sort of brightness file exists under '/sys', edit it in the source and try again.\n");
  69. return 1;
  70. }
  71. else {
  72. fscanf(fp, "%d", &brightness);
  73. status = fclose(fp);
  74. }
  75. // Now that the file indeed exists, get the maximum brightness:
  76. fp = fopen(MAX_BRIGHTFILE, "r");
  77. if (fp == NULL) {
  78. printf("Error: maximum brightness file does not exist.\n");
  79. printf("Make sure this file exists under '/sys', edit it in the source and try again.\n");
  80. return 1;
  81. }
  82. else {
  83. // Read the maximum possible value from it:
  84. fscanf(fp, "%d", &maxbrightness);
  85. status = fclose(fp);
  86. }
  87. // Read command-line arguments:
  88. if (argc == 1) {
  89. printf("The current brightness is %d, or %.1f%%\n", brightness, 100.0*brightness / maxbrightness);
  90. printf("Pass a value from 1 to 100 to set the new brightness.\n");
  91. return 0;
  92. }
  93. // Scan the input, see if the chars '-' or '+' are present. If they are,
  94. // we will set the brightness relative to the current (respecting limits)
  95. at = parseArg(argv[1]);
  96. if (at.sign == '!') {
  97. printf("[DEBUG] Setting *absolute* brightness\n");
  98. is_absolute = 1;
  99. }
  100. else {
  101. printf("[DEBUG] Setting *relative* brightness\n");
  102. is_absolute = 0;
  103. }
  104. // Here's now how we actually do the logic of it: the user will pass a
  105. // number between 1 and 100 as $1 and from this, we will calculate a
  106. // percentage of the maximum allowed brightness. If the boundaries are
  107. // respected (and the value passed is actually a digit, not a string),
  108. // then we overwrite the system's brightness file with that safe value.
  109. if (is_absolute == 1) {
  110. multiplier = atoi(argv[1]);
  111. // integer parsing errors are expressed as a 0, so we can check
  112. // the bounds:
  113. if (multiplier > 100 || multiplier < 1) {
  114. printf("Error: pass a number from 1 to 100 to set new brightness.\n");
  115. return 1;
  116. }
  117. // If everything is within bounds, then:
  118. brightness = (int)((0.01 * multiplier) * maxbrightness);
  119. }
  120. else {
  121. // relative change. Get the "int" version of percentual brightness:
  122. multiplier = (int)((100.0 * brightness) / maxbrightness);
  123. if (at.sign == '-')
  124. multiplier -= at.value;
  125. else
  126. multiplier += at.value;
  127. if (multiplier <= 0) {
  128. printf("Cannot set brightness lower than 0. Already at minimum.\n");
  129. multiplier = 2;
  130. }
  131. else if (multiplier >= 100) {
  132. printf("Cannot set brightness higher than 100. Already at max.\n");
  133. multiplier = 100;
  134. }
  135. }
  136. // If everything is within bounds, then:
  137. brightness = (int)((0.01 * multiplier) * maxbrightness);
  138. fp = fopen(BRIGHTFILE, "w");
  139. if (fp == NULL) {
  140. printf("Error: could not open the brightness file for writing.\n");
  141. printf("Try it as root or with sudo as member of the 'video' group.\n");
  142. return 1;
  143. }
  144. else {
  145. fprintf(fp, "%d\n", brightness);
  146. status = fclose(fp);
  147. printf("The new brightness is %d, or %d%%\n", brightness, multiplier);
  148. }
  149. return 0;
  150. }