· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Virtual Terminal Keyboard

Virtual terminal 입력

  • VT(tty)로부터 글자를 입력받는 예제 입니다. 이것은 많은 분들이 궁굼해 하는 부분으로 알고 있습니다. 좋은 참고자료 되기를 바랍니다.
  • 대부분의 구현설명은 termios사용법에 대한 문서를 찾아보시면 그리 어렵지 않게 구현 가능합니다. 필자는 "man termios"에서 이러한 방법을 찾았습니다.
  • 해당 참고 자료로는 "/usr/include/linux/vt.h" 및 "/usr/include/linux/kd.h" 를 참조하시면 여러가지 다양한 기능을 사용할수 있습니다.
  • 아래의 예제는 단점이 한가지 있는데 일부 키를 입력받지 못합니다. 예를 들면 "한/영" 키를 예로 들수 있습니다. 이것을 입력받도록 하려면 VT mode를 사용하면 방법이 없는듯 하며 K_RAW mode를 사용해야 합니다. 또한 이를 사용하게 되면 키보드 코드가 Scan code로 입력이 들어옵니다. 또한 struct vt_mode를 사용하는 것이 아니고 ioctl cmd KDGKBMODE를 사용하여 전환하게 합니다. 즉, 아래의 예제에서 ioctl 부분을 전부 KDGKBMODE, KDSKBMODE 로 바꿔줘야 합니다. 이에 대한 모드로는 /usr/include/linux/kd.h 에 그 내용이 있으니 참조 하시기 바랍니다.
  • 경우에 따라서는 Serial console상에서 입력 받는 키보드 및 별도의 psaux를 통한 키보드 2가지를 동시에 처리할 경우가 있습니다. 필자가 만든 프로그램이 그런적이 있었는데 이때는 /dev/tty, /dev/console 2개를 매핑하여 작용하도록 한적이 있습니다. 사실 대부분은 이 2가지의 디바이스를 다루면 거의 모든 키보드 입력이 이뤄지지만 경우에 따라서는 다른 경우도 있습니다. 하지만 결국 termios 의 사용에 대해서는 아래의 예제와 맥락이 거의 동일합니다. 중요한것은 키보드 디바이스 이름이 어떤것이냐와 키보드를 다룰때 어떤 MODE를 사용하는가를 결정하면 된다는 예기가 되겠습니다.
  • 프로그램 종료키는 Escape 를 2번 연속 누르면 빠져나옵니다.
  • 주의! : 이것을 백그라운드 모드로 실행하시면 프로그램이 비 정상 종료가 될겁니다. 표준입력 소유권 검사(백그라운드 검사)를 참조하시고 어디가 어떤 이유에서 그런 결과를 발생하는지를 확인하시고 자신의 것으로 만들어 보세요.

