PS/2 analyzer: missing modifier-dependent Set 2 codes: Alt+PrintScreen (0x84), Ctrl+Pause (0xE0 0x7E)

Summary

The built-in PS/2 Keyboard/Mouse analyzer labels several of the modifier-dependent Set 2 scan codes as “Unrecognized Key.” Two confirmed examples so far:

  • Alt + PrintScreen0x84 / F0 84
  • Ctrl + PauseE0 7E / E0 F0 7E

In both cases the analyzer already decodes the unmodified form of the same physical key, so these look like missing entries in the Set 2 table rather than a deeper issue.

Environment

  • Logic 2 version 2.4.44
  • Saleae Device: Logic MSO, Hardware revision Rev0B/Rev0E
  • Keyboard: IBM Model M (1987, P/N 1391401), keyboard ID AB 83, Scan Code Set 2 (default)
  • PS/2 breakout on a 5 V supply

Reproduction

1. Alt + PrintScreen

Press & release PrintScreen; then press & hold Alt, tap PrintScreen, release Alt. Decoded output:

MAKE  [PRINT SCREEN]    (0xE0, 0x12, 0xE0, 0x7C)               OK
BREAK [PRINT SCREEN]    (0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12)   OK
MAKE  [ALT (RIGHT)]     (0xE0, 0x11)                           OK
MAKE  Unrecognized Key  (0x84)                                 <-- missing
BREAK Unrecognized Key  (0xF0, 0x84)                           <-- missing
BREAK [ALT (RIGHT)]     (0xE0, 0xF0, 0x11)                     OK

2. Ctrl + Pause

Tap Pause (unmodified); then press & hold Ctrl, tap Pause, release Ctrl. Decoded output:

[PAUSE/BREAK]           (0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77)   OK
MAKE  [CONTROL (RIGHT)] (0xE0, 0x14)                           OK
MAKE  Unrecognized Key  (0xE0, 0x7E)                           <-- missing
BREAK Unrecognized Key  (0xE0, 0xF0, 0x7E)                     <-- missing
BREAK [CONTROL (RIGHT)] (0xE0, 0xF0, 0x14)                     OK

Why these are correct (not keyboard quirks)

In Set 2, both the PrintScreen/SysRq and Pause/Break keys emit different codes depending on modifier state. From the IBM PC AT Technical Reference (and Microsoft’s Keyboard Scan Code Specification, Appendix A):

PrintScreen / SysRq

PrintScreen pressed with Make Break
(none) E0 12 E0 7C E0 F0 7C E0 F0 12
Shift E0 7C E0 F0 7C
Ctrl E0 7C E0 F0 7C
Alt 84 F0 84

With Alt held, the keyboard suppresses the fake-shift sequence and emits the bare single byte 0x84.

Pause / Break

Pause pressed with Make Break
(none) E1 14 77 E1 F0 14 F0 77 (none — Pause has no break code)
Ctrl E0 7E E0 F0 7E

With Ctrl held, the key becomes Break and emits a separate sequence that — unlike Pause — does have a normal make/break pair.

Both behaviors match the captures exactly; the keyboard is fully spec-compliant.

Request 1 (bug): decode the modifier-dependent Set 2 codes

In every one of these cases the keyboard firmware has already done the modifier detection and handed the host a distinct code, so the analyzer needs no modifier-state tracking — just the missing table entries:

  • 0x84MAKE [PRINT SCREEN] (SysRq) — emitted for Alt + PrintScreen
  • F0 84BREAK [PRINT SCREEN] (SysRq)
  • E0 7EMAKE [PAUSE/BREAK] (Break) — emitted for Ctrl + Pause
  • E0 F0 7EBREAK [PAUSE/BREAK] (Break)

0x84 is unambiguous on a 101/102-key keyboard (it only maps to a different position in 122-key terminal Set 3, which doesn’t apply here), and USB HID folds SysRq into the PrintScreen usage (0x46), so labeling it as PrintScreen keeps it consistent with the E0 7C frames above. Either Alt triggers it and the emitted byte is identical regardless of side, so the fix is naturally Alt-agnostic. Likewise, labeling E0 7E as PAUSE/BREAK stays consistent with the unmodified Pause frame.

These two are the substitution cases (a wholly different code). The same exceptional-handling table also covers the navigation cluster and keypad-/ shift-prefix handling; completing the table would resolve that whole class in one pass.

Request 2 (enhancement): scan-code-set selection

The analyzer appears to assume Set 2. That is the correct default — per the AT Technical Reference, keyboards power up in Set 2 and a Reset restores it — so this is not a bug. But two related improvements would help when capturing non-default keyboards (e.g. IBM terminal boards that start in Set 3):

  1. A manual Set 1 / Set 2 / Set 3 selector in the analyzer settings.
  2. Optionally, auto-detect from the stream: track the host→device F0 nn (Select Alternate Scan Codes) command, and decode the F0 00 query response (0x43 / 0x41 / 0x3F = Set 1 / 2 / 3).

References

Happy to attach the .sal captures if they’re useful for reproducing.

Relating to your other post:

See:

… you can submit a PR to add the missing features, and they can (eventually) be merged for everyone; Meanwhile, you can build and use the fix locally immediately:

PS: I think Saleae has balanced open source extensions with guarding proprietary core capabilities pretty well. I think they could enhance the APIs even more, to allow more open extensions & community enhancements.