如何为英特尔图形上的“监视器插入”创建回调?

Posted

技术标签:

【中文标题】如何为英特尔图形上的“监视器插入”创建回调?【英文标题】:How to create a callback for "monitor plugged" on an intel graphics? 【发布时间】:2011-07-25 02:22:11 【问题描述】:

我有一个带有英特尔图形的eeepc。我想将脚本挂钩到通过 VGA 插入的监视器的事件。该怎么做?

【问题讨论】:

对于寻找 Windows 解决方案的人:***.com/questions/1440285/…***.com/questions/3267722/…***.com/questions/5981520/… 【参考方案1】:

作为一个粗略的解决方案,您可以在 sysfs 上进行轮询。在我的笔记本电脑上,我有:

$ cat /sys/class/drm/card0-LVDS-1/status
connected

$ cat /sys/class/drm/card0-VGA-1/status
disconnected

我猜这需要内核 DRM 和可能的 KMS。

要查看是否可以自动触发某些内容,您可以运行 udevadm monitor --property,并在您(断开)连接监视器时观察是否报告了事件。

使用我的 radeon,我在第一次连接 VGA 显示器时收到一个事件,但在随后断开连接和重新连接时没有任何事件。该事件应类似于(以您的为例):

KERNEL[1303765357.560848] change /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV_LOG=0
ACTION=change
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
SUBSYSTEM=drm
HOTPLUG=1
DEVNAME=dri/card0
DEVTYPE=drm_minor
SEQNUM=2943
MAJOR=226
MINOR=0

很遗憾,没有太多可匹配的对象,但只要图片中只有一张不太重要的显卡即可。查找 udev 从系统上获取规则的位置(可能是 /etc/udev/rules.d/),并创建一个 99-monitor-hotplug.rules 文件:

ACTION=="change", SUBSYSTEM=="drm", ENVHOTPLUG=="1", RUN+="/root/hotplug.sh"

udev 将在连接显示器时运行hotplug.sh。作为测试,我将以下内容放在/root/hotplug.sh 中(不要忘记使此脚本可执行):

#!/bin/sh

for output in DVI-I-1 LVDS-1 VGA-1; do
        echo $output >> /root/hotplug.log
        cat /sys/class/drm/card0-$output/status >> /root/hotplug.log
done

这样,在我连接了外部显示器后,我在hotplug.log 中获得了一个条目。即使过滤ACTION=="change",我仍然在启动时收到了一些事件,因此您可能希望在脚本中以某种方式考虑到这一点。

【讨论】:

好的开始,但我不喜欢投票。 @Tass 如果你收到事件,ping 我,我可能会想出一个 udev 规则来运行脚本 感谢安迪!我创建了一个受这篇文章启发的脚本。您可以在github.com/codingtony/udev-monitor-hotplug 获取它。它使用 xrandr 在插入/拔出显示器时打开和关闭显示器。我希望它会有所帮助。 “我第一次连接 VGA 显示器时收到一个事件,但在随后的断开连接和重新连接时没有事件”对我来说也是如此,但它似乎只在第一次执行我的脚本。每次断开并重新连接显示器时,是否都会调用 hotplug.sh 自定义脚本? 我正在尝试进行设置以解决系统在未连接监视器的情况下启动的可能性。对我来说,udev 显示连接和断开事件,但前提是在系统启动时连接了监视器。如果 udev 启动时没有任何连接,知道如何让它引起注意吗?诉诸投票将需要一个更混乱的脚本......【参考方案2】:

This other answer 走在正确的道路上:您想收听来自udev 的 DRM 事件。

I've implemented a Python script 在 USB 设备或外部显示器(未)插入时运行一些代码。我在下面包含了该脚本的最小版本(未经测试):

#!/usr/bin/env python3
import pyudev

def udev_event_received(device):
    ...  # Your code here!

context = pyudev.Context()
monitor_drm = pyudev.Monitor.from_netlink(context)
monitor_drm.filter_by(subsystem='drm')
observer_drm = pyudev.MonitorObserver(monitor_drm, callback=udev_event_received, daemon=False)

observer_drm.start()

# This will prevent the program from finishing:
observer_drm.join()

另见:

How can I run code whenever a USB device is (un)plugged, without requiring root permissions? How can I listen for 'usb device inserted' events in Linux, in Python? pyudev documentation - Asynchronous monitoring