/* Code by JaeHyuk Cho <mailto:minzkn@infoeq.com> Made in KOREA http://minzkn.pe.ky */ #ifndef DEF_SOURCE_mzplugin_vt_c #define DEF_SOURCE_mzplugin_vt_c "mzplugin_vt.c" #include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <malloc.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> #include <termios.h> #include <sys/vt.h> #ifndef t_MZ_VT typedef struct ts_VT { int Handle, InitLevel; struct termios NewTermios, OldTermios; struct vt_mode NewMode, OldMode; }t_VT; #define t_VT t_VT #endif t_VT *MZ_OpenVT(void); t_VT *MZ_CloseVT(t_VT *s_Handle); int MZ_ReadVT(t_VT *s_Handle, int s_TimeOut /* mSec */); static void __MZ_CopyMemory__(void *s_To, const void *s_From, int s_Size) { #ifdef WIN32 (void)memcpy(s_To, s_From, (size_t)s_Size); #else __asm__ volatile( "\n\t" "cld\n\t" "shrl $1, %2\n\t" "jnc 0f\n\t" "movsb %%ds:(%1), %%es:(%0)\n\t" "0:\n\t" "shrl $1, %2\n\t" "jnc 0f\n\t" "movsw %%ds:(%1), %%es:(%0)\n\t" "0:\n\t" "repz movsl %%ds:(%1), %%es:(%0)\n\t" "\n\t" : : "D"(s_To), "S"(s_From), "c"(s_Size) ); #endif } t_VT *MZ_OpenVT(void) { const char c_DefaultTTY[] = {"/dev/tty"}; t_VT *s_Return; int s_IsOK = 0; char *s_TTY_Name; s_Return = (t_VT *)malloc(sizeof(t_VT)); if(s_Return) { s_Return->InitLevel = 0; s_TTY_Name = ttyname(STDIN_FILENO); s_Return->Handle = open(s_TTY_Name ? s_TTY_Name : c_DefaultTTY, O_RDONLY | O_NOCTTY); if(s_Return->Handle != (-1)) { s_Return->InitLevel |= 0x00000001; if(ioctl(s_Return->Handle, VT_GETMODE, (void *)(&s_Return->OldMode)) != (-1)) { s_Return->InitLevel |= 0x00000002; __MZ_CopyMemory__((void *)(&s_Return->NewMode), (void *)(&s_Return->OldMode), sizeof(struct vt_mode)); s_Return->NewMode.mode = VT_PROCESS; if(ioctl(s_Return->Handle, VT_SETMODE, (void *)(&s_Return->NewMode)) != (-1)) { s_Return->InitLevel |= 0x00000004; } } /* else fprintf(stdout, "ioctl set VT_MODE error !\n"); */ if(tcgetattr(STDIN_FILENO, (struct termios *)(&s_Return->OldTermios)) != (-1)) { s_Return->InitLevel |= 0x00000008; /* 3 */ __MZ_CopyMemory__((void *)(&s_Return->NewTermios), (void *)(&s_Return->OldTermios), sizeof(struct termios)); s_Return->NewTermios.c_iflag &= (~BRKINT); s_Return->NewTermios.c_iflag |= (IGNBRK); s_Return->NewTermios.c_lflag &= (~( ISIG | ECHO | ICANON )); tcsetattr(STDIN_FILENO, TCSANOW, (struct termios *)(&s_Return->NewTermios)); s_IsOK = 1; } else fprintf(stdout, "get tcgetattr error !\n"); } if(s_IsOK == 0)s_Return = MZ_CloseVT(s_Return); } return(s_Return); } t_VT *MZ_CloseVT(t_VT *s_Handle) { if(s_Handle) { if(s_Handle->Handle != (-1)) { if((s_Handle->InitLevel & 0x00000008)) { tcsetattr(STDIN_FILENO, TCSANOW, (struct termios *)(&s_Handle->OldTermios)); tcflush(s_Handle->Handle, TCIOFLUSH); } if((s_Handle->InitLevel & 0x00000004))ioctl(s_Handle->Handle, VT_SETMODE, (void *)(&s_Handle->OldMode)); if((s_Handle->InitLevel & 0x00000001))close(s_Handle->Handle); } free(s_Handle); s_Handle = (t_VT *)0; } return(s_Handle); } int MZ_ReadVT(t_VT *s_Handle, int s_TimeOut /* mSec */) { int s_Return = (-1), s_ReadBytes; fd_set s_FD_Read; struct timeval s_LocalTimeVal; unsigned char s_Byte; if(s_Handle) { if(s_Handle->Handle != (-1)) { if(s_TimeOut > 0) { /* Select */ s_LocalTimeVal.tv_sec = s_TimeOut / 1000, s_LocalTimeVal.tv_usec = (s_TimeOut % 1000) * 1000; FD_ZERO(&s_FD_Read); FD_SET(s_Handle->Handle, &s_FD_Read); if(select(s_Handle->Handle + 1, (fd_set *)(&s_FD_Read), (fd_set *)0, (fd_set *)0, (struct timeval *)(&s_LocalTimeVal)) > 0) { if(FD_ISSET(s_Handle->Handle, &s_FD_Read)) { if(read(s_Handle->Handle, (void *)(&s_Byte), sizeof(s_Byte)) > 0)s_Return = (int)s_Byte; } } } else { /* Block */ s_ReadBytes = read(s_Handle->Handle, (void *)(&s_Byte), sizeof(s_Byte)); if(s_ReadBytes > 0)s_Return = (int)s_Byte; } } } return(s_Return); } int main(void) { int s_Return = 0, s_Escape, s_Key; t_VT *s_VT; s_VT = MZ_OpenVT(); if(s_VT) { fprintf(stdout, "Use VT : Handle=%d\n", s_VT->Handle); s_Escape = 0; while(1) { s_Key = MZ_ReadVT(s_VT, 8000); if(s_Key >= 0) { if(s_Key == 0x1b)s_Escape++; else s_Escape = 0; fprintf(stdout, "[%c(0x%02x)]\n", (s_Key < 0x20 || s_Key >= 0x7f) ? '.' : s_Key, s_Key); } else fprintf(stdout, "Wait for key : 'ESC' key double press to exit.\n"); if(s_Escape >= 2)break; } s_VT = MZ_CloseVT(s_VT); } else fprintf(stdout, "Can not open VT !\n"); return(s_Return); } #endif /* End of source */



sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2004-12-04 20:53:31
Processing time 0.0052 sec