PS/2 driver not working as expected

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

PS/2 driver not working as expected

Post by deleted8917 »

I'm trying to add a PS/2 keyboard driver, it reads the keys, but the problem is that returns any character except the one that was pressed on the keyboard.

Code: Select all

#include <stdint.h>
#include "kernel/terminal.h"
#include "kernel/kernel.h"
#include "kernel/pic.h"

int kernelmain(void)
{
    PIC_remap(0x20, 0x28);
    clear_screen();
    textcolor(RED);
    println("Hello protected mode! ");
    textcolor(CYAN);
    println("AAABBBCCC ");
    println("Ñandú áéíóú ");
    outb(0xED, 2); /* Turn on CapsLock LED (doesn't works)*/
    char c = 0;
    while (c != 1)
    {
        if (inb(0x60) != c) /* IF key isn't escape key */
        {
            c = inb(0x60); /* 0x60 returns the pressed key */
            if (c > 0)
                putch(c);
        }
    }
	
	return 0;
}

At first I thought it might be the putch function, but doing some tests, I saw that putch wasn't the problem.
Why doesn't it work?
btw, also I tried with unsigned char c, but it gives a worse result.
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: PS/2 driver not working as expected

Post by Octocontrabass »

Code: Select all

    outb(0xED, 2); /* Turn on CapsLock LED (doesn't works)*/
You can't send commands directly to the keyboard. You must tell the keyboard controller to send the command to the keyboard.
konniskatt wrote:Why doesn't it work?
The keyboard sends scan codes, not characters. You must translate from scan codes to characters in order to display anything.
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: PS/2 driver not working as expected

Post by deleted8917 »

Now I'm trying to write an translator, but I get some problems (again...)

Code: Select all

char scan2char(char scn)
{
    char keych;
    switch (scn)
    {
        case 10:
            keych = 'q';
            break;
        case 11:
            keych = 'w';
            break;
        case 12:
            keych = 'e';
            break;
        case 13:
            keych = 'r';
            break;
        case 14:
            keych = 't';
            break;
        case 15:
            keych = 'y';
            break;
    }
    return keych;
}
It works, except for one thing: the keyboard layout shifted...
e.x: if I press 9 I get q, if I press 0 I get w, you understand.
btw, if it helps, my keyboard layout is the latinoamerican one.
FusT
Member
Member
Posts: 91
Joined: Wed Sep 19, 2012 3:43 am
Location: The Netherlands

Re: PS/2 driver not working as expected

Post by FusT »

https://wiki.osdev.org/PS/2_Keyboard#Scan_Code_Set_2
This is the default scancode set for PS/2 keyboards.
Also, you probably should use a lookup table/matrix instead of abusing switch/case to decode scancodes to ASCII.
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: PS/2 driver not working as expected

Post by deleted8917 »

FusT wrote:https://wiki.osdev.org/PS/2_Keyboard#Scan_Code_Set_2
This is the default scancode set for PS/2 keyboards.
Also, you probably should use a lookup table/matrix instead of abusing switch/case to decode scancodes to ASCII.
Still not working properly...
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: PS/2 driver not working as expected

Post by Octocontrabass »

konniskatt wrote:It works, except for one thing: the keyboard layout shifted...
That's the difference between 10 and 0x10. Also, you really should be using an array lookup for that instead of a switch statement.
FusT wrote:https://wiki.osdev.org/PS/2_Keyboard#Scan_Code_Set_2
This is the default scancode set for PS/2 keyboards.
Yes, but by default the PS/2 controller will translate the scan codes it receives from set 2 to set 1, so all the scan codes you receive from the PS/2 controller will be set 1.

It's possible to reconfigure the PS/2 controller to disable the translation, and it's a good idea to do it in case something other than a keyboard is plugged in. However, most computers are actually emulating the PS/2 controller in firmware to provide USB support, and that emulation doesn't function very well if you try to change any of the defaults. You have to disable the emulation, either by disabling USB legacy support in the BIOS setup or by starting your own USB driver and performing the appropriate handoff. (Be careful: the BIOS setup may require USB legacy support in order to function with a USB keyboard!)
FusT
Member
Member
Posts: 91
Joined: Wed Sep 19, 2012 3:43 am
Location: The Netherlands

