From: "Anthony.Appleyard" Organization: Materials Science Centre To: eliz AT is DOT elta DOT co DOT il, djgpp-workers AT delorie DOT com, dj AT delorie DOT com Date: Tue, 13 Jan 1998 10:46:34 GMT Subject: MCLSSAA2 AT fs2 DOT mt DOT umist DOT ac DOT uk: Hooking interrupt 9 : amended Reply-to: Anthony DOT Appleyard AT umist DOT ac DOT uk Message-ID: <25A7F473B51@fs2.mt.umist.ac.uk> Precedence: bulk Thanks to Eli Zaretski for his comments. Herewith an amended version with more help:- ------------------------------------------------------------------ extern int (*_djgpp_kbd_callback)(int X); /* initial value == 0 */ ///// This line should be inserted in some suitable #insert<***.h> file. If _djgpp_kbd_callback is nonzero, the function that it points to is automatically called whenever a keyboard event occurs such as a key being pressed or released. When it is called:- X &255 == the keyboard event code (X>> 8)&255 == keyboard shift status as if from (AH=2, int 16h) (X>>16)&255 == keyboard extended shift status as if from (AH=12h, int 16h) If _djgpp_kbd_callback() returns nonzero, that keyboard event is not passed on to DOS. This would let the user e.g. recognise and intercept `Prt Scr' and use it for some purpose of his own. bits of shift status bits of extended shift status 7 Insert active 7 SysReq key pressed 6 CapsLock active 6 CapsLock pressed 5 NumLock active 5 NumLock pressed 4 ScrollLock active 4 ScrollLock pressed 3 Alt key pressed 3 right Alt key pressed 2 Ctrl key pressed 2 right Ctrl key pressed 1 left shift key pressed 1 left Alt key pressed 0 right shift key pressed 0 left Ctrl key pressed These current values of these two bytes are kept in conventional memory at addresses 0x417 and 0x418 respectively. The keyboard keys are numbered between 0 and 127. The code for pressing a key is as here; the code for releasing that key is 0x80 = 128 higher. `Numshift' is an imaginary key whose press and release codes are sometimes manufactured by something in BIOS around some of the `grey key' events. If `numshift' is treated as an extra shift key, the effect is that those `grey keys' are shifted by the current Numlock state and not by the two real shift keys. Don't blame me, blame whoever invented the PC BIOS. Some of the keys when pressed or released produce two keyboard events, of which the first is 0xe0, and the second is the key's code (plus 128 on release). I represent this feature here by adding 0x100 = 256 to the code. On my PC pressing Pause/Break key produces the sequence `e1 1d 45', and releasing it produces `e1 9d c5': i.e. `e1' followed by the codes for `left ctrl' and `numlock' in that order. The `e1 1d' seems to be the functioning part of the sequence that causes the pausing or the break. On my PC pressing `Prt Scr'/`Sys Req' key produces `e0 2a' followed by three `press padstar' sequences; releasing `Prt Scr'/`Sys Req' produces a `release padstar' sequence followed by `e0 aa'. Due to wide differences between national keyboard layouts, I have named the non-alphanumeric printing keys neutrally, e.g. `k_2rof0' means "the key two to the right of 0" (`=' `+' on UK and USA keyboards). This refers to the layout on a desktop keyboard. Laptop keys tend to be somewhat differently arranged. enum{k_esc=1, k_1, k_2, k_3, k_4, k_5, k_6, k_7, k_8, k_9, k_0, k_1rof0, k_2rof0, k_backspace, k_tab, k_Q, k_W, k_E, k_R, k_T, k_Y, k_U, k_I, k_O, k_P, k_1rofP, k_2rofP, k_enter, k_lctrl, k_A, k_S, k_D, k_F, k_G, k_H, k_J, k_K, k_L, k_1rofL, k_2rofL, k_1lof1, k_lshift, k_3rofL, k_Z, k_X, k_C, k_V, k_B, k_N, k_M, k_1rofM, k_2rofM, k_3rofM, k_rshift, k_padstar, k_lalt, k_space, k_capslock, k_F1, k_F2, k_F3, k_F4, k_F5, k_F6, k_F7, k_F8, k_F9, k_F10, k_numlock, k_scrolllock, k_pad7, k_pad8, k_pad9, k_padminus, k_pad4, k_pad5, k_pad6, k_padplus, k_pad1, k_pad2, k_pad3, k_pad0, k_paddot, k_1lofZ=0x56, k_F11, k_F12, k_padenter=0x11c, k_rctrl=0x11d, k_numshift=0x12a, k_padslash=0x135, k_ralt=0x138, k_home=0x147, k_uparrow=0x148, k_pageup=0x149, k_leftarrow=0x14b, k_rightarrow=0x14d, k_end=0x14f, k_downarrow=0x150, k_pagedown=0x151, k_insert=0x152, k_delete=0x153, k_lwin=0x15b, k_rwin=0x15c, k_menu=0x15d}; ================================================================== Suggested alterations to D:\DJGPPV2\SRC\LIBC\GO32\EXCEPTN.S :- ================================================================== *** _ex.old Mon Jan 12 14:54:06 1998 --- _ex.s Tue Jan 13 10:33:46 1998 *************** *** 284,292 **** --- 284,327 ---- iret .align 4 + .global __djgpp_kbd_callback + __djgpp_kbd_callback: .int 0 /* int (*_djgpp_kbd_callback)(int X); */ + /* If not 0, the interrupt 9 hook routine will call this function with:- */ + /* X &255 == keyboard event */ + /* (X>> 8)&255 == keyboard shift status as if from (AH=2, int 16h) */ + /* (X>>16)&255 == keyboard extended shift status as if from (AH=12h, int 16h) */ + _calldjgpp_kbd_callback: + xorl %eax,%eax /* must return 0 if no function */ + pushl %ebx /* save EBX */ + movl __djgpp_kbd_callback,%ebx + testl %ebx,%ebx /* if zero, there is no function */ + je NOUSERHDLR + pushw %fs + pushf + sti /* disable interrupts */ + movw __go32_info_block+26,%ax + movw %ax,%fs /* FS = _dos_ds */ + .byte 0x64 /* use segment reg FS */ + movw 0417,%ax /* [0x417] [0x418] are shift status */ + sall $8,%eax /* move EAX one byte up */ + inb $0x60,%al /* read keyboard event into AL */ + pushl %eax /* parameter for call */ + call *%ebx /* call the function */ + popf + popw %fs /* don't restore EAX, it's the result */ + NOUSERHDLR: + popl %ebx + ret + .global ___djgpp_kbd_hdlr ___djgpp_kbd_hdlr: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + testl %eax,%eax /* nonzero, no default handling of the event */ + JE CARRYON + popl %eax + iret + CARRYON: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ *************** *** 317,322 **** --- 352,363 ---- .global ___djgpp_kbd_hdlr_pc98 ___djgpp_kbd_hdlr_pc98: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + testl %eax,%eax /* nonzero, no default handling of the event */ + JE CARRYON2 + popl %eax + iret + CARRYON2: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */