it-swarm.it

Come posso rilevare quando un monitor è collegato o scollegato?

Esiste un evento che viene attivato quando collego o esco da un monitor esterno nel DisplayPort del mio laptop? ACPID e UDEV non reagiscono affatto.

Sto usando la grafica integrata su un chip Intel. Qui è una discussione simile che ha già un paio d'anni.

Non voglio usare il polling ma devo avere una configurazione che imposta automaticamente le impostazioni del display a seconda che il display sia collegato.

54
janoliver

NOTA: Questo è stato testato su un laptop con una scheda grafica guidata i915.


Sfondo

NOTA: Quando viene collegata una nuova schermata, nessun evento viene inviato all'host, questo è rimasto vero anche dopo la mia ultima modifica. Quindi l'unico modo è usare il polling. Cercando di renderli il più efficienti possibile ...

EDIT # 3

Finalmente c'è una soluzione migliore (tramite ACPI):

Non c'è ancora nessun evento, ma ACPI sembra più efficiente di xrandr per indagare. (Nota: questo richiede i moduli del kernel ACPI caricati, ma non richiede i privilegi di root).

La mia soluzione finale (usando bash):

isVgaConnected() {
    local crtState
    read -a < /proc/acpi/video/VID/CRT0/state crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

Ora un test:

$ if isVgaConnected; then echo yes; else echo no; fi 
yes

È collegato, quindi ora lo scollego:

$ if isVgaConnected; then echo yes; else echo no; fi 
no

NOTA: ${1:+*-1+1} allow a boolean argomento: se qualcosa è presente, la risposta verrebbe invertita: ( crtState >> 4 ) * -1 + 1.

e la sceneggiatura finale:

#!/bin/bash

export crtProcEntry=/proc/acpi/video/VID/CRT0/state

isVgaConnected() {
    local crtState
    read -a < $crtProcEntry crtState
    test $(( ( ${crtState[1]} >>4 ) ${1:+*-1+1} )) -ne 0
}

delay=.1
unset switch
isVgaConnected || switch=not
while :;do
    while isVgaConnected $switch;do
        sleep $delay
      done
    if [ "$switch" ];then
        unset switch
        echo VGA IS connected
        # doing something while VGA is connected
      else
        switch=not
        echo VGA is NOT connected.
        # doing something else, maybe.
      fi
  done

AVVERTENZE: più leggero di xrandr, ma non poco importante con un ritardo inferiore a 0,02 secondi, lo script Bash andrà in cima al processo dei mangiatori di risorse (top)!

Mentre questo costa ~ 0,001 secondi:

$ time read -a </proc/stat crtStat

Ciò richiede ~ 0,030 sec:

$ read -a < /proc/acpi/video/VID/CRT0/state crtState

Questo è grande! Quindi, a seconda di ciò di cui hai bisogno, delay potrebbe essere ragionevolmente impostato tra 0.5 e 2.

EDIT # 2

Ho finalmente trovato qualcosa, usando questo:

Dichiarazione di non responsabilità importante: Giocare con /proc e /sys voci potrebbero danneggiare il tuo sistema !!! Quindi non provare quanto segue sui sistemi di produzione.

mapfile watchFileList < <(
    find /sys /proc -type f 2>/dev/null |
    grep -i acpi\\\|i91 
)

Prompt=("/" "|" '\' '-');

l=0
while :; do
  mapfile watchStat < <(
    grep -H . ${watchFileList[@]} 2>/dev/null
  )

  for ((i=0;i<=${#watchStat[@]};i++)); do
    [ "${watchStat[i]}" == "${oldStat[i]}" ] || echo ${watchStat[i]}
  done

  oldStat=("${watchStat[@]}")
  sleep .5
  printf "\r%s\r" ${Prompt[l++]}
  [ $l -eq 4 ]&&l=0
done

... dopo alcune pulizie di ingressi indesiderati:

for ((i=0;i<=${#watchFileList[@]};i++)); do
  [[ "${watchFileList[$i]}" =~ /sys/firmware/acpi/interrupts/sci ]] &&
      unset watchFileList[$i] && echo $i
done

Sono stato in grado di leggere questo:

/proc/acpi/video/VID/CRT0/state:state: 0x1d
/proc/acpi/video/VID/CRT0/state:state: 0x0d
/proc/acpi/video/VID/CRT0/state:state: 0x1d

Quando collego, scollego e ricollego il cavo del monitor.

Quando viene richiesta la configurazione (in esecuzione system/preferences/monitor o xrandr), le schede grafiche eseguono un tipo di scan, quindi eseguendo xrandr -q ti dà le informazioni, ma devi sondare lo stato.

Ho scansionato tutti i log (kernel, demone, X e così via) cercando tra /proc & /sys e chiaramente non sembra esistere nulla che soddisfi la tua richiesta.

Ho provato anche questo:

export spc50="$(printf "%50s" "")"
watch -n1  '
    find /proc/acpi/video -type f |
        xargs grep -H . |
        sed "s/^\([^:]*):/\1'$spc50'}:/;
             s/^\(.\{50\}\) *:/\1 /"'

Dopo tutto ciò, se esegui System/Preferences/Monitor mentre non è stato appena collegato o scollegato alcun nuovo schermo, lo strumento apparirà semplicemente (normalmente). Ma se hai già collegato o scollegato una schermata, a volte eseguirai questo strumento e vedrai il tuo desktop creare un tipo di ripristina o aggiorna (uguale se si esegue xrandr).

Ciò sembra confermare che questo strumento richiede xrandr (o funziona allo stesso modo) eseguendo periodicamente il polling dello stato, a partire dal momento in cui viene eseguito.

Potresti provare te stesso:

$ for ((i=10;i--;)); do xrandr -q | grep ' connected' | wc -l; sleep 1; done
1
1
1
2
2
2
1
1
1
1

Questo mostrerà quante schermate (display) sono collegate, per 10 secondi.

Mentre questo funziona, collega e/o scollega lo schermo/monitor e guarda cosa succede. Quindi potresti creare una piccola funzione di Bash test:

isVgaConnected() {
    local xRandr=$(xrandr -q)
    [ "$xRandr" == "${xRandr#*VGA1 con}" ] || return 0
    return 1
}

che sarebbe utilizzabile come in:

$ if isVgaConnected; then echo yes; fi

Ma fai attenzione, xrandr impiega circa da 0,140 sec a 0,200 sec mentre non si verifica alcun cambiamento su plug e fino a 0,700 secondi ogni volta che qualcosa è stato collegato o scollegato poco prima ( NOTA: Sembra non essere una risorsa mangiatore).

EDIT # 1

Per essere sicuro di non insegnare qualcosa di sbagliato, ho cercato nel Web e nei documenti, ma non ho trovato nulla su DBus e schermate.

Finalmente, ho corso in due diverse finestre dbus-monitor --system (Ho giocato anche con le opzioni) e la piccola sceneggiatura che ho scritto:

$ for ((i=1000;i--;)); do isVgaConnected && echo yes || echo no; sleep .5; done

... e ancora una volta collegato, che scollegato il monitor, molte volte. Quindi ora potrei dire:

  • In questa configurazione, utilizzando il driver i915 , non c'è altro modo che eseguire xrandr -q per sapere se un monitor è collegato o meno.

Ma fai attenzione, perché non sembrano esserci altri modi. Ad esempio, xrandr sembra condividere queste informazioni, quindi il mio desktop GNOME passerebbe automaticamente a xinerama ... quando ho eseguito xrandr.

Alcuni documenti

14
F. Hauri

Le seguenti righe sono apparse in udevadm monitor

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

quando si collega un monitor al connettore VGA. Quindi potrebbe esserci un modo per capirlo.

4
sebastianwagner

Ho continuato a usare srandrd . Monitora gli eventi X e attiva lo script quando uno schermo viene collegato o disconnesso.

3
scorpp

Per coloro che, per qualsiasi motivo, non vogliono seguire il percorso hotplug, è comunque possibile non eseguire il polling all'interno di uno script usando inotifywait:

 #!/Bin/bash 
 
 = SCREEN_LEFT DP2 
 = SCREEN_RIGHT eDP1 
 START_DELAY = 5 
 
 renice +19 $$>/dev/null 
 
 sleep $ START_DELAY 
 
 OLD_DUAL = "dummy" 
 
 mentre [ 1]; do 
 DUAL = $ (cat /sys/class/drm/card0-DP-2/status)[.____.
 se ["$ OLD_DUAL"! = "$ DUAL"]; quindi 
 se ["$ DUAL" == "connesso"]; quindi 
 echo 'Impostazione doppio monitor' 
 xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal --below $ SCREEN_LEFT 
 Else 
 Echo 'Impostazione monitor singolo' 
 Xrandr --auto 
 Fi 
 
 OLD_DUAL = "$ DUAL" 
 fi 
 
 inotifywait -q -e chiudi/sys/class/drm/card0-DP-2/status>/dev/null 
 fatto 
 

È meglio invocato dal tuo .xsessionrc, senza dimenticare il finale &. Il polling con xrandr ha causato seri problemi di usabilità sul mio laptop nuovo di zecca (il mouse si arrestava periodicamente).

3
Balzola

Ovviamente ci dovrebbe essere qualcosa! :) Il filesystem/sys dice a userspace quale hardware è disponibile, quindi gli strumenti di userspace (come udev o mdev) possono popolare dinamicamente una directory "/ dev" con nodi di dispositivo che rappresentano l'hardware attualmente disponibile. Linux fornisce due interfacce hotplug:/sbin/hotplug e netlink.

C'è una piccola demo C nel seguente file. http://www.kernel.org/doc/pending/hotplug.txt

0
roncsak

Per lo più software di sistema/applicazione su Linux oggi hanno usato alcune tecniche ipc per comunicare tra loro. D-Bus è ora utilizzato principalmente con le applicazioni GNOME e potrebbe essere d'aiuto.

Linux Journal:

D-BUS può facilitare l'invio di eventi o segnali attraverso il sistema, consentendo a diversi componenti del sistema di comunicare e infine integrarsi meglio. Ad esempio, un dæmon Bluetooth può inviare un segnale di chiamata in arrivo che il lettore musicale può intercettare, disattivando il volume fino al termine della chiamata.

wiki:

D-Bus fornisce sia un demone di sistema (per eventi come "nuovo dispositivo hardware aggiunto" o "coda della stampante modificata") che un demone per sessione di accesso per utente (per esigenze di comunicazione tra processi generali tra le applicazioni utente)

C'è anche una Python per questo, e Ubuntu ha recentemente usato questa capacità che ha chiamato " zeitgeist ".

0
Amir Naghizadeh