[gnome-color-manager] Add a udev prober that makes DDC/CI i2c devices available for the user to use



commit a5a4d5a8c1817fe7c829fd09ffc6ec105b0d9a74
Author: Richard Hughes <richard hughsie com>
Date:   Tue Aug 10 11:33:59 2010 +0100

    Add a udev prober that makes DDC/CI i2c devices available for the user to use

 contrib/gnome-color-manager.spec.in |    1 +
 libcolor-glib/gcm-ddc-client.c      |   10 +++--
 libcolor-glib/gcm-ddc-control.c     |    6 ++-
 libcolor-glib/gcm-ddc-control.h     |    4 +-
 libcolor-glib/gcm-ddc-device.c      |   22 ++++++-----
 libcolor-glib/gcm-self-test.c       |   16 ++++++++
 rules/.gitignore                    |    4 ++
 rules/55-gcm-i2c.rules              |   18 +++++++++
 rules/Makefile.am                   |   27 ++++++++++++-
 rules/gcm-udev-ddc.c                |   72 +++++++++++++++++++++++++++++++++++
 10 files changed, 161 insertions(+), 19 deletions(-)
---
diff --git a/contrib/gnome-color-manager.spec.in b/contrib/gnome-color-manager.spec.in
index c6cee42..7e2a846 100644
--- a/contrib/gnome-color-manager.spec.in
+++ b/contrib/gnome-color-manager.spec.in
@@ -91,6 +91,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &> /dev/null || :
 %defattr(-,root,root,-)
 %doc AUTHORS COPYING NEWS README
 /lib/udev/rules.d/*.rules
+/lib/udev/gcm-*
 %{_bindir}/gcm-*
 %{_libexecdir}/*
 %dir %{_datadir}/gnome-color-manager
diff --git a/libcolor-glib/gcm-ddc-client.c b/libcolor-glib/gcm-ddc-client.c
index 7fe1fc8..2d8d3d5 100644
--- a/libcolor-glib/gcm-ddc-client.c
+++ b/libcolor-glib/gcm-ddc-client.c
@@ -35,6 +35,8 @@
 #include <gcm-ddc-client.h>
 #include <gcm-ddc-device.h>
 
+#include "egg-debug.h"
+
 static void     gcm_ddc_client_finalize	(GObject     *object);
 
 #define GCM_DDC_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_DDC_CLIENT, GcmDdcClientPrivate))
@@ -98,12 +100,12 @@ gcm_ddc_client_ensure_coldplug (GcmDdcClient *client, GError **error)
 		gcm_ddc_device_set_verbose (device, client->priv->verbose);
 		ret = gcm_ddc_device_open (device, filename, &error_local);
 		if (!ret) {
-			if (client->priv->verbose == GCM_VERBOSE_OVERVIEW)
-				g_warning ("failed to open %s: %s", filename, error_local->message);
+			if (client->priv->verbose >= GCM_VERBOSE_OVERVIEW)
+				egg_debug ("failed to open %s: %s", filename, error_local->message);
 			g_clear_error (&error_local);
 		} else {
-			if (client->priv->verbose == GCM_VERBOSE_OVERVIEW)
-				g_debug ("success, adding %s", filename);
+			if (client->priv->verbose >= GCM_VERBOSE_OVERVIEW)
+				egg_debug ("success, adding %s", filename);
 			any_found = TRUE;
 			g_ptr_array_add (client->priv->devices, g_object_ref (device));
 		}
diff --git a/libcolor-glib/gcm-ddc-control.c b/libcolor-glib/gcm-ddc-control.c
index 3cb724a..680b834 100644
--- a/libcolor-glib/gcm-ddc-control.c
+++ b/libcolor-glib/gcm-ddc-control.c
@@ -34,6 +34,8 @@
 #include <gcm-ddc-device.h>
 #include <gcm-ddc-control.h>
 
+#include "egg-debug.h"
+
 static void     gcm_ddc_control_finalize	(GObject     *object);
 
 #define GCM_DDC_CONTROL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_DDC_CONTROL, GcmDdcControlPrivate))
@@ -311,7 +313,7 @@ gcm_ddc_control_parse (GcmDdcControl *control, guchar id, const gchar *values)
 	/* just save this */
 	control->priv->id = id;
 	if (control->priv->verbose == GCM_VERBOSE_OVERVIEW)
