2014-12-08 1 views
1

내 프로그램에서 사용자가 F1-12와 같은 특수 키 스트로크를 누르면 인터럽트를 수신하려고합니다.이 프로그램은 nasm으로 작성되었습니다. 필자는 주요 기능을 시작할 때 기능 키 입력을 기다릴 필요가 있습니다. 나는 이것이 BIOS의 int 16h에서 가능하다는 것을 알고 있으며, 이는 스캔 코드를 반환한다. 리눅스에서 어떻게이 일을 할 수 있습니까?Linux에서 syscall을 사용하여 키 스트로크 인터럽트를 기다리는 방법은 무엇입니까?

+0

쉽지 않습니다! 이것은 당신을 도울 수 있습니다 : http://www.unusedino.de/linuxassembly/articles/rawkb.html –

+0

고마워요, 나는 이것을 시도하고 작동하지 않습니다, 나는/dev/tty도 시도했습니다 - 결과가 없습니다. – freakz

답변

2

필요한 코드는 다소 복잡합니다. 나는 결국 원시 ioctl, 읽기 및 쓰기로 C에서 F1을 검사하는 방법을 알아 냈습니다. 어셈블리 및 Linux 시스템 콜에 익숙하다면 nasm으로의 변환은 간단해야합니다.

F1이 아닌 나머지 부분 만 검사한다는 점에서 원하는 것은 아닙니다. F1의 시퀀스는 0x1b, 0x4f, 0x50입니다. od -t x1으로 다른 시퀀스를 찾아서 키를 누를 수 있습니다. 예를 들어, F2는 0x1b, 0x4f, 0x51입니다.

기본 개념은 현재 터미널 속성을 가져 와서 nonblocking 및 raw (cfmakeraw)로 업데이트 한 다음 다시 설정한다는 것입니다. ioctl syscall이 이에 사용됩니다.

#include <unistd.h> 
#include <sys/ioctl.h> 
#include <termios.h> 

struct ktermios { 
    tcflag_t c_iflag; 
    tcflag_t c_oflag; 
    tcflag_t c_cflag; 
    tcflag_t c_lflag; 
    cc_t c_line; 
    cc_t c_cc[19]; 
}; 

int getch() { 
    unsigned char c; 
    read(0, &c, sizeof(c)); 
    return c; 
} 

int main(int argc, char *argv[]) { 
    struct ktermios orig, new; 
    ioctl(0, TCGETS, &orig); 
    ioctl(0, TCGETS, &new); 

    // from cfmakeraw documentation 
    new.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); 
    new.c_oflag &= ~OPOST; 
    new.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 
    new.c_cflag &= ~(CSIZE | PARENB); 
    new.c_cflag |= CS8; 

    ioctl(0, TCSETS, &new); 

    while (1) { 
     if (getch() == 0x1b && getch() == 0x4f && getch() == 0x50) { 
      break; 
     } 
    } 

    write(1, "Got F1!\r\n", 9); 
    ioctl(0, TCSETS, &orig); 
    return 0; 
} 

나는 이것을 this answer에 기반하여 매우 유용했습니다.

관련 문제