Page 2 of 4

Re: Keyboard decoder logic

Posted: Thu Jan 26, 2017 9:49 pm
by Brendan
Hi,
octacone wrote:My keyboard is an USB keyboard, which means that I don't use that port at all.
Your keyboard is a USB keyboard, and therefore you probably shouldn't be using it for testing PS/2 drivers in the first place.

The firmware's code to do "legacy emulation for USB" (which you're relying on now) is almost always minimal and/or buggy, and this prevents an OS from doing adequate PS/2 controller initialisation and testing reliably. In addition to that, USB keyboard and USB mouse can have multiple modes - e.g. a "normal mode" where all of the device's features can be used and a (technically optional) "boot device mode" where the protocol the device uses is restricted to a standardised minimum set of features (to make it easier for the firmware's "legacy emulation of USB" code).
octacone wrote:When I checked all the scan codes I got, they corresponded to the first keyboard layout set. Doesn't disabling it mean that I will get a whole other set of key codes that I will have to map, bummer.
You checked all the scan codes that you got; and because your PS/2 controller initialisation is bad (and doesn't disable "scancode translation") you ended up getting scancode set 1 (even though keyboard is using scancode set 2).

For real PS/2 devices; if a keyboard only supports scancode set 2 and that keyboard is plugged into the 2nd PS/2 port (where the PS/2 controller doesn't support scancode translation); then there is only one possible choice. If you use scancode set 2 then you can cover all possible scenarios. If you try to use scancode set 1 then you will have to support scancode set 2 for some cases (or fail to support those cases).
octacone wrote:Am I handling those multi bytes the right way?
You mostly want a state machine to decode scancodes. For scancode set 1 the states would be:
  • state 0: no escape sequence bytes yet
    state 1: 0xE0 was received
    state 2: 0xE0, 0x2A was received (first 2 bytes of "print screen pressed")
    state 3: 0xE0, 0x2A, 0xE0 was received (first 3 bytes of "print screen pressed")
    state 4: 0xE0, 0xB7 was received (first 2 bytes of "print screen released")
    state 5: 0xE0, 0xB7, 0xE0 was received (first 3 bytes of "print screen released")
    state 6: 0xE1 was received
    state 7: 0xE1, 0x1D was received (first 2 bytes of "pause")
    state 8: 0xE1, 0x1D, 0x45 was received (first 3 bytes of "pause")
    state 9: 0xE1, 0x1D, 0x45, 0xE1 was received (first 4 bytes of "pause")
    state 10: 0xE1, 0x1D, 0x45, 0xE1, 0x9D was received (first 5 bytes of "pause")
For scancode set 2 the states would be:
  • state 0: no escape sequence bytes yet
    state 1: 0xE0 was received
    state 2: 0xE0, 0xF0 was received
    state 3: 0xF0 was received
    state 4: 0xE0, 0x12 was received (first 2 bytes of "print screen pressed")
    state 5: 0xE0, 0x12, 0xE0 was received (first 3 bytes of "print screen pressed")
    state 6: 0xE0, 0xF0, 0x7C was received (first 3 bytes of "print screen released")
    state 7: 0xE0, 0xF0, 0x7C, 0xE0 was received (first 4 bytes of "print screen released")
    state 8: 0xE0, 0xF0, 0x7C, 0xE0, 0xF0 was received (first 5 bytes of "print screen released")
    state 9: 0xE1 was received
    state 10: 0xE1, 0x14 (first 2 bytes of "pause")
    state 11: 0xE1, 0x14, 0x77 (first 3 bytes of "pause")
    state 12: 0xE1, 0x14, 0x77, 0xE1 (first 4 bytes of "pause")
    state 13: 0xE1, 0x14, 0x77, 0xE1, 0xF0 (first 5 bytes of "pause")
    state 14: 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14 (first 6 bytes of "pause")
    state 15: 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0 (first 7 bytes of "pause")
Each time you receive a byte, you use the current state and the received byte to determine the new state. For example, if you've received the byte 0x12 and you're in "state 15" (for scancode set 2) then something has gone wrong because that's not a valid byte for "state 15" (even though 0x12 is a valid byte for other states).

On top of that; you may receive any of the "special bytes" listed here at any time (even when you're in the middle of receiving a multi-byte scan code). Most of these indicate some sort of problem and either causes your state machine to be reset (because driver re-tested and reset the device), or causes your driver to tell the OS "device is faulty" and terminate itself. Some of the special bytes (command acknowledged, command needs to be resent and echo) don't effect the state machine.


Cheers,

Brendan

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 10:04 am
by Octacone
Brendan wrote:Hi,
octacone wrote:My keyboard is an USB keyboard, which means that I don't use that port at all.
Your keyboard is a USB keyboard, and therefore you probably shouldn't be using it for testing PS/2 drivers in the first place.

The firmware's code to do "legacy emulation for USB" (which you're relying on now) is almost always minimal and/or buggy, and this prevents an OS from doing adequate PS/2 controller initialisation and testing reliably. In addition to that, USB keyboard and USB mouse can have multiple modes - e.g. a "normal mode" where all of the device's features can be used and a (technically optional) "boot device mode" where the protocol the device uses is restricted to a standardised minimum set of features (to make it easier for the firmware's "legacy emulation of USB" code).
octacone wrote:When I checked all the scan codes I got, they corresponded to the first keyboard layout set. Doesn't disabling it mean that I will get a whole other set of key codes that I will have to map, bummer.
You checked all the scan codes that you got; and because your PS/2 controller initialisation is bad (and doesn't disable "scancode translation") you ended up getting scancode set 1 (even though keyboard is using scancode set 2).

For real PS/2 devices; if a keyboard only supports scancode set 2 and that keyboard is plugged into the 2nd PS/2 port (where the PS/2 controller doesn't support scancode translation); then there is only one possible choice. If you use scancode set 2 then you can cover all possible scenarios. If you try to use scancode set 1 then you will have to support scancode set 2 for some cases (or fail to support those cases).
octacone wrote:Am I handling those multi bytes the right way?
You mostly want a state machine to decode scancodes. For scancode set 1 the states would be:
  • state 0: no escape sequence bytes yet
    state 1: 0xE0 was received
    state 2: 0xE0, 0x2A was received (first 2 bytes of "print screen pressed")
    state 3: 0xE0, 0x2A, 0xE0 was received (first 3 bytes of "print screen pressed")
    state 4: 0xE0, 0xB7 was received (first 2 bytes of "print screen released")
    state 5: 0xE0, 0xB7, 0xE0 was received (first 3 bytes of "print screen released")
    state 6: 0xE1 was received
    state 7: 0xE1, 0x1D was received (first 2 bytes of "pause")
    state 8: 0xE1, 0x1D, 0x45 was received (first 3 bytes of "pause")
    state 9: 0xE1, 0x1D, 0x45, 0xE1 was received (first 4 bytes of "pause")
    state 10: 0xE1, 0x1D, 0x45, 0xE1, 0x9D was received (first 5 bytes of "pause")
For scancode set 2 the states would be:
  • state 0: no escape sequence bytes yet
    state 1: 0xE0 was received
    state 2: 0xE0, 0xF0 was received
    state 3: 0xF0 was received
    state 4: 0xE0, 0x12 was received (first 2 bytes of "print screen pressed")
    state 5: 0xE0, 0x12, 0xE0 was received (first 3 bytes of "print screen pressed")
    state 6: 0xE0, 0xF0, 0x7C was received (first 3 bytes of "print screen released")
    state 7: 0xE0, 0xF0, 0x7C, 0xE0 was received (first 4 bytes of "print screen released")
    state 8: 0xE0, 0xF0, 0x7C, 0xE0, 0xF0 was received (first 5 bytes of "print screen released")
    state 9: 0xE1 was received
    state 10: 0xE1, 0x14 (first 2 bytes of "pause")
    state 11: 0xE1, 0x14, 0x77 (first 3 bytes of "pause")
    state 12: 0xE1, 0x14, 0x77, 0xE1 (first 4 bytes of "pause")
    state 13: 0xE1, 0x14, 0x77, 0xE1, 0xF0 (first 5 bytes of "pause")
    state 14: 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14 (first 6 bytes of "pause")
    state 15: 0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0 (first 7 bytes of "pause")
Each time you receive a byte, you use the current state and the received byte to determine the new state. For example, if you've received the byte 0x12 and you're in "state 15" (for scancode set 2) then something has gone wrong because that's not a valid byte for "state 15" (even though 0x12 is a valid byte for other states).

On top of that; you may receive any of the "special bytes" listed here at any time (even when you're in the middle of receiving a multi-byte scan code). Most of these indicate some sort of problem and either causes your state machine to be reset (because driver re-tested and reset the device), or causes your driver to tell the OS "device is faulty" and terminate itself. Some of the special bytes (command acknowledged, command needs to be resent and echo) don't effect the state machine.


Cheers,

Brendan
I don't really have a choice since my only option is an USB keyboard. I do have PS/2 keyboards but not a place to plug them into. Not initializing them properly? Okay I will take a look into that, also I will let it use the second key set. I really really want to get this done properly. So I will give myself some time to do everything as it is supposed to be done. Are there any detailed PS/2 initialization documents? Right now I am not handling special bytes at all.

@dozniak @MichaelFarthing @Octocontrabass
I am quite shocked! :o I thought that was the way of handling multi bytes. Looks like I screwed something up. Then how am I supposed to handle them after all?

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 10:41 am
by Brendan
Hi,
octacone wrote:I don't really have a choice since my only option is an USB keyboard. I do have PS/2 keyboards but not a place to plug them into. Not initializing them properly? Okay I will take a look into that, also I will let it use the second key set. I really really want to get this done properly.
If you don't have PS/2 (and only have USB emulating PS/2 badly) and do PS/2 initialisation properly, you probably won't be able to test your code properly (and if you do test your code you won't know if any problems are because of your code or because of the firmware).
octacone wrote:Are there any detailed PS/2 initialization documents?
Yes - the wiki page has a relatively thorough description of initialising the PS/2 controller.


Cheers,

Brendan

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 10:53 am
by dozniak
octacone wrote: Then how am I supposed to handle them after all?
EXACTLY as described in the Brendan post you over-quoted above. Did you even read it?

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 10:59 am
by Octacone
Brendan wrote:Hi,
octacone wrote:I don't really have a choice since my only option is an USB keyboard. I do have PS/2 keyboards but not a place to plug them into. Not initializing them properly? Okay I will take a look into that, also I will let it use the second key set. I really really want to get this done properly.
If you don't have PS/2 (and only have USB emulating PS/2 badly) and do PS/2 initialisation properly, you probably won't be able to test your code properly (and if you do test your code you won't know if any problems are because of your code or because of the firmware).
octacone wrote:Are there any detailed PS/2 initialization documents?
Yes - the wiki page has a relatively thorough description of initialising the PS/2 controller.


Cheers,

Brendan
:( That is really disappointing. Even if I make it all work I won't know for sure. That is my only option then. What about a laptop keyboard, what kind of an interfaces does it use internally?

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 11:01 am
by Octacone
dozniak wrote:
octacone wrote: Then how am I supposed to handle them after all?
EXACTLY as described in the Brendan post you over-quoted above. Did you even read it?
Sure I did. But HOW TO HANDLE MULTIPLE BYTES when I am only getting one specific hexadecimal value? Not getting that concept. :? What those states are??? How to get 7 scan codes when I am only getting one per interrupt? Do you even understand what I am saying?

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 11:07 am
by Brendan
Hi,
octacone wrote: :( That is really disappointing. Even if I make it all work I won't know for sure. That is my only option then. What about a laptop keyboard, what kind of an interfaces does it use internally?
That depends on the laptop. Some use USB, some use PS/2 (and some do dodgy stuff with "auto-PS/2-port switching", and usually there's a touchpad and no mouse).


Cheers,

Brendan

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 11:20 am
by Brendan
Hi,
octacone wrote:Sure I did. But HOW TO HANDLE MULTIPLE BYTES when I am only getting one specific hexadecimal value? Not getting that concept. :? What those states are??? How to get 7 scan codes when I am only getting one per interrupt? Do you even understand what I am saying?
Like...

Code: Select all

    switch(state) {
    case 0:
        switch(receivedByte) {
            case 0xE1:
                state = 9;      // 0xE1 was received
                return;
            default:
                handleUnexpected();
                return;
        }
        break;
    case 9:      // 0xE1 was received
        switch(receivedByte) {
            case 0x14:
                state = 10;     // 0xE1,0x14 was received
                return;
            default:
                handleUnexpected();
                return;
        }
        break;
    case 10:     // 0xE1,0x14 was received
        switch(receivedByte) {
            case 0x77:
                state = 11;     // 0xE1,0x14,0x77 was received
                return;
            default:
                handleUnexpected();
                return;
        }
        break;
    case 11:     // 0xE1,0x14,0x77 was received
        switch(receivedByte) {
            case 0xE1:
                state = 12;     // 0xE1,0x14,0x77,0xE1 was received
                return;
            default:
                handleUnexpected();
                return;
        }
        break;

    case 15:     // 0xE1,0x14,0x77,0xE1,0xF0,0x14,0xF0 was received
        switch(receivedByte) {
            case 0x77:     // 0xE1,0x14,0x77,0xE1,0xF0,0x14,0xF0,0x77 (entire "pause" scancode)
                handleKeycode(KEYCODE_PAUSE, PRESSED);
                handleKeycode(KEYCODE_PAUSE, RELEASED);
                state = 0;
                return;
            default:
                handleUnexpected();
                return;
        }
        break;
Of course I missed a lot of cases, and you'll want to use lookup tables to simplify some of the cases (otherwise your "switch()" will be massive).

Note that you can do something like "switch( state << 8 | receivedByte) {" so that there's only one "switch()"; and if you really want you can just have a big lookup table and do something like:

Code: Select all

    temp =  state << 8 | receivedByte;
    state = lookupTable[temp].nextState;
    if(state == 0) {    // Must've got the whole scancode
        keycode = lookupTable[temp].keycode;
        flags = lookupTable[temp].flags;
        if(flags says it was pressed) {
            handleKeycode(keycode, PRESSED);
        }
        if(flags says it was released) {
            handleKeycode(keycode, RELEASED);
        }

Cheers,

Brendan

Re: Keyboard decoder logic

Posted: Sat Jan 28, 2017 7:01 pm
by dozniak
octacone wrote: Sure I did. But HOW TO HANDLE MULTIPLE BYTES when I am only getting one specific hexadecimal value? Not getting that concept. :? What those states are??? How to get 7 scan codes when I am only getting one per interrupt? Do you even understand what I am saying?
You can't handle multiple bytes because you get bytes one at a time from the keyboard controller.

You'll have to save previously received bytes in some sort of "state". Google for Finite State Machine.

Re: Keyboard decoder logic

Posted: Wed Feb 01, 2017 4:23 pm
by Octacone
I will leave that state machine alone for now. Need to take couple of months in order to understand how it works. :oops:

This thing right here is my first direct "text to code" contact: (It surely sucks, but at least it is my own creation)

Code: Select all

-removed-
-old code-
-now it is much better and properly written-
I (mostly) did it as Wiki suggested. How bad is it? It surely is bad since I am not getting any keyboard interrupts cause of that code.

Re: Keyboard decoder logic

Posted: Thu Feb 02, 2017 1:31 am
by FusT
You may be going way too fast for the PS/2 controller.
As I remember from writing my PS/2 driver's initialization routine you should read the answers from the PS/2 controller after sending a command to ensure it acknowledges the command (see the wiki for this).
Also, for some commands (like "disable port X") you should use a wait_and_poll_port kind of method (with a timeout!) to clear the controller's output buffer before sending another command or you'll get some really weird results.

Re: Keyboard decoder logic

Posted: Thu Feb 02, 2017 2:04 am
by Octocontrabass
octacone wrote:How bad is it?
Port 0x20 has nothing to do with the keyboard controller. Perhaps you wanted command 0x20?

Re: Keyboard decoder logic

Posted: Fri Feb 03, 2017 11:46 am
by Octacone
FusT wrote:You may be going way too fast for the PS/2 controller.
As I remember from writing my PS/2 driver's initialization routine you should read the answers from the PS/2 controller after sending a command to ensure it acknowledges the command (see the wiki for this).
Also, for some commands (like "disable port X") you should use a wait_and_poll_port kind of method (with a timeout!) to clear the controller's output buffer before sending another command or you'll get some really weird results.
"Too fast" (working on this for past 2 weeks). :P

Whenever I try to read something, I get nothing. Like no response or wrong response.
I know I should add some timeout but don't know exactly where, like after every write call or only for specific commands.

Re: Keyboard decoder logic

Posted: Fri Feb 03, 2017 11:51 am
by Octacone
Octocontrabass wrote:
octacone wrote:How bad is it?
Port 0x20 has nothing to do with the keyboard controller. Perhaps you wanted command 0x20?
Right now I am talking about the PS/2 controller itself.
I am generally very confused when it comes to PS/2-keyboard port relation. There are so many ports that are the same but do different things. Does any of you know for sure what ports am I supposed to use when reading and writing from/to my PS/2 controller? 0x64 or 0x60 or 0x20 for reading or something else for reading responses? Wiki is kind of messy + there is an edit made by Sortie that talks about wrong response replies and ports.

Re: Keyboard decoder logic

Posted: Fri Feb 03, 2017 11:51 am
by Schol-R-LEA
octacone wrote:
FusT wrote:You may be going way too fast for the PS/2 controller
"Too fast" (working on this for past 2 weeks). :P
I think that FusT meant that your handler is going to fast, not the code development, and is saying that you need to insert a wait of some kind into the code.