Welcome to My World (www.dgmayor.com)

소프트웨어/C & 자료구조 & 커널 & DB

15. 인터럽트 - 키보드 드라이버 2

dgmayor 2022. 6. 14. 11:22
728x90
 

14 ~ 15 강 소스코드입니다.
 
 
 
--------------------------------------------------------------------------------
 

자 저번 강의에 이어서 ScanCode를 아스키코드로 바꾸는 작업을 진행해봅시다.
 
interrupt.h에 다음과 같은 함수를 하나 선언해줍시다.
( ScanCode가 담긴 char 형을 받아 아스키값을 리턴해줄겁니다. )
 
 
 
unsigned char transScan(unsigned char);
 
 

그리고 이 함수를 interrupt.c 에 다음과 같이 구현해봅시다.
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
unsigned char transScan(unsigned char target)
{
    unsigned char result;
 
    switch (target) 
    {
    case 0x1E: result = 'a'break;
    case 0x30: result = 'b'break;
    case 0x2E: result = 'c'break;
    case 0x20: result = 'd'break;
    case 0x12: result = 'e'break;
    case 0x21: result = 'f'break;
    case 0x22: result = 'g'break;
    case 0x23: result = 'h'break;
    case 0x17: result = 'i'break;
    case 0x24: result = 'j'break;
    case 0x25: result = 'k'break;
    case 0x26: result = 'l'break;
    case 0x32: result = 'm'break;
    case 0x31: result = 'n'break;
    case 0x18: result = 'o'break;
    case 0x19: result = 'p'break;
    case 0x10: result = 'q'break;
    case 0x13: result = 'r'break;
    case 0x1F: result = 's'break;
    case 0x14: result = 't'break;
    case 0x16: result = 'u'break;
    case 0x2F: result = 'v'break;
    case 0x11: result = 'w'break;
    case 0x2D: result = 'x'break;
    case 0x15: result = 'y'break;
    case 0x2C: result = 'z'break;
    case 0x39: result = ' 'break// 스페이스
    case 0x0E: result = 0x08break// 백스페이스 아스키코드 = 8
    default: result = 0xFFbreak
        // 구현안된 것은 무시한다. 구분자는 0xFF
    }
    return result;
}
 
cs
 

철저한 노가다(...)의 산물입니다만... 어찌되었던 이제 스캔코드가 아스키코드로 변환되어 나올 겁니다!
0x08은 아스키로 백스페이스에 해당됩니다. 그리고 나머지 스캔코드 값들 ( 때는 것까지 포함해서! )은 0xFF로 돌려줍시다. 그리고 0xFF로 리턴한 경우 가볍게 무시(...)하면 됩니다.
 
무슨 말인지 모르겠다구요? int_keyboard()에 구현된 것을 보면 바로 이해할 수 있을 겁니다. 그 전에 특정 라인에 써진 문자들을 모두 지워주는 kprintf_line_clear() 함수를 function.h와 function.h에 각각 추가합시다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
// function.h 에 추가
void kprintf_line_clear(int); 
 
// function.c에 추가
void kprintf_line_clear(int line)
{
    char *video = (char*)(0xB8000 + 160 * line);
    for (int i = 0; i < 160 ; i++)
    {
        *video++ = 0;
        *video++ = 0x03;
    }
}
cs

 
--------------------------------------------------------------------------------
 

좋습니다! 이제 idt_keyboard를 다음과 같이 수정합시다.
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// interrupt.c 맨 상단에 추가
static unsigned char keyboard[160= { 0, };
static unsigned short index = 0;
 
void idt_keyboard()
{
 
    __asm__ __volatile__
    (
        "push gs;"
        "push fs;"
        "push es;"
        "push ds;"
        "pushad;"
        "pushfd;"
        "xor al,al;"
        "in al, 0x60;"
    );
 
    __asm__ __volatile__("mov %0, al;" :"=r"(keybuf) );
    
    keybuf = transScan(keybuf);
 
    if (keybuf == 0x08 && index != 0 ) // 백스페이스 입력
        keyboard[--index] = 0;
    else if (keybuf != 0xFF && keybuf != 0x08)
        keyboard[index++= keybuf;
 
    kprintf_line_clear(8);
    kprintf(keyboard,8,0);
 
    __asm__ __volatile__
    (
        "mov al, 0x20;"
        "out 0x20, al;"
    );
 
    __asm__ __volatile__
    (
        "popfd;"
        "popad;"
        "pop ds;"
        "pop es;"
        "pop fs;"
        "pop gs;"
        "leave;"
        "nop;"
        "iretd;"
    );
 
}
 
 
cs
 
 

keyboard 버퍼에 index 값을 적절히 조절하면서 하나씩 쌓아가는 모습입니다. 이 때 백스페이스를 입력했을 때에는 index 값을 빼고 0을 저장함으로서 버퍼 값을 하나 날리는 것을 확인할 수가 있습니다.
 
이렇게 만들어진 버퍼를 8줄에 출력합니다. ( 그 전에 clear 함수를 불러 해당 열에 있는 모든 잔상을 지워버립니다. )
 
자! 이제 키보드로부터 입력받을 모든 준비가 끝났습니다! 컴파일하고 실행해봅시다!
 
 
 
 
 

감격의 도가니탕이 아닐 수 없군요. DOS나 Linux shell 과 똑같이 영문 입력이 가능하고 또 자유롭게 지울 수도 있습니다!!
 
이렇게해서 키보드 디바이스 드라이버를 구현해봤습니다. 사실상 영문 소문자만 입력가능하고 대문자나 숫자, 느낌표나 따옴표 등등 입력이 안되는 허접한 드라이버입니다. 하지만 운영체제 자체를 만드는 데 의의를 두고 계속 진행해보도록 하겠습니다.
( 원리를 알았으니 좀 더 디테일하게 만드는 것은 시간문제겠죠? 스스로 수정해서 더 나은 드라이버를 만들어보세요 )
 
다음 강의에서는 HoGoS 만의 Shell을 만들어보도록 하겠습니다. 처음에는 허접한 명령어만 소화할 겁니다. 하지만 파일시스템, 프로세스, 메모리 등등을 구현하면서 점점 더 많은 명령어를 지원하게 될 겁니다.
 
감사합니다.
728x90