termios and keyboard medium raw mode

Discussion in 'C Programming' started by Brice Rebsamen, Mar 13, 2008.

  1. 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 & 0x80)==0x80 ? 0 : 1;
    if ( i+2 < n && ( buf & 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;
    }
     
    Brice Rebsamen, Mar 13, 2008
    #1
    1. Advertising

  2. Kenny McCormack, Mar 13, 2008
    #2
    1. Advertising

  3. Brice Rebsamen

    Mark Bluemel Guest

    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.programmer would probably be a good start.
     
    Mark Bluemel, Mar 13, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John J Lee
    Replies:
    3
    Views:
    509
    bruno at modulix
    Dec 1, 2005
  2. Edward Loper
    Replies:
    0
    Views:
    491
    Edward Loper
    Aug 7, 2007
  3. John J Lee
    Replies:
    0
    Views:
    537
    John J Lee
    Aug 7, 2007
  4. Edward Loper

    mmm-mode, python-mode and doctest-mode?

    Edward Loper, Aug 9, 2007, in forum: Python
    Replies:
    0
    Views:
    448
    Edward Loper
    Aug 9, 2007
  5. Neal Becker
    Replies:
    0
    Views:
    393
    Neal Becker
    Aug 9, 2007
Loading...

Share This Page