Get scancode set command

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
arkady
Posts: 17
Joined: Wed Jan 02, 2008 3:14 pm
Location: Poland

Get scancode set command

Post by arkady »

My keyboard (not usb) gives me weird answer when "get scancode" command is sent (0xf0, 0x00). First byte is acked (0xfa), the second is 0xfe (resend?). On Vmware all I get is 0xfa twice. I am pretty sure it isn't any kind of timing issue - I just wait for bit1 of 0x64 to be cleared before writing commands/data to 0x60. I can read "keyboard controller command byte" (0x20 command) and it returns answer with bit6 set = translation is used. I know that most probably the scancode set used is #2 - I get scancodes exactly the same as those from set #1 not-translated.

Is it common nowadays that keyboards do not support "get scancode set" command? And how do I tell which scancode is used when this command is not working? I can only tell whether translation is on or off (unless command 0x20 "get keyboard controller command byte" is not always supported - is it?). Should I assume set #2 - especially when translation is used and a keyboard does not answer corretly to 0xf0 command?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Get scancode set command

Post by Brendan »

Hi,
arkady wrote:My keyboard (not usb) gives me weird answer when "get scancode" command is sent (0xf0, 0x00). First byte is acked (0xfa), the second is 0xfe (resend?). On Vmware all I get is 0xfa twice. I am pretty sure it isn't any kind of timing issue - I just wait for bit1 of 0x64 to be cleared before writing commands/data to 0x60. I can read "keyboard controller command byte" (0x20 command) and it returns answer with bit6 set = translation is used. I know that most probably the scancode set used is #2 - I get scancodes exactly the same as those from set #1 not-translated.
Some/most keyboards only support scancode set #2, and some keyboards don't support "get scancode set" properly (if at all) or "set scancode set". To make a generic keyboard driver you have no real choice - you need to set scancode set #2 (which always "works", even if it's ignored by the keyboard because it doesn't support scan code sets) and forget about "get scancode set".

If you know exactly which keyboard is plugged in then you can do things a little better - e.g. use a different scancode set if you know the keyboard supports it, and have support any non-standard keys, etc. Unfortunately there's no way to auto-detect the keyboard type properly, so this becomes messy.

Probably the best way to do it is to have a generic keyboard driver which uses scancode set #2 by default, but is capable of switching to other scancodes (if you want that); and use generic tables (that can easily be replaced/customised for specific keyboards) that tells the generic keyboard driver which features the keyboard supports and how to translate scancodes into unicode/keypresses.


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.
arkady
Posts: 17
Joined: Wed Jan 02, 2008 3:14 pm
Location: Poland

Re: Get scancode set command

Post by arkady »

For a simple keyboard driver like mine, supporting set #2 only seems quite reasonable then. Actually, I already have one which handles things like: buffer, multi-key presses, switching leds... Funny thing is that until recently I was sure my keyboard uses set #1. When I finally got to properly initializing the keyboard (which I should do first) it turned out that translated set #2 is used - which I think is the same as un-translated #1 (?).

One more question about keyboard & switching leds. Which is correct handling of CAPS down in keyboard IRQ:
1. receive CAPS down interrupt -> issue 0xed in the same interrupt -> leave interrupt -> wait for 0xfa (ack 0xed) which fires another interrupt -> issue 0x04 in that “next” interrupt (caps led on) -> leave interrupt -> on another interrupt 0xfa (ack 0x04) will be received
2. receive CAPS down interrupt -> issue 0xed, followed by 0x04 in the same interrupt (caps led on) -> leave interrupt -> on next interrupts two 0xfa’s (ack 0xed & 0x04) will be received (?)

Thx for your replies, and Brendan for clarifying things!
Last edited by arkady on Fri Mar 12, 2010 12:17 pm, edited 1 time in total.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Get scancode set command

Post by Brendan »

Hi,
arkady wrote:For a simple keyboard driver like mine, supporting set #2 only seems quite reasonable then. Actually, I already have one which handles things like: buffer, multi-key presses, switching leds... Funny thing is that until recently I was sure my keyboard uses set #1. When I finally got to properly initializing the keyboard (which I should do first) it turned out that translated set #2 is used - which I think is the same as un-translated #1 (?).
For ancient 80x86 computers (e.g. 8086) the keyboard was scancode set #1. For backward compatibility, when IBM added newer keyboards that used/supported scancode set #2 they also added "scancode translation" to the keyboard controller chip (so, the keyboard sends set #2 to the controller, the controller translates to set #1 and old software reads set #1 from keyboard controller). If/when you initialise the keyboard controller you can (optionally) disable this translation.

Basically, you probably were using "set #2 translated to set #1" before, and you may be using "set #2 with no translation" now.
arkady wrote:One more question about keyboard & switching leds. Which is correct handling of CAPS down in keyboard IRQ:
1. receive CAPS down interrupt -> issue 0xed in the same interrupt -> leave interrupt -> wait for 0xfa (ack 0xed) which fires another interrupt -> issue 0x04 in that “next” interrupt (caps led on) -> leave interrupt -> on another interrupt 0xfa (ack 0x04) will be received
2. receive CAPS down interrupt -> issue 0xed, followed by 0x04 in the same interrupt (caps led on) -> leave interrupt -> on next interrupts two 0xfa’s (ack 0xed & 0x04) will be received (?)
From memory: Receive CAPS down interrupt -> issue 0xED followed by "new LED state flags" in the same interrupt -> leave interrupt. On the (hopefully) next interrupt receive one 0xFA (ACK). I don't think you get two ACKs as it's one (2-byte) command (and not two 1-byte commands). Note that the hardware itself is a little racey (you might receive a scancode or something after you sent 0xED but before you receive an ACK).


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.
arkady
Posts: 17
Joined: Wed Jan 02, 2008 3:14 pm
Location: Poland

Re: Get scancode set command

Post by arkady »

Brendan wrote: Basically, you probably were using "set #2 translated to set #1" before...
That's correct. And using set #2 without translation is a thing "to do"... a bit later.
Brendan wrote: From memory: Receive CAPS down interrupt -> issue 0xED followed by "new LED state flags" in the same interrupt -> leave interrupt. On the (hopefully) next interrupt receive one 0xFA (ACK). I don't think you get two ACKs as it's one (2-byte) command (and not two 1-byte commands). Note that the hardware itself is a little racey (you might receive a scancode or something after you sent 0xED but before you receive an ACK).
And this is what I did when implemented "leds" at first - 0xED and "new LED state byte" in one interrupt. But then redesigned it to be 0xED and "new LED state byte" in two separate interrupts. Which, as Brendan wrote, is not necessary (but still works). I checked it and right after sending 0xED byte, bit-1 of 0x64 port is cleared = can send another byte (new LED state) right away.

The only confusing thing is ACKing commands by the keyboard. When CAPS is pressed and released both in "all in one interrupt" scenario ("A") and in "two separate interrupts" scenario ("B"), I get two ACKs (3a fa fa ba). But a weird thing happens when CAPS and NUM (or SCROLL) are pressed almost simultaneously. In "A" scenario I get: 3a 45 fa fa ba c5, although I change the state of LEDs twice and my keyboard usually seems to ACK every byte sent (0xED and "change LED state" byte). In "B" scenario I get: 3a fa 45 fa fa ba c5 (3 ACKs) but LED state is still changed twice. That is quite unexpected behaviour... I think I'm gonna hate my keyboard :wink:

Thanks again for helpful hints, Brendan!
Post Reply