【讨论】:

【参考方案3】:

您有三个选择:

    轮询 sysfs 中的特定条目。 使用 inotify 检测 sysfs 中的更改。 使用带有 NETLINK_KOBJECT_UEVENT 的 netlink 套接字,并为您想要的设备侦听 change uevent。

在提到的任何一种方式中,您仍然需要以一种或另一种方式进行投票,所以我只选择第一种。

【讨论】:

inotifynetlink 套接字都可以让您使用select() 和朋友。你真的考虑过“投票”吗? 使用 select() 或 poll() 进行“轮询更新”的美妙之处在于,您可以进入睡眠状态,直到超时或内核唤醒您,告诉您其中一件事'正在“轮询”已经发生(有点误导。它与大多数人所说的“轮询”是和不同的。它甚至是 GPIO 中断的接口......;)) - 所以它不那么浪费CPU 资源等。最好使用 select() 或 poll() 接口“轮询”。 inotify 不适用于 sysfs 更改,因为它本身不是真正的文件系统。如果您不相信我,请尝试一下。 sudo inotifywait -e modify -m --format '%:e %f' /sys/class/drm/something 所以你的第二个选项无效。 “不,inotify 在 sysfs 上不起作用,或者如果它起作用,那是“意外”,您为此获得的任何数据都可能完全错误。” Greg KH on 2014-03-29 @DenilsonSáMaia 您的链接今天已损坏,或者我无法访问它...【参考方案4】:

感谢塞巴斯蒂安瓦格纳!

有了这些信息,我已经能够在电视关闭的情况下成功启动我的 Kodi 媒体中心。 事实上,当电视关闭时,英特尔驱动程序不想设置模式,当我后来打开电视时,我得到了一个空白屏幕。 Kodi 日志显示以下行:

WARNING: CXRandR::Query - output HDMI1 has no current mode, assuming disconnected

所以我在 /etc/udev/rules.d/99-monitor-hotplug.rules 中创建了以下行:

ACTION=="change", SUBSYSTEM=="drm", ENVHOTPLUG=="1", RUN+="/usr/sbin/hotplugtv.sh"

/usr/sbin/hotplugtv.sh 的内容(我的 X 服务器以 root 身份运行):

#!/bin/bash

export DISPLAY=:0
export XAUTHORITY=/root/.Xauthority

/bin/date 2>&1 >> /var/log/hotplugtv.log;
if [[ $(cat /sys/class/drm/card0-HDMI-A-1/status | grep -Ec "^connected") -eq 1 ]]; then
        echo "TV connected!" >> /var/log/hotplugtv.log;
        /bin/sleep 2s;
        /usr/bin/xrandr --verbose --output HDMI1 --auto 2>&1 >> /var/log/hotplugtv.log;
else
        echo "TV disconnected!" >> /var/log/hotplugtv.log;
fi

当您对脚本进行任何更改时,不要忘记重新加载 udev 规则(这让我发疯了!):

udevadm control --reload-rules

请小心禁用 Kodi 中的任何屏幕保护程序,因为当您最终打开电视电源时,它们会永远保持激活状态。 另一方面,节能/DPMS 似乎工作正常。

【讨论】:

【参考方案5】:

假设您正在运行 X,脚本可以解析 xrandr 的输出以查看连接了哪些监视器。这应该适用于任何显卡。您可能会使用该工具来利用脚本中的更改。

它不能解决自动运行脚本的通知问题。虽然我没有一个很好的通用解决方案,但一个常见的情况是检测何时存在外接显示器,因为笔记本电脑连接到扩展坞。在这种情况下,您可以让脚本触发连接到扩展坞时触发的其他内容,例如添加或移除 USB 键盘或以太网。

【讨论】:

以上是关于如何为英特尔图形上的“监视器插入”创建回调?的主要内容,如果未能解决你的问题,请参考以下文章

如何为已弃用的英特尔 IPP API 找到替代 API?

傲腾持久内存如何为数据赋能,加速应用落地?

英特尔图形处理器第8代架构

如何为 theano 启用我的 MacBook Pro GPU 优化?

如何为 HTML 应用程序发出通知

英特尔的Linux Xe内核图形驱动程序