Use of shift with keyboard

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
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Use of shift with keyboard

Post by jrothwell »

EDIT: Just as a side note, due to the fact that I'm not using this as my actual OS project, existing drivers that work in the same way as Bran's would be fine, as I would be able to see how the driver accomplishes using shift.

Hi there,

I'm rather new to OS development.
I am currently using Bran's tutorial as a start point, and once I understand everything in there, I will write my own from scratch.

However, I have come to a problem...

kb.c

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 <system.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 = inportb(0x60);

    /* If the top bit of the byte we read from the keyboard is
    *  set, that means that a key has just been released */
    if (scancode & 0x80)
    {
        /* You can use this one to see if the user released the
        *  shift, alt, or control keys... */
    }
    else
    {
        /* 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 */
        putch(kbdus[scancode]);
    }
}

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    irq_install_handler(1, keyboard_handler);
}
Right, basically, I can't see a way to read whether or not shift is being held down, and how to then use an upper case letter. I know that LSHIFT's scancode number is 42, but how would I go about reading if it is being held down?

I have read everywhere that I can, tried many different tags in google etc., so if somebody could give me a hand, or point me in the direction of a tutorial on this, it would be a great help...

Thanks in advance,
Joe
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Use of shift with keyboard

Post by bewing »

You have to keep track of keyups as well as keydowns. Left shift key goes down -- set a global bitflag or two. Handler IRETs. Right shift key goes down, set an additional bitflag. IRET. Left shift key goes up -- clear a bitflag. IRET. Right shift goes up -- clear the last bitflags. If a "shift" bitflag is set, you use a different or additional mapping step to get to shifted-ascii, which may or may not be part of the interrupt handler -- and the shifted ascii value may be returned in addition to the unshifted value.
User avatar
salil_bhagurkar
Member
Member
Posts: 261
Joined: Mon Feb 19, 2007 10:40 am
Location: India

Re: Use of shift with keyboard

Post by salil_bhagurkar »

If you know the scancode, then you just need to check when it appears. When it does, set a flag. There will be another scancode for the release of the shift key (IMHO 0x80 anded with the press scancode). When this appears, you clear the flag. When the flag is set, and some other key comes in, you know that it has appeared with shift pressed.
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Re: Use of shift with keyboard

Post by jrothwell »

Hi there again:

Basically, I tried a few things with no success,
and then tried this:

Code: Select all

#include <system.h>


unsigned char kbdusnsh[128] =
{
    -1,  27, '1', '2', '3', '4', '5', '6', '7', '8',	/* 9 */
  '9', '0', '-', '=', '\b', '\t',
  'q', 'w', 'e', 'r',
  '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 */
    58,	/* 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 */
   
};

	unsigned char kbdusysh[128] =
{
 0,  0, '!', '"', '£', '$', '%', '^', '&', '*',	/* 9 */
  '(', ')', '_', '+', '\b', '\t',
  'Q', 'W', 'E', 'R',
  'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',		/* Enter key */
    0,			/* 29   - Control */
  'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';',	/* 39 */
 '|', '¬',   42,		/* Left shift */
 '\\', 'Z', 'X', 'C', 'V', 'B', 'N',			/* 49 */
  'M', '<', '>', '?',   0,					/* Right shift */
  0,
    0,	/* Alt */
  ' ',	/* Space bar */
    58,	/* 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;
    int lshiftpress;
    /* Read from the keyboard's data buffer */
    scancode = inportb(0x60);

    /* If the top bit of the byte we read from the keyboard is
    *  set, that means that a key has just been released */
    while ((scancode == 42) & 0x1C)
    {
        lshiftpress = 1;

    }
    while ((scancode == 42) & 0x80)
	{
		lshiftpress = 0;
	}
	
    if (scancode & 0x80)
	{
	}
    {
        /* 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 */

	if (lshiftpress == 1)
	{
        putch(kbdusysh[scancode]);
	
	}
	else if (lshiftpress == 0)
	{
	putch(kbdusnsh[scancode]);
	}
    }
}

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    irq_install_handler(1, keyboard_handler);
}
and now I have this problem...
When shift isn't pressed, if I press "a" it shows on screen as "aA", and if I have shift pressed, it shows "aA*".

I'm not getting this at all... would someone mind going into a little more detail? ><

Sorry... and thanks again...
Joe
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Use of shift with keyboard

Post by Troy Martin »

I'm having a similar problem in my assembly language OS (although, no uppercase comes out and the star is big and centred.) I'm guessing the issue is the same, so I'll just wait for the outcome and adapt it.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Re: Use of shift with keyboard

