12. 키보드 디바이스 드라이버를 업그레이드하자

들어가기

데이터를 전달하는 큐를 구현해 인터럽트 핸들러에서 셸 코드로 키 정보를 전달.

본론

12.1 인터럽트 핸들러와 큐

12.1.1 인터럽트 핸들러와 어떻게 통신할까?

  • 인터럽트 핸들러는 디바이스에서 읽은 데이터를 버퍼에 저장하고, 프로그램은 버퍼를 확인하여 이를 처리.

12.1.2 큐란 무엇인가?

  • FIFO 구조의 자료구조.

12.1.3 범용 큐 설계

  • 범용 큐의 설계에 있어서 두 가지 상황을 고려.
    • 삽입이나 제거한 뒤에 위치가 버퍼의 최댓값을 초과하는 경우.
    • 삽입하거나 제거한 뒤에 두 위치가 같아지는 경우.
  • 전자는 인덱스를 다시 처음으로 되돌려 환형 큐 형식으로 설계.
  • 후자는 다시 두 가지 상황을 고려.
    • 제거 동작을 수행한 후 두 위치가 같아지는 경우.
    • 삽입 후 두 위치가 같아지는 경우.

12.1.4 범용 큐 구현과 사용 방법

typedef struct kQueueManagerStruct {
    int iDataSize;
    int iMaxDataCount;

    void* pvQueueArray;
    int iPutIndex;
    int iGetIndex;

    // 큐에 수행된 마지막 명령이 삽입인지 저장인지 확인.
    bool bLastOperationPut;
}QUEUE;
  • bLastOperationPut 필드는 삽입 위치와 제거 위치가 같아지는 경우를 처리하려고 추가한 필드.
  • 삽입 동작을 수행할 때 True, 제거 동작을 수행할 때 False.
 void kInitializeQueue(QUEUE* pstQueue, void* pvQueueBuffer, int iMaxDataCount, int iDataSize) {
    pstQueue -> iMaxDataCount = iMaxDataCount;
    pstQueue -> iDataSize = iDataSize;
    pstQueue -> pvQueueArray = pvQueueBuffer;

    pstQueue -> iPutIndex = 0;
    pstQueue -> iGetIndex = 0;
    pstQueue -> bLastOperationPut = FALSE;
 }
  • 초기화하는 함수는 큐 버퍼 어드레스와 데이터의 크기를 설정하고 나머지 필드를 0으로 설정.

12.2 키보드 디바이스 드라이버 업그레이드

12.2.1 키 정보를 저장하는 자료구조와 큐 생성

typedef struct kKeyDataStruct {
    // 키보드에서 전달된 스캔 코드
    BYTE bScanCode;
    // 변환한 아스키 코드
    BYTE bASCIICode;
    // 키 상태를 저장하는 플래그
    BYTE bFlags;
}KEYDATA;
  • 키 정보를 전달하는데 사용할 자료구조.
  • 전체 코드는 12.3 참조.

12.2.2 키보드 핸들러 수정

  • 전체 코드는 12.3 참조.

12.2.3 셀 코드 수정

  • 전체 코드는 12.3 참조.

12.3 키보드 디바이스 드라이버의 업그레이드와 빌드

12.3.1 큐 파일 추가

Queue.c 코드 보기
Queue.h 코드 보기

12.3.2 키보드 디바이스 드라이버 파일 수정

Keyboard.c 코드 보기
Keyboard.h 코드 보기

12.3.3 인터럽트 핸들러 파일과 유틸리티 파일 수정

InterruptHandler.c 코드 보기

12.3.4 C 언어 커널 엔트리 포인트 파일 수정

Utility.c 코드 보기
Utility.h 코드 보기

12.3.5 빌드와 실행

마치며

끝.

Share