== 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¹ø ¿¬¼Ó ´©¸£¸é ºüÁ®³ª¿É´Ï´Ù. * ÁÖÀÇ! : ÀÌ°ÍÀ» ¹é±×¶ó¿îµå ¸ðµå·Î ½ÇÇàÇϽøé ÇÁ·Î±×·¥ÀÌ ºñ Á¤»ó Á¾·á°¡ µÉ°Ì´Ï´Ù. [Ç¥ÁØÀÔ·Â ¼ÒÀ¯±Ç °Ë»ç(¹é±×¶ó¿îµå °Ë»ç)]¸¦ ÂüÁ¶ÇÏ½Ã°í ¾îµð°¡ ¾î¶² ÀÌÀ¯¿¡¼­ ±×·± °á°ú¸¦ ¹ß»ýÇÏ´ÂÁö¸¦ È®ÀÎÇϽðí ÀÚ½ÅÀÇ °ÍÀ¸·Î ¸¸µé¾î º¸¼¼¿ä. {{{#!vim c /* Code by JaeHyuk Cho Made in KOREA http://minzkn.pe.ky */ #ifndef DEF_SOURCE_mzplugin_vt_c #define DEF_SOURCE_mzplugin_vt_c "mzplugin_vt.c" #include #include #include #include #include #include #include #include #include #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 */ }}}