Saturday, 16 April 2016

Detect keyboard status and hide menu entries in E2B

We can detect the status of the keyboard using grub4dos to read the BIOS Data area.
For instance, we can tell if CAPS LOCK or SCROLL LOCK was on or not.

Here is a simple grub4dos batch file which will report the keyboard status as detected by the BIOS (not all keys may be reported accurately under a VM):

# Use BIOS Data Area to get keyboard status
# Some may not work under a VM (e.g. right-ctrl, insert on VBox)
# B417 ALT and CTRL will detect both left and right keys

read 0x417 > nul
set /A B417=%@retval% > nul
calc %B417% & 0x80 > nul && echo INSERT
calc %B417% & 0x40 > nul && echo CAPS-LOCK
calc %B417% & 0x20 > nul && echo NUM-LOCK
calc %B417% & 0x10 > nul && echo SCROLL-LOCK
calc %B417% & 0x08 > nul && echo ALT (left or right)
calc %B417% & 0x04 > nul && echo CTRL (left or right)
calc %B417% & 0x02 > nul && echo LEFT-SHIFT
calc %B417% & 0x01 > nul && echo RIGHT-SHIFT

read 0x418 > nul
set /A B418=%@retval% > nul
calc %B418% & 0x80 > nul && echo INSERT KEY DOWN
calc %B418% & 0x40 > nul && echo CAPS-LOCK KEY DOWN
calc %B418% & 0x20 > nul && echo NUM-LOCK KEY DOWN
calc %B418% & 0x10 > nul && echo SCROLL-LOCK DOWN
calc %B418% & 0x08 > nul && echo SUSPEND TOGGLED
calc %B418% & 0x04 > nul && echo SYSTEM KEY DOWN
calc %B418% & 0x02 > nul && echo LEFT-ALT KEY DOWN
calc %B418% & 0x01 > nul && echo LEFT-CTRL KEY DOWN

read 0x497 > nul
set /A B497=%@retval% > nul
calc %B497% & 0x04 > nul && echo CAPS-LOCK LED ON
calc %B497% & 0x02 > nul && echo NUM-LOCK LED ON
calc %B497% & 0x01 > nul && echo SCROLL LOCK LED ON

read 0x496 > nul
set /A B496=%@retval% > nul
calc %B496% & 0x10 > nul && echo 101/102 KEY ENHANCED KBD
calc %B496% & 0x08 > nul && echo RIGHT-ALT GR KEY DOWN
calc %B496% & 0x04 > nul && echo RIGHT-CTRL KEY DOWN

Note: even an EeePC netbook reports a 101\102 KEY ENHANCED KBD!

We can use a similar method in the Guest Mode menu file, for instance instead of this bit of code (taken from $$$$GUEST_MENU_F4.mnu):

### sleep for 3 seconds to give user chance to press a key
call Fn.73 3
### get secret keypress now
call Fn.20
set /A key=%@retval% > nul
# F1=0x3b00, F2=0x3c00, F3=0x3d00= F4=3e00.. F10=4400, ESC=0x011B, PrntSrc=0x372A, Home=0x4700
### uncomment next line if you want to display the key code for whatever key you press
#pause --wait=3 Press secret key... ;; echo key=%key% && pause --wait=3
# 0x3e00 = F4 - absorb keypress using Fn.19 if we found it
if not exist DONEPWD if %key%==0x3e00 set ASK= && call Fn.19 
set key=

we can replace it with:
#Check if CAPS LOCK is on
if not exist DONEPWD calc *0x417 & 0x40 > nul && set ASK=

where *0x417 means the contents of memory address 0x417.
I have added a Sample mnu File ($$$$GUEST_MENU_CAPS_LOCK.mnu) to the E2B v1.80f Beta version which uses this code.

We can also use this trick to show or hide menu entries by using it in a .txt file for any ISO (e.g. Mageia-5-LiveDVD-KDE4-x86_64-DVD.iso):

iftitle [calc *0x417 & 0x40] Magia 5 Live DVD KDE4 64-bit\n Only displayed if CAPS LOCK is on

If we place the two files (.iso and .txt) in the \_ISO\LINUX folder, then the menu entry will only be listed in the LINUX menu if CAPS LOCK is on at the time that we go into it from the Main menu.

The same iftitle line can be used in .mnu files as well. Instead of

iftitle [if exist $HOME$/ubuntu-13.04-desktop-i386.iso] Ubuntu 13.04\n Boot using .mnu file with persistence

set ISO=$HOME$/ubuntu-13.04-desktop-i386.iso
set PER=/ubuntu1304-rw
etc. etc....

We can use this instead:

iftitle [calc *0x417 & 0x40 && if exist $HOME$/ubuntu-13.04-desktop-i386.iso] Ubuntu 13.04\n Boot using .mnu file with persistence (if CAPS LOCK is pressed)

set ISO=$HOME$/ubuntu-13.04-desktop-i386.iso
set PER=/ubuntu1304-rw
etc. etc.

P.S. Note that grub/linux can behave oddly if CAPS LOCK is on. If you boot to a linux ISO with CAPS LOCK on, it may not boot correctly until you toggle CAPS LOCK off again!

You can also detect the keyboard status during boot-up of E2B. For instance, you could test for the SHIFT key being held down in the \_ISO\MyE2B.cfg file as E2B boots and shutdown the system if it is not being held down...

# get special keys from BIOS kbd status location - e.g. SHIFT, CTRL, etc. into n for use later
set n=
read 0x417 > nul
set /A n=%@retval% > nul
# bits in n = LShift=01, RShift=02,CTRL=04,ALT=08,SCROLL=10,NUM=20,CAPS=40,INS=80
# check for either SHIFT key (note: may not give correct scan codes under a VM, e.g. under VBOX LShift=2, Insert=0)
calc %n%&0x03 || if not exist DONEMENU halt
set n=