Mail Archives: djgpp-workers/1998/01/14/11:03:52
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 -