Post by jrothwell »

The star is big and centered for me as well, although I just think this is the default font...

I'm not sure how to do this, but it seems to me like its printing both kbdusysh and kbdusnsh... for me as well, when I press shift but without pressing anything else, when I release I get the star...
Obviously the shift key is corresponding to * for some reason, and I haven't solved my problem of capital/lower, instead I am now printing both...
Seemingly my lshiftpress variable isn't working, so I'm stuck completely...
What I was trying to do with this was:
if shift is pressed, lshiftpress is true, and therefore use kbdusysh for printing, and if it isn't pressed, lshiftpress is false and therefore use kbdusnsh for printing... its using both though...

I'm going to try and work on it overnight...
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Use of shift with keyboard

Post by Troy Martin »

The star appears to be some kind of control code, as another asterisk is something else entirely.
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Re: Use of shift with keyboard

Post by jrothwell »

It is 2:40AM here in the UK and I haven't gotten any further...

Would someone please go into a little more detail or give a link or something?

Thanks,

Joe
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Use of shift with keyboard

Post by pcmattman »

Your handler is wrong.

Try something more like this:

Code: Select all

/* Handles the keyboard interrupt */
void keyboard_handler(struct regs *r)
{
    unsigned char scancode;
    static int lshiftpress = 0; // will persist across all calls of the handler
	
    /* Read from the keyboard's data buffer */
    scancode = inportb(0x60);

    /* If the top bit of the byte we read from the keyboard is
     *  set, that means that a key has just been released 
	 */
	if(scancode & 0x1C)
	{
		if(scancode == 42)
			lshiftpress = 1;
	}
	
	if(scancode & 0x80)
	{
		if(scancode == 42)
		{
			lshiftpress = 0;
		}
		else
		{
			if(lshiftpress)
				putch(kbdusysh[scancode]);
			else
				putch(kbdusnsh[scancode]);
		}
	}
}
I can't say for certain it'll work, but I hope you can see what's different and at least pick up the basic idea behind it.
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Re: Use of shift with keyboard

Post by jrothwell »

@pcmattman:
This gave a strange different problem...
Now when I load what I get is this scenario:
1) it uses my shift characters without shift being pressed,
2) I can type for as long as I want like this,
3) When I hit shift, it stops being able to type anything... even when released...

There is one good thing: it got rid of the asterisk xD

On a serious note though, some questions about your code there:
Why "if (scancode & 0x1C);" ? I thought that 0x1C refers to the make for "A"...

Also... am I supposed to be using 0x12 for the L_Shift key, rather than 42? 42 is it's number according to the layout, but its make scancode is 0x12...

I'm really tired xD it is 3:15AM, and I have work at 6:45AM XD

Anyway, if anyone has any tips please feel free to leave them... I'm going to sleep now...

Night all,
thanks again

Joe
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Use of shift with keyboard

Post by pcmattman »

Ok. As I said, I wasn't sure if it would actually work - it was more or less a conceptual thing.

The basic outline should be something more like:

Code: Select all

void key_handler()
{
    static int lshiftpressed = 0;
    unsigned char scancode;

    scancode = inb(0x60);

    if(scancode & 0x80)
    {
        // Handle key up event - check that SHIFT isn't pressed anymore
    }
    else
    {
        // Handle key down event - check for SHIFT for example
    }
}
In both event sections you handle the incoming scancode. Also, IIRC, for the key up event, you will need to remove the 0x80 from the scancode, or else when you use it as an offset into your 128 byte scancode -> ASCII translation table you'll be working from the end of the array :)
User avatar
salil_bhagurkar
Member
Member
Posts: 261
Joined: Mon Feb 19, 2007 10:40 am
Location: India

Re: Use of shift with keyboard

Post by salil_bhagurkar »

Okay, why don't you get a bit crude and just print out the scancodes in the handler and observe what is happening? Print out the scancodes, then add condition for the shift key you see. Then start coding to your normal handler step by step, observing the debug output at each stage.

This should tell you exactly which condition is failing.
jrothwell
Posts: 6
Joined: Thu May 14, 2009 10:16 am

Re: Use of shift with keyboard

Post by jrothwell »

I have decided to review the majority of the C language again before coming back to this project; I guess I missed some valuable points and so I need to fill in the gaps.
Equally, I think that I am going to learn ASM fully, and start reading as many OS Development theory articles, how systems work etc again.

There is no point trying to do something this complex with a limited knowledge of what you are doing.

Sorry to have wasted everybody's time; see you in a few weeks when I have relearnt what I need to.

Thanks,
Joe
Post Reply