Input/Output Device Driver Reference/Keyboard Device Driver

The keyboard physical device driver is separated into two separate drivers: the device-independent driver (KBDBASE.SYS) and the device-dependent driver (IBMKBD.SYS).

The device-independent driver (DI) is OS/2-specific. It handles the monitors, screen groups, code paging, translation, and special needs processing. It also communicates hardware changes with the device-dependent driver through an inter-device-driver communication (IDC) interface.

The device-dependent (DD) driver handles the hardware interrupts and keyboard hardware commands. It also passes scan codes and notifications of a hot plug to the device-independent driver IDC. These drivers function on ISA/EISA or Micro Channel machines.

Overview
The physical keyboard device-dependent driver receives the make-and-break keystroke scan codes along with special keyboard hardware codes. The scan codes are stored until a completed key stroke is received. A key packet is then passed to the device-independent driver which performs one or more of the following operations: (see the following figure):
 * Translates the scan code to an ASCII character
 * Recognizes the key as a special key and signals the appropriate routine for processing
 * Passes the translated scan code's character data record to the monitor dispatcher for further custom processing by monitors
 * Places the translated scan code's character record into the appropriate session's keyboard input buffer

In addition, the physical keyboard device driver supports code page switching. The following is a result of this support:
 * Each handle can use one of two system-wide code pages. One code page is current and the other code page can be switched to. Each handle can also use the PC US 437 code page.
 * The code pages used are defined in CONFIG.SYS with the CODEPAGE and DEVINFO commands.
 * Using the KEYB command, the language layout of the keyboard can be changed.
 * Code pages specified with the CODEPAGE command in CONFIG.SYS are for one language only. However, it is possible that code page support for different languages can result if default code pages are not accepted during execution of the KEYB command. This can occur when attempting to load translation tables in a non-supported code page for that language.
 * The user can control, by the KbdSetCp subsystem function or the CHCP command, which of the two code pages is used in the translation of scan codes.
 * Two subsystem functions support code page switching:
 * KbdSetCp - Set to an installed code page, which is loaded if necessary.
 * KbdGetCp - Get the current in-use code page.
 * KbdSetCustXt adds a custom code page option.
 * KbdXlate translates a scan code.
 * KbdSetCp, KbdGetCp, and KbdXlate can be replaced in the subsystem by the use of the KbdRegister function.
 * Code page number, Language ID of the translation table, Subcountry ID, language default table indicator, and keyboard type indicator can all be found in the Translation table header of each country's keyboard layout. For more information, refer to "Set Code Page" (Function 50h), which can be found in the OS/2 Physical Device Driver Reference.



The physical keyboard device driver is the interface between the physical keyboard and applications as shown in the following figure.

(1) is part of the physical device driver interrupt handler.

(2) is part of the physical device driver strategy routine.

(3) is part of the base subsystem/router.

Keyboard Initialization
The device-independent driver (KBDBASE.SYS) loads prior to CONFIG.SYS, and the device-dependent driver (IBMKBD.SYS) is loaded as a BASEDEV= in CONFIG. SYS. IBMKBD.SYS uses a DEVHELP_ATTACHDD call to get the address of KBDBASE.SYS. The device-dependent driver then registers with the device-independent driver so that the appropriate inter-device-driver communication (IDC) can occur.

Keyboard Run-Time Operation
When a session is started, a default logical keyboard already exists. This keyboard is identified to the subsystem by a zero handle. Any program can share the keyboard by using Handle 0. If multiple programs use the default keyboard they must coordinate their access to it. The default keyboard logically terminates when the session terminates.

If a program wants a logical keyboard separate from the default logical keyboard, it issues a KbdOpen. This open creates a new logical keyboard, but does not make the physical-to-logical bond. As a result of an open, a handle unique within a process is returned to the caller, which is later used to identify the logical keyboard. The handle ownership is tied to the process; handles are not inherited. Use of KbdOpen does not prohibit the process from using the default keyboard.

To make the physical-to-logical bond, the process issues the KbdGetFocus using the handle which identifies the logical keyboard. When the bond is made, the logical keyboard can receive keystrokes. Note that type-ahead keystrokes are not possible before the bond is made. The keyboard API can be used only when the bond is made, or with Handle 0 when no other handle has the bond.

The bond represents a foreground keyboard (one physical-to-logical bond exists for each session). This is the default or a created logical keyboard. To break the bond, issue a KbdFreeFocus call. If other threads have a KbdGetFocus outstanding, the thread having the highest priority gets the bond. If there are no KbdGetFocus calls outstanding, the physical keyboard reverts to the default keyboard.

A logical keyboard is destroyed with a KbdClose. The close frees the focus, flushes the buffer, and deallocates the KCB and related memory. The close is done by the process kill mechanism, if it is not performed by the program.