Re: PS/2 driver not working as expected

Post by FusT »

konniskatt wrote:Still not working properly...
What is "not working properly"? There really isn't enough information to even start to grasp what's wrong, but I'm guessing it's something to do with the difference between decimal and hexadecimal, as Octocontrabass has pointed out.
Octocontrabass wrote:Yes, but by default the PS/2 controller will translate the scan codes it receives from set 2 to set 1, so all the scan codes you receive from the PS/2 controller will be set 1.
Right, forgot about that. It has been a long time since I touched on the PS/2 controller.
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: PS/2 driver not working as expected

Post by deleted8917 »

I've made it work, I don't know what I did. But the leds on the keyboard still don't work. My question now is: how can I use the modifier keys? (Control, Shift, Alt, Altgr, Function key...)
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: PS/2 driver not working as expected

Post by BenLunt »

konniskatt wrote:I've made it work, I don't know what I did. But the leds on the keyboard still don't work. My question now is: how can I use the modifier keys? (Control, Shift, Alt, Altgr, Function key...)
No offense intended, however, if you are asking this, you still don't understand how you communicate with a keyboard.

The keyboard has absolutely no idea what a "modifier" key is. i.e.: It hasn't a clue what a "shift" key, "ctrl" key, or any other key is, other than it has a "make" code and a "break" code for each key on that keyboard. Period.

Your PS2 driver should simply "monitor" the PS2 port(s) receiving and sending bytes as needed. Nothing more. When a byte is ready to be received from the PS2 hardware, your driver places it in the next position of a FIFO buffer, probably about 64 bytes in size, but can be smaller, or much larger. The same driver monitors a similar buffer and when it receives a byte, your PS2 driver sends it to the controller at the next available instance. That's it. It does nothing more.

You should then have another driver that monitors that 64-byte FIFO buffer. When a byte is placed in it by the PS2 driver, this driver (say a keyboard driver) checks to see if there is a valid make or break code existing in this buffer. If so, it removes it from the buffer and then does some task specific to the make or break code. If this make code is the make code for the Shift key, you then set a flag that the Shift key is down. Then, every other make code that is found, needs to check with this flag to see if you "received" a capital "A" or a small case "a", for example. When the break code for the shift key is found, clear the flag. Same goes for all other "modifier" keys.

Now, there are a few other things you need to know. These make/break codes can be different values for different keyboards. This is why a lookup table was mentioned in a previous post. Once you figure out which keyboard and its scan code set, you then "call" that particular table.

Also, at times, there can be bogus (or unknown) codes placed in the FIFO buffer. After a certain time (specified by how you decided to do it), simply remove these unknown codes (or even single bytes) from the FIFO buffer or you will eventually fill the buffer.

With this technique, the keyboard can be attached via any interface: PS2, AT, USB, whatever, as long as it simply fills a FIFO buffer. The keyboard buffer (you probably ought to call it something else) will simply monitor the FIFO buffer with absolutely no clue to the interface (PS2, AT, or USB). This way, you can have multiple keyboards attached using multiple interfaces.

Also, when this "keyboard driver" (named something else) see's that a Caps Lock make/break has been received, it should send some kind of message to all keyboards so that each keyboard attached sets the LED for that operation, if it has one.

For example, what if I have a keyboard that does not have the normal numbers on the right, like some older keyboards? This keyboard could use the PS2 interface. Then I run down to my local supply shop and buy a cheap num-pad only keyboard that happens to be USB. You now have two keyboards attached, each using a different interface, yet you need you OS to see only one input device interface.

Does this make sense?

Ben

P.S. This is explained in detail in Volume Four of my book series.
- http://www.fysnet.net/osdesign_book_series.htm
Post Reply