10110111 / usb2ps2conv

Firmware for a converter from USB keyboard to PS/2 computer
56 stars 3 forks source link

PS/2 working in bios but not within XP ? #3

Open homepark1 opened 2 years ago

homepark1 commented 2 years ago

I'm using the compiled binary in a STM32F407 DISCO-board. PS/2 timing checked with scope seems to be correct. Booting pc allow to get into bios and all keys seem to work. As soon XP starts, no key seems to work. ( also tried safe mode) What could be the reason for this ?

10110111 commented 2 years ago

What do the status LEDs show? Also, could you obtain debug output by compiling the firmware with -DENABLE_DEBUG_OUTPUT=ON and connecting a USB-UART dongle as described in the README? This should provide some info on what's going on.

homepark1 commented 2 years ago

Sorry for replying late. The LEDs are exactly the same during Bios and XP: Just the green LED. I'll provide some debuglogs soon.

homepark1 commented 2 years ago

xp.log bios.log

So here come the logs. ( there is a 20% chance, that I swapped bios and xp by accident.)

10110111 commented 2 years ago

there is a 20% chance, that I swapped bios and xp by accident

Yeah, apparently, you did, although the timings seem to imply that you entered BIOS Setup after running WinXP.

Keyboard report: 0x0000000000000000
pass byte to PS/2: 02
pass byte to PS/2: F0
pass byte to PS/2: 0D
sendByte(F0)
Keyboard report: 0x00000000002b0000
pass byte to PS/2: 01
pass byte to PS/2: 0D
Keyboard report: 0x0000000000000000
pass byte to PS/2: 02
pass byte to PS/2: F0
pass byte to PS/2: 0D
Keyboard report: 0x00000000002b0000
pass byte to PS/2: 01
pass byte to PS/2: 0D

This (and subsequent output) implies that sendByte is no longer called after Tab is released and the first byte if its scancode is emitted.

  1. One reason might be that XP's i8042 driver for some reason makes the controller busy. This would be visible on the oscilloscope (bus stuck at DATA=high, CLK=low). If this is the case, it would be useful to find out what leads to this (i.e. the activity on the bus before this inhibition condition happens, some several dozens of clock cycles in length).
  2. Another reason might be that the state machine in ps2-kbd-emulator.cpp has a bug (in BusDriver::handleISR() method). This would need some extended debugging — maybe additional prints, or maybe some pin banging to watch via oscilloscope.

As case 1 seems easier, could you check whether it is the problem? If you can't, we'll have to proceed to the more general case 2.

homepark1 commented 2 years ago

Case 1 seems to be the case. PC13 ( clk) stays at 5V until I press any key. I seem some action, before the signal stays low forever. I'll have to build some better adapters to measure the signals better to provide a picture.

homepark1 commented 2 years ago

usb2ps2 These are the last words as I pressed key-up in the fully booted xp environment.

10110111 commented 2 years ago

How does the blue LED behave if you apply the following patch? In particular, I'm interested whether it turns on at any point, and whether it remains on when the CLK line gets stuck low.

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 75c4a92..9a2be05 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -7,6 +7,7 @@
 #include "ps2-kbd-emulator.h"
 #include "hid-keybd.h"
 #include "util.h"
+#include "led.h"

 // Reference used: https://www.avrfreaks.net/sites/default/files/PS2%20Keyboard.pdf

