OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 2:31 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 49 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Keyboard decoder logic
PostPosted: Thu Jan 26, 2017 9:49 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 10:04 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 10:41 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 10:53 am 
Offline
Member
Member
User avatar

Joined: Thu Jul 12, 2012 7:29 am
Posts: 723
Location: Tallinn, Estonia
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?

_________________
Learn to read.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 10:59 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 11:01 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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?

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 11:07 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 11:20 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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:
    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:
    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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Sat Jan 28, 2017 7:01 pm 
Offline
Member
Member
User avatar

Joined: Thu Jul 12, 2012 7:29 am
Posts: 723
Location: Tallinn, Estonia
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.

_________________
Learn to read.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Wed Feb 01, 2017 4:23 pm 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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:
-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.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Last edited by Octacone on Sat Feb 04, 2017 4:13 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Thu Feb 02, 2017 1:31 am 
Offline
Member
Member

Joined: Wed Sep 19, 2012 3:43 am
Posts: 91
Location: The Netherlands
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.


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Thu Feb 02, 2017 2:04 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5143
octacone wrote:
How bad is it?

Port 0x20 has nothing to do with the keyboard controller. Perhaps you wanted command 0x20?


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Fri Feb 03, 2017 11:46 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Fri Feb 03, 2017 11:51 am 
Offline
Member
Member
User avatar

Joined: Fri Aug 07, 2015 6:13 am
Posts: 1134
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.

_________________
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader


Top
 Profile  
 
 Post subject: Re: Keyboard decoder logic
PostPosted: Fri Feb 03, 2017 11:51 am 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
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.

_________________
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 49 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 112 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group