delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/01/14/11:03:52

Date: Wed, 14 Jan 1998 18:01:21 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: Anthony DOT Appleyard AT umist DOT ac DOT uk
cc: djgpp-workers AT delorie DOT com
Subject: Re: MCLSSAA2 AT fs2 DOT mt DOT umist DOT ac DOT uk: Hooking interrupt 9
In-Reply-To: <27011525706@fs2.mt.umist.ac.uk>
Message-ID: <Pine.SUN.3.91.980114133046.8730U-100000@is>
MIME-Version: 1.0

On Wed, 14 Jan 1998, Anthony.Appleyard wrote:

> + enum{        /* numbers of the keys */
> +   k_esc = 1,
> +   k_1,

Why are these needed on a system-wide header?  As far as I could see, 
they aren't used anywhere in the code, right?

<keys.h> already has definitions for all the PC keys, but they are the 
codes returned by the BIOS, not the scan codes.  If you think these scan 
codes should be available system-wide, I suggest to add your definitions 
there, not to <sys/exceptn.h>.

> + 	cli				/* disable interrupts */

I think this is both slow and unnecessary.  Charles Sandmann agrees with
that, so I think this line should go away. 

> + 	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 */

I already asked why do you need to do this when the original handler code 
already loads the _dos_ds selector into DS, two lines after you call the 
callback code.  Moving that line higher is all you need to do, no?

>   ==================================================================
>   Herewith a .TXH file for it, say call it djgppkbh.txh :-
>   ------------------------------------------------------------------

This needs more work in the markup.  Below is a somewhat changed version
which shows what you missed.  Some noteworthy comments:

  1) Function names, variable names, keywords and similar tokens
     should be written as @code{foo}.  This produces `foo' in Info and
     is typeset in a typewriter face.

  2) Parts that should not be reindented and refilled should be
     surrounded by @display DOT  DOT  DOT  AT end display.  Otherwise, the spacing
     of the words will be changed to fill text, which is not what you
     want.

  3) Names of keys should use the @key{} markup.  Names of parameters
     (such as the `keycode' parameter of this function) should use
     @var{}.  File names should use @file{}.

  4) If you want to make an ordered list, use @table or @itemize, see
     below.

  5) Don't use double quotes; use `` and '' instead.  These will be
     converted into double quotes in Info, but in the printed version
     they will produce the `` and '' glyphs as God intended.

  6) You need to use @{ and @} in the examples where you need { and },
     respectively, since the braces are special.

  7) Make a good-faith effort to verify that your example works.  This
     means, at the very least, to compile it with -Wall and see that
     it doesn't generate any warnings or errors.  It is best to make
     sure that it actually works and doesn't crash.  In this case, you
     haven't locked the code and the data, and it would surely crash,
     since it is called from within an interrupt handler.  (Neither
     did you mention this in the description.)  In my version below, I
     added some locking code, but I didn't test it.  One thing which
     is definitely not right is that GCC assumes SS == DS, which is
     incorrect in the interrupt handler, so the callback code should
     take care of that also.  I think that the example needs to be
     written in assembly, for all these reasons, lest people decide
     that it is all too easy to write it in C and end up scrogging
     their hard disks.  I would also mention thesse considerations in
     the docs.

Note that I have taken liberty to change some of your wording, especially
where it made an impression that it is specific to ``my PC'' (who is ``me'',
anyway?)

-------------------------------------------------------------------
@node _djgpp_kbd_callback, misc
@subheading Syntax

@example
#include <sys/exceptn.h>
extern int (*_djgpp_kbd_callback)(int keycode);
@end example

@subheading Description

If @code{_djgpp_kbd_callback} is not zero, it is a pointer to a user-definable
function which is automatically called whenever a keyboard event occurs such
as a key being pressed or released. This is useful to let the program see
the raw keyboard events. Note that the code and data of the callback
needs to be locked, as it is called from within an interrupt handler.

This function is called with a single parameter @var{keycode} which is
constructed as follows:

@table @code{}
@item X & 255
the keyboard scan code.

@item (X >> 8) & 255
keyboard shift status as if from function AH=2 of interrupt 16h.

