Skip to content

Instantly share code, notes, and snippets.

@phongvh
Last active September 5, 2021 10:08
Show Gist options
  • Save phongvh/4bab143533d8d75f907c5096e3c2caef to your computer and use it in GitHub Desktop.
Save phongvh/4bab143533d8d75f907c5096e3c2caef to your computer and use it in GitHub Desktop.

Getting scancode from a PS/2 keyboard

Keyboard is a basic input device containing a organised matrix switches in them.The keyboard is a basic input device connected to the CPU through a PS/2 or USB or a serial port.The data sent by the keyboard is received by a micro-controller chip(8042 or 8048) on the System's motherborad.This micro-controller is the chip which controls and manages the incomming and outgoing data of the keyboard.A PS/2 mouse is also controlled by the same micro-controller(i.e; 8042 or 8048).

How it works???

When a key is pressed , the keyboard sends a signal to the micro controller telling that a key was pressed .Then the controller fires an IRQ 1 to the Programmable Interrupt Controller and keeps the data ready in the (0x60 port) buffer which then will be read by the operating system.

Job of the Operating System :

The operating system must collect the data from the port "0x60"(Keyboard Data port) whenever an IRQ 1 is fired.This interrupt is fired by the micro-controller when data is ready to be read.The data sent by the microcontroller when a key is pressed is known as a scancode. The operating system then must convert the scancode into a ASCII Value to know what key was pressed.

The extra uses of the keyboard micro-controller:

This controller is used to control the keyboard and the mouse.There are many other uses of this micro controller.This micro-controller chip also helps in enabling A_20 gate ,rebooting or halting,and also helps in managing the speaker along with the Programmable Interval Timer and more.

**IO Ports:
0x60 :Data Register(Read\Write)
0x64:Command Register(Read\Write) **

Examples in C(Protected Mode only)

Enabling/Disabling or Restarting the keyboard:

unsigned int restart_keyboard()
{    
   int data = inportb(0x61);     
   outportb(0x61,data | 0x80);//Disables the keyboard  
   outportb(0x61,data & 0x7F);//Enables the keyboard  
   return 0;
}

Getting the scancode from keyboard controller:

unsigned char get_scancode()
{
    unsigned char inputdata;
    intputdata = inportb(KEYMOS_DATAREG );
    return inputdata;
}

Processing the scancode:

unsigned char kblayout [128] { ... }//Fill your layout yourself 
void keyboard_handler(struct regs *r)
{ 
     unsigned char scancode; 
     unsigned int shift_key = 0;
     scancode = get_scancode();
     if(scancode == 0x2A)     
     {
          shift_key = 1;//Shift key is pressed
     }      
     else if(scancode & 0xAA)
     {
          int shift_key= 0;//Shift Key is not pressed
     }      
     else    
     {          
         if (scancode & 0x80)
         {
              int shiftaltctrl = 1;//Put anything to see what special keys were pressed
         }
         else
         {  
              printtxt(kblayout[scancode]); //Prints the character which was pressed         
         }     
     }
}

You can implement the same method to check control keys and alt keys.(New page is coming on keyboard special keys)

Setting the Keyboard LED's (Light emitting diode):

This simple code is used to control the keyboard's led's.

#define SCROLL_LED 1 
#define NUM_LED 2 
#define CAPS_LED 4

void kkybrd_set_leds (int numled, int capsled, int scrollled) 
{     
     unsigned char temp = 0;     
     temp = (scrollled) ? (temp | SCROLL_LED ) : (temp & SCROLL_LED);    
     temp = (numled) ?  (num | NUM_LED) : (num & NUM_LED);   
     temp = (capsled) ? (num | CAPS_LED) : (num & CAPS_LED); 
     while((inportb(0x64)&2)!=0){} //Wait for the keyboard controller to receive command 
     outportb(0x60,0xED);
     while((inportb(0x64)&2)!=0){} //Wait for the keyboard controller to receive command  
     outportb(0x60,temp); 
}

Installing the keyboard handler:
You need to have an ISR and other interrupt stuff in your kernel to receive interrupts.This code will install keyboard irq to your operating system's irq management."keyboard handler" will be called whenever a IRQ 1 is fired.

register_irq(1,keyboard_handler);

Information regarding the keyboard:

The variable kblayout is a keyboard layout.A keyboard layout contains the order of the keyboard buttons that are arranged in a keyboard.Note that there are hundreds of keyboard layouts in the world.

A scancode is a data packet carrying information regarding a state of a key for example the shift key.There are 2 types of scancodes, make code and break code.A make code is sent when a key was pressed and a break code is sent when a key is released.There is a number for each make code and break code for each key on the keyboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment