termios and keyboard medium raw mode

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Brice Rebsamen

    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;
    }
  • Kenny McCormack

    #2
    Re: termios and keyboard medium raw mode

    In article <91e22c96-9007-4eda-bd93-6eca084ebb1b@e6 g2000prf.google groups.com>,
    Brice Rebsamen <brice.rebsamen @gmail.comwrote :
    >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);
    (With love and affection)

    Off topic. Not portable. Cant discuss it here. Blah, blah, blah.

    --
    Useful clc-related links:





    Comment

    • Mark Bluemel

      #3
      Re: termios and keyboard medium raw mode

      Brice Rebsamen wrote:
      Hi
      >
      I wrote the following program that reads the keyboard in medium raw
      mode (keycode mode).
      [Snip]
      I am using linux, kernel 2.6.22 and gcc. Portability is not an issue.
      I suggest you try a group appropriate to your platform, as this question
      is about platform-specifics rather than the C language.

      comp.unix.progr ammer would probably be a good start.

      Comment

      Working...