Page 1 of 1

Keyboard not working

Posted: Tue Oct 31, 2017 5:50 pm
by sofferjacob
Hi,
I recently tried to add keyboard support to my kernel. Right now the driver is very similar to the one in Bran's Kernel Development tutorial (I just changed a few things). The keyboard doesn't work, there is no reaction in the kernel when a key is pressed. Still for some reason sometimes it works without me making any changes to the code (I literally don't change the code, I just recompile the kernel). Before you ask:
- Interrupts are enabled.
- The PIT and timers work fine, so I don't think something related to interrupts is the problem.

The code in my keyboard driver is the following:

Code: Select all

/* bkerndev - Bran's Kernel Development Tutorial
*  By:   Brandon F. ([email protected])
*  Desc: Keyboard driver
*
*  Notes: No warranty expressed or implied. Use at own risk. */
#include "hal.h"

/* KBDUS means US Keyboard Layout. This is a scancode table
*  used to layout a standard US keyboard. I have left some
*  comments in to give you an idea of what key is what, even
*  though I set it's array index to 0. You can change that to
*  whatever you want using a macro, if you wish! */
unsigned char kbdus[128] =
    {
        0, 27, '1', '2', '3', '4', '5', '6', '7', '8',    /* 9 */
        '9', '0', '-', '=', '\b',                         /* Backspace */
        '\t',                                             /* Tab */
        'q', 'w', 'e', 'r',                               /* 19 */
        't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',     /* Enter key */
        0,                                                /* 29   - Control */
        'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
        '\'', '`', 0,                                     /* Left shift */
        '\\', 'z', 'x', 'c', 'v', 'b', 'n',               /* 49 */
        'm', ',', '.', '/', 0,                            /* Right shift */
        '*',
        0,   /* Alt */
        ' ', /* Space bar */
        0,   /* Caps lock */
        0,   /* 59 - F1 key ... > */
        0, 0, 0, 0, 0, 0, 0, 0,
        0, /* < ... F10 */
        0, /* 69 - Num lock*/
        0, /* Scroll Lock */
        0, /* Home key */
        0, /* Up Arrow */
        0, /* Page Up */
        '-',
        0, /* Left Arrow */
        0,
        0, /* Right Arrow */
        '+',
        0, /* 79 - End key*/
        0, /* Down Arrow */
        0, /* Page Down */
        0, /* Insert Key */
        0, /* Delete Key */
        0, 0, 0,
        0, /* F11 Key */
        0, /* F12 Key */
        0, /* All other keys are undefined */
};

/* Handles the keyboard interrupt */
void keyboard_handler(struct regs *r)
{
    unsigned char scancode;

    /* Read from the keyboard's data buffer */
    scancode = inb(0x60);
        /* Here, a key was just pressed. Please note that if you
        *  hold a key down, you will get repeated key press
        *  interrupts. */

        /* Just to show you how this works, we simply translate
        *  the keyboard scancode into an ASCII value, and then
        *  display it to the screen. You can get creative and
        *  use some flags to see if a shift is pressed and use a
        *  different layout, or you can add another 128 entries
        *  to the above layout to correspond to 'shift' being
        *  held. If shift is held using the larger lookup table,
        *  you would add 128 to the scancode when you look for it */
        kputc(kbdus[scancode]);
}

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    registerInterruptHandler(IRQ1, keyboard_handler, NF);
}
Thank you in advance for the help.

Re: Keyboard not working

Posted: Tue Oct 31, 2017 7:45 pm
by Brendan
Hi,
sofferjacob wrote:Still for some reason sometimes it works without me making any changes to the code (I literally don't change the code, I just recompile the kernel). Before you ask:
- Interrupts are enabled.
- The PIT and timers work fine, so I don't think something related to interrupts is the problem.
One potential problem goes like this:
  • GRUB displays a menu for you to choose which OS to boot
  • You choose an OS to boot and hit the enter key
  • GRUB prepares to boot the OS, including disabling IRQs
  • You take your finger off of the enter key, causing keyboard to send "enter key released" to the PS/2 controller, which causes an IRQ at the PIC chip (that can't be sent to the CPU yet because IRQs are disabled)
  • The OS reinitialises the PIC chips, causing the pending IRQ to be lost, and leaving a byte stuck in the PS/2 controller's 1-byte buffer
  • Keyboard can't send any new data to PS/2 controller because PS/2 controller's 1-byte buffer is full, and PS/2 controller can't/won't generate a new "byte received" interrupt because it can't receive a new byte
  • The OS doesn't initialise the PS/2 controller properly (and then doesn't initialise the keyboard itself properly); so everything stays jammed up.
If the user takes their finger off of the enter key fast enough the IRQ can occur before GRUB disables IRQs and the problem is avoided; and if the user takes their finger off of the enter key slow enough the IRQ can occur after the OS has reinitialised the PIC chips and the problem is avoided; and because it's a timing problem "fast enough" and "slow enough" depend on how fast CPU and disk are (and typically it breaks for end users, but works fine for developers who are trying to debug it ;) ).

Of course this is just a random guess (only one of the many possible problems).


Cheers,

Brendan

Re: Keyboard not working

Posted: Tue Oct 31, 2017 9:37 pm
by sofferjacob
Hi Brendan,
I tested your theory and indeed when I released the enter key quickly the keyboard was working, although for some reason it is not printing the right letters. Anyways, at least it is working now, I will try to fix the issue with the PS/2 controller in the next few days and if I need any help I will post here.
Again thanks for the help.