Search This Blog

Tuesday, July 31, 2018

KVM - Snooping PS/2 keystrokes for hotkey

Projects / KVM Switch  Original post date: 03/29/2017

The idea is to snoop the PS/2 keystrokes passively for supporting hotkey for switching to a different PC. It is a bit different than interfacing to the keyboard directly.

Electrical
I have decided to use the I2C pins as they are "True Open Drain" pins and the only 5V tolerant pins in the STM8.  They can handle a bit of abuses that happens on a PS/2 port.

STM8 I2C pins Absolute maximum rating

Protocol

The PS/2 protocol is bidirectional and the protocols are slightly different. If Data = '0' on the first falling edge of Clock, then it is a response or scan code from keyboard to PC.


If Data = '1' on the falling edge of Clock, then it is a PS/2 command for the keyboard.

Synchronization

We have to keep track of the different number of data bits of the two protocols. A count down timer is used to determine if synchronization is lost.

I use the falling edge of clock for interrupt. Inside the IRQ, the Data bits are LSB first. A state machine is used to keep track of the protocol. A timer is used to determine whether or not synchronization has been lost and is used to reset the state machine.  This code has been tested extensively.


Here is the scan code decoding output (in Hex, P: parity bit.) from my main event loop.
PS/2 uses odd parity.

The key pressed trace shows the duration while Digital 3 shows the pause between key presses. The final glitch is the detection of double click. The "!" is the output when it detects a double click. My delays are around 70-75ms.

Snooping PS/2 keystrokes for hotkey - part 2

My development set up:

  • My new STM8 Breakout board with on board USB serial port
  • PS/2 splitter to monitor traffic between a PS/2 keyboard and a hub with PS/2 converter
  • Logic analyzer
Hotkey sequence timing
It works. :) The key pressed trace shows the duration while Digital 3 shows the pause between key presses. The final glitch is the detection of double click. The "!" is the output when it detects a double click. My delays are around 70-75ms.

This is a time stamp of the PS/2 scan code generated from me double clicking the Left Control key captured and decoded from a logic analyzer.


So let's make an upper limit of 250ms, 200ms, 250ms for the 3 timing intervals.

For a successful double click event:
  • The scan code sequence is: 0x14, ( 0xf0,0x14), 0x14
  • 3 sets of timings that needs to be satisfied for a double click event.
Here is the preliminary state machine that does the checking. Basically each state checks against expected scan code and within countdown timer limits before proceeding to the next state. If it fails, then reset to the idle state and start again.



Pretty mechanical and boring code. There are probably ways to improve and what not. I am skimping on the error checking for now. As with all coding exercises, there are things I might have missed etc., but probably enough to the next part.

The test code is under the file area. The project is for Cosmic C.

The code is missing the else statements for the state machine that reset the state to default.

else
  Hotkeys.State = HK_Idle;

With some minor changes with the code from previous project log, the hotkey is now triggering the HDMI switch by shorting it to ground for 100ms.  I just have to add some code to map the HDMI Mux setting back to the USB Mux.

The HDMI Mux to USB Mux mapping is done inside the main event loop as it does not require real time.  It works independently of the hotkey.  Since it involves Read Modify Write operation that shares GPIO port with the interrupt code, I surround the GPIO code with a pair of sim() and rim()  to disable and re-enable interrupt.


I have uploaded the STM8S board and firmware files on github.




No comments:

Post a Comment

Note: Only a member of this blog may post a comment.