Mail Archives: djgpp/2003/05/27/09:15:19
Ethan Rosenberg wrote:
> Is anyone aware of a C program which will write a string directly to the
> keyboard buffer?
>
> Thank you.
>
> Ethan Rosenberg
>
>
There probably is.
If you want to make one yourself (why would you be here otherwise?):
There are at least two ways. One way will write to the circular BIOS
keyboard buffer, and will work on all IBM compatible PCs, but will not
work with programs that bypass the BIOS. The second will only work with
some PCs, but can make programs that bypass the BIOS see the keys.
The first method requires dosmemget and dosmemput.
The second method requires direct access to the keyboard ports and a
keyboard controller that can have a scancode stuffed into it (MCA
compatible controllers).
/*
* stuffs a key into the BIOS circular keyboard buffer.
* The keycode is a two-byte value.
* returns -1 on failure, the keycode on success
*/
int stuff_bios_key (short key){
int firstfree, next, start, end, newkeypos, newkey;
ptr = 0;
newkey = key;
/* get first free slot */
_dosmemgetw (0x41C, 1, &newkeypos);
/* get next character slot */
_dosmemgetw (0x41A, 1, &next);
/* get start of keyboard buffer */
_dosmemgetw (0x480, 1, &start);
/* get end of keyboard buffer */
_dosmemgetw (0x482, 1, &end);
/* check firstfree against next */
firstfree = (newkeypos + 2 - start) % (end - start) + start;
/* if there is a space available, then insert the keycode */
if (((firstfree < next) ? next - firstfree : firstfree - next) > 1){
_dosmemputw (&firstfree, 1, 0x41C);
_dosmemputw (&newkey, 1, 0x400 + newkeypos);
_dosmemgetw (0x400 + newkeypos, 1, &newkey);
/*
* if there was no space available, or the write silently failed,
* then fail, otherwise succeed
*/
if (newkey == key){
return key;
}
return -1;
}
/*
* stuffs a scancode into the keyboard controller.
* returns -1 on failure, the scancode on success
*/
int stuff_hardware_key (char scancode){
char ret, curscan;
int iter;
/* get the current scancode, for checking */
curscan = inportb (0x60);
/* send the controller the command to write kbd output buffer */
outportb (0x64, 0xD2);
/* wait for controller to be ready for next write */
while ((inportb (0x64) & 2) != 0);
/* write scancode to keyboard output buffer */
outportb (0x60, scancode);
/* check that write succeeded */
for (iter = 0;
iter < 10000 && (ret = inportb (0x60)) == curscan;
iter++);
/*
* if the controller sent the scancode or an acknowledge,
* and did not send a resend, then succeed, otherwise
* fail.
*/
if (ret == 0xFE || (ret != scancode && ret != 0xFA)){
return -1;
} else {
return scancode;
}
}
- Raw text -