summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-07-01 13:21:13 +1000
committerDave Airlie <airlied@redhat.com>2013-07-03 14:12:05 +1000
commit131b7a87506adb304be9c479803d6952dce599cd (patch)
tree7f392f2d8cce58bfef225a4bfd5e991b814aa535
parent9075ac50655b1035275a4b79d6cfdc0de38dcca0 (diff)
qxl: add uevent handler support
This allows the driver to process uevents from the kernel when the mode changes. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--configure.ac14
-rw-r--r--src/Makefile.am6
-rw-r--r--src/qxl_drmmode.c62
-rw-r--r--src/qxl_drmmode.h10
-rw-r--r--src/qxl_kms.c3
5 files changed, 94 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index d481cc1..8b2d450 100644
--- a/configure.ac
+++ b/configure.ac
@@ -135,6 +135,20 @@ fi
AM_CONDITIONAL(BUILD_XSPICE, test "x$enable_xspice" = "xyes")
AM_CONDITIONAL(BUILD_QXL, test "x$enable_qxl" = "xyes")
+AC_ARG_ENABLE([udev],
+ AS_HELP_STRING([--disable-udev], [Disable libudev support [default=auto]]),
+ [enable_udev="$enableval"],
+ [enable_udev=auto])
+if test "x$enable_udev" != "xno"; then
+ PKG_CHECK_MODULES(LIBUDEV, [libudev], [LIBUDEV=yes], [LIBUDEV=no])
+ if test "x$LIBUDEV" = xyes; then
+ AC_DEFINE(HAVE_LIBUDEV, 1,[libudev support])
+ elif test "x$enable_udev" != "xauto"; then
+ AC_MSG_ERROR([Building with udev requested but libudev not found])
+ fi
+fi
+AM_CONDITIONAL(LIBUDEV, test x$LIBUDEV = xyes)
+
PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= 0.12.0])
# AC_CHECK_FILE is not supported when cross compiling
diff --git a/src/Makefile.am b/src/Makefile.am
index 4349b4e..d6a5445 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,7 +27,7 @@
SUBDIRS=uxa
-AM_CFLAGS = $(SPICE_PROTOCOL_CFLAGS) $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(DRM_CFLAGS)
+AM_CFLAGS = $(SPICE_PROTOCOL_CFLAGS) $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) $(DRM_CFLAGS) @LIBUDEV_CFLAGS@
if BUILD_QXL
qxl_drv_la_LTLIBRARIES = qxl_drv.la
@@ -35,6 +35,10 @@ qxl_drv_la_LDFLAGS = -module -avoid-version
qxl_drv_ladir = @moduledir@/drivers
qxl_drv_la_LIBADD = uxa/libuxa.la
+if LIBUDEV
+qxl_drv_la_LIBADD += $(LIBUDEV_LIBS)
+endif
+
qxl_drv_la_SOURCES = \
qxl.h \
diff --git a/src/qxl_drmmode.c b/src/qxl_drmmode.c
index c1f5c15..03b4124 100644
--- a/src/qxl_drmmode.c
+++ b/src/qxl_drmmode.c
@@ -875,4 +875,66 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
return TRUE;
}
+#ifdef HAVE_LIBUDEV
+static void
+drmmode_handle_uevents(int fd, void *closure)
+{
+ drmmode_ptr drmmode = closure;
+ ScrnInfoPtr scrn = drmmode->scrn;
+ struct udev_device *dev;
+ dev = udev_monitor_receive_device(drmmode->uevent_monitor);
+ if (!dev)
+ return;
+
+ RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
+ udev_device_unref(dev);
+}
+#endif
+
+void qxl_drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+#ifdef HAVE_LIBUDEV
+ struct udev *u;
+ struct udev_monitor *mon;
+
+ 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;
+ }
+
+ drmmode->uevent_handler =
+ xf86AddGeneralHandler(udev_monitor_get_fd(mon),
+ drmmode_handle_uevents,
+ drmmode);
+
+ drmmode->uevent_monitor = mon;
+#endif
+}
+
+void qxl_drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+#ifdef HAVE_LIBUDEV
+ if (drmmode->uevent_handler) {
+ struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
+ xf86RemoveGeneralHandler(drmmode->uevent_handler);
+
+ udev_monitor_unref(drmmode->uevent_monitor);
+ udev_unref(u);
+ }
+#endif
+}
+
#endif
diff --git a/src/qxl_drmmode.h b/src/qxl_drmmode.h
index df076c7..04752ec 100644
--- a/src/qxl_drmmode.h
+++ b/src/qxl_drmmode.h
@@ -34,6 +34,9 @@
#include "xf86str.h"
#include "randrstr.h"
#include "xf86Crtc.h"
+#ifdef HAVE_LIBUDEV
+#include "libudev.h"
+#endif
typedef struct {
int fd;
@@ -42,6 +45,10 @@ typedef struct {
drmModeFBPtr mode_fb;
int cpp;
ScrnInfoPtr scrn;
+#ifdef HAVE_LIBUDEV
+ struct udev_monitor *uevent_monitor;
+ InputHandlerProc uevent_handler;
+#endif
} drmmode_rec, *drmmode_ptr;
typedef struct {
@@ -78,6 +85,9 @@ typedef struct {
} drmmode_output_private_rec, *drmmode_output_private_ptr;
extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
+
+extern void qxl_drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
+extern void qxl_drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
#endif
#endif
diff --git a/src/qxl_kms.c b/src/qxl_kms.c
index b673294..b091a12 100644
--- a/src/qxl_kms.c
+++ b/src/qxl_kms.c
@@ -95,6 +95,7 @@ qxl_close_screen_kms (CLOSE_SCREEN_ARGS_DECL)
qxl_screen_t *qxl = pScrn->driverPrivate;
Bool result;
+ qxl_drmmode_uevent_fini(pScrn, &qxl->drmmode);
pScreen->CloseScreen = qxl->close_screen;
result = pScreen->CloseScreen (CLOSE_SCREEN_ARGS);
@@ -198,6 +199,8 @@ qxl_create_screen_resources_kms(ScreenPtr pScreen)
set_surface (pPixmap, qxl->primary);
+ qxl_drmmode_uevent_init(pScrn, &qxl->drmmode);
+
if (!uxa_resources_init (pScreen))
return FALSE;