Keyboard not working

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
sofferjacob
Posts: 7
Joined: Tue Feb 28, 2017 11:44 am
Libera.chat IRC: sofferjacob

Keyboard not working

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Keyboard not working

Post 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
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.
sofferjacob
Posts: 7
Joined: Tue Feb 28, 2017 11:44 am
Libera.chat IRC: sofferjacob

Re: Keyboard not working

Post 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.
Post Reply