Page 1 of 1

Help reading line input from keyboard

Posted: Mon Oct 30, 2017 9:31 pm
by thumble
So, I've recently picked up OS development again, and decided to add basic command functionality to my OS.
Here is the code I have so far:

Code: Select all

char buf[1024];
short index;

/* initialize the above variables w/ memset, index=0 */

void kb_irq_handler(struct regs *r) {
    uint8_t scancode = inb(0x60);
    char c = scanToAscii(scancode);
    putchar(c);

    if(index == 1023) {
        print("Buffer overflow!");
        memset(&buf, '\0', 1024);
        index = 0;
        return;
    } else if(c == '\n') {
        buf[index] = '\0';
        test();
        index = 0;
        memset(&buf, '\0', 1024);
    } else {
        buf[index] = c;
        index++;
    }
}

void test() {
    char* str = &buf;
    writestring(buf);
    writestring("\n$ ");
}
This code is meant to read a line and print that out again, but it doesn't work that way, and I'm reasonably sure it's not actually reading a line. Using the QEMU monitor, I printed out the data at buf; it seems to be just junk data. I'm quite sure there's a dumb mistake in my code, but not sure where it is. Could someone help point out where I'm blundering?

Re: Help reading line input from keyboard

Posted: Mon Oct 30, 2017 10:06 pm
by thumble
EDIT:
It turns out that somehow index was incremented twice..?
By adding another conditional I fixed it.
I'm not too sure how this works, but here is the updated function (with much omitted code):

Code: Select all

if(index == 1023) {
    print("Buffer overflow!");
    ...
} else if(c == '\n') {
    buf[index] = '\0';
    ...
} else if(c == '\0') {
    buf[index] = ' ';  /* ?? fixed  it */
} else {
    buf[index] = c;
    ++index;
}

Re: Help reading line input from keyboard

Posted: Mon Oct 30, 2017 10:07 pm
by Brendan
Hi,
thumble wrote:So, I've recently picked up OS development again, and decided to add basic command functionality to my OS.
Here is the code I have so far:

Code: Select all

char buf[1024];
short index;

/* initialize the above variables w/ memset, index=0 */

void kb_irq_handler(struct regs *r) {
    uint8_t scancode = inb(0x60);
    char c = scanToAscii(scancode);
    putchar(c);

    if(index == 1023) {
        print("Buffer overflow!");
        memset(&buf, '\0', 1024);
        index = 0;
        return;
    } else if(c == '\n') {
        buf[index] = '\0';
        test();
        index = 0;
        memset(&buf, '\0', 1024);
    } else {
        buf[index] = c;
        index++;
    }
}

void test() {
    char* str = &buf;
    writestring(buf);
    writestring("\n$ ");
}
This code is meant to read a line and print that out again, but it doesn't work that way, and I'm reasonably sure it's not actually reading a line. Using the QEMU monitor, I printed out the data at buf; it seems to be just junk data. I'm quite sure there's a dumb mistake in my code, but not sure where it is. Could someone help point out where I'm blundering?
For a random estimate; I'd say that for about 85% of the bytes the keyboard can send it's impossible to convert them to ASCII. Some are control bytes ("resent", "BAT response"), almost half are "key released", a lot are special keys (like "shift key pressed" or "F3 key pressed" or "PageUp key pressed"), and a lot are just pieces of a multi-byte scancode.

For all of these bytes that are impossible to convert to ASCII, you convert them to ASCII.

Note: Building command functionality inside the keyboard IRQ handler is a massive mistake most often caused by implementing a keyboard driver before you have the necessary framework (memory management, event handling, etc).


Cheers,

Brendan

Re: Help reading line input from keyboard

Posted: Mon Oct 30, 2017 10:27 pm
by thumble
Duly noted. Thank you.

Re: Help reading line input from keyboard

Posted: Mon Oct 30, 2017 11:14 pm
by thumble
Oh, now I know why the fix works!
In scanToAscii(), a non-ASCII value sets a boolean for it and returns a null that shouldn't be printed! This prematurely terminates the string.
[facepalm]