-		g_debug ("add control 0x%02x (%s)", id, gcm_ddc_control_get_description (control));
+		egg_debug ("add control 0x%02x (%s)", id, gcm_ddc_control_get_description (control));
 
 	/* do we have any values to parse */
 	if (values == NULL)
@@ -322,7 +324,7 @@ gcm_ddc_control_parse (GcmDdcControl *control, guchar id, const gchar *values)
 	for (i=0; split[i] != NULL; i++) {
 		value = atoi (split[i]);
 		if (control->priv->verbose == GCM_VERBOSE_OVERVIEW)
-			g_debug ("add value %i to control 0x%02x", value, id);
+			egg_debug ("add value %i to control 0x%02x", value, id);
 		g_array_append_val (control->priv->values, value);
 	}
 out:
diff --git a/libcolor-glib/gcm-ddc-control.h b/libcolor-glib/gcm-ddc-control.h
index 75ca1a7..3c40106 100644
--- a/libcolor-glib/gcm-ddc-control.h
+++ b/libcolor-glib/gcm-ddc-control.h
@@ -97,7 +97,7 @@ void		 gcm_ddc_control_set_verbose		(GcmDdcControl	*control,
 							 GcmVerbose verbose);
 gboolean	 gcm_ddc_control_run			(GcmDdcControl	*control,
 							 GError		**error);
