From: cnc AT netcom8 DOT netcom DOT com (Christopher Christensen) Date: Thu, 27 Jan 1994 16:39:46 PST To: djgpp AT sun DOT soe DOT clarkson DOT edu Subject: keyboard ISR/real mode callback problems... 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 : ----------------------------------------------------------------------