簡體   English   中英

Linux內核:如何捕獲按鍵並用另一個鍵替換它?

[英]Linux Kernel: How to capture a key press and replace it with another key?

我試圖涉足低級編程。 我的目標是讓用戶在終端中鍵入密鑰,捕獲並輸出另一個密鑰。 因此,例如,如果用戶鍵入“a”,我會鍵入“b”,如果他鍵入“b”,則輸出“c”等。

這樣做的步驟是什么? 我已經熟悉如何訪問Linux內核源代碼,編譯它並使用它。

謝謝。

考慮下一個簡單的內核模塊

#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()input_report_key() )。

細節

實際中斷處理程序(在鍵盤驅動程序中 )作為共享中斷請求,這允許我們也請求中斷,從而在我們的ISR中處理它(除了原始鍵盤驅動程序中的ISR)。 中斷請求在kbd2_init()

該模塊的工作原理如下:

  1. 捕獲按鍵事件(為每個按鍵事件調用硬件中斷處理程序kbd2_isr()
  2. 讀取按鍵的掃描碼(通過inb()函數)
  3. 並通過pr_info()打印出來

現在,您想要替換該掃描代碼。 我相信你可以使用outb()函數(在x86上)。 所以我留給你。

如果你想知道我們為什么要求1號IRQ,請參閱drivers / input / serio / i8042-io.h

#else
# define I8042_KBD_IRQ  1

另外一定要檢查驅動程序/ input / serio / i8042.c中是否共享此IRQ:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM