Linux Device Driver displaying what character pressed

Theory:

When a key is pressed, the keyboard sends a

  • start bit(low) 
  • 8 data bits for the scancode
  • odd parity
  • stop bit(high)



Keyboard controller reads the data and performs error checking (parity) and if any error asks for retransmission

What is scan code?

A scan code is a number sent by the keyboard controller once a key has been pressed or released.

E.g. "Enter" has a scan code of 0x1C.

A keyboard generates two scan codes for each key typed on the system, one scan code for press and the other for release.

Release scan code is 128 (80h) plus the press scan code

Code:





#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
const unsigned char kbdus[128] =
{
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
'9', '0', '-', '=', '\b', /* Backspace */
'\t', /* Tab */
'q', 'w', 'e', 'r', /* 19 */
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
0, /* 29 - Control */
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
'\'', '`', 0, /* Left shift */
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
'm', ',', '.', '/', 0, /* Right shift */
'*',
0, /* Alt */
' ', /* Space bar */
0, /* Caps lock */
0, /* 59 - F1 key ... > */
0, 0, 0, 0, 0, 0, 0, 0,
0, /* < ... F10 */
0, /* 69 - Num lock*/
0, /* Scroll Lock */
0, /* Home key */
0, /* Up Arrow */
0, /* Page Up */
'-',
0, /* Left Arrow */
0,
0, /* Right Arrow */
'+',
0, /* 79 - End key*/
0, /* Down Arrow */
0, /* Page Down */
0, /* Insert Key */
0, /* Delete Key */
0, 0, 0,
0, /* F11 Key */
0, /* F12 Key */
0, /* All other keys are undefined */
};
MODULE_LICENSE("GPL");
static int irq = 1, dev = 0xaa;
#define KBD_DATA_REG 0x60 /* I/O port for keyboard data */
#define KBD_SCANCODE_MASK 0x7f
#define KBD_STATUS_MASK 0x80
static irqreturn_t keyboard_handler(int irq, void *dev)
{
char scancode;
scancode = inb(KBD_DATA_REG);
pr_info("Character %c %s\n",
kbdus[scancode & KBD_SCANCODE_MASK],
scancode & KBD_STATUS_MASK ? "Released" : "Pressed");
return IRQ_NONE;
}
/* registering irq */
static int test_interrupt_init(void)
{
pr_info("%s: In init\n", __func__);
return request_irq(irq, keyboard_handler, IRQF_SHARED,"my_keyboard_handler", &dev);
}
static void test_interrupt_exit(void)
{
pr_info("%s: In exit\n", __func__);
synchronize_irq(irq); /* synchronize interrupt */
free_irq(irq, &dev);
}
module_init(test_interrupt_init);
module_exit(test_interrupt_exit);
view raw keyboard.c hosted with ❤ by GitHub


Output:




Notes:

1. This driver will not work for USB Keyboard, as there scan codes are different, it works only for the integrated keyboard on the Laptop.
2. kbdus array is for US Keyboard layout.
3. When you press a key, interrupt is generated, the interrupt handler reads the keyboard data register which exists at 0x60, which is the scan code, this scan code is converted to ASCII Character

Comments

Popular posts from this blog

bb.utils.contains yocto

Difference between RDEPENDS and DEPENDS in Yocto

PR, PN and PV Variable in Yocto