Harvie / ps2dev

Arduino library to emulate PS2 keyboard/mouse
MIT License
114 stars 27 forks source link

Should available() method check data pin in adition to clock pin? #8

Closed Harvie closed 4 years ago

Harvie commented 4 years ago

I was trying this week to tweak together a little project of mine which has been open for quite a while.

For this project it would be very usefull to have an Arduino input keystrokes over PS2 to a computer.

I've been trying for days with several examples using your Arduino ps2dev library but somehow I cannot get it to work.

I can see on the scope there is data communication from the Arduino to the PC (Asus Intel Atom having physical PS2 mouse and keyboard ports).

When I enable serial logging in the library I see data and responses getting passed over, but the computer (running CentOS Linux) never actually accepts the data sent to it:

received data ED received parity 1 calculated parity 1 sending FA sent 0 received data 0 received parity 1 calculated parity 1 sending FA sent 0 LEDs: 0 174910sending 5A sent 0 sending F0 sending 5A .received data ED received parity 1 calculated parity 1 sending FA sent 0 received data 0 received parity 1 calculated parity 1 sending FA sent 0 LEDs: 0 174910sending 5A sent 0 sending F0 sending 5A .received data ED received parity 1 calculated parity 1 sending FA sent 0 received data 0 received parity 1 calculated parity 1 sending FA sent 0 LEDs: 0 174910sending 5A sent 0 sending F0 sending 5A .received data ED received parity 1 calculated parity 1 sending FA sent 0 received data 0 received parity 1 calculated parity 1

When I plug in a PS2 keyboard into the PC it works fine.

I tried the ps2mouse example and reconnected the Arduino PS2 to the mouse port ofcourse. Not a single bit of movement to be seen.

Kind regards,

Arno Bekker Hello, i hope we will find where the problem lays. Do you have github account? To be honest, i've never used the mouse part. Not even tried. Some guys recently sent me some improvements on github and i've merged it without any further testing.

You can see the recent changes here: https://github.com/Harvie/ps2dev/commits/master

Before other people start contributing, the keyboard was working for me like 95% of the time and people claimed to improve it further, but i am not sure. Perhaps you can try some older versions/commits to see if some of them will work better.

Also you might try to discuss changes they made in the pull request pages directly with the authors:

https://github.com/Harvie/ps2dev/pulls?q=is%3Apr+is%3Aclosed

I don't really have PS2 computer to do the tests. But recently i ordered PS2 to USB converter, so hopefully i will be able to use it for debugging when i'll get bit less busy. In the meantime i will be happy to include any bugfixes you make. Just create PR on github and i will review the code and merge it. I've been working on the PS2 comms last days and I managed to find what was causing the problem in the library, its the available function:

int PS2dev::available() { // Arno: main issue resolved - host was not able to signal for data return ( (digitalRead(_ps2data) == LOW) || (digitalRead(_ps2clk) == LOW) ); }

The Host tries to send the 0xED command as a response on every character I was trying to send via the library.

I figured somehow the host was not able to send the 0xED earlier to set the LEDs and reported that 0xED on everything I was sending. Changing the available() function to check both clock and data resolves the problem.

En passant I figured the debug serial output could much more clear, in my version its like this now:

Init PS2: TX: 0xAA 0 RX: 0xF2 rp=0 cp=0 TX: 0xFA 0 TX: 0xAB 0 TX: 0x83 0 RX: 0xF4 rp=0 cp=0 TX: 0xFA 0 RX: 0xED rp=1 cp=1 TX: 0xFA 0 RX: 0x0 rp=1 cp=1 TX: 0xFA 0 LEDs: 0

I do have a Github account and can report what I've found over Github if you like.

Arno Bekker

Harvie commented 4 years ago

That's good news. Do you know how to use git and make pull request with your changes on github?

BTW if host tries to send data often, maybe we should just call keyboard.keyboard_handle(&leds) more often (eg. after each button sent)... It will handle incoming data. I already forgot how PS2 protocol works since the last time i've been doing the modifications... Do you thing that's a good idea?

Problem is that every PS2 implementation is bit different, so we need to be sure that we are compatible with everyone. I see the code that you suggest was already there, but i've commented it out.. I am not really sure why... Probably i was thinking it's not needed. I think we can include it again. But i would be happy if i had some deeper theorethical undestanding of why this is done.

Harvie commented 4 years ago

Here http://www.burtonsys.com/ps2_chapweske.htm they say following:

Host-to-Device Communication:

The packet is sent a little differently in host-to-device communication...

First of all, the PS/2 device always generates the clock signal. If the host wants to send data, it must first put the Clock and Data lines in a "Request-to-send" state as follows:

Inhibit communication by pulling Clock low for at least 100 microseconds. Apply "Request-to-send" by pulling Data low, then release Clock.

The device should check for this state at intervals not to exceed 10 milliseconds. When the device detects this state, it will begin generating Clock signals and clock in eight data bits and one stop bit. The host changes the Data line only when the Clock line is low, and data is read by the device when Clock is high. This is opposite of what occours in device-to-host communication.

I am not yet sure what this means for our code... But i think it implies that when hosts requests communication, it holds clock low only initialy and then continues to hold data low instead. so if we don't catch the request on clock during the first 100 microseconds it might be missed unless we check the data line as welll. Which is speaking in favor of change that you suggest.

thomotron commented 4 years ago

I strongly recommend that both the clock and data lines be sampled. Assuming the device isn't transmitting anything, there shouldn't be any other reason that the data line is low, so according to the spec we can safely assume that the host is in an RTS state.

From what I can tell, the clock is only pulled low to inhibit communication and force the device to listen, which isn't a problem if it isn't actively transmitting anything, so really it should be looking out for the data line being held low. That also lines up with having to check once every 10ms or less, since the data line should be held low within that period.

Harvie commented 4 years ago

@thomotron thanks for peer review. Fixed in a043002 , closing.