Keyboard inb(0x60) Can not find out key on KeyUp

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
devchild
Posts: 4
Joined: Mon May 30, 2016 2:42 pm

Keyboard inb(0x60) Can not find out key on KeyUp

Post by devchild »

Hi,

I am trying to figure out which key was pressed when the keyboard reports a KeyUp in the status_register.
I can figure out which key is pressed when the key go's down but not when it go's up.

For example when I:
- press 'k'
- then press 'f' without releasing 'k'
- then release 'k'
- then release 'f'

The I get:
- KeyDown 'k'
- KeyDown 'f'
- KeyUp
- KeyUp

The code I use, looks similar to the following:

Code: Select all


static char* _qwertzuiop = "qwertzuiop"; // 0x10-0x1c
static char* _asdfghjkl = "asdfghjkl";
static char* _yxcvbnm = "yxcvbnm";
static char* _num = "123456789";
char keyboard_to_ascii(uint8_t key)
{
	//kprintf("key=0x%x\n", key);
	if(key == 0x1C) return '\n';
	if(key == 0x39) return ' ';
	if(key == 0xE) return '\r';
	if(key == POINT_RELEASED) return '.';
	if(key == SLASH_RELEASED) return '/';
	if(key == ZERO_PRESSED) return '0';
	if(key >= ONE_PRESSED && key <= NINE_PRESSED)
		return _num[key - ONE_PRESSED];
	if(key >= 0x10 && key <= 0x1C)
	{
		return _qwertzuiop[key - 0x10];
	} else if(key >= 0x1E && key <= 0x26)
	{
		return _asdfghjkl[key - 0x1E];
	} else if(key >= 0x2C && key <= 0x32)
	{
		return _yxcvbnm[key - 0x2C];
	}
	return 0;
}


uint8_t status_register = inb(0x64);
if (status_register & (1 << 0))
{
    uint8_t cc = inb(0x60);
    if ((cc & 128) == 128)
    {
      char c = keyboard_to_ascii(cc);
      puts("KeyUp:"); // cc  <=== is the key I pressed.
    }
    else
    {
      char c = keyboard_to_ascii(cc); // <=== is always blank.
      puts("KeyDown:"); // 
    }
}
How can I find out which key was released?
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by Octocontrabass »

What value is key down for the letter "q"?

What value is key up for the letter "q"?

How does your "keyboard_to_ascii" function handle each of those two values?
devchild
Posts: 4
Joined: Mon May 30, 2016 2:42 pm

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by devchild »

Octocontrabass wrote:What value is key down for the letter "q"?

What value is key up for the letter "q"?

How does your "keyboard_to_ascii" function handle each of those two values?

I get 0x90 for 'q' up and 0x10 for 'q' down.
I see where this is going :), looks like I need to write a better keyboard_to_ascii() method.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by Brendan »

Hi,
devchild wrote:I see where this is going :), looks like I need to write a better keyboard_to_ascii() method.
Looks like you need to understand that ASCII is almost completely useless.

If I'm writing a space invaders game and want my spaceship to fire it's main laser weapon while the control key is pressed, which ASCII character do you send for "control pressed" and which ASCII character do you send for "control released"?

What is the ASCII character for "F6", or "PrtScrn", or "alt + q", or "control + 3"?

What are the ASCII characters for this (Hebrew) keyboard:

Image

Think of a keyboard driver as a series of layers. The first layer gets a byte from the keyboard, and doesn't belong in the keyboard driver at all (and belongs in a PS/2 controller driver instead).

