輸入裝置驅動之按鍵裝置驅動

2021-07-07 07:36:52 字數 3261 閱讀 9512

linux輸入子系統就是乙個基於分層模式的系統,其基本的層次分解如下圖所示。

在圖中我們可以發現輸入子系統主要包括三個部分裝置驅動層(input driver)、核心層(input core)和輸入事件驅動層。輸入子系統的劃分使得輸入裝置的驅動程式設計越來越簡單,但是其中的思想採用我們學習的重點和難點。

input子系統處理輸入事務,任何輸入裝置的驅動程式都可以通過input輸入子系統提供的介面註冊到核心,利用子系統提供的功能來與使用者空間互動。輸入裝置一般包括鍵盤,滑鼠,觸控螢幕等,在核心中都是以輸入裝置出現的。下面分析input輸入子系統的結構,以及功能實現。

1. input子系統是分層結構的,總共分為三層: 硬體驅動層,子系統核心層,事件處理層。 

(1)、其中硬體驅動層負責操作具體的硬體裝置,這層的**是針對具體的驅動程式的,需要驅動程式的作者來編寫。

(2)、子系統核心層是鏈結其他兩個層之間的紐帶與橋梁,向下提供驅動層的介面,向上提供事件處理層的介面。

(3)、事件處理層負責與使用者程式打交道,將硬體驅動層傳來的事件報告給使用者程式。

2. 各層之間通訊的基本單位就是事件,任何乙個輸入裝置的動作都可以抽象成一種事件,如鍵盤的按下,觸控螢幕的按下,滑鼠的移動等。事件有三種屬性:型別(type),編碼(code),值(value),input子系統支援的所有事件都定義在input.h中,包括所有支援的型別,所屬型別支援的編碼等。事件傳送的方向是 硬體驅動層-->子系統核心-->事件處理層-->使用者空間。

在驅動程式設計中,我們對於裝置的驅動設計主要集中在裝置驅動層的實現,但是這與之前的裝置驅動開發存在較大的差別,主要是因為裝置驅動不再是編寫基本操作的實現過程,也就是不在是對struct file_operations 這個結構體物件的填充和實現。在輸入裝置驅動中的主要實現包括下面幾個過程:

1、分配乙個輸入裝置物件。並完成響應結構體元素的填充,主要包括支援的事件型別和事件代號等。

分配物件的函式:

struct input_dev *input_allocate_device(void);

釋放物件函式:

void input_free_device(struct input_dev *dev);

設定支援的事件型別和事件**:

通常採用set_bit函式實現:

設定支援的事件型別(支援按鍵事件)

set_bit(ev_key,input_dev->evbit);

設定支援的事件**(支援按鍵1)

set_bit(key_1, input_dev->keybit);

2、完成輸入裝置物件的註冊,將裝置物件註冊到輸入子系統當中去,當然也有對應的釋放函式。

註冊裝置到核心:

int input_register_device(struct input_dev *dev);

登出裝置:

void input_unregister_device(struct input_dev *dev);

3、向核心層(input core)匯報事件的發生以及傳輸事件型別和事件**等。這一部分通常是採用中斷的方法實現,在中斷中向上一層次(input core)傳送發生事件的事件型別、事件代號以及事件對應的值等。但是上報的內容結構體都是基於乙個固定結構體的

struct input_event,在使用者空間也可以採用這個結構體實現對事件的訪問。

structinput_event ;/

*埠集合*

/static const

int gpios[numbers_buttons]=;

/*事件代號集合*

/static const

int keys[numbers_buttons]=;

/*中斷處理程式*

/static irqreturn_t button_interrupt(

int irq,void* p)}/

*返回值*

/return irq_retval(irq_handled);}

/*裝置初始化函式*

/static int __init tq2440_button_init(void)

/*設定相應的事件處理型別,按鍵事件*

/set_bit(ev_key,button_dev-

>evbit);/

*申請中斷*

/for

(i= 0; i < numbers_buttons;

++ i)

/*裝置名,防止出現錯誤*

/button_dev-

>name= input_name;

/*註冊輸入裝置*

/err

= input_register_device(button_dev);if

(err

)printk(

"initialized\n");

return 0;

/*錯誤處理*

/err_free_dev:

/*登出裝置*

/input_unregister_device(button_dev)

;return err;}

/*裝置退出函式*

/static void __exit tq2440_button_exit(void)}/

*載入和解除安裝*

/module_init(tq2440_button_init)

;module_exit(tq2440_button_exit);/

*license和作者資訊*

/module_license(

"gpl");

module_author(

"gp-");

測試**:

#include

#include

#include

#include

#include

#include

#include

/*事件結構體*

/struct input_event buff;

int main(

int argc,char *

*argv)

while

(1)}

close(fd)

;exit

(0);}

測試效果:

從效果上來看,**基本上實現了按鍵的識別,但是該驅動程式的問題是按鍵並不能實現消抖操作。

蛻變成蝶 Linux裝置驅動之按鍵裝置驅動

在上述的驅動系列部落格中,我們已經了解了關於阻塞和非阻塞 非同步通知 輪詢 記憶體和i o口訪問 併發控制等知識,按鍵裝置驅動相對來說是比較簡單的,本章內容可以加深我們對字元裝置驅動架構 阻塞與非阻塞 中斷定時器等相關知識的理解。在嵌入式的系統中,按鍵的硬體原理簡單,就是通過乙個上拉電阻將處理器的外...

Linux裝置驅動之《字元裝置驅動》

linux裝置中最大的特點就是裝置操作猶如檔案操作一般,在應用層看來,硬體裝置只是乙個裝置檔案。應用程式可以像操作檔案一樣對硬體裝置進行操作,如open close read write 等。下面是乙個字元裝置驅動程式的簡單實現test.c 模組分析 1.初始化裝置驅動的結構體 struct fil...

Linux裝置驅動之字元裝置驅動

一 linux裝置的分類 linux系統將裝置分成三種基本型別,每個模組通常實現為其中某一類 字元模組 塊模組或網路模組。這三種型別有 字元裝置 字元裝置是個能夠像位元組流 類似檔案 一樣被訪問的裝置,由字元裝置驅動程式來實現這種特性。字元裝置可以通過檔案系統節點來訪問,比如 dev tty1等。這...