-gboolean	 gcm_ddc_control_request			(GcmDdcControl	*control,
+gboolean	 gcm_ddc_control_request		(GcmDdcControl	*control,
 							 guint16	*value,
 							 guint16	*maximum,
 							 GError		**error);
@@ -107,7 +107,7 @@ gboolean	 gcm_ddc_control_set			(GcmDdcControl	*control,
 gboolean	 gcm_ddc_control_reset			(GcmDdcControl	*control,
 							 GError		**error);
 guchar		 gcm_ddc_control_get_id			(GcmDdcControl	*control);
-const gchar	*gcm_ddc_control_get_description		(GcmDdcControl	*control);
+const gchar	*gcm_ddc_control_get_description	(GcmDdcControl	*control);
 GArray		*gcm_ddc_control_get_values		(GcmDdcControl	*control);
 
 G_END_DECLS
diff --git a/libcolor-glib/gcm-ddc-device.c b/libcolor-glib/gcm-ddc-device.c
index f7a3347..6d8d59b 100644
--- a/libcolor-glib/gcm-ddc-device.c
+++ b/libcolor-glib/gcm-ddc-device.c
@@ -45,6 +45,8 @@
 #include <gcm-ddc-device.h>
 #include <gcm-ddc-control.h>
 
+#include "egg-debug.h"
+
 static void     gcm_ddc_device_finalize	(GObject     *object);
 
 #define GCM_DDC_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_DDC_DEVICE, GcmDdcDevicePrivate))
@@ -385,7 +387,7 @@ gcm_ddc_device_read (GcmDdcDevice *device, guchar *data, gsize data_length, gsiz
 
 	if ((buf[1] & GCM_MAGIC_BYTE2) == 0) {
 		/* Fujitsu Siemens P19-2 and NEC LCD 1970NX send wrong magic when reading caps. */
-		g_debug ( "Invalid response, magic is 0x%02x, correcting", buf[1]);
+		egg_debug ( "Invalid response, magic is 0x%02x, correcting", buf[1]);
 	}
 
 	len = buf[1] & ~GCM_MAGIC_BYTE2;
@@ -464,8 +466,8 @@ gcm_ddc_device_add_control (GcmDdcDevice *device, const gchar *index_str, const
 static gboolean
 gcm_ddc_device_set_device_property (GcmDdcDevice *device, const gchar *key, const gchar *value)
 {
-	if (device->priv->verbose == GCM_VERBOSE_OVERVIEW)
-		g_debug ("key=%s, value=%s", key, value);
+	if (device->priv->verbose >= GCM_VERBOSE_OVERVIEW)
+		egg_debug ("key=%s, value=%s", key, value);
 	if (g_strcmp0 (key, "type") == 0) {
 		if (g_strcmp0 (value, "lcd") == 0)
 			device->priv->kind = GCM_DDC_DEVICE_KIND_LCD;
@@ -567,16 +569,16 @@ gcm_ddc_device_ensure_controls (GcmDdcDevice *device, GError **error)
 		/* try to read */
 		ret = gcm_ddc_device_capabilities_request (device, offset, buf, sizeof(buf), &len, error);
 		if (!ret) {
-			if (device->priv->verbose == GCM_VERBOSE_PROTOCOL)
-				g_warning ("Failed to read capabilities offset 0x%02x.", offset);
+			if (device->priv->verbose >= GCM_VERBOSE_PROTOCOL)
+				egg_warning ("Failed to read capabilities offset 0x%02x.", offset);
 			retries--;
 			continue;
 		}
 
 		/* not enough data */
 		if (len < 3) {
-			if (device->priv->verbose == GCM_VERBOSE_PROTOCOL)
-				g_warning ("Not enough capabilities data at offset 0x%02x.", offset);
+			if (device->priv->verbose >= GCM_VERBOSE_PROTOCOL)
+				egg_debug ("Not enough capabilities data at offset 0x%02x.", offset);
 			retries--;
 			continue;
 		}
@@ -584,7 +586,7 @@ gcm_ddc_device_ensure_controls (GcmDdcDevice *device, GError **error)
 		/* check response */
 		if (buf[0] != GCM_CAPABILITIES_REPLY) {
 			if (device->priv->verbose == GCM_VERBOSE_PROTOCOL)
-				g_warning ("Not correct capabilities reply at offset 0x%02x.", offset);
+				egg_warning ("Not correct capabilities reply at offset 0x%02x.", offset);
 			retries--;
 			continue;
 		}
@@ -592,7 +594,7 @@ gcm_ddc_device_ensure_controls (GcmDdcDevice *device, GError **error)
 		/* check offset */
 		if ((buf[1] * 256 + buf[2]) != offset) {
 			if (device->priv->verbose == GCM_VERBOSE_PROTOCOL)
-				g_warning ("Not correct capabilities offset at offset 0x%02x.", offset);
+				egg_warning ("Not correct capabilities offset at offset 0x%02x.", offset);
 			retries--;
 			continue;
 		}
@@ -604,7 +606,7 @@ gcm_ddc_device_ensure_controls (GcmDdcDevice *device, GError **error)
 	} while (len != 3);
 
 	if (device->priv->verbose == GCM_VERBOSE_OVERVIEW)
-		g_debug ("raw caps: %s", string->str);
+		egg_debug ("raw caps: %s", string->str);
 
 	/* parse */
 	ret = gcm_ddc_device_parse_caps (device, string->str);
diff --git a/libcolor-glib/gcm-self-test.c b/libcolor-glib/gcm-self-test.c
index 2c229e6..a72e8f7 100644
--- a/libcolor-glib/gcm-self-test.c
+++ b/libcolor-glib/gcm-self-test.c
@@ -141,10 +141,26 @@ gcm_test_ddc_device_func (void)
 static void
 gcm_test_ddc_client_func (void)
 {
+	gboolean ret;
+	GPtrArray *array;
+	GError *error = NULL;
 	GcmDdcClient *client;
 
 	client = gcm_ddc_client_new ();
 	g_assert (client != NULL);
+	gcm_ddc_client_set_verbose (client, GCM_VERBOSE_OVERVIEW);
+
+	array = gcm_ddc_client_get_devices (client, &error);
+	g_assert_no_error (error);
+	g_assert (array != NULL);
+
+	/* ensure we have at least one usable device */
+	g_assert_cmpint (array->len, >, 0);
+	g_ptr_array_unref (array);
+
+	ret = gcm_ddc_client_close (client, &error);
+	g_assert_no_error (error);
+	g_assert (ret);
 
 	g_object_unref (client);
 }
diff --git a/rules/.gitignore b/rules/.gitignore
new file mode 100644
index 0000000..c4433c9
--- /dev/null
+++ b/rules/.gitignore
@@ -0,0 +1,4 @@
+.deps
+.libs
+*.o
+gcm-udev-ddc
diff --git a/rules/55-gcm-i2c.rules b/rules/55-gcm-i2c.rules
new file mode 100644
index 0000000..d6255a7
--- /dev/null
+++ b/rules/55-gcm-i2c.rules
@@ -0,0 +1,18 @@
+##############################################################################################################
+# Copyright (C) 2010 Richard Hughes <richard hughsie com>
+#
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Ensure i2c-dev is loaded and the permissions of DDC/CI devices are
+# relaxed for any i2c devices so we can interact with them from userspace.
+
+# ensure userspace driver is loaded
+SUBSYSTEM=="i2c-adapter", ACTION=="add", RUN+="/sbin/modprobe i2c-dev"
+
+# make acl managed if a DDC device
+SUBSYSTEM=="i2c-dev", ACTION=="add", PROGRAM="gcm-udev-ddc /dev/%k", ENV{DDC_DEVICE}="1"
diff --git a/rules/Makefile.am b/rules/Makefile.am
index e2fea9a..8df12e9 100644
--- a/rules/Makefile.am
+++ b/rules/Makefile.am
@@ -1,7 +1,32 @@
+INCLUDES =							\
+	$(GLIB_CFLAGS)						\
+	$(GUDEV_CFLAGS)						\
+	$(GTK_CFLAGS)						\
+	-I$(top_srcdir)/libcolor-glib				\
+	-DI_KNOW_THE_LIBCOLOR_GLIB_API_IS_SUBJECT_TO_CHANGE
+
+COLOR_GLIB_LIBS =						\
+	$(top_builddir)/libcolor-glib/libcolor-glib.la
+
 udevrulesdir = $(slashlibdir)/udev/rules.d
 udevrules_DATA =						\
 	95-gcm-colorimeters.rules				\
-	95-gcm-devices.rules
+	95-gcm-devices.rules					\
+	55-gcm-i2c.rules
+
+udevproberdir = $(slashlibdir)/udev
+udevprober_PROGRAMS =						\
+	gcm-udev-ddc
+
+gcm_udev_ddc_SOURCES =						\
+	gcm-udev-ddc.c
+
+gcm_udev_ddc_LDADD =						\
+	$(COLOR_GLIB_LIBS)					\
+	-lm
+
+gcm_udev_ddc_CFLAGS =						\
+	$(WARNINGFLAGS_C)
 
 EXTRA_DIST =							\
 	$(udevrules_DATA)
diff --git a/rules/gcm-udev-ddc.c b/rules/gcm-udev-ddc.c
new file mode 100644
index 0000000..7af7f9d
--- /dev/null
+++ b/rules/gcm-udev-ddc.c
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <libcolor-glib.h>
+
+/**
+ * main:
+ **/
+int
+main (int argc, char **argv)
+{
+	guint retval = 1;
+	gboolean ret;
+	GError *error = NULL;
+	GcmDdcDevice *device;
+	const gchar *edid_md5;
+
+	g_type_init ();
+
+	/* find devices */
+	device = gcm_ddc_device_new ();
+
+	/* check we got a device */
+	if (argv[1] == NULL) {
+		g_printerr ("FAILED get device\n");
+		goto out;
+	}
+
+	/* get the default device */
+	ret = gcm_ddc_device_open (device, argv[1], &error);
+	if (!ret) {
+		g_printerr ("FAILED to open device: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* check we can use it */
+	edid_md5 = gcm_ddc_device_get_edid_md5 (device, &error);
+	if (edid_md5 == NULL) {
+		g_print ("FAILED to get edid: %s\n", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* success */
+	retval = 0;
+out:
+	g_object_unref (device);
+	return retval;
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]