Mail Archives: djgpp/1994/01/27/20:38:54
I'm having a problem hooking in my own keyboard interrupt handler.
Hooking the protected mode int 9 vector seems to work fine, it's
the real mode int 9 that is giving me problems. I allocate a real
mode "iret" callback which should point to my interrupt handler
and then I hook the real mode int 9 vector to point to the real
mode callback. The problem is that when I run the program, keystrokes
are STILL somehow getting to the default keyboard handler... most
of my keystrokes are getting to my own interrupt handler, but once in
a while one will slip through to the standard keyboard handler -- I
can tell because if I hit NumLock many times I can make the NumLock
light come on and my interrupt handler isn't supposed to do that.
I don't see how keystrokes can find their way to the standard keyboard
handler when I've hooked both protected and real mode int 9 vectors!
The debugger is not much good to me with this problem since once the
keyboard is hooked, I can't do anything in the debugger. I really
need a solution to this problem since my keyboard handler tracks the
state of each key and if it misses a "break" code, the program thinks
that key is stuck, which is really annoying.
Also, I occasionally see an "Unsupported interrupt 0x2f" pop up which
seems to be related somehow, and I've had the program lock up once or
twice.
I've included some relevant bits of my source code as well as the
output of the debugging printf statements below in case someone can
see any obvious mistakes.
What I'd like to know is:
1. Has anyone successfully taken over the keyboard interrupt with DJGPP?
2. What would be the safest and cleanest way to do so?
3. Does go32 do anything strange with the keyboard interrupt?
4. Do real mode callbacks actually work? Do they do anything besides
calling the protected mode routine and then returning with iret?
5. What could be causing some my keystrokes to go to the standard keyboard
handler? Is _go32_dpmi_set_real_mode_interrupt_vector() chaining to
the standard handler? Is the real mode callback chaining to the standard
handler? Is go32 stealing back the interrupt vector for brief periods?
Any hints, comments, suggestions, guesses, etc. would be most welcome..
---------- assembly source for the ISR ----------
/* kbd_pm_isr() -- protected mode keyboard interrupt service routine */
.align 2
.globl _kbd_pm_isr
_kbd_pm_isr:
call _kbd_rm_isr
iret # protected mode version ends with IRET
/* kbd_rm_isr() -- real mode keyboard interrupt service routine */
.align 2
.globl _kbd_rm_isr
_kbd_rm_isr:
pushl %eax
pushl %edx
...isr details deleted...
popl %edx
popl %eax
ret
---------- C source for hooking the interrupt ----------
extern void kbd_pm_isr();
extern void kbd_rm_isr();
_go32_dpmi_seginfo old_pm_kbd_irq;
_go32_dpmi_seginfo old_rm_kbd_irq;
_go32_dpmi_seginfo kbd_callback;
_go32_dpmi_seginfo new_kbd_irq;
_go32_dpmi_registers kbd_regs;
int kbd_hooked=0;
void kbd_hook()
{
int err;
/* protected mode install */
/* just a precaution */
if (kbd_hooked) {printf("error: keyboard already hooked\n"); exit(0);}
/* the ISR needs %ds */
ds_save=_go32_my_ds();
/* save old PM vector */
err=_go32_dpmi_get_protected_mode_interrupt_vector(9, &old_pm_kbd_irq);
if (err) {printf("error: failed to get pm interrupt vector\n"); exit(0);}
/* setup new PM vector */
new_kbd_irq.pm_selector=_go32_my_cs();
new_kbd_irq.pm_offset=(intu32) kbd_pm_isr;
printf("new pm int9 vector %04x:%08lx\n",
new_kbd_irq.pm_selector, new_kbd_irq.pm_offset);
/* hook it */
err=_go32_dpmi_set_protected_mode_interrupt_vector(9, &new_kbd_irq);
if (err) {printf("error: failed to set pm interrupt vector\n"); exit(0);}
/* real mode install */
/* save old RM vector */
err=_go32_dpmi_get_real_mode_interrupt_vector(9, &old_rm_kbd_irq);
if (err) {printf("error: failed to get rm interrupt vector\n"); exit(0);}
printf("old rm int9 vector %04x:%04x\n",
old_rm_kbd_irq.rm_segment, old_rm_kbd_irq.rm_offset);
/* setup new RM vector via callback */
kbd_callback.pm_selector=_go32_my_cs();
kbd_callback.pm_offset=(intu32) kbd_rm_isr;
err=_go32_dpmi_allocate_real_mode_callback_iret(&kbd_callback, &kbd_regs);
if (err) {printf("error: failed to allocate rm callback\n"); exit(0);}
printf("rm iret callback allocated at %04x:%04x\n",
kbd_callback.rm_segment, kbd_callback.rm_offset);
printf("callback calls %04x:%08lx\n",
kbd_callback.pm_selector, kbd_callback.pm_offset);
/* hook the callback */
err=_go32_dpmi_set_real_mode_interrupt_vector(9, &kbd_callback);
if (err) {printf("error: failed to set rm interrupt vector\n"); exit(0);};
/* just a test to make sure it worked */
err=_go32_dpmi_get_real_mode_interrupt_vector(9, &new_kbd_irq);
printf("new rm int9 vector %04x:%04x\n",
new_kbd_irq.rm_segment, new_kbd_irq.rm_offset);
kbd_hooked=1;
}
---------- program "debugging" output ----------
new pm int9 vector 00d8:00002976
old rm int9 vector 09cf:2f95
rm iret callback allocated at 09cf:2d82
callback calls 00d8:0000297c
new rm int9 vector 09cf:2d82
--
----------------------------------------------------------------------
: Christopher : Huntington Beach California, USA :
: Christensen : email: cnc AT netcom DOT com :
----------------------------------------------------------------------
- Raw text -