@@ -123,11 +124,15 @@ static void outMode(GPIO_TypeDef* gpio, const uint16_t pin)
 static void high(GPIO_TypeDef* gpio, const uint16_t pin)
 {
     inMode(gpio,pin);
+    if(gpio==CLK_GPIO)
+        ledOn(LED_BLUE);
 }
 static void low(GPIO_TypeDef* gpio, const uint16_t pin)
 {
     outMode(gpio,pin);
     gpio->BSRR = 1u<<(pin+16); // set the pin low
+    if(gpio==CLK_GPIO)
+        ledOff(LED_BLUE);
 }
 static bool read(GPIO_TypeDef* gpio, const uint16_t pin)
 {
homepark1 commented 2 years ago

The blue and green LED are on all the time. From powerup the STM32F4 during Bios, up to windows. They also stay on, if I press a key within XP. (.. which fails..)

10110111 commented 2 years ago

And the brightness of the blue doesn't change when you type in BIOS Setup, right?

homepark1 commented 2 years ago

No change in brightness is noticeable when in Bios.

10110111 commented 2 years ago

OK. So, apparently, CLK is indeed released by STM and held low by the host. This makes me wonder... do you have any real PS/2 keyboard to test instead of this emulator?

homepark1 commented 2 years ago

Using the PS2 keyboard, there is no problem anywhere. Using STM32F4 and pressing a key in XP makes the pc refuse to work with PS2 keyboard. ( I changed keyboards within XP after pressing a key on STM)

10110111 commented 2 years ago

Really strange. And what if you boot with the keyboard, press a key, and then swap to the emulator? Does it work normally then?

homepark1 commented 2 years ago

Booted into XP with PS2. Pressed some keys: worked. Switched to STM32: Worked !! Pretty strange...

10110111 commented 2 years ago

OK, maybe we get some command that we handle wrongly. Could you reproduce the problem, saving UART log after the following patch?

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 75c4a92..73384f8 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -611,6 +611,7 @@ void PS2_Process()
                 clearKbdBuffer();
             }

