it-swarm-vi.com

Làm cách nào để phát hiện khi màn hình được cắm hoặc rút phích cắm?

bất kỳ sự kiện nào được kích hoạt khi tôi cắm hoặc tắt màn hình ngoài vào DisplayPort của máy tính xách tay của tôi không? ACPID và UDEV hoàn toàn không phản ứng.

Tôi đang sử dụng đồ họa trên bo mạch trên chip intel. Ở đây là một cuộc thảo luận tương tự đã có một vài năm tuổi.

Tôi không muốn sử dụng bỏ phiếu nhưng tôi cần có một số cấu hình tự động cài đặt cài đặt hiển thị tùy thuộc vào việc màn hình có được kết nối hay không.

54
janoliver

LƯU Ý: Điều này đã được thử nghiệm trên máy tính xách tay với card đồ họa điều khiển i915.


Lý lịch

LƯU Ý: Khi màn hình mới được cắm, không có sự kiện nào được gửi đến Máy chủ, điều này vẫn đúng ngay cả sau lần chỉnh sửa cuối cùng của tôi. Vì vậy, cách duy nhất là sử dụng bỏ phiếu. Cố gắng làm cho chúng hiệu quả nhất có thể ...

EDIT # 3

Cuối cùng, có một giải pháp tốt hơn (thông qua ACPI):

Vẫn không có sự kiện, nhưng ACPI có vẻ hiệu quả hơn xrandr để hỏi. (Nota: Điều này yêu cầu các mô-đun hạt nhân ACPI được tải, nhưng không yêu cầu quyền root).

Giải pháp cuối cùng của tôi (sử dụng bash):

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

Bây giờ là một bài kiểm tra:

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

Nó đã được cắm, vì vậy bây giờ tôi rút phích cắm:

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

LƯU Ý: ${1:+*-1+1} cho phép một đối số boolean : Nếu một cái gì đó có mặt , câu trả lời sẽ được đảo ngược: ( crtState >> 4 ) * -1 + 1.

và kịch bản cuối cùng:

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

CẢNH BÁO: nhẹ hơn xrandr, nhưng không quan trọng với độ trễ nhỏ hơn 0,02 giây, tập lệnh Bash sẽ đi đến đầu quá trình ăn tài nguyên (top)!

Trong khi chi phí này ~ 0,001 giây:

$ time read -a </proc/stat crtStat

Điều này cần ~ 0,030 giây:

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

Thứ này lớn! Vì vậy, tùy thuộc vào những gì bạn cần, delay có thể được đặt hợp lý giữa 0.52.

EDIT # 2

Cuối cùng tôi đã tìm thấy một cái gì đó, bằng cách sử dụng này:

Từ chối trách nhiệm quan trọng: Chơi với /proc/sys mục có thể phá vỡ hệ thống của bạn !!! Vì vậy, đừng thử những điều sau đây trên các hệ thống sản xuất.

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

... Sau khi dọn dẹp các mục không mong muốn:

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

Tôi đã có thể đọc điều này:

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

Khi tôi cắm, rút ​​phích cắm và cắm lại vào cáp màn hình.

Khi cấu hình được hỏi (chạy system/preferences/monitor hoặc xrandr), các card đồ họa thực hiện một kiểu quét , vì vậy, chạy xrandr -q cung cấp cho bạn thông tin, nhưng bạn phải thăm dò tình trạng.

Tôi đã quét tất cả các bản ghi, (kernel, daemon, X, v.v.) tìm kiếm thông qua /proc & /sys, và rõ ràng không có gì tồn tại thỏa mãn yêu cầu của bạn.

Tôi cũng đã thử điều này:

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

Sau tất cả, nếu bạn chạy System/Preferences/Monitor trong khi không có màn hình mới vừa được cắm, cũng không được rút ra, công cụ sẽ xuất hiện đơn giản (bình thường). Nhưng nếu bạn đã cắm hoặc rút màn hình trước đó, đôi khi bạn sẽ chạy công cụ này và bạn sẽ thấy máy tính để bàn của mình tạo kiểu đặt lại hoặc refresh (tương tự nếu bạn chạy xrandr).

Điều này dường như xác nhận rằng công cụ này yêu cầu xrandr (hoặc hoạt động theo cách tương tự) bằng cách bỏ phiếu theo trạng thái định kỳ, bắt đầu từ thời điểm nó chạy.

Bạn có thể tự thử:

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

Điều này sẽ hiển thị số lượng màn hình (màn hình) được kết nối, trong 10 giây.

Trong khi điều này chạy, cắm và/hoặc rút phích cắm màn hình/màn hình của bạn và xem điều gì sẽ xảy ra. Vì vậy, bạn có thể tạo một hàm kiểm tra Bash nhỏ:

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

có thể sử dụng như trong:

$ if isVgaConnected; then echo yes; fi

Nhưng hãy cẩn thận, xrandr mất khoảng 0.140 giây đến 0.200 giây trong khi không có thay đổi nào xảy ra trên phích cắm và lên đến 0,700 giây mỗi khi có thứ gì đó được cắm hoặc rút phích cắm ngay trước đó ( LƯU Ý: Có vẻ như không phải là tài nguyên người ăn).

EDIT # 1

Để đảm bảo tôi không dạy điều gì đó không chính xác, tôi đã tìm kiếm trên Web và các tài liệu, nhưng không tìm thấy gì về DBus và Screens .

Cuối cùng, tôi đã chạy trong hai cửa sổ khác nhau dbus-monitor --system (Tôi cũng đã chơi với các tùy chọn) và kịch bản nhỏ tôi đã viết:

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

... và một lần nữa cắm, hơn là rút phích cắm màn hình, nhiều lần. Vì vậy, bây giờ tôi có thể nói:

  • Trong cấu hình này, sử dụng trình điều khiển i915 , không có cách nào khác ngoài chạy xrandr -q để biết màn hình có được cắm hay không.

Nhưng hãy cẩn thận, vì dường như không có cách nào khác. Chẳng hạn, xrandr dường như chia sẻ thông tin này, vì vậy máy tính để bàn Gnome của tôi sẽ tự động chuyển sang xinerama ... khi tôi chạy xrandr.

Một số tài liệu

14
F. Hauri

Các dòng sau xuất hiện trong 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)

khi gắn màn hình vào Đầu nối VGA. Vì vậy, có thể có một cách để tìm ra điều này.

4
sebastianwagner

Tôi bị mắc kẹt khi sử dụng srandrd . Nó theo dõi các sự kiện X và kích hoạt tập lệnh của bạn khi màn hình được kết nối hoặc ngắt kết nối.

3
scorpp

Đối với những người, vì bất kỳ lý do gì, không muốn đi theo con đường cắm nóng, vẫn có thể không bỏ phiếu trong một tập lệnh bằng cách sử dụng inotifywait:

[.__.] #!/bin/bash [.___] renice +19 $$>/dev/null [.__.] [.__.] ngủ $ START_DELAY [.__.] [.__.] OLD_DUAL = "dummy" [.__.] [.__.] trong khi [ 1]; làm [.___.] DUAL = $ (cat/sys/class/drm/card0-DP-2/status) [. ___. [[. ___.] if ["$ OLD_DUAL"! = "$ DUAL"]; sau đó [.__.] nếu ["$ DUAL" == "được kết nối"]; sau đó [.__.] echo 'Thiết lập màn hình kép' [.__.] xrandr --output $ SCREEN_LEFT --auto --rotate bình thường --pose 0x0 --output $ SCREEN_RIGHT --auto --rotate bình thường - tin $ SCREEN_LEFT [.__.] Khác [.__.] Echo 'Thiết lập màn hình đơn' [.__.] Xrandr --auto [.__.] Fi [.__.] [.__.] OLD_DUAL = "$ DUAL" [ .__.] fi [.___.] [.__.] inotifywait -q -e close/sys/class/drm/card0-DP-2/status>/dev/null [.__.] đã thực hiện [.__. ] [.__.]

Nó được gọi tốt nhất từ ​​.xsessionrc của bạn, không quên kết thúc &. Thăm dò ý kiến ​​với xrandr đã đưa ra các vấn đề về khả năng sử dụng nghiêm trọng trên máy tính xách tay hoàn toàn mới của tôi (chuột sẽ bị đình trệ định kỳ).

3
Balzola

Rõ ràng là nên có một cái gì đó! Hệ thống tập tin :)/sys cho người dùng biết phần cứng nào có sẵn, vì vậy các công cụ không gian người dùng (như udev hoặc mdev) có thể tự động điền vào thư mục "/ dev" với các nút thiết bị đại diện cho phần cứng hiện có. Linux cung cấp hai giao diện hotplug:/sbin/hotplug và netlink.

Có một bản demo C nhỏ trong tệp sau. http://www.kernel.org/doc/pending/hotplug.txt

0
roncsak

Hầu hết các phần mềm hệ thống/ứng dụng trên Linux ngày nay đã sử dụng một số kỹ thuật ipc để giao tiếp với nhau. D-Bus hiện được sử dụng chủ yếu với các ứng dụng Gnome và có thể giúp ích.

Tạp chí Linux :

D-BUS có thể tạo điều kiện gửi các sự kiện hoặc tín hiệu thông qua hệ thống, cho phép các thành phần khác nhau trong hệ thống giao tiếp và cuối cùng để tích hợp tốt hơn. Ví dụ: thiết bị Bluetooth có thể gửi tín hiệu cuộc gọi đến mà trình phát nhạc của bạn có thể chặn, tắt âm lượng cho đến khi cuộc gọi kết thúc.

wiki:

D-Bus cung cấp cả trình nền hệ thống (cho các sự kiện như "thiết bị phần cứng mới được thêm vào" hoặc "hàng đợi máy in đã thay đổi") và trình nền phiên cho mỗi người dùng đăng nhập (cho nhu cầu giao tiếp giữa các quy trình chung giữa các ứng dụng người dùng)

Thậm chí còn có một thư viện Python cho việc này và gần đây ubfox đã sử dụng khả năng này có tên là " zeitgeist ".

0
Amir Naghizadeh