it-swarm-id.com

Bagaimana saya bisa mendeteksi ketika monitor dicolokkan atau dicabut?

Apakah ada kejadian yang dipicu saat saya mencolokkan atau lepaskan monitor eksternal ke DisplayPort laptop saya? ACPID dan UDEV tidak bereaksi sama sekali.

Saya menggunakan grafis onboard pada chip intel. Di Sini adalah diskusi serupa yang sudah berusia beberapa tahun.

Saya tidak ingin menggunakan polling tetapi saya perlu memiliki beberapa konfigurasi yang mengatur pengaturan tampilan secara otomatis tergantung pada apakah layar terhubung.

54
janoliver

CATATAN: Ini diuji pada laptop dengan kartu grafis yang digerakkan i915.


Latar Belakang

CATATAN: Ketika layar baru dicolokkan, tidak ada acara dikirim ke Host, ini tetap benar bahkan setelah edit terakhir saya. Jadi satu-satunya cara adalah menggunakan polling. Mencoba menjadikannya seefisien mungkin ...

EDIT # 3

Akhirnya ada satu solusi yang lebih baik (melalui ACPI):

Masih belum ada acara, tetapi ACPI tampaknya lebih efisien daripada untuk meminta xrandr. (Catatan: Ini membutuhkan modul kernel ACPI dimuat, tetapi tidak memerlukan hak akses root).

Solusi terakhir saya (menggunakan bash):

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

Sekarang ujian:

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

Itu sudah terhubung, jadi sekarang saya mencabutnya:

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

CATATAN: ${1:+*-1+1} mengizinkan a boolean argumen: Jika ada sesuatu, jawabannya akan terbalik: ( crtState >> 4 ) * -1 + 1.

dan skrip terakhir:

#!/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

PERINGATAN: lebih ringan dari xrandr, tetapi tidak tidak penting dengan penundaan yang lebih kecil dari 0,02 detik, skrip Bash akan menuju ke puncak proses pemakan sumber daya (top)!

Sementara ini biaya ~ 0,001 detik:

$ time read -a </proc/stat crtStat

Ini membutuhkan ~ 0,030 detik:

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

Ini besar! Jadi tergantung pada apa yang Anda butuhkan, delay dapat diatur antara 0.5 dan 2.

EDIT # 2

Saya akhirnya menemukan sesuatu, menggunakan ini:

Penafian penting: Bermain dengan /proc dan /sys entri dapat merusak sistem Anda !!! Jadi jangan coba yang berikut ini pada sistem produksi.

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

... setelah beberapa pembersihan entri yang tidak diinginkan:

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

Saya sudah bisa membaca ini:

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

Saat saya mencolokkan, cabut, dan pasang kembali kabel monitor.

Ketika konfigurasi diminta (menjalankan system/preferences/monitor atau xrandr), kartu grafis melakukan jenis memindai, jadi jalankan xrandr -q memberi Anda info, tetapi Anda harus memilih statusnya.

Saya telah memindai semua log, (kernel, daemon, X, dan sebagainya) mencari melalui /proc & /sys, dan jelas tidak ada yang memenuhi permintaan Anda.

Saya sudah mencoba ini juga:

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

Setelah semua itu, jika Anda menjalankan System/Preferences/Monitor Meskipun tidak ada layar baru yang baru saja dicolokkan, atau dicabut, alat akan muncul secara sederhana (normal). Tetapi jika Anda sudah memasang atau mencabut layar sebelumnya, kadang-kadang Anda akan menjalankan alat ini dan Anda akan melihat desktop Anda membuat jenis reset atau menyegarkan (sama jika Anda menjalankan xrandr).

Ini sepertinya mengkonfirmasi bahwa alat ini meminta xrandr (atau berfungsi dengan cara yang sama) dengan memungut status secara berkala, mulai saat dijalankan.

Anda bisa mencoba sendiri:

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

Ini akan menampilkan berapa banyak layar (display) yang terhubung, selama 10 detik.

Saat ini berjalan, tancapkan dan/atau cabut layar/monitor Anda dan lihat apa yang terjadi. Jadi Anda bisa membuat fungsi tes Bash kecil:

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

yang bisa digunakan seperti pada:

$ if isVgaConnected; then echo yes; fi

Tapi hati-hati, xrandr membutuhkan waktu sekitar 0,140 detik hingga 0,200 detik sementara tidak ada perubahan yang terjadi pada colokan dan hingga 0,700 detik setiap kali sesuatu dicolokkan atau dicabut sebelum ( CATATAN: Tampaknya tidak menjadi sumber daya pemakan).

EDIT # 1

Untuk memastikan saya tidak mengajarkan sesuatu yang salah, saya telah mencari di Web dan dokumen, tetapi tidak menemukan apa pun tentang DBus dan Layar.

Akhirnya, saya sudah menjalankan di dua jendela yang berbeda dbus-monitor --system (Saya juga bermain dengan opsi) dan skrip kecil yang saya tulis:

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

... dan lagi terpasang, daripada mencabut monitor, berkali-kali. Jadi sekarang saya bisa mengatakan:

  • Dalam konfigurasi ini, menggunakan driver i915 , tidak ada cara lain selain menjalankan xrandr -q untuk mengetahui apakah monitor dicolokkan atau tidak.

Tetapi berhati-hatilah, karena tampaknya tidak ada cara lain. Sebagai contoh, xrandr tampaknya berbagi info ini, jadi desktop GNOME saya akan beralih ke xinerama secara otomatis ... ketika saya menjalankan xrandr.

Beberapa dokumen

14
F. Hauri

Baris berikut muncul di 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)

saat memasang monitor ke Konektor-VGA. Jadi mungkin ada cara untuk mencari tahu ini.

4
sebastianwagner

Saya terjebak menggunakan srandrd . Ini memonitor peristiwa X dan memicu skrip Anda ketika layar terhubung atau terputus.

3
scorpp

Bagi mereka yang, untuk alasan apa pun, tidak ingin mengambil rute hotplug, masih mungkin untuk tidak melakukan polling dalam skrip menggunakan inotifywait:

 #!/bin/bash 
 
 SCREEN_LEFT = DP2 
 SCREEN_RIGHT = eDP1 
 START_DELAY = 5 
 
 renice +19 $$>/dev/null 
 
 sleep $ START_DELAY 
 
 OLD_DUAL = "dummy" 
 
 sementara [ 1]; do 
 DUAL = $ (cat /sys/class/drm/card0-DP-2/status)[.____.
 jika ["$ OLD_DUAL"! = "$ DUAL"]; lalu 
 jika ["$ DUAL" == "terhubung"]; lalu 
 gema 'Dual monitor setup' 
 xrandr --output $ SCREEN_LEFT --auto --rotate normal --pos 0x0 --output $ SCREEN_RIGHT --auto --rotate normal - di bawah $ SCREEN_LEFT 
 Lain 
 Gema 'Pengaturan monitor tunggal' 
 Xrandr --auto 
 Fi 
 
 OLD_DUAL = "$ DUAL" 
 fi 
 
 inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null 
 dilakukan 
 

Paling baik dipanggil dari .xsessionrc Anda, jangan lupa bagian akhirnya &. Polling dengan xrandr memberikan masalah kegunaan serius pada laptop baru saya (mouse akan berhenti secara berkala).

3
Balzola

Jelas harus ada sesuatu! :)/sys filesystem memberitahu userspace perangkat keras apa yang tersedia, sehingga alat userspace (seperti udev atau mdev) dapat secara dinamis mengisi direktori "/ dev" dengan node perangkat yang mewakili perangkat yang saat ini tersedia perangkat keras. Linux menyediakan dua antarmuka hotplug:/sbin/hotplug dan netlink.

Ada demo C kecil di file berikut. http://www.kernel.org/doc/pending/hotplug.txt

0
roncsak

Sebagian besar perangkat lunak sistem/aplikasi di Linux saat ini menggunakan beberapa teknik IPC untuk berkomunikasi satu sama lain. D-Bus sekarang sebagian besar digunakan dengan aplikasi GNOME, dan mungkin membantu.

Jurnal Linux:

D-BUS dapat memfasilitasi pengiriman acara, atau sinyal, melalui sistem, yang memungkinkan berbagai komponen dalam sistem untuk berkomunikasi dan pada akhirnya untuk mengintegrasikan dengan lebih baik. Misalnya, Bluetooth Dæmon dapat mengirim sinyal panggilan masuk yang dapat disadap pemutar musik Anda, mematikan volume hingga panggilan berakhir.

wiki:

D-Bus memasok daemon sistem (untuk acara seperti "perangkat keras baru ditambahkan" atau "antrian printer berubah") dan daemon sesi masuk per pengguna (untuk kebutuhan komunikasi antar proses umum di antara aplikasi pengguna)

Bahkan ada pustaka Python untuk ini, dan ubuntu baru-baru ini menggunakan kemampuan ini yang disebut " zeitgeist ".

0
Amir Naghizadeh