Linux内核:如何捕获按键并用另一个键replace?

我试图涉足低级别的编程。 我的目标是让用户在terminalinput一个密钥,捕获并输出另一个密钥。 例如,如果用户键入“a”,我会输出“b”,如果他input“b”,我输出“c”等。

什么是这样做的步骤? 我已经熟悉如何访问Linux内核源代码,编译并使用它。

谢谢。

Solutions Collecting From Web of "Linux内核:如何捕获按键并用另一个键replace?"

考虑下一个简单的内核模块:

#include <linux/kernel.h> #include <linux/module.h> #include <linux/interrupt.h> #include <asm/io.h> #define KBD_IRQ 1 /* IRQ number for keyboard (i8042) */ #define KBD_DATA_REG 0x60 /* I/O port for keyboard data */ #define KBD_SCANCODE_MASK 0x7f #define KBD_STATUS_MASK 0x80 static irqreturn_t kbd2_isr(int irq, void *dev_id) { char scancode; scancode = inb(KBD_DATA_REG); /* NOTE: i/o ops take a lot of time thus must be avoided in HW ISRs */ pr_info("Scan Code %x %s\n", scancode & KBD_SCANCODE_MASK, scancode & KBD_STATUS_MASK ? "Released" : "Pressed"); return IRQ_HANDLED; } static int __init kbd2_init(void) { return request_irq(KBD_IRQ, kbd2_isr, IRQF_SHARED, "kbd2", (void *)kbd2_isr); } static void __exit kbd2_exit(void) { free_irq(KBD_IRQ, (void *)kbd2_isr); } module_init(kbd2_init); module_exit(kbd2_exit); MODULE_LICENSE("GPL"); 

这是最简单和最基本的键盘记录器 。 它可以很容易地重新替换扫描码 。

免责声明

  • 这个模块不是跨平台的(只能在x86架构上工作,因为它使用了inb()函数)
  • 我相信它只适用于PS / 2键盘(不适用于USB键盘)
  • 它在硬件IRQ处理程序中执行缓慢的I / O操作(我的意思是pr_info() ),应该避免这种情况(理想情况下应该使用线程化的IRQ ))。

但是我认为这对于教育目的是很好的 – 它非常小,并且非常好地展示了这个想法(不需要像input_devinput_register_device()serio_write()input_event()input_report_key()等那样搞乱API。

细节

真正的中断处理程序(在键盘驱动程序中 )作为共享中断请求,这允许我们也请求中断,并在我们的ISR (除了原始键盘驱动程序中的ISR)处理它。 中断请求在kbd2_init()

该模块的工作原理如下:

  1. 捕获按键事件(为每个按键事件调用硬件中断处理程序kbd2_isr()
  2. 读取按键的扫描码(通过inb()函数)
  3. 并通过pr_info()打印出来

现在,您要替换该扫描代码。 我相信你可以用这个(在x86上) outb()函数。 所以我把它留给你。

如果您想知道为什么我们要求1号IRQ,请参阅drivers / input / serio / i8042-io.h :

 #else # define I8042_KBD_IRQ 1 

另外请务必检查这个IRQ是否在drivers / input / serio / i8042.c中共享 :

 error = request_irq(I8042_KBD_IRQ, i8042_interrupt, IRQF_SHARED, "i8042", i8042_platform_device); 

这里是i8042键盘控制器的文档: AT键盘控制器 。

有用的常量

为了避免幻数 ,你可以使用下一个定义。

从drivers / input / serio / i8042-io.h :

 /* * Register numbers. */ #define I8042_COMMAND_REG 0x64 #define I8042_STATUS_REG 0x64 #define I8042_DATA_REG 0x60 

从include / linux / i8042.h :

 /* * Status register bits. */ #define I8042_STR_PARITY 0x80 #define I8042_STR_TIMEOUT 0x40 #define I8042_STR_AUXDATA 0x20 #define I8042_STR_KEYLOCK 0x10 #define I8042_STR_CMDDAT 0x08 #define I8042_STR_MUXERR 0x04 #define I8042_STR_IBF 0x02 #define I8042_STR_OBF 0x01