termios and keyboard medium raw mode



Hi

I wrote the following program that reads the keyboard in medium raw
mode (keycode mode). Here is the initialization code, the full code is
at the end.

fd = open("/dev/tty0", O_RDONLY);
tcgetattr ( fd, &newkbd );
newkbd.c_lflag &= ~ (ECHO | ICANON | ISIG);
newkbd.c_iflag = 0;
newkbd.c_cc[VMIN] = 18;
newkbd.c_cc[VTIME] = 1;
tcsetattr ( fd, TCSAFLUSH, &newkbd );
ioctl ( fd, KDSKBMODE, K_MEDIUMRAW );

It's suppose to control the value of linvel and rotvel (linear and
rotational velocity) when the user presses the arrow keys or the WASD
keys. To handle multi keys at the same time, I set the value when the
user presses the key, and reset it to 0 on release.

However it doesn't work. Let say I press UP, then RIGHT while
maintaining UP pressed, then release UP while maintaining RIGHT
pressed, then release RIGHT. In that case, I receive the following
events: UP pressed, RIGHT pressed, Right released. UP released is
missing. What am I doing wrong? Can you suggest another way of doing
this?

Also, the terminal keeps scrolling down, as if I was constantly
pressing ENTER. Why? Besides, I have to run this code as super user,
which is not really nice...

I am using linux, kernel 2.6.22 and gcc. Portability is not an issue.



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include <linux/keyboard.h>

int fd=-1, oldkbmode=K_RAW;
struct termios orig_kb;
float linvel=0, rotvel=0;

void clean_up ( void ) {
ioctl ( fd, KDSKBMODE, oldkbmode );
tcsetattr ( fd, 0, &orig_kb );
close ( fd );
}

void printVel(int i) {
printf("%f %f\n", linvel, rotvel);
alarm(1);
}

int main(){
int keycode, pressed, controlPressed=0;
unsigned char buf[18]; /* divisible by 3 */
int i,n;
struct termios newkbd;

/* Open and configure the keyboard */
fd = open("/dev/tty0", O_RDONLY);
tcgetattr ( fd, &orig_kb );
tcgetattr ( fd, &newkbd );
newkbd.c_lflag &= ~ (ECHO | ICANON | ISIG);
newkbd.c_iflag = 0;
newkbd.c_cc[VMIN] = 18;
newkbd.c_cc[VTIME] = 1;
tcsetattr ( fd, TCSAFLUSH, &newkbd );

/* Set medium raw mode: we receive keycodes. */
ioctl ( fd, KDGKBMODE, &oldkbmode );
ioctl ( fd, KDSKBMODE, K_MEDIUMRAW );

/* Restore the normal keyboard mode on exit */
atexit(clean_up);

/* Every 1 second, print the value of linvel and rotvel */
signal(SIGALRM, printVel);
alarm(1);

while( 1 ){
/* Wait until a key is pressed or released */
n = read ( fd, buf, sizeof ( buf ) );

/* Retrieve the key code and whether the key was pressed or
released */
i = 0;
while ( i < n ) {
pressed = (buf[i] & 0x80)==0x80 ? 0 : 1;
if ( i+2 < n && ( buf[i] & 0x7f ) == 0
&& ( buf[i+1] & 0x80 ) != 0 && ( buf[i+2] & 0x80 ) != 0 )
{
keycode = ( ( buf[i+1] & 0x7f ) << 7 ) | ( buf[i+2] & 0x7f );
i += 3;
}
else keycode = ( buf[i++] & 0x7f );
}

/* Take appropriate action */
switch ( keycode ) {
case 103: //UP ARROW
case 17: //W
linvel = pressed ? 1 : 0;
break;
case 108: //DOWN ARROW
case 31: //S
linvel = pressed ? -1 : 0;
break;
case 105: //LEFT ARROW
case 30: //A
rotvel = pressed ? -1 : 0;
break;
case 106: //RIGHT ARROW
case 32: //D
rotvel = pressed ? 1 : 0;
break;
case 29: //CTRL
controlPressed = pressed;
break;
case 46: //C
if( controlPressed && pressed ) exit(0);
break;
}
}
return 0;
}
.



Relevant Pages

  • How to detect multiple simultaneous key presses? And a thread question
    ... detect multiple simultaneous key presses in C# let me know (in the ... keys c and d being pressed simultaneously or nearly so). ... public bool externalBoolMagicNumber; ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: keypad scanner
    ... >> Or four keys pressed along a diagonal. ... Without diodes, ... but wnen it's low it's pulled low. ... >multiple key presses? ...
    (comp.arch.embedded)
  • Re: security code
    ... allowed to press either single keys or a pair of number keys ...  Two consecutive keypresses could be replaced by a double ... keypress at any of 4 places in the sequence, but then the order of the ... sequence in any of 3 ways (the sequence of double and single presses ...
    (rec.puzzles)
  • Re: Detecting shift/alt keys
    ... >>>How do I detect when a user presses the shift or alt keys? ...
    (comp.lang.pascal.delphi.misc)
  • two questions - no common theme
    ... I'd like to be able to bind callbacks to presses of the arrow ... Peace, ...
    (comp.lang.python)