+            printf("Got command: %02X\n", (unsigned)cmd);
             switch(cmd)
             {
             case CMD_READ_ID:
10110111 commented 2 years ago

Even better, this patch, for more complete log:

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 75c4a92..1c8f7ee 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -576,6 +576,7 @@ void PS2_Process()
         {
             // Request to send detected, accept the command
             const auto byte=busDriver.getByteReceived();
+            printf("Got byte from host: %02X\n", (unsigned)byte);

             if((lastCommand&0x80)!=0 && (byte&0x80)==0)
             {
homepark1 commented 2 years ago

putty.log Here comes the log. Powerup, booting in to XP. Pressing left windows-key..with no effect.

10110111 commented 2 years ago

Yeah, there seems to be a stray input byte 00. Please retry with the updated patch below.

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 75c4a92..466003e 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -549,6 +549,7 @@ void PS2_Process()
         // We succeed in any case. Just need to wait 500-750 ms before sending success code.
         BATStartTimeMs=HAL_GetTick();
         kbdState=KeyboardState::DelayBeforeBAT;
+        printf("Starting BAT...\n");
         break;
     case KeyboardState::DelayBeforeBAT:
         if(HAL_GetTick() - BATStartTimeMs < DELAY_MS_BEFORE_SENDING_BAT_CODE)
@@ -556,6 +557,7 @@ void PS2_Process()
         setLEDs(0);
         busDriver.sendByte(REPLY_BAT_SUCCESS);
         kbdState=KeyboardState::SendingBAT_WaitingForTransmissionEnd;
+        printf("Ending BAT...\n");
         break;
     case KeyboardState::SendingBAT_WaitingForTransmissionEnd:
         if(!busDriver.isIdle())
@@ -563,6 +565,7 @@ void PS2_Process()
         kbdEnabled=true;
         kbdBusy=false;
         kbdState=KeyboardState::WaitingForCommands;
+        printf("BAT done\n");
         break;
     case KeyboardState::WaitingForCommands:
         kbdBusy=false;
@@ -576,6 +579,7 @@ void PS2_Process()
         {
             // Request to send detected, accept the command
             const auto byte=busDriver.getByteReceived();
+            printf("Got byte from host: %02X\n", (unsigned)byte);

             if((lastCommand&0x80)!=0 && (byte&0x80)==0)
             {
10110111 commented 2 years ago

I've pushed an update with much more debug output. Please get the logs from the current master. On my WinXP machine everything works without any issues, so apparently, the problem is machine-dependent.

homepark1 commented 2 years ago

putty.log putty2.log You're right. I tried an other machine with XP, where everything works. So it's machine dependent. Find attached logs with the master-version. I tested two times just booting into XP on the buggy machine. Pressing a key doesn't produce any more logs in my terminal.

10110111 commented 2 years ago

Very interesting. The host spams the keyboard with Reset command every 10 ms. Apparently, even ACK can't be sent to any of these commands, since the reset isn't even initiated (no "Starting BAT" line). I've pushed some more debug prints to make sure it is so.

This behavior of the host is strange though. Could you capture an oscillogram of what happens when you get the repeated "Got byte from host: FF" output? I suspect that the host doesn't actually want to send FF, but we somehow interpret the DATA line as such input.

homepark1 commented 2 years ago

1 2 putty.log Find some more logs here. I'm not happy with my scope pics. Pic 1 shows the situation while XP is booting. ( triggering on lower edge of clk). Pic 2 occurs after pressing a key. Maybe I can get a logicanalyzer working to improve.

10110111 commented 2 years ago

Actually, the first picture might become useful if you stretch time scale so as to resolve the second and third bursts of CLK. You know their relative offsets from the first trigger, so it should be easy to aim.

homepark1 commented 2 years ago

I started my very vintage logicanalyzer and tried to catch some events during xp booting. It's hard to trigger. Maybe stm32 could toggle a pin when an interesting event shows up ? overview IMG_20220317_1836483 IMG_20220317_1838344 IMG_20220317_1839096 IMG_20220317_1839401 IMG_20220317_1840034 IMG_20220317_1840309 IMG_20220317_1844392 IMG_20220317_1845060

10110111 commented 2 years ago

We can turn on the blue led after reading 0xFF byte. This will be visible as logical high on PD15.

Here's the patch for this:

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 3626b5e..b59487d 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -7,6 +7,7 @@
 #include "ps2-kbd-emulator.h"
 #include "hid-keybd.h"
 #include "util.h"
+#include "led.h"

 // Reference used: https://www.avrfreaks.net/sites/default/files/PS2%20Keyboard.pdf

@@ -518,6 +519,7 @@ static void clearKbdBuffer()

 void PS2_Process()
 {
+    ledOff(LED_BLUE);
     enum class KeyboardState
     {
         Initialization,
@@ -639,6 +641,7 @@ void PS2_Process()
                 break;
             }
             case CMD_RESET:
+                ledOn(LED_BLUE);
                 kbdState=KeyboardState::SendingACK;
                 stateToGoToAfterAck=KeyboardState::Initialization;
                 USBH_UsrLog("Handling CMD_RESET");
homepark1 commented 2 years ago

Just tried it. The orange LED is on, but there is no blue LED nor a pulse on PD15.

homepark1 commented 2 years ago

I'll try to get a more advanced analyzer. This might take some time.

10110111 commented 2 years ago

The orange LED is on, but there is no blue LED nor a pulse on PD15.

I suppose the pulse is just too short for your device. Try removing the ledOff call, the LED will then shine all the time after reading the first 0xFF byte.

homepark1 commented 2 years ago

ledOff gives a strange result: directly after powerup, the blue led is on. So I waited a few seconds to plug in the ps2. Now the blue led doesn't shine. I'll think about a more complete trace of the ps2 signals.

10110111 commented 2 years ago

ledOff gives a strange result

After you remove ledOff, only ledOn should remain. The diff should look like this:

diff --git a/src/ps2-kbd-emulator.cpp b/src/ps2-kbd-emulator.cpp
index 3626b5e..a1880cc 100644
--- a/src/ps2-kbd-emulator.cpp
+++ b/src/ps2-kbd-emulator.cpp
@@ -7,6 +7,7 @@
 #include "ps2-kbd-emulator.h"
 #include "hid-keybd.h"
 #include "util.h"
+#include "led.h"

 // Reference used: https://www.avrfreaks.net/sites/default/files/PS2%20Keyboard.pdf

@@ -639,6 +640,7 @@ void PS2_Process()
                 break;
             }
             case CMD_RESET:
+                ledOn(LED_BLUE);
                 kbdState=KeyboardState::SendingACK;
                 stateToGoToAfterAck=KeyboardState::Initialization;
                 USBH_UsrLog("Handling CMD_RESET");

directly after powerup, the blue led is on

Is it really on before you get Handling CMD_RESET message? In you latest logs this message appeared 2.8 seconds after power on.

homepark1 commented 2 years ago

The blue LED is on directly after powerup. I just removed the Ledoff(LED_Blue) Today I bought a better logicanalyzer, which allows minutes of recording and save to .cvs. Find attached the complete conversation on PS2 until I press a key in XP at the end.

digital.csv IMG_20220319_2059028 IMG_20220319_2059348 IMG_20220319_2100355

10110111 commented 2 years ago

The host seems to indeed generate a request to send, and then sends 0xFF command. But then for some reason, indeed, it just doesn't let the device to acknowledge this command with 0xFA reply, and this happens on each communication. Even when we get the Set LEDs command 0xED, the ACK is interrupted by the host.

Could you capture the same exchange for a real PS/2 keyboard?

homepark1 commented 2 years ago

So here comes my original PS2. Powerup, booting into XP. Then I pressed about 3 keys there.. I think I swapped the clk/data pins compared to my previous measurement..

digital.csv pics.odt

10110111 commented 2 years ago

Why are CLK and DATA low here on start, while they were high in the previous capture? Did the process of measurement change?

homepark1 commented 2 years ago

I think this might me due to the powerup-procedures. On PS2, there is no voltage anywhere until pc boots. On STC32F4, I sometimes hooked up an USB-powersupply, so it was already powered up on pc powerup. As bios works in all cases, I don't think this part is critical. But if you want me to measure some more sequences, it's not a big deal. I have lots of adapters now.

10110111 commented 2 years ago

I'd like to make an apples-to-apples comparison. I.e. power should be taken from the PS/2 port and nothing else. And the measurement should start from the same point (preferably, right before the PC gets power, to see all the power-up events on the bus).

homepark1 commented 2 years ago

Here come apples only: The analyzer watches the pins at PS2 in the middle of a PS2-cable. I first plugged the PS2 keyboard. Then I plugged the stm32 just at the PS2. (As the stm32 lights are partly on, the pc seems to put 5V standby on ps2.) In the archive you find the two measurements as spreadsheet and overview pic. both.zip

homepark1 commented 2 years ago

Addon: at the end of both recordings, I press left windows key once, after XP desktop is up for a few seconds.

10110111 commented 2 years ago

I still can't seem to figure out why the very beginning is different: in the STM case CLK and DATA are both high, while in the case of keyboard they are both low. Does the keyboard really hold the line low for some time after turning on?

Also, if we suppose that the pattern at 1.66732 in STM trace is the same as the pattern at 1.999696 in keyboard trace, then there's a strange jitter of CLK at 2.582906 in STM trace and a dip at 3.974709 with a jitter a bit later, all of which don't exist in the keyboard trace.

I can't reproduce this jitter on my system, and I expect this to be the behavior of the host, rather than the STM. But your trace of the keyboard signals doesn't contain it, which makes me wonder.

tmk commented 2 years ago

Hi, Didn't try this STM32 converter yet, I'm still interested in seeing how to solve this issue.

I converted csv data and looked into signals with sigrok pulseview.

STM seems to take quite longer time to response with first FF command than ps/2 keyboard for some reason. ps/2 host doesn't like that and kind of time out?

Screenshot_2022-03-21_13-01-38

10110111 commented 2 years ago

ps/2 host doesn't like that and kind of time out?

I don't think it's so. First, the docs (ref. 1 in README) say thta the response must be no later than 20 ms. Your screenshot shows 8.33 ms. Second, if this converter is plugged after initialization of a real keyboard, everything works fine (see this comment).

10110111 commented 2 years ago

@tmk

Where did you take IBMPC KBD decoder for sigrok? I've just installed sigrok, and it doesn't have such a decoder. Is it something custom you made?

tmk commented 2 years ago

It is my adhoc modified version of PS/2 decoder.

Not sure but copy two .py file into ~/.local/share/libsigrokdecode/decoders/ibmpc_kbd/, it may work perhaps. https://gist.github.com/tmk/dbf117ee59cebb710d9c86353fed0861

EDIT: I couldn't import the CSV files directly to pulseview and had to convert them to VCD format using this script. https://gist.github.com/tmk/89dd2241a4410ddc31abd439a8389954

homepark1 commented 2 years ago

The CLK&DATA low/high can be explaned by powerup-procedures: After the pc is plugged in, both signals are low. This is the same for STM and PS2. After shutting down XP regulary, CLK&DATA are high. So I repeated these recordings again. Now with unplugging the pc completely for each measurement. In XP, I press left Win once.

4.zip

10110111 commented 2 years ago

Looks as if the main difference is the delay before the reply. What if you connect the USB keyboard only after XP boots? Does it work then? If not, please comment out all the calls after PS2_Process() in the main loop inside main.cpp and capture the bus signals when XP boots. This will make the keyboard input not work, but should remove the delay and let us see whether the host becomes satisfied then.

homepark1 commented 2 years ago

Booting XP without anything in PS2Port, than attaching STM into a booted XP doesn't work. So I commented out the comands after PS2_Process(), so it's basically just a loop over PS2_Process(). In this case, the lines stay high. I made two traces of each test. 5.zip