delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2003/05/27/09:15:19

From: Ben Peddell <killer DOT lightspeed AT bigpond DOT com>
User-Agent: Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.1) Gecko/20020826
X-Accept-Language: en-us, en
MIME-Version: 1.0
Newsgroups: comp.os.msdos.djgpp
Subject: Re: Keyboard Buffer
References: <3 DOT 0 DOT 1 DOT 16 DOT 20030527000004 DOT 40ff90b4 AT earthlink DOT net>
Lines: 88
Message-ID: <ziJAa.44364$1s1.597903@newsfeeds.bigpond.com>
Date: Tue, 27 May 2003 23:10:02 +1000
NNTP-Posting-Host: 144.139.176.234
X-Trace: newsfeeds.bigpond.com 1054040351 144.139.176.234 (Tue, 27 May 2003 22:59:11 EST)
NNTP-Posting-Date: Tue, 27 May 2003 22:59:11 EST
Organization: Telstra BigPond Internet Services (http://www.bigpond.com)
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

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 -


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