The usual PC keyboards are capable of producing three sets of scancodes. Writing 0xf0 followed by 1, 2 or 3 to port 0x60 will put the keyboard in scancode mode 1, 2 or 3. Writing 0xf0 followed by 0 queries the mode, resulting in a scancode byte 0x43, 0x41 or 0x3f from the keyboard.
Set 1 contains the values that the XT keyboard (with only one set of scancodes) produced, with extensions for new keys. Someone decided that another numbering was more logical and invented scancode Set 2. However, it was realized that new scancodes would break old programs, so the keyboard output was fed to a 8042 microprocessor on the motherboard that could translate Set 2 back into Set 1. Indeed a smart construction. This is the default today. Finally there is the PS/2 version, Set 3, used by nobody.
Sets 2 and 3 are designed to be translated by the 8042. Set 1 should not be translated.
Not all keyboards support all scancode sets. For example, my MyCom laptop only supports scancode Set 2, and its keyboard does not react at all when in mode 1 or 3.
The key press / key release is coded as follows: For Set 1, if the make code of a key is c, the break code will be c+0x80. If the make code is e0 c, the break code will be e0 c+0x80. The Pause key has make code e1 1d 45 e1 9d c5 and does not generate a break code. For Set 2, if the make code of a key is c, the break code will be f0 c. If the make code is e0 c, the break code will be e0 f0 c. The Pause key has make code e1 14 77 e1 f0 14 f0 77. For Set 3, by default most keys do not generate a break code - only CapsLock, LShift, RShift, LCtrl and LAlt do. (On Microsoft keyboards, also LWin, RWin, Menu, Back, Forward, Stop, Mail, Search, Favorites, Web/Home, MyComputer, Calculator, Sleep do. On a BTC keyboard, also the Macro key does.) However, in Scancode Mode 3 it is possible to enable or disable key repeat and the production of break codes either on a key-by-key basis or for all keys at once. And just like for Set 2, key release is indicated by a f0 prefix in those cases where it is indicated. There is nothing special with the Pause key in scancode mode 3.
The 8042 microprocessor translates the incoming byte stream produced by the keyboard, and turns an f0 prefix into an OR with 80 for the next byte. (Some implementations do this for the next byte that does not have this bit set already. A consequence is that in Set 3 the keys with Set-3 value 0x80 or more are broken in a peculiar way: hitting such a key and then some other key turns the make code for this last key into a break code. For example the Sleep key on a Microsoft Internet keyboard generates 54 / d4 for press/release. But pressing and releasing first Menu and then Sleep produces 8d 8d d4 d4 as translation of 8d f0 8d 54 f0 54. Other implementations are OK.)
Unless told not to translate, the keyboard controller translates kscancodes into scancodes using the following table (in hex):
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f |
00 | ff | 43 | 41 | 3f | 3d | 3b | 3c | 58 | 64 | 44 | 42 | 40 | 3e | 0f | 29 | 59 |
10 | 65 | 38 | 2a | 70 | 1d | 10 | 02 | 5a | 66 | 71 | 2c | 1f | 1e | 11 | 03 | 5b |
20 | 67 | 2e | 2d | 20 | 12 | 05 | 04 | 5c | 68 | 39 | 2f | 21 | 14 | 13 | 06 | 5d |
30 | 69 | 31 | 30 | 23 | 22 | 15 | 07 | 5e | 6a | 72 | 32 | 24 | 16 | 08 | 09 | 5f |
40 | 6b | 33 | 25 | 17 | 18 | 0b | 0a | 60 | 6c | 34 | 35 | 26 | 27 | 19 | 0c | 61 |
50 | 6d | 73 | 28 | 74 | 1a | 0d | 62 | 6e | 3a | 36 | 1c | 1b | 75 | 2b | 63 | 76 |
60 | 55 | 56 | 77 | 78 | 79 | 7a | 0e | 7b | 7c | 4f | 7d | 4b | 47 | 7e | 7f | 6f |
70 | 52 | 53 | 50 | 4c | 4d | 48 | 01 | 45 | 57 | 4e | 51 | 4a | 37 | 49 | 46 | 54 |
80 | 80? | 81 | 82 | 41 | 54 | 85 | 86 | 87 | 88 | 89 | 8a | 8b | 8c | 8d | 8e | 8f |
90 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 9a | 9b | 9c | 9d | 9e | 9f |
a0 | a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | aa | ab | ac | ad | ae | af |
b0 | b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | ba | bb | bc | bd | be | bf |
c0 | c0 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | ca | cb | cc | cd | ce | cf |
d0 | d0 | d1 | d2 | d3 | d4 | d5? | d6? | d7 | d8 | d9? | da? | db | dc | dd | de? | df |
e0 | e0 | e1 | e2? | e3? | e4? | e5 | e6 | e7? | e8 | e9 | ea | eb | ec | ed? | ee? | ef? |
f0 | - | f1? | f2? | f3? | f4? | f5? | f6? | f7? | f8? | f9? | fa? | fb? | fc? | fd? | fe? | ff |
A reference for the first half of this table is the book by Gary J Konzak
PC 8042 Controller, ISBN 0-929392-21-3.
(Report by vojtech@suse.cz
.)
A way to check this table is: (i) put the keyboard in untranslated modes 1, 2, 3 and look at the resulting values, and (ii) put the keyboard in translated scancode modes 1, 2, 3. Now compare the values. The entries with question marks were not checked in this way.
Note that the range 01-7f of this table is 1-1. In the second half of the table, translated and untranslated values are equal in all known cases, with the two exceptions 83 and 84.
One asks the controller to transmit untranslated scancodes by writing a keyboard controller command with bit 5 set and bit 6 cleared. E.g., use the command byte 45 to get translated codes, and 24 to get untranslated codes that do not cause interrupts.
Can these other scancode sets be used? Probably not.
(i) My MyCom laptop does not support scancode sets 1 and 3 at all.
(ii) Some laptops have special key combinations that bring one into a setup or configuration utility. It is impossible to do anything useful, or to get out of it again, when the scancode mode is not translated Set 2.
(iii) Many keyboards have bugs in scancode sets 1 and/or 3 but are fine in scancode Set 2. Vojtech Pavlik reports that his BTC keyboard has the same codes for the '1' and '2' keys in Set3, both having the code for '1'). On my BTC keyboard the key up value for Esc and 1 are both ff in scancode Set 1.
(iv) A big advantage of Set 3 is that each key generates a unique code so that one does not need to parse sequences. However, the BTC keyboard mentioned above generates e0 6f for its Macro key also in scancode mode 3.
(v) Some keyboard controllers cannot handle Set 3 values that are larger than 0x7f, and give peculiar results for some keys on the Microsoft Internet keyboard in translated scancode mode 3.
(vi) The USB legacy support only supports translated Set 2.
(vii) The Microsoft Keyboard Scan Code Specification writes: In the very early days of Windows NT, an attempt was made to use the much more orthogonal Scan Code Set 3, but due to bugs in the implementation of this Scan Code Set on numerous OEM keyboards, the idea was abandoned. And also Scan Code Set 3 is not used or required for operation of Microsoft operating systems.