All of lore.kernel.org
 help / color / mirror / Atom feed
From: Keith Packard <keithp@keithp.com>
To: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Subject: [PATCH] intel: Listen for hotplug uevents (V3)
Date: Mon,  4 Oct 2010 10:43:38 -0700	[thread overview]
Message-ID: <1286214218-10551-1-git-send-email-keithp@keithp.com> (raw)
In-Reply-To: <AANLkTi=K9Hdzf=rFEGKBaynw9i9HQqb1MwqX9Z+iN8Fg@mail.gmail.com>

From: Adam Jackson <ajax@redhat.com>

This connects the kernel uevent indicating monitor hotplugging to the
RandR notification events so that X applications can be notified
automatically when monitors are connected or disconnected.

This also adds a configuration option to disable hotplug events.

V2: missed a #ifdef HAVE_UDEV around some udev-specific declarations

V3: document Hotplug option in man page

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 configure.ac       |    5 ++
 man/intel.man      |    6 +++
 src/Makefile.am    |    4 +-
 src/intel.h        |   12 +++++
 src/intel_driver.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index e066b3d..58fa929 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,6 +47,11 @@ AC_PROG_LIBTOOL
 PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.0], [gen4asm=yes], [gen4asm=no])
 AM_CONDITIONAL(HAVE_GEN4ASM, test x$gen4asm = xyes)
 
