[weston] libbacklight: Fix backlight detection

Submitted by Armin Krezović on Feb. 15, 2017, 6:21 p.m.

Details

Message ID 20170215182116.864-1-krezovic.armin@gmail.com
State New
Headers show
Series "libbacklight: Fix backlight detection" ( rev: 1 ) in Wayland

Not browsing as part of any series.

Commit Message

Armin Krezović Feb. 15, 2017, 6:21 p.m.
On recent kernels, backlight directory does not contain
information about the device, but rather about the
connector. In this case, matching device pci_id and
connector device doesn't work.

This patch makes use of connector name, checks if
the connector directory is present in the device's
/sys path and matches it to the correct backlight
interface, if any.

It also fixes the safe_strtoint usage, so it doesn't
fail when newline is present.

Signed-off-by: Armin Krezović <krezovic.armin@gmail.com>
---
 Makefile.am                    |  8 +++--
 libweston/compositor-drm.c     | 49 ++++--------------------------
 libweston/libbacklight.c       | 31 +++++++++++++------
 libweston/libbacklight.h       |  1 +
 libweston/weston-drm-helpers.c | 48 ++++++++++++++++++++++++++++++
 libweston/weston-drm-helpers.h | 67 ++++++++++++++++++++++++++++++++++++++++++
 tests/setbacklight.c           | 28 ++++++++++++------
 7 files changed, 169 insertions(+), 63 deletions(-)
 create mode 100644 libweston/weston-drm-helpers.c
 create mode 100644 libweston/weston-drm-helpers.h

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index cdf82ab4..f9a72319 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -378,7 +378,9 @@  drm_backend_la_SOURCES =			\
 	shared/helpers.h			\
 	shared/timespec-util.h			\
 	libweston/libbacklight.c		\
-	libweston/libbacklight.h
+	libweston/libbacklight.h		\
+	libweston/weston-drm-helpers.c		\
+	libweston/weston-drm-helpers.h
 
 if ENABLE_VAAPI_RECORDER
 drm_backend_la_SOURCES += libweston/vaapi-recorder.c libweston/vaapi-recorder.h
@@ -1465,7 +1467,9 @@  noinst_PROGRAMS += setbacklight
 setbacklight_SOURCES =				\
 	tests/setbacklight.c			\
 	libweston/libbacklight.c		\
-	libweston/libbacklight.h
+	libweston/libbacklight.h		\
+	libweston/weston-drm-helpers.c		\
+	libweston/weston-drm-helpers.h
 setbacklight_CFLAGS = $(AM_CFLAGS) $(SETBACKLIGHT_CFLAGS)
 setbacklight_LDADD = $(SETBACKLIGHT_LIBS)
 endif
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 2a80c6d7..418bd600 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -53,6 +53,7 @@ 
 #include "shared/timespec-util.h"
 #include "gl-renderer.h"
 #include "weston-egl-ext.h"
+#include "weston-drm-helpers.h"
 #include "pixman-renderer.h"
 #include "libbacklight.h"
 #include "libinput-seat.h"
@@ -1798,45 +1799,6 @@  drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
 	output->dpms = level;
 }
 
-static const char * const connector_type_names[] = {
-	[DRM_MODE_CONNECTOR_Unknown]     = "Unknown",
-	[DRM_MODE_CONNECTOR_VGA]         = "VGA",
-	[DRM_MODE_CONNECTOR_DVII]        = "DVI-I",
-	[DRM_MODE_CONNECTOR_DVID]        = "DVI-D",
-	[DRM_MODE_CONNECTOR_DVIA]        = "DVI-A",
-	[DRM_MODE_CONNECTOR_Composite]   = "Composite",
-	[DRM_MODE_CONNECTOR_SVIDEO]      = "SVIDEO",
-	[DRM_MODE_CONNECTOR_LVDS]        = "LVDS",
-	[DRM_MODE_CONNECTOR_Component]   = "Component",
-	[DRM_MODE_CONNECTOR_9PinDIN]     = "DIN",
-	[DRM_MODE_CONNECTOR_DisplayPort] = "DP",
-	[DRM_MODE_CONNECTOR_HDMIA]       = "HDMI-A",
-	[DRM_MODE_CONNECTOR_HDMIB]       = "HDMI-B",
-	[DRM_MODE_CONNECTOR_TV]          = "TV",
-	[DRM_MODE_CONNECTOR_eDP]         = "eDP",
-#ifdef DRM_MODE_CONNECTOR_DSI
-	[DRM_MODE_CONNECTOR_VIRTUAL]     = "Virtual",
-	[DRM_MODE_CONNECTOR_DSI]         = "DSI",
-#endif
-};
-
-static char *
-make_connector_name(const drmModeConnector *con)
-{
-	char name[32];
-	const char *type_name = NULL;
-
-	if (con->connector_type < ARRAY_LENGTH(connector_type_names))
-		type_name = connector_type_names[con->connector_type];
-
-	if (!type_name)
-		type_name = "UNNAMED";
-
-	snprintf(name, sizeof name, "%s-%d", type_name, con->connector_type_id);
-
-	return strdup(name);
-}
-
 static int
 find_crtc_for_connector(struct drm_backend *b,
 			drmModeRes *resources, drmModeConnector *connector)
