因为Linux 版 Steam 中一个长期未修复的 bug,我想阻止特定程序(Steam)对特定设备(Sony DualShock 4 控制器)进行任何访问。
我尝试围绕自定义组设置一些 udev 规则,然后以不属于该组的自定义用户身份运行 Steam,但当su
无法执行 GUI 操作并且pkexec
没有可行(或安全)的方法来保存任何环境变量时,这种方法就失效了,导致了许多问题,包括由于该自定义用户的 /home 目录不存在而立即失败。现在我没主意了。
答案1
我最终发现我可以使用沙盒来实现这一点。特别是 firejail。我想出了一个命令,它只阻止 hidraw 设备(包括所有蓝牙控制器,也是 Steam 检测蓝牙 DS4 的方式)。我通过蓝牙使用的唯一控制器是我的 DS4,所以这对我来说是一个足够好的解决方案:
firejail --noprofile --blacklist="/dev/hidraw*" /usr/bin/steam
它完全有效!Steam 无法看到 DS4,也不会崩溃。但是,某些游戏(如《中土世界:暗影魔多》)似乎不喜欢这种方法。大多数游戏都可以正常工作,但 SoM 可以看到我的 DS4(甚至知道它是 DS4,因为它会显示 PlayStation 按钮提示,尽管我使用 欺骗 Steam 认为它是 360 控制器sc-controller
),但拒绝接受来自它的任何输入。我还有一些工作要做。
编辑:成功!经过更多测试,我发现 SoM 的问题在于游戏不是最好的 Linux 移植,并且根本不兼容任何与 DS4 相关的非 DS4 本身的东西。也就是说,尝试让它使用任何用户空间驱动程序(xboxdrv、ds4drv、sc-controller 等)模拟其他东西,无法很好地与这款游戏配合使用。因此,我去编写了一个用于启动 Steam 的完整脚本,它会阻止我的整个蓝牙适配器而不是 hidraw 设备。由于这个 Steam 错误是由 PulseAudio 配置引起的,我冒险一试,认为如果我只是阻止 Steam 对控制器整个 USB 设备的访问,但让 Steam 发现它的所有部分,从 hidraw 到 /dev/input/jsX,它就会起作用。而且它确实起作用了。以下是我的脚本的相关部分:
#!/bin/bash
BLUETOOTH="$(lsusb | grep "8087:07dc")" # those are my BT adapter's device and vendor IDs; yours may be different
BUS="$(echo "$BLUETOOTH" | sed 's/.*Bus \([0-9]\+\).*/\1/')"
DEV="$(echo "$BLUETOOTH" | sed 's/.*Device \([0-9]\+\).*/\1/')"
BLACKLIST="/dev/bus/usb/$BUS/$DEV"
firejail --noprofile --blacklist="$BLACKLIST" /usr/bin/steam
(我冒了这个险,而不是阻止控制器发出任何与声音相关的东西,因为虽然控制器里确实有声卡,虽然这可能就是 Steam 出现此问题的原因,但我找不到通过 /sys 或 /dev 访问与所述声卡相关的任何东西的方法。)
答案2
好吧,这个答案与问题不太相符,因为它要求阻止对特定程序的访问。但如果什么都不起作用,有一个非常简单的解决方案,即禁用对任何导致程序或游戏出现问题的设备的读取访问。使用该程序后,重新打开设备访问。
此 POSIX 命令禁用对选定设备文件的读取访问
sudo chmod a-r /dev/input/js* # list device files with whitespace separation
当读取被禁用时,任何程序都将无法从设备获取输入。
此命令再次启用它
sudo chmod a+r /dev/input/js*
一些应用程序管理器有启动前和退出后脚本,可以在其中输入这些信息。但这个解决方案并不理想。在此期间,其他程序都无法读取该设备。
但firejail
绝对是更好的答案并且应该可以在任何主流操作系统上运行(我猜除了原生 Windows)。