intel: Listen for hotplug uevents (V3)
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>
This commit is contained in:
parent
a1c54f6964
commit
b066ddda31
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:=#
|
||||
|
|
|
|||
12
src/intel.h
12
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.
|
||||
|
|
@ -441,6 +449,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 {
|
||||
|
|
|
|||
|
|
@ -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* */
|
||||
|
|
@ -804,6 +806,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)
|
||||
{
|
||||
|
|
@ -1010,6 +1116,10 @@ I830ScreenInit(int scrnIndex, ScreenPtr screen, int argc, char **argv)
|
|||
|
||||
intel->suspended = FALSE;
|
||||
|
||||
#if HAVE_UDEV
|
||||
I830UeventInit(scrn);
|
||||
#endif
|
||||
|
||||
return uxa_resources_init(screen);
|
||||
}
|
||||
|
||||
|
|
@ -1091,6 +1201,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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue