haimgel / display-switch

Turn a $30 USB switch into a full-featured multi-monitor KVM switch
https://haim.dev/posts/2020-07-28-dual-monitor-kvm/
MIT License
2.85k stars 112 forks source link

Add single DP support with switch back on removal #10

Closed 0xpr03 closed 3 years ago

0xpr03 commented 4 years ago

Just a quick draft for how I can use it with a single displayport input. Thus my windows system has to switch for both machines by detecting addition and removal of USB devices.

Feel free to merge, I just don't think you'll be interested to merge it with this exact change.

0xpr03 commented 4 years ago

(And it's annoying that you can't see the console output. My windows doesn't display anything on startup and cargo can't be killed by Ctrl+C. Seems to be caused by the sub window created by us. Had to debug this for some time to figure out why nothing's responding.)

haimgel commented 4 years ago

Thanks for sharing! I'm not going to merge this, because:

  1. While "single DP" change works in your case, it does not work in others. It's better to approach this via #6
  2. Your PR is for Windows only, I aim to have parity with MacOS impl.
  3. The config file change is not backward-compatible.

However, the approach overall makes sense. I'm adding code right now to unify the codebase into Rust only, and will pick pieces from this PR, so we'll have this or similar functionality.

0xpr03 commented 4 years ago

Yeah making this quick hack work for every type of setup will come with some configuration and/or UI requirements to let people figure out their setup. Feel free to close this, otherwise it's just another possible setup people could just grab and use. (It's kinda setup and forget anyway.)

AaronFriel commented 3 years ago

@0xpr03 and @haimgel I've submitted another PR #11 which builds on this one and has per-handle on connect and on disconnect behavior. I found that my Dell P2715Q monitors would stop listening to DDC/CI inputs sometimes on the inactive ports. To make it work reliably, I set up both computers to change input sources on both connection and disconnection.

The thing I think that would make this far, far better is if there was some sort of stable identifier of the monitor - a serial number, a unique code, etc. I am a total novice here and I don't know the Windows API or the DDC/CI spec. Somehow Windows knows when switching back and forth which screen to set on the left and which on the right, even if the handles sometimes get reversed. That made using different input sources for each monitor - HDMI for one and DisplayPort for another - unreliable. Sometimes the left monitor would have handle 0, sometimes the right.

Do you know if there's a way to obtain a stable identifier of any kind via API?

haimgel commented 3 years ago

Sorry I changed the code a lot over the weekend (it's basically all Rust now, even on MacOS).

Do you know if there's a way to obtain a stable identifier of any kind via API?

Yeah I was afraid this would be a problem... Now, on the DDC level, monitors should expose a plethora of data, including make/model/serial number. On the API level, I haven't checked how well this is exposed on the API level on different OSes, but on Windows i2c-hi's #info method returns all the fields None except for the ID field, which is the monitor name (and it would be the same if you have two identical monitors).

I've also read somewhere that some manufacturers "saved" on eeeprom so all their monitors report the same serial number, the code should account for that possibility (e.g. uniqueness is not guaranteed).

AaronFriel commented 3 years ago

@haimgel perhaps something can be gleaned from this tool by Nirsoft: https://www.nirsoft.net/utils/control_my_monitor.html

Even though my two monitors report exactly the same VCP data on all values - literally identical. The screenshot below shows (for accessibility) two instances of the nirsoft tool open, one connected to my graphics card's DISPLAY1 and one connected to DISPLAY2. And with different codes preceding them, perhaps the serial numbers? Edit: Confirmed, those are the same serial numbers Powershell reports below.

Screenshot follows:

image

Lastly, it looks like Windows is getting serial numbers and other info via i2c:

# powershell
gwmi -Namespace root/WMI -Class WmiMonitorID | Select SerialNumberID

SerialNumberID
--------------
{71, 51, 68, 55...}
{53, 57, 74, 74...}
AaronFriel commented 3 years ago

It looks like on Windows then the best API to get the serial number would be via WMI or CIM, which is likely to be a very stable API.

haimgel commented 3 years ago

It looks like on Windows then the best API to get the serial number would be via WMI or CIM

Agree, it looks promising.

haimgel commented 3 years ago

I'm closing this, as "switch back on removal" is now in Master, together with "raw" identifiers for monitors.

Getting the mapping between DDC-control handle and the monitor's serial number on Windows is quite problematic, though... I couldn't find satisfactory answers. The best one is on StackOverflow but it still does not give a reliable, always-working mapping. Deferring this for a later time.