2 * libbacklight - userspace interface to Linux backlight control
4 * Copyright © 2012 Intel Corporation
5 * Copyright 2010 Red Hat <mjg@redhat.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
28 * Matthew Garrett <mjg@redhat.com>
29 * Tiago Vignatti <vignatti@freedesktop.org>
34 #include "libbacklight.h"
38 #include <linux/types.h>
46 static long backlight_get(struct backlight *backlight, char *node)
53 if (asprintf(&path, "%s/%s", backlight->path, node) < 0)
56 fd = open(path, O_RDONLY);
62 ret = read(fd, &buffer, sizeof(buffer));
68 value = strtol(buffer, NULL, 10);
76 long backlight_get_brightness(struct backlight *backlight)
78 return backlight_get(backlight, "brightness");
81 long backlight_get_max_brightness(struct backlight *backlight)
83 return backlight_get(backlight, "max_brightness");
86 long backlight_get_actual_brightness(struct backlight *backlight)
88 return backlight_get(backlight, "actual_brightness");
91 long backlight_set_brightness(struct backlight *backlight, long brightness)
98 if (asprintf(&path, "%s/%s", backlight->path, "brightness") < 0)
101 fd = open(path, O_RDWR);
107 ret = read(fd, &buffer, sizeof(buffer));
113 if (asprintf(&buffer, "%ld", brightness) < 0) {
118 ret = write(fd, buffer, strlen(buffer));
124 ret = backlight_get_brightness(backlight);
125 backlight->brightness = ret;
134 void backlight_destroy(struct backlight *backlight)
140 free(backlight->path);
145 struct backlight *backlight_init(struct udev_device *drm_device,
146 uint32_t connector_type)
148 const char *syspath = NULL;
149 char *pci_name = NULL;
150 char *chosen_path = NULL;
152 DIR *backlights = NULL;
153 struct dirent *entry;
154 enum backlight_type type = 0;
156 struct backlight *backlight = NULL;
162 syspath = udev_device_get_syspath(drm_device);
166 if (asprintf(&path, "%s/%s", syspath, "device") < 0)
169 ret = readlink(path, buffer, sizeof(buffer) - 1);
175 pci_name = basename(buffer);
177 if (connector_type <= 0)
180 backlights = opendir("/sys/class/backlight");
184 /* Find the "best" backlight for the device. Firmware
185 interfaces are preferred over platform interfaces are
186 preferred over raw interfaces. For raw interfaces we'll
187 check if the device ID in the form of pci match, while
188 for firmware interfaces we require the pci ID to
189 match. It's assumed that platform interfaces always match,
190 since we can't actually associate them with IDs.
192 A further awkwardness is that, while it's theoretically
193 possible for an ACPI interface to include support for
194 changing the backlight of external devices, it's unlikely
195 to ever be done. It's effectively impossible for a platform
196 interface to do so. So if we get asked about anything that
197 isn't LVDS or eDP, we pretty much have to require that the
198 control be supplied via a raw interface */
200 while ((entry = readdir(backlights))) {
201 char *backlight_path;
203 enum backlight_type entry_type;
206 if (entry->d_name[0] == '.')
209 if (asprintf(&backlight_path, "%s/%s", "/sys/class/backlight",
213 if (asprintf(&path, "%s/%s", backlight_path, "type") < 0)
216 fd = open(path, O_RDONLY);
221 ret = read (fd, &buffer, sizeof(buffer));
229 if (!strncmp(buffer, "raw\n", sizeof(buffer)))
230 entry_type = BACKLIGHT_RAW;
231 else if (!strncmp(buffer, "platform\n", sizeof(buffer)))
232 entry_type = BACKLIGHT_PLATFORM;
233 else if (!strncmp(buffer, "firmware\n", sizeof(buffer)))
234 entry_type = BACKLIGHT_FIRMWARE;
238 if (connector_type != DRM_MODE_CONNECTOR_LVDS &&
239 connector_type != DRM_MODE_CONNECTOR_eDP) {
240 /* External displays are assumed to require
241 gpu control at the moment */
242 if (entry_type != BACKLIGHT_RAW)
248 if (asprintf(&path, "%s/%s", backlight_path, "device") < 0)
251 ret = readlink(path, buffer, sizeof(buffer) - 1);
258 parent = basename(buffer);
260 /* Perform matching for raw and firmware backlights -
261 platform backlights have to be assumed to match */
262 if (entry_type == BACKLIGHT_RAW ||
263 entry_type == BACKLIGHT_FIRMWARE) {
264 if (!(pci_name && !strcmp(pci_name, parent)))
268 if (entry_type < type)
275 chosen_path = strdup(backlight_path);
278 free(backlight_path);
285 backlight = malloc(sizeof(struct backlight));
290 backlight->path = chosen_path;
291 backlight->type = type;
293 backlight->max_brightness = backlight_get_max_brightness(backlight);
294 if (backlight->max_brightness < 0)
297 backlight->brightness = backlight_get_actual_brightness(backlight);
298 if (backlight->brightness < 0)
301 closedir(backlights);
304 closedir(backlights);