@@ -2610,18 +2572,19 @@  create_output_for_connector(struct drm_backend *b,
 	output->pipe = i;
 	output->connector_id = connector->connector_id;
 
-	output->backlight = backlight_init(drm_device,
-					   connector->connector_type);
-
 	output->base.enable = drm_output_enable;
 	output->base.destroy = drm_output_destroy;
 	output->base.disable = drm_output_disable;
-	output->base.name = make_connector_name(connector);
+	output->base.name = weston_make_drm_connector_name(connector);
 
 	output->destroy_pending = 0;
 	output->disable_pending = 0;
 	output->original_crtc = NULL;
 
+	output->backlight = backlight_init(drm_device,
+					   output->base.name,
+					   connector->connector_type);
+
 	weston_output_init(&output->base, b->compositor);
 	weston_compositor_add_pending_output(&output->base, b->compositor);
 
diff --git a/libweston/libbacklight.c b/libweston/libbacklight.c
index 4bbc6db4..da627abc 100644
--- a/libweston/libbacklight.c
+++ b/libweston/libbacklight.c
@@ -67,6 +67,9 @@  static long backlight_get(struct backlight *backlight, char *node)
 		goto out;
 	}
 
+	if (buffer[ret - 1] == '\n')
+		buffer[ret - 1] = '\0';
+
 	if (!safe_strtoint(buffer, &value)) {
 		ret = -1;
 		goto out;
@@ -151,10 +154,12 @@  void backlight_destroy(struct backlight *backlight)
 }
 
 struct backlight *backlight_init(struct udev_device *drm_device,
+				 const char *connector_name,
 				 uint32_t connector_type)
 {
 	const char *syspath = NULL;
-	char *pci_name = NULL;
+	char *connector = NULL;
+	char *connector_path = NULL;
 	char *chosen_path = NULL;
 	char *path = NULL;
 	DIR *backlights = NULL;
@@ -171,16 +176,20 @@  struct backlight *backlight_init(struct udev_device *drm_device,
 	if (!syspath)
 		return NULL;
 
-	if (asprintf(&path, "%s/%s", syspath, "device") < 0)
+	if (asprintf(&connector, "%s-%s", basename(syspath), connector_name) < 0)
 		return NULL;
 
-	ret = readlink(path, buffer, sizeof(buffer) - 1);
-	free(path);
-	if (ret < 0)
-		return NULL;
+	if (asprintf(&connector_path, "%s/%s", syspath, connector) < 0)
+		goto err_conn;
+
+	backlights = opendir(connector_path);
+	free(connector_path);
 
-	buffer[ret] = '\0';
-	pci_name = basename(buffer);
+	if (!backlights)
+		goto err_conn;
+
+	closedir(backlights);
+	backlights = NULL;
 
 	if (connector_type <= 0)
 		return NULL;
@@ -271,7 +280,7 @@  struct backlight *backlight_init(struct udev_device *drm_device,
 		   platform backlights have to be assumed to match */
 		if (entry_type == BACKLIGHT_RAW ||
 		    entry_type == BACKLIGHT_FIRMWARE) {
-			if (!(pci_name && !strcmp(pci_name, parent)))
+			if (!(connector && !strcmp(connector, parent)))
 				goto out;
 		}
 
@@ -309,10 +318,14 @@  struct backlight *backlight_init(struct udev_device *drm_device,
 		goto err;
 
 	closedir(backlights);
+	free(connector);
+
 	return backlight;
 err:
 	closedir(backlights);
 	free (chosen_path);
 	free (backlight);
+err_conn:
+	free(connector);
 	return NULL;
 }
diff --git a/libweston/libbacklight.h b/libweston/libbacklight.h
index 8717ab10..2a069353 100644
--- a/libweston/libbacklight.h
+++ b/libweston/libbacklight.h
@@ -55,6 +55,7 @@  struct backlight {
  * matching drm subsytem and with status of connected.
  */
 struct backlight *backlight_init(struct udev_device *drm_device,
+				 const char *connector_name,
 				 uint32_t connector_type);
 
 /* Free backlight resources */
diff --git a/libweston/weston-drm-helpers.c b/libweston/weston-drm-helpers.c
new file mode 100644
index 00000000..1ab01aca
--- /dev/null
+++ b/libweston/weston-drm-helpers.c
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "shared/helpers.h"
+#include "weston-drm-helpers.h"
+
+#include <stdio.h>
+#include <xf86drm.h>
+
+char *
+weston_make_drm_connector_name(const drmModeConnector *con)
+{
+	char name[32];
+	const char *type_name = NULL;
+
+	if (con->connector_type < ARRAY_LENGTH(connector_type_names))
+		type_name = connector_type_names[con->connector_type];
+
+	if (!type_name)
+		type_name = "UNNAMED";
+
+	snprintf(name, sizeof name, "%s-%d", type_name, con->connector_type_id);
+
+	return strdup(name);
+}
diff --git a/libweston/weston-drm-helpers.h b/libweston/weston-drm-helpers.h
new file mode 100644
index 00000000..41442a3a
--- /dev/null
+++ b/libweston/weston-drm-helpers.h
@@ -0,0 +1,67 @@ 
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef WESTON_DRM_HELPERS_H
+#define WESTON_DRM_HELPERS_H
+
+#include <stdint.h>
+#include <string.h>
+#include <xf86drmMode.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const char * const connector_type_names[] = {
+	[DRM_MODE_CONNECTOR_Unknown]     = "Unknown",
+	[DRM_MODE_CONNECTOR_VGA]         = "VGA",
+	[DRM_MODE_CONNECTOR_DVII]        = "DVI-I",
+	[DRM_MODE_CONNECTOR_DVID]        = "DVI-D",
+	[DRM_MODE_CONNECTOR_DVIA]        = "DVI-A",
+	[DRM_MODE_CONNECTOR_Composite]   = "Composite",
+	[DRM_MODE_CONNECTOR_SVIDEO]      = "SVIDEO",
+	[DRM_MODE_CONNECTOR_LVDS]        = "LVDS",
+	[DRM_MODE_CONNECTOR_Component]   = "Component",
+	[DRM_MODE_CONNECTOR_9PinDIN]     = "DIN",
+	[DRM_MODE_CONNECTOR_DisplayPort] = "DP",
+	[DRM_MODE_CONNECTOR_HDMIA]       = "HDMI-A",
+	[DRM_MODE_CONNECTOR_HDMIB]       = "HDMI-B",
+	[DRM_MODE_CONNECTOR_TV]          = "TV",
+	[DRM_MODE_CONNECTOR_eDP]         = "eDP",
+#ifdef DRM_MODE_CONNECTOR_DSI
+	[DRM_MODE_CONNECTOR_VIRTUAL]     = "Virtual",
+	[DRM_MODE_CONNECTOR_DSI]         = "DSI",
+#endif
+};
+
+char *
+weston_make_drm_connector_name(const drmModeConnector *con);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WESTON_DRM_HELPERS_H */
diff --git a/tests/setbacklight.c b/tests/setbacklight.c
index 3bfc7d1e..b0f0a6a0 100644
--- a/tests/setbacklight.c
+++ b/tests/setbacklight.c
@@ -41,12 +41,19 @@ 
 #include <xf86drmMode.h>
 
 #include "libbacklight.h"
+#include "weston-drm-helpers.h"
 
-static uint32_t
-get_drm_connector_type(struct udev_device *drm_device, uint32_t connector_id)
+struct setbacklight_connector {
+	char *name;
+	uint32_t type;
+};
+
+static int
+get_drm_connector_name_and_type(struct udev_device *drm_device, uint32_t connector_id,
+				struct setbacklight_connector *c)
 {
 	const char *filename;
-	int fd, i, connector_type;
+	int fd, i;
 	drmModeResPtr res;
 	drmModeConnectorPtr connector;
 
@@ -75,12 +82,14 @@  get_drm_connector_type(struct udev_device *drm_device, uint32_t connector_id)
 			continue;
 		}
 
-		connector_type = connector->connector_type;
+		c->name = weston_make_drm_connector_name(connector);
+		c->type = connector->connector_type;
+
 		drmModeFreeConnector(connector);
 		drmModeFreeResources(res);
 
 		close(fd);
-		return connector_type;
+		return 0;
 	}
 
 	close(fd);
@@ -107,21 +116,22 @@  get_normalized_backlight(struct backlight *backlight)
 static void
 set_backlight(struct udev_device *drm_device, int connector_id, int blight)
 {
-	int connector_type;
 	long max_brightness, brightness, actual_brightness;
 	struct backlight *backlight;
 	long new_blight;
+	struct setbacklight_connector connector;
 
-	connector_type = get_drm_connector_type(drm_device, connector_id);
-	if (connector_type < 0)
+	if (get_drm_connector_name_and_type(drm_device, connector_id, &connector) < 0)
 		return;
 
-	backlight = backlight_init(drm_device, connector_type);
+	backlight = backlight_init(drm_device, connector.name, connector.type);
 	if (!backlight) {
 		printf("backlight adjust failed\n");
 		return;
 	}
 
+	free(connector.name);
+
 	max_brightness = backlight_get_max_brightness(backlight);
 	printf("Max backlight: %ld\n", max_brightness);