@item (X >> 16) & 255
keyboard extended shift status as if from function AH=12h of interrupt 16h.
@end table

If @code{_djgpp_kbd_callback} returns nonzero, that keyboard event is
not passed on to DOS. This would let the user e.g. recognize and
intercept @key{PrtScr} and use it for some purpose of his own instead of
DOS handling it.

@display
  bits of shift status		        bits of extended shift status
  7	@key{Insert} active             7     @key{SysReq} key pressed
  6	@key{CapsLock} active           6     @key{CapsLock} pressed
  5	@key{NumLock} active            5     @key{NumLock} pressed
  4	@key{ScrollLock} active         4     @key{ScrollLock} pressed
  3	@key{Alt} key pressed           3     right @key{Alt} key pressed
  2	@key{Ctrl} key pressed          2     right @key{Ctrl} key pressed
  1	left @key{Shift} key pressed    1     left @key{Alt} key pressed
  0	right @key{Shift} key pressed   0     left @key{Ctrl} key pressed
@end display

The current values of these two bytes are kept in conventional memory at
linear addresses 0x417 and 0x418 respectively.

Pressing a keyboard key generates a scan code between 0 and 127. The scan code
for pressing a key is as listed in the header file @file{keys.h}; the code for
releasing that key is 0x80 = 128 higher.

The keys introduced with the extended 101-key keyboard, when pressed or
released, produce two keyboard events, of which the first is 0xe0, and the
second is the key's scan code (plus 128, 0x100, on release).

@key{Numshift} is an imaginary key whose press and release codes are
manufactured by the BIOS when the ``grey key'' are pressed.  This allows
to differentiate between the grey @key{Home} key and the @key{Home/7}
key on the numeric pad.
If @key{Numshift} is treated as an extra shift key, the effect is that those
``grey keys'' are shifted by the current @key{Numlock} state and not by the
two real shift keys.

Two keys are special in that they produce more than two-byte sequence
when pressed or released:

@itemize @bullet{}

@item
Pressing the @key{Pause/Break} key produces the sequence @code{e1 1d 45}, and
releasing it produces @code{e1 9d c5}; i.e. @code{e1} followed by the codes
for left @key{Ctrl} and @key{Numlock}, in that order. In the sequence, the
@code{e1 1d} is the functioning part that causes the pausing or the break.

@item
Pressing @key{PrtScr/SysReq} key produces @code{e0 2a e0 37}; releasing it
produces @code{e0 b7 e0 aa}.

Due to wide differences between national keyboard layouts, the
non-alphanumeric printing keys are called neutrally, e.g. @code{k_2rof0}
means ``the key two to the right of 0'' (@key{=/+} on UK and USA keyboards).
This refers to the layout on a desktop keyboard. Laptop keys tend to be
somewhat differently arranged.

@subheading Return Value

This function is a callback, so it is up to the user what it returns.
The return value should be 0 if you want the keyboard event to be
processed as usual after you have processed it, otherwise 1.

@subheading Example

@example

#include <sys/farptr.h>
#include <sys/exceptn.h>
#include <dpmi.h>

char print_wanted = 0;

unsigned trap_prscr_size = ...; /* the size of the code in trap_prscr */

int trap_prscr(int X) @{
  if((X&0xff) == 0x2a)                    /* if it is left shift or Prt Scr */
    if(!((X>>8)&15))                      /* not if shift or ctrl or alt */
       if(_farpeekb(_dos_ds,0x496)&2)     /* if it is next after 0xe0 event */
          @{                              /* then it is a Prt Scr */
            print_wanted = 1; /* leave note to call my own printout routine */
            return 1;         /* no, I DON'T want DOS's method right now */
          @}
  return 0;                   /* else default */
@}
  ......
int main() @{
__dpmi_meminfo lockmem;
lockmem.address = __djgpp_base_address + (unsigned) &trap_prscr;
lockmem.size = trap_prscr_size;
__dpmi_lock_linear_region(&lockmem);

lockmem.address = __djgpp_base_address + (unsigned) &print_wanted;
lockmem.size = sizeof(print_wanted);
__dpmi_lock_linear_region(&lockmem);

_djgpp_kbd_callback = trap_prscr;
  ......
@}
@end example

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019