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);
77 long backlight_get_brightness(struct backlight *backlight)
79 return backlight_get(backlight, "brightness");
82 long backlight_get_max_brightness(struct backlight *backlight)
84 return backlight_get(backlight, "max_brightness");
87 long backlight_get_actual_brightness(struct backlight *backlight)
89 return backlight_get(backlight, "actual_brightness");
92 long backlight_set_brightness(struct backlight *backlight, long brightness)
99 if (asprintf(&path, "%s/%s", backlight->path, "brightness") < 0)
102 fd = open(path, O_RDWR);
108 ret = read(fd, &buffer, sizeof(buffer));
114 if (asprintf(&buffer, "%ld", brightness) < 0) {
119 ret = write(fd, buffer, strlen(buffer));
125 ret = backlight_get_brightness(backlight);
126 backlight->brightness = ret;
135 void backlight_destroy(struct backlight *backlight)
141 free(backlight->path);
146 struct backlight *backlight_init(struct udev_device *drm_device,
147 uint32_t connector_type)
149 const char *syspath = NULL;
150 char *pci_name = NULL;
151 char *chosen_path = NULL;
153 DIR *backlights = NULL;
154 struct dirent *entry;
155 enum backlight_type type = 0;
157 struct backlight *backlight = NULL;
163 syspath = udev_device_get_syspath(drm_device);
167 if (asprintf(&path, "%s/%s", syspath, "device") < 0)
170 ret = readlink(path, buffer, sizeof(buffer) - 1);
176 pci_name = basename(buffer);
178 if (connector_type <= 0)
181 backlights = opendir("/sys/class/backlight");
185 /* Find the "best" backlight for the device. Firmware
186 interfaces are preferred over platform interfaces are
187 preferred over raw interfaces. For raw interfaces we'll
188 check if the device ID in the form of pci match, while
189 for firmware interfaces we require the pci ID to
190 match. It's assumed that platform interfaces always match,
191 since we can't actually associate them with IDs.
193 A further awkwardness is that, while it's theoretically
194 possible for an ACPI interface to include support for
195 changing the backlight of external devices, it's unlikely
196 to ever be done. It's effectively impossible for a platform
197 interface to do so. So if we get asked about anything that
198 isn't LVDS or eDP, we pretty much have to require that the
199 control be supplied via a raw interface */
201 while ((entry = readdir(backlights))) {
202 char *backlight_path;
204 enum backlight_type entry_type;
207 if (entry->d_name[0] == '.')
210 if (asprintf(&backlight_path, "%s/%s", "/sys/class/backlight",
214 if (asprintf(&path, "%s/%s", backlight_path, "type") < 0)
217 fd = open(path, O_RDONLY);
222 ret = read (fd, &buffer, sizeof(buffer));
230 if (!strncmp(buffer, "raw\n", sizeof(buffer)))
231 entry_type = BACKLIGHT_RAW;
232 else if (!strncmp(buffer, "platform\n", sizeof(buffer)))
233 entry_type = BACKLIGHT_PLATFORM;
234 else if (!strncmp(buffer, "firmware\n", sizeof(buffer)))
235 entry_type = BACKLIGHT_FIRMWARE;
239 if (connector_type != DRM_MODE_CONNECTOR_LVDS &&
240 connector_type != DRM_MODE_CONNECTOR_eDP) {
241 /* External displays are assumed to require
242 gpu control at the moment */
243 if (entry_type != BACKLIGHT_RAW)
249 if (asprintf(&path, "%s/%s", backlight_path, "device") < 0)
252 ret = readlink(path, buffer, sizeof(buffer) - 1);
259 parent = basename(buffer);
261 /* Perform matching for raw and firmware backlights -
262 platform backlights have to be assumed to match */
263 if (entry_type == BACKLIGHT_RAW ||
264 entry_type == BACKLIGHT_FIRMWARE) {
265 if (!(pci_name && !strcmp(pci_name, parent)))
269 if (entry_type < type)
276 chosen_path = strdup(backlight_path);
279 free(backlight_path);
286 backlight = malloc(sizeof(struct backlight));
291 backlight->path = chosen_path;
292 backlight->type = type;
294 backlight->max_brightness = backlight_get_max_brightness(backlight);
295 if (backlight->max_brightness < 0)
298 backlight->brightness = backlight_get_actual_brightness(backlight);
299 if (backlight->brightness < 0)
302 closedir(backlights);
305 closedir(backlights);