以下這段代碼能夠在 X86 上很好的運行,他主要是重新分配鍵盤的 IRQ ,讀取鍵盤的數據寄存器,安排隊列的運行,最終打印出 scancode 的值和按鍵狀態。 #include linux /kernel.h #include lin" name="description" />
MILY: 宋體">以下這段代碼能夠在X86上很好的運行,他主要是重新分配鍵盤的IRQ,讀取鍵盤的數據寄存器,安排隊列的運行,最終打印出scancode的值和按鍵狀態。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/keyboard.h>
/* Bottom Half - 一旦內核模塊認為它做任何事都是安全的時候這將被內核調用。 */
static void got_char(void *scancode)
{
printk("Scan Code %x %s.n",
(int) *((char *) scancode) & 0x
*((char *) scancode) & 0x80 ? "Released" : "Pressed");
}
/* 這個函數為鍵盤中斷服務。它讀取來自鍵盤的相關信息然后安排當內核認為bottom half安全的時候讓它運行 */
void irq_handler(int irq,
void *dev_id,
struct pt_regs *regs)
{
/* 這些變量是靜態的,因為它們需要對 bottom half 可見(通過指針)。 */
static unsigned char scancode;
static struct tq_struct task = {NULL, 0, got_char, &scancode};
unsigned char status;
/* Read keyboard status */
status = inb(0x64);
scancode = inb(0x60);
/* 安排 bottom half 運行 */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
queue_task(&task, &tq_immediate);
#else
queue_task_irq(&task, &tq_immediate);
#endif
mark_bh(IMMEDIATE_BH);
}
/* 初始化模塊--登記 IRQ 句柄 */
int init_module()
{
/* 既然鍵盤的句柄不能和我們的共存,在我們做事情前我們不得不關閉它(釋放它的 IRQ)。
* 因為我們不知道它在哪兒,所以以后沒有辦法恢復它--因此當我們做完時計算機將被重新啟動。
*/
free_irq(1, NULL);
/* 請求 IRQ 1,鍵盤的 IRQ,指向我們的 irq_handler。 */
return request_irq(
1, /* PC上的鍵盤的 IRQ 號 */
irq_handler, /* 我們的句柄 */
SA_SHIRQ,
/* SA_SHIRQ 意味著我們將另一個句柄用于這個 IRQ。
*
* SA_INTERRUPT 能使句柄為一個快速中斷。
*/
"test_keyboard_irq_handler", NULL);
}
/* 清除 */
void cleanup_module()
{
/* 它在這兒只是為了完全。它是完全不相關的,因為我們沒有辦法恢復通常的鍵盤中斷因此計算機完全沒用 * 了,需要被重新啟動。 */
free_irq(1, NULL);
}