Keystroke Monitors
Some applications need to view the raw keystrokes as they arrive from the keyboard at interrupt time. These applications might consume, modify, or replace keystrokes. This is made possible by the keystroke monitor function.

An application operating with the OS/2 system cannot register a keyboard monitor for a Presentation Manager session. When DosMonReg is issued with keyboard devices, the INDEX parameter indicates which OS/2 session, requested by the caller, is to register the monitor. The INDEX parameter indicates an OS/2 session from 0-15. (For more information on DevHlp_ DosGetInfoSeg, refer to the OS/2 Physical Device Driver Reference.)

An INDEX parameter value of -1 indicates that the session of the calling thread is being requested. If the caller requests either the Presentation Manager session or a DOS session, a MONITORS_NOT_SUPPORTED error is returned. For both of these sessions, the error return code is generated, regardless of the caller's specific usage of the INDEX parameter (explicit/ implicit).

The size of the physical keyboard device driver's monitor chain buffer is 16 bytes. This is the value to be used in calculating the sizes of the input/output buffers required for the DosMonReg function. The physical keyboard device driver supports device monitors. This physical device driver passes its information to the monitors in packets.

The following figure describes the content and format of keystroke monitor data packets. /\ | MonFlagWord:     Word | || | C |XlatedChar:   Byte | | h || | a |XlatedScan:   Byte | | r || | D |DBCS Status:  Byte | | a || | t |DBCS Shift:   Byte | | a || |  |Shift State:   Word | | R || | e |Milliseconds: DWord | | c || | o |                   | | r |                   | | d |                   | || | KbdDDFlagWord    Word | \/

MonFlagWord (Lower Byte)
Monitor Dispatcher Flags.

Bits 7-3 RESERVED. Must be passed untouched for packets that are passed on. Must be set to 0 on packets that are inserted by a monitor.

Bit 2 FLUSH. This is a flush packet. No other information in the packet has meaning. Monitor must flush its internal buffers and pass the packet quickly.

Bit 1 CLOSE. Not used by keystroke monitors.

Bit 0 OPEN. Not used by keystroke monitors.

MonFlagWord (Upper Byte)
Original Scan code, as read from the hardware. If 0, this packet was inserted for other reasons. See. Monitors pass this field untouched or put 0 here if they insert a packet.

CharData Record
For information regarding the Read Character Data Records IOCtl, refer to Function 74h, Category 04h in the OS/2 Physical Device Driver Reference.

KbdDDFlagWord
Has the following bits:

Bits 15-14 Available. These bits are available for communication between monitors; they are not used by the physical device driver. The monitor applications coordinate the use of these flags.

Bits 13-10 RESERVED=0. Monitors must pass these flags as is. They must set these flags to 0 in packets they create.

Bit 9 ACCENTED. This key is translated using the previous key passed, which is an accent key. Where an accent key is pressed, and the following key does not use the accent, a packet containing the accent character itself is first passed with this bit set. The scan code field of MonFlagWord (see above) would be 0, indicating a non-key generated record. A valid packet containing that following keystroke is then passed without this bit set.

Bit 8 MULTIMAKE. The translation process sees this scan code as a typematic repeat of a toggle key or a shift key. Because toggle and shift keys only change state on the first make after each key-break, no state information is changed. For example, the NumLock toggle bit in the shift status WORD is not changed, even though this can be the NumLock key. If this key is a valid character, it does not go into the Keyboard Input Buffer (KIB) once this bit is set.

Bit 7 SECONDARY. The scan code prior to the one in this packet was the Secondary Key Prefix (see below).

Bit 6 KEY BREAK. This record is generated by the release (the break) of the key involved.

Bits 5-0 KEY TYPE. This numeric field flags the physical device driver and reports that this is a key that requires action. The number in this field is filled in during the translation of the scan code. The value allows the driver to act on keystrokes without regard for what scan codes the keyboard uses or character codes that the current translation process may be using. The following values are currently defined:
 * Value for keys that are always placed in the KIB. Zero = no special action, always place in KIB.
 * Values acted on prior to passing packet to monitors. Except for the final keystroke of the DUMP key sequences, all of these values are passed on to the monitors. They are not placed in the KIB. The XlatedChar and XlatedScan fields are undefined for these values:

01h ACK. This scan code is a keyboard acknowledge. Personal Computer IBM* AT* attached keyboards set this value on an FAh scan code.

02h SECONDARY KEY PREFIX. This scan code is a prefix generated by the Enhanced Keyboard. It indicates that the next scan code coming is one of the secondary keys that exists on that keyboard. Usually set on an E0h scan code or an E1h scan code.

03h KBD OVERRUN. This scan code is an overrun indication from the keyboard. On an IBM Personal Computer AT-attached keyboard, this value would be set on an FFh scan code.

04h RESEND. This scan code is a resend request from the keyboard. On an IBM Personal Computer AT-attached keyboard, this value would be set on an FEh scan code.

05h REBOOT KEY. This scan code completes the multi-key restart sequence. On an IBM Personal Computer AT attached-keyboard, this value would be used when the Ctrl+Alt+Delete sequence is used.

06h DUMP KEY. This scan code completes the multi-key Stand Alone Dump request sequence. On an IBM Personal Computer AT-attached keyboard, this value would be used on completion of the second consecutive press of Ctrl+Alt+NumLock or Ctrl+Alt+F10 without other keystrokes between the two presses.

07h-0Ah See entries below.

0Bh INVALID ACCENT COMBINATION. This scan code follows an accent scan code but the combination is not valid, and neither key is put in the KIB.

Note:This is set if the Canadian-French code pages are in use.

0Ch SYSTEM-DEFINED HOT KEYS.

0D-0Fh RESERVED. Treated as undefined. See entry 3Fh.


 * Values acted on after passing packet to monitors. Except where noted, these values are placed in the KIB when the physical device driver is in binary mode; they are not placed in the KIB when the physical device driver is in ASCII mode. (Also listed are those that never get placed in the KIB.)

07h SHIFT KEY. This scan code translates as a shift key and affects the shift status fields of the CharData record, but does not generate a defined character. It is not placed in the KIB. The XlatedChar field is undefined. The scan codefield is 0.

08h PAUSE KEY. This scan code is translated as the key sequence meaning pause. On an IBM Personal Computer AT-attached keyboard, this value is used when the Ctrl+NumLock sequence is used. The key itself is not placed in the KIB.

09h PSEUDO-PAUSE KEY. This scan code is translated into the value that is treated as the Pause key when the physical device driver is in ASCII mode. On most keyboards, this would be when the Ctrl+S combination is used. The key itself is not placed in the KIB.

0Ah WAKE-UP KEY. This scan code follows a Pause key or Pseudo-Pause key, which causes the Pause state to end. The key itself is not placed in the KIB.

10h ACCENT KEY. This scan code is translated and used as a key to alter the translation of the next key to come in.

The packet containing this value is passed when the accent key is pressed, but it is not put into the KIB, unless the Accented bit is ON. The next key determines this decision. If the next key is one that can be accented, then it is passed by itself with the Accented bit ON. If that next key cannot be accented by this accent, then two packets are passed. The first contains the character to print for the accent itself. It has the Accent key value and the Accented flag (which allows the packet to be put in the KIB). The second packet contains a regular translation of that following key.


 * Note:The two packets get passed for every language except Canadian-French. See entry 0Bh.

11h BREAK KEY. This scan code is translated as the key sequence meaning break. On the IBM Personal Computer AT-attached keyboard, this value is used where the Ctrl+Break sequence is used.

12h PSEUDO-BREAK KEY. This scan code is translated into the value that is treated as the Break key when the physical device driver is in ASCII mode. On most keyboards, this would be when the Ctrl+C combination is used. Notice that the event generated by this key is separate from the one generated by the Break key when in the binary mode.

13h PRINT SCREEN KEY. This scan code is translated as the key sequence meaning Print Screen. On an IBM Personal Computer AT-attached keyboard, this value is used where the Shift+PrtSc sequence is used.

14h PRINT ECHO KEY. This scan code is translated as the key sequence meaning Print Echo. This value is used where the Ctrl+PrtSc sequence is used.

15h PSEUDO-PRINT ECHO KEY. This scan code is translated into the value that is treated as the Print Echo key when the physical device driver is in ASCII mode. On most keyboards, this would show as the Ctrl+P combination.

16h PRINT-FLUSH KEY. This scan code is translated into the key sequence Print-Flush. This value is used where the Ctrl+Alt+PrtSc sequence is used.

17h-2Fh RESERVED=0. Treated as undefined. See entry 3Fh.


 * Values for packets not generated by a keystroke:

30h-37h RESERVED.

38h-3Eh RESERVED. Treated as undefined. See entry 3Fh.


 * Value for keys the translation process does not recognize:

3Fh UNDEFINED. This scan code, or its combination with the current shift state, is not recognized in the translation process.

Special Key Processing
The operating system examines each incoming keyboard character to determine if it should cause an asynchronous signal to be sent to some process (for example, Ctrl+C). The physical keyboard device driver responds to the keystrokes as shown in the following table:
 * 1) The value xxh represents the translated ASCII field in the character data record.
 * 2) The value xx:yyh represents the translated ASCII (that is, translated scan code fields of the character data record).
 * 3) Ctrl+NumLock has no effect on an IBM Enhanced keyboard; the Pause key provides this function.

Other special keys are shown in the following table:

In addition to passing individual characters, the physical device driver must specifically recognize the character (or character sequence, or other special action) that indicates the special signal, or hot key, to the Session Manager. When this event is recognized, the SendEvent Device Helper service is started.

The "System Hot Key" is defined by IOCtl Category 04h, Function 56h in the OS/2 Physical Device Driver Reference.

The Device-Dependent Driver
The device-dependent driver uses a state machine to control the hardware interrupts. The following is a diagram of the state machine:




 * NOCMDIPG (No Command In Progress (*)):This is the base state. It accepts scan codes as keystrokes and it passes them in a key packet to the DI driver. It also checks for an override (FFh) scan code. This is usually the start of a hot plug sequence; therefore, move to the [HOTPLGPG] state.
 * RCVDE0SC (Received E0h Scan Code (*)):If [NOCMDIPG] receives an E0h scan code, it jumps to this state to await the remaining keystroke scan byte. These two bytes are then passed to the DI driver in a key packet. Upon completion, return to the state [NOCMDIPG].
 * HOTPLGPG (Notify Hot-Plug in Progress):If [NOCMDIPG] receives FFh, it jumps to this state and waits for the next scan code. If the next scan code is an AAh, it starts the hot plug sequence. If not, then it beeps the keyboard and returns to [NOCMDIPG] state to pass the scan code to the DI driver.
 * SENTLEDC (Sent LED Command (!)):The change LEDs command has been sent to the keyboard and is now awaiting an ACK from the keyboard. When one is received, send the new LED data byte to the keyboard and go to [SENTLEDD] to wait for an ACK.
 * SENTLEDD (Sent LED Data (!)):The LED byte is sent to the keyboard and is awaiting an ACK. When one is received, go to [NOCMDIPG] and wait for the next scan code.
 * SENTTYPC (Sent Typematic Command (!)):The change type rate/delay command has been sent to the keyboard, and is now awaiting an ACK from the keyboard. When one is received, send the new type rate/delay data byte to the keyboard and go to [SENTTYPD] to wait for an ACK.
 * SENTTYPD (Sent Typematic Rate (!)):The new type rate/delay byte has been sent to the keyboard and is awaiting an ACK. When one is received, go to [NOCMDIPG] and wait for the next scan code.
 * SENTIDCM (Sent Read ID Command):The Read ID command has been sent to the keyboard, and is now awaiting an ACK from the keyboard. When one is received, start a timer and go to [WAITIDB1] to await the first ID byte (go to [GTKBDCMD] upon timeout).
 * WAITIDB1 (Wait for First ID Byte):The Read ID command has been sent and ACK has been received. The device driver is waiting for the first ID byte. When one is received, go to [WAITIDB2] to await the second ID byte.
 * WAITIDB2 (Wait for Second ID Byte):The first ID byte has been received, and the driver is now waiting for the second ID byte. When the byte has been received, request the controller command byte and go to [GTKBDCMD].
 * GTKBDCMD (Get Controller Command Byte(!)):The device driver waits for the command byte from the keyboard controller. If the Scan-Code Set is set to 1, then the driver makes the request to change the Scan-Code Set. If the Scan-Code Set is set to 2, then the driver goes to [SENTSCSC].
 * SENTSCSC (Sent Out Scan-Code Set Change(!)):When the device driver receives an ACK, it sends out the correct Scan-Code Set to the keyboard and then goes to [SENTSCSD] to wait for an ACK.
 * SENTSCSD (Sent Out Correct Scan-Code Set(!)):The device driver is waiting for an ACK from the keyboard to acknowledge that it has completed the request. To ensure that the type rate/delay is correct, send off the change type rate/delay command and go to [SENTTYPC].


 * Note:The state sequence from SENTIDCM to SENTSCSD should only occur during init and after every Hot Plug as it is part of the setup routine.


 * (*) This state generates a keystroke packet.
 * (!) This state starts a timer that resets the state machine and flags an error, if time runs out.

Building the Physical Keyboard Device Driver
To build the physical keyboard device driver, you must do the following:
 * 1) Ensure that the TOOLS directory in the IBM Device Driver Source Kit for OS/2 is part of the current path.
 * 2) Create NMAKE using the following Make files provided in the device driver:
 * 3) *SRC\DEV\KBD\KBDBASE\MAKEFILE
 * 4) *SRC\DEV\KBD\IBMKBD\MAKEFILE
 * For example:CD:\DDK\SRC\DEV\KBD\KBDBASE\NMAKE