· 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 */

ID
Password
Join
The Tree of Learning bears the noblest fruit, but noble fruit tastes bad.


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.0038 sec