+PKG_CHECK_MODULES(UDEV, [libudev], [udev=yes], [udev=no])
+if test x"$udev" = xyes; then
+	AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection])
+fi
+
 AH_TOP([#include "xorg-server.h"])
 
 # Define a configure option for an alternate module directory
diff --git a/man/intel.man b/man/intel.man
index 31860f2..fa7f7dc 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -192,6 +192,12 @@ Enable XvMC driver. Current support MPEG2 MC on 915/945 and G33 series.
 User should provide absolute path to libIntelXvMC.so in XvMCConfig file.
 .IP
 Default: Disabled.
+.TP
+.BI "Option \*qHotplug\*q \*q" boolean \*q
+This option controls whether the driver automatically notifies
+applications when monitors are connected or disconnected.
+.IP
+Default: enabled.
 
 .SH OUTPUT CONFIGURATION
 On 830M and better chipsets, the driver supports runtime configuration of
diff --git a/src/Makefile.am b/src/Makefile.am
index b0a1cf7..ab70207 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,13 +26,13 @@ SUBDIRS = xvmc render_program legacy
 # _ladir passes a dummy rpath to libtool so the thing will actually link
 # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
 
-AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
+AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @UDEV_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \
 	@PCIACCESS_CFLAGS@ -I$(top_srcdir)/uxa -I$(top_srcdir)/src/render_program
 
 intel_drv_la_LTLIBRARIES = intel_drv.la
 intel_drv_la_LDFLAGS = -module -avoid-version
 intel_drv_ladir = @moduledir@/drivers
-intel_drv_la_LIBADD = -lm @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la legacy/liblegacy.la
+intel_drv_la_LIBADD = @UDEV_LIBS@ -lm @DRM_LIBS@ -ldrm_intel ../uxa/libuxa.la legacy/liblegacy.la
 intel_drv_la_LIBADD += @PCIACCESS_LIBS@
 
 NULL:=#
diff --git a/src/intel.h b/src/intel.h
index b816aeb..1234b94 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -34,6 +34,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #if 0
 #define I830DEBUG
 #endif
@@ -70,6 +74,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "intel_driver.h"
 
+#if HAVE_UDEV
+#include <libudev.h>
+#endif
+
 #include "uxa.h"
 /* XXX
  * The X server gained an *almost* identical implementation in 1.9.
@@ -435,6 +443,10 @@ typedef struct intel_screen_private {
 	 */
 	Bool fallback_debug;
 	unsigned debug_flush;
+#if HAVE_UDEV
+	struct udev_monitor *uevent_monitor;
+	InputHandlerProc uevent_handler;
+#endif
 } intel_screen_private;
 
 enum {
diff --git a/src/intel_driver.c b/src/intel_driver.c
index 4391672..63b26a4 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -107,6 +107,7 @@ typedef enum {
    OPTION_DEBUG_FLUSH_BATCHES,
    OPTION_DEBUG_FLUSH_CACHES,
    OPTION_DEBUG_WAIT,
+   OPTION_HOTPLUG,
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
@@ -125,6 +126,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_DEBUG_FLUSH_BATCHES, "DebugFlushBatches", OPTV_BOOLEAN, {0}, FALSE},
    {OPTION_DEBUG_FLUSH_CACHES, "DebugFlushCaches", OPTV_BOOLEAN, {0}, FALSE},
    {OPTION_DEBUG_WAIT, "DebugWait", OPTV_BOOLEAN, {0}, FALSE},
+   {OPTION_HOTPLUG,	"HotPlug",	OPTV_BOOLEAN,	{0},	TRUE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -801,6 +803,110 @@ intel_flush_callback(CallbackListPtr *list,
 	}
 }
 
+#if HAVE_UDEV
+static void
+I830HandleUEvents(int fd, void *closure)
+{
+    ScrnInfoPtr scrn = closure;
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+    struct udev_device *dev;
+    const char *hotplug;
+    struct stat s;
+    dev_t udev_devnum;
+
+    dev = udev_monitor_receive_device(intel->uevent_monitor);
+    if (!dev)
+	return;
+
+    udev_devnum = udev_device_get_devnum(dev);
+    fstat(intel->drmSubFD, &s);
+    /*
+     * Check to make sure this event is directed at our
+     * device (by comparing dev_t values), then make
+     * sure it's a hotplug event (HOTPLUG=1)
+     */
+
+    hotplug = udev_device_get_property_value(dev, "HOTPLUG");
+
+    if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
+	hotplug && atoi(hotplug) == 1)
+	RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
+
+    udev_device_unref(dev);
+}
+
+static void
+I830UeventInit(ScrnInfoPtr scrn)
+{
+    intel_screen_private *intel = intel_get_screen_private(scrn);
+    struct udev *u;
+    struct udev_monitor *mon;
+    Bool hotplug;
+    MessageType from = X_CONFIG;
+
+    if (!xf86GetOptValBool(intel->Options, OPTION_HOTPLUG, &hotplug)) {
+	from = X_DEFAULT;
+	hotplug = TRUE;
+    }
+
+    xf86DrvMsg(scrn->scrnIndex, from, "hotplug detection: \"%s\"\n",
+	       hotplug ? "enabled" : "disabled");
+    if (!hotplug)
+	return;
+
+    u = udev_new();
+    if (!u)
+	return;
+
+    mon = udev_monitor_new_from_netlink(u, "udev");
+
+    if (!mon) {
+	udev_unref(u);
+	return;
+    }
+
+    if (udev_monitor_filter_add_match_subsystem_devtype(mon,
+							"drm",
+							"drm_minor") < 0 ||
+	udev_monitor_enable_receiving(mon) < 0)
+    {
+	udev_monitor_unref(mon);
+	udev_unref(u);
+	return;
+    }
+
+    intel->uevent_handler =
+	xf86AddGeneralHandler(udev_monitor_get_fd(mon),
+			      I830HandleUEvents,
+			      scrn);
+    if (!intel->uevent_handler) {
+	udev_monitor_unref(mon);
+	udev_unref(u);
+	return;
+    }
+
+    intel->uevent_monitor = mon;
+}
+
+static void
+I830UeventFini(ScrnInfoPtr scrn)
+{
+    intel_screen_private *intel = intel_get_screen_private(scrn);
+
+    if (intel->uevent_handler)
+    {
+	struct udev *u = udev_monitor_get_udev(intel->uevent_monitor);
+
+	xf86RemoveGeneralHandler(intel->uevent_handler);
+
+	udev_monitor_unref(intel->uevent_monitor);
+	udev_unref(u);
+	intel->uevent_handler = NULL;
+	intel->uevent_monitor = NULL;
+    }
+}
+#endif /* HAVE_UDEV */
+
 static Bool
 I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 {
@@ -1007,6 +1113,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
 
 	intel->suspended = FALSE;
 
+#if HAVE_UDEV
+	I830UeventInit(scrn);
+#endif
+
 	return uxa_resources_init(screen);
 }
 
@@ -1088,6 +1198,10 @@ static Bool I830CloseScreen(int scrnIndex, ScreenPtr screen)
 	ScrnInfoPtr scrn = xf86Screens[scrnIndex];
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 
+#if HAVE_UDEV
+	I830UeventFini(scrn);
+#endif
+
 	if (scrn->vtSema == TRUE) {
 		I830LeaveVT(scrnIndex, 0);
 	}
-- 
1.7.1

  reply	other threads:[~2010-10-04 17:43 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-03 22:13 [PATCH] intel: Listen for hotplug uevents Keith Packard
2010-10-03 23:08 ` [PATCH] intel: Listen for hotplug uevents (V2) Keith Packard
2010-10-03 23:15   ` Peter Stuge
2010-10-03 23:34     ` Keith Packard
2010-10-04  9:25   ` [Intel-gfx] " Chris Wilson
2010-10-04 10:51   ` Geir Ove Myhr
2010-10-04 17:43     ` Keith Packard [this message]
2010-10-04 20:57       ` [PATCH] intel: Listen for hotplug uevents (V3) Geir Ove Myhr

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1286214218-10551-1-git-send-email-keithp@keithp.com \
    --to=keithp@keithp.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.