You are not logged in.

#1 2013-09-24 17:49:35

Kotrfa
Member
Registered: 2012-10-25
Posts: 213

[SOLVED]udev rule doesn't work (hotplug monitor)

>>SOLUTION HERE<<

Hello,

I'm trying to execute script which sets resolution, when external monitor is connected:

Here is my udev rule:

cat /etc/udev/rules.d/95-monitor-hotplug.rules

#Rule for executing commands when an external screen is plugged in.
ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/usr/local/bin/hotplug_monitor.sh"

and here is /usr/local/bin/hotplug_monitor.sh script, which is working, when is executed manualy:

export DISPLAY=:0.0
 
 function connect(){
 xrandr --output HDMI1 --right-of LVDS1 --preferred --primary --output LVDS1 --preferred 
 }
  
  function disconnect(){
  xrandr --output HDMI1 --off
  }
xrandr | grep "HDMI1 connected" &> /dev/null && connect || disconnect

this is output from udevadm monitor:


udevadm monitor

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[536.731457] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
UDEV  [536.732637] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)

Does anyone knows, where the problem is?

Thanks

Last edited by Kotrfa (2013-09-26 18:25:29)

Offline

#2 2013-09-24 18:27:33

ilsensine
Member
Registered: 2013-03-26
Posts: 32

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

First of all, xrandr needs to be run as the currently logged user profile. You can see a hidden file called .Xauthority in your home directory; without this file, even root can't access the display or execute xrandr.
You can log and read the error message if you change the last line of your script into something like
xrandr | grep "HDMI1 connected" > /dev/null 2>/var/log/hp_monitor.log && connect || disconnect

Last edited by ilsensine (2013-09-24 18:28:11)

Offline

#3 2013-09-24 18:41:51

Kotrfa
Member
Registered: 2012-10-25
Posts: 213

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

I changed it to this:

export DISPLAY=:0.0
 
function connect(){
    xrandr --output HDMI1 --right-of LVDS1 --preferred --primary --output LVDS1 --preferred 
}
  
function disconnect(){
      xrandr --output HDMI1 --off
}
   
xrandr | grep "HDMI1 connected" > /dev/null 2> /home/dan/hp_monitor.log && connect || disconnect

created hp_monitor.log at that destination and add 777 permisions. But I haven't get anything there. log in /var/log doesnt work either.

Offline

#4 2013-09-24 20:40:11

brebs
Member
Registered: 2007-04-03
Posts: 3,742

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

See use of XAUTHORITY.

Is HOTPLUG=="1" something new? Have you checked that your script even gets run?

Offline

#5 2013-09-25 14:24:20

Kotrfa
Member
Registered: 2012-10-25
Posts: 213

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

I tried to change the script to something like: "sleep 10" and when I plug in/out, I can't see that process using ps aux. So I guess it is not even executed, how brebs suggests. Do you have any idea what can be wrong with the rule? I tried remove HOTPLUG and it doesn't change anything.

Thanks

Offline

#6 2013-09-25 14:43:06

brebs
Member
Registered: 2007-04-03
Posts: 3,742

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

Filtering on "change", rather than "add|remove", looks pretty strange to me. I suggest you google for udev debugging, and use this for starters:

udevadm monitor

To check if your script is running, simply add e.g. this to its start:

echo `date` >> /root/monitor.log

Offline

#7 2013-09-25 18:55:04

Kotrfa
Member
Registered: 2012-10-25
Posts: 213

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

EDIT: Solution is on the end of this post

I tried some variants but without success. Can't find out where the problem is:


Here is output of unplug/plug:

udevadm monitor --environment --udev 
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV  [1370.249130] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
ACTION=change
DEVNAME=/dev/dri/card0
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_00_02_0
ID_PATH=pci-0000:00:02.0
ID_PATH_TAG=pci-0000_00_02_0
MAJOR=226
MINOR=0
SEQNUM=1884
SUBSYSTEM=drm
TAGS=:seat:uaccess:
USEC_INITIALIZED=715

UDEV  [1371.357396] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
ACTION=change
DEVNAME=/dev/dri/card0
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_00_02_0
ID_PATH=pci-0000:00:02.0
ID_PATH_TAG=pci-0000_00_02_0
MAJOR=226
MINOR=0
SEQNUM=1885
SUBSYSTEM=drm
TAGS=:seat:uaccess:
USEC_INITIALIZED=715
udevadm info -a -p /devices/pci0000:00/0000:00:02.0/drm/card0

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:02.0/drm/card0':
    KERNEL=="card0"
    SUBSYSTEM=="drm"
    DRIVER==""
    ATTR{gt_RP1_freq_mhz}=="350"
    ATTR{gt_min_freq_mhz}=="350"
    ATTR{gt_RPn_freq_mhz}=="350"
    ATTR{gt_RP0_freq_mhz}=="1150"
    ATTR{gt_cur_freq_mhz}=="800"
    ATTR{gt_max_freq_mhz}=="1150"

  looking at parent device '/devices/pci0000:00/0000:00:02.0':
    KERNELS=="0000:00:02.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="i915"
    ATTRS{irq}=="48"
    ATTRS{subsystem_vendor}=="0x144d"
    ATTRS{broken_parity_status}=="0"
    ATTRS{class}=="0x030000"
    ATTRS{consistent_dma_mask_bits}=="40"
    ATTRS{dma_mask_bits}=="40"
    ATTRS{local_cpus}=="00000000,0000000f"
    ATTRS{device}=="0x0116"
    ATTRS{msi_bus}==""
    ATTRS{local_cpulist}=="0-3"
    ATTRS{vendor}=="0x8086"
    ATTRS{subsystem_device}=="0xc0c7"
    ATTRS{boot_vga}=="1"
    ATTRS{numa_node}=="-1"
    ATTRS{d3cold_allowed}=="1"

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

here is how does the rule looks like:

ACTION=="change", SUBSYSTEM="drm",KERNEL=="card0", RUN+="/usr/local/bin/hotplug_monitor.sh; echo 'date' >> /root/monitor.log"

SOLUTION:
There are some details:
You don't have to name "change" and you can't add more than one command to "RUN" parametr (so it can't be something like: "command >> foo.log" etc.).



udev rule:

KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/dan/.Xauthority", RUN+="/usr/local/bin/hotplug_monitor.sh"

My script:

#! /usr/bin/bash

export DISPLAY=:0
export XAUTHORITY=/home/dan/.Xauthority

function connect(){
    xrandr --output HDMI1 --right-of LVDS1 --preferred --primary --output LVDS1 --preferred 
}
  
function disconnect(){
      xrandr --output HDMI1 --off
}
   
xrandr | grep "HDMI1 connected" &> /dev/null && connect || disconnect

Now it works

Last edited by Kotrfa (2013-09-26 18:24:40)

Offline

#8 2015-12-10 10:10:08

lah
Member
Registered: 2014-08-26
Posts: 28

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

Hi,

I got this rule working for some times but now it doesn't work all times. After some investigations udev rule can be triggered whereas monitor has not yet been added to x renderers, so it is disconnected in xrandr.
You can think about adding a sleep in rule to wait monitor :

while ! xrandr  | grep 'HDMI1 connected' ; do sleep 1; done;

It works, but you will get your dual monitor ok after > 5s! If you poll manually xrandr HDMI is connected after some 100ms. It's not a good idea to do long processing in an udev rule! Sleeping in this rule delay monitor adding in X. You can refer this article : http://jasonwryan.com/blog/2014/01/20/udev/
So to solve this problem : use systemd (a service or a device), and use a condition on monitor status on sysfs instead of checking xrandr

if [ $(cat /sys/class/drm/card0-HDMI-A-1/status) == "connected" ] ; then

Udev rule :

ACTION=="change", KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/bin/systemctl start hot_plug.service"

Systemd unit in /etc/systemd/system/hot_plug.service

[Unit]
Description=Monitor hotplug

[Service]
Type=simple
RemainAfterExit=no
User=remi
ExecStart=/usr/local/bin/hotplug_monitor.sh

[Install]
WantedBy=multi-user.target
#!/bin/bash

######################################
## /usr/local/bin/hotplug_monitor.sh
######################################
X_USER=remi
export DISPLAY=:0
export XAUTHORITY=/home/$X_USER/.Xauthority
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

function connect()
{   
    #dual monitor - HDMI1 at right - xfce panel on left (LVDS1)
    xrandr --output HDMI1 --right-of LVDS1 --preferred  --output HDMI1 --primary >> /tmp/screen

    #Set xfce panel on primary monitor
    xfconf-query -v -c xfce4-panel -p /panels/panel-0/output-name -s HDMI1 
}

function disconnect(){
     xrandr --output HDMI1 --off
     #Set xfce panel on LVDS1
     xfconf-query -c xfce4-panel -p /panels/panel-0/output-name -s LVDS1
}

if [ $(cat /sys/class/drm/card0-HDMI-A-1/status) == "connected" ] ; then
  connect
elif [ $(cat /sys/class/drm/card0-HDMI-A-1/status) == "disconnected" ] ; then
  disconnect
else 
  exit
fi

You will see I'm modifying an xfce property, indeed xfce panel always on left with dual monitor ( https://bugzilla.xfce.org/show_bug.cgi?id=9338 ), in order to get it on right I have to call

xfconf-query -v -c xfce4-panel -p /panels/panel-0/output-name -s HDMI1 

lah

Offline

#9 2015-12-12 23:48:03

WorMzy
Administrator
From: Scotland
Registered: 2010-06-16
Posts: 12,455
Website

Re: [SOLVED]udev rule doesn't work (hotplug monitor)

Thank you for sharing, but I think it's time to close this thread.

https://wiki.archlinux.org/index.php/Fo … bumping.22

Closing.


Sakura:-
Mobo: MSI MAG X570S TORPEDO MAX // Processor: AMD Ryzen 9 5950X @4.9GHz // GFX: AMD Radeon RX 5700 XT // RAM: 32GB (4x 8GB) Corsair DDR4 (@ 3000MHz) // Storage: 1x 3TB HDD, 6x 1TB SSD, 2x 120GB SSD, 1x 275GB M2 SSD

Making lemonade from lemons since 2015.

Offline

Board footer

Powered by FluxBB