The second layer converts those bytes into "key codes" using a state machine. The state machine is needed because some keys send multiple bytes (e.g. pause/break). The "key code" could be a single integer representing where the key is on the keyboard (and at least in theory could literally be the key's location - e.g. "row * 32 + column"). This layer also creates a "flags" that says if the key was pressed or released.

The third layer keeps track of which keys are currently being pressed and which aren't, using (e.g.) a bitfield with 256 bits. If a key is pressed that was already pressed then the key was repeated and wasn't pressed; and this layer would change the "flags" to indicate that (so that the "flags" now contains "pressed/repeated/released").

The fourth layer uses "modifier key data" and "keyboard layout tables"; plus the "key code" and the bitfield of which keys are currently being pressed; to set more flags in the "flags" (based on the "modifier key data") and then use both the "flags" and the "key code" with the "keyboard layout tables" to determine which (hopefully Unicode codepoint) character is involved (if any). Note that there are 2 different types of modifier keys - normal modifier keys (shift, control, alt), and ones that toggle something (capslock, numlock, scrolllock); and for the toggles you need to keep track of its current state and which LED it effects (if any). You can/should assume there may be up to 8 LEDs (where any "modifier toggle key" could effect any of the 8 LEDs). Both the "modifier key data" and the "keyboard layout tables" need to be pure data without any code; because (later on) these will be loaded from disk (and will be different for different keyboard layouts).

The fifth layer sends the entire resulting packet of information to a normal process (e.g. to GUI, to terminal emulator, etc). This "keypress packet" includes the original key code, the Unicode codepoint (if any), plus the "flags". The "flags" contains the pressed/repeated/released (from 2nd and 3rd layer), plus one bit per modifier key (from 4th layer).

You might also want to provide a way for software to ask the driver if a key is currently being held down (e.g. "bool isDown(int keycode)"), and to ask the driver what each key looks like (e.g. "string getDescription(keycode)"). To understand this, imagine a game that uses the key at "row=1, column=2" for forward, and the 3 keys at "row = 2, column = 1 to 3" for left/backward/right. Normally it doesn't care what these keys are (only the key's location/key code matters); but in its "keyboard settings" menu (and/or in its help system) it might want to display which keys the player should use to play the game - for a QWERTY keyboard it'd want to display "WASD", for an AZERTY keyboard it'd want to display "ZQSD", for Dvorack it'd want to display ",AOE", for French BEPO it'd want to display "EAUI", for Turkish F it would want to display "GUIE", etc. If the game can ask the keyboard driver what to display it makes things so much easier.


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.
devchild
Posts: 4
Joined: Mon May 30, 2016 2:42 pm

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by devchild »

Yeah, the conversion method is just for debugging purposes.
I just figured out that the keyboard actually sends multiple scan_codes when pressing ALT_GR, etc.
Well, nothing is simple I guess.

I think the multiple layer approach is a good idea for the keyboard.
Does anyone know if there is a scan_code to mac_be(belgian) conversion map available somewhere?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by Brendan »

Hi,
devchild wrote:I think the multiple layer approach is a good idea for the keyboard.
Does anyone know if there is a scan_code to mac_be(belgian) conversion map available somewhere?
There isn't a list of "scancode -> key" tables for all the different keyboard layouts anywhere (that I know of). Instead, most OSs just provide a utility/tool that anyone can use to generate any keyboard layout (and save it in whatever file format the OS's keyboard driver expects). Before a utility/tool exists you end up doing it by hand (which isn't too painful if you're only doing a small number of keyboard layouts).

As far as I know, Apple's "Belgian" keyboard layout is identical to the standard French AZERTY keyboard layout:

Image

Note that the scancodes depend on the key's location and not what is written on it, so if you have have scancode information for US QWERTY it's not hard to figure out what the same scancode would give for French AZERTY.


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.
User avatar
Kazinsal
Member
Member
Posts: 559
Joined: Wed Jul 13, 2011 7:38 pm
Libera.chat IRC: Kazinsal
Location: Vancouver
Contact:

Re: Keyboard inb(0x60) Can not find out key on KeyUp

Post by Kazinsal »

My most hated keyboard layout is the Canadian Multilingual Standard.

Every anglophone Canadian I know (myself included) hates it. I don't know anyone from Quebec who likes it; they use a proper Canadian French keyboard layout. But yet, it comes on every single laptop keyboard sold in Canada so manufacturers don't have to have separate laptop SKUs for Quebec and the rest of Canada.

Image
Post Reply