輸入子系統驅動

在這裏插入圖片描述

輸入子系統程序編寫:
APP: open, read, write. ----> 對應提供驅動程序的讀寫等函數。

驅動: drv_open, drv_read, drv_write

硬件

代碼步驟:
1,確定主設備號:
可以自已確定,也可讓內核分配。
2,要構造驅動中的“open,read,write 等”
是將它們放在一個“file_operations”結構體中.
File_operations==> .open, .read, .write, .poll 等。
這裏"open"函數會去配置硬件的相關引腳等,還有註冊中斷。
3, register_chrdev 註冊字符設備構造的“file_operations”結構:
使用這個 file_operations 結構體。是把這個結構放到內核的某個以此設備的“主設備號”爲
下標的數組中去。
Register_chrdev(主設備號,設備號, file_operations 結構) .
4,入口函數:
調用這個“register_chrdev()”函數。內核裝載某個模塊時,會自動調用這個“入口函數”。
5,出口函數

實例編寫:
①,參考: linux-2.6.22.6\drivers\input\keyboard\gpio_keys.c

②,先包含頭文件 和 初略框架:
頭文件:
在這裏插入圖片描述
初略代碼框架:
在這裏插入圖片描述
③,入口函數的框架:
在這裏插入圖片描述
3.1,定義 input_dev 結構變量:
在這裏插入圖片描述
3.2,用函數來分配這個 input_dev *buttons_dev 變量:
分配“input_dev”結構體是“input_allocate_device()”,則這裏自已民寫分配一個“input_dev”
結構是用此函數。
在這裏插入圖片描述
正常情況下要判斷此“Input_dev”結構是否分配成功,但這裏爲簡化代碼不予判斷。但
一般都會成功的。
3.3,自已的操作:用“set_bit()”設置某一位:
在這裏插入圖片描述
上面用 set_bit()設置了 evbit 數組中的“EV_KEY”按鍵類事件。但按鍵有 26 個字母還有其
他符號按鍵,那麼能產生這一類“EV_KEY”裏的哪些按鍵事件?要產生哪些按鍵事件,要看具體的原理圖:
在這裏插入圖片描述
而現在要寫一個通用的“按鍵”驅動程序。在爲這裏開發板上只有 4 個鍵,要是有很多就可
能設置成普通鍵盤那樣了。但現在單板上只有 4 個按鍵,則這裏定義成“L,S,Enter 和左 shift
鍵”。
3.4,能產生這類操作裏的哪些事件
在這裏插入圖片描述
3.5,註冊“input_dev”結構:
在這裏插入圖片描述
註冊了“input_dev”結構體之後,就會把這裏具體的“buttons_dev”設備結構體掛到內核
的“input_dev”輸入設備的鏈表中去。接着就從右邊的“input_handler”鏈表中一個個取出
來具體的 id_table[]與“buttons_dev”進行比較。若是能匹配說明“input_handler”結構中的
“id_table”能支持這個“input_dev”設備“buttons_dev”,這時支持後,就會接着調用
“input_handler”結構中的“.connect”函數。
到了“.connect”建立連接這個過程時,就會創建一個新的結構“input_handle” ,這個結
構中有兩個成員“.handler”(具體處理方式)和“.dev”(具體設備)。“.dev”指向左邊的設
備層,“.handle”指向右邊的“處理方式”層。這個“input_handle”結構會分別放到左邊設
備層的“input_dev”這個結構成員“h_list”鏈表中,也掛到處理方式層的“input_handler”
結構的成員“h_list”鏈表中去。
3.6,硬件相關操作的準備工作:
首先,定義一個結構體“pin”腳描述。
在這裏插入圖片描述
接着,定義 4 個按鍵的具體引腳定義和按鍵值。
在這裏插入圖片描述
3.7,硬件的相關操作:
首先,註冊 4 箇中斷:
在這裏插入圖片描述
上面爲減少代碼,判斷“request_irq()”的返回值代碼省略去了。
其次,中斷處理函數的編寫、定義“定時器”和“中斷函數”:
在這裏插入圖片描述
接着,定時器初始化 和 定時器初始化函數定義::
在這裏插入圖片描述
定時器初始化函數“buttons_timer_function()”的編寫:
“確定按鍵值” —>“喚醒應用程序” 或 “發送信號”。
這裏只需要上報"按鍵值":上報事件— input_event 上報事件.
在“硬件相關的操作”中,有數據產生時用“input_event()”上報事件:
—>input_event()函數會從“input_device->h_list"鏈表中找到結構“input_handle”中的
“handle”成員,以此最終找到右邊純軟件的“處理方式”層中的“input_handler”結構,
調用此結構中的“.event”函數。
3.8,buttons_timer_function功能函數的完成
上報事件原型:void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
參 1, struct input_dev *dev: input_dev 結構變量指針。這裏爲“buttons_dev” .
參 2, unsigned int type:哪類事件。這裏爲“EV_KEY”按鍵類事件。
參 3, unsigned int code:哪個值。這裏是指哪一個按鍵,爲“pin_desc *pindesc->key_val”
(KEY_L,KEY_S,KEY_ENTER,KEY_LEFTSHIFT) .
參 4,int value: 這裏表示“按下”或是“鬆開”。
上報事件後,還有一個上報同步事件:
原型: void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)。
事件類:是同步類事件“EV_SYN”。
後面 code 形參“SYN_REPORT”和 value 形參值爲“0”時表示這個事件已經上報完了。
在這裏插入圖片描述
④,出口函數:
4.1,添加兩個頭文件:
在這裏插入圖片描述
4.2,釋放中斷:
原型: void free_irq(unsigned int irq, void *dev_id)
參 1, unsigned int irq:中斷號。
參 2, void dev_id: pin 腳描述結構數組組元。
在這裏插入圖片描述
4.3,消除註冊到內核定時器目錄上的內容:
名稱: del_timer()
功能: 消除註冊到內核定時器目錄上的內容
原型:
#include <linux/timer.h>
int del_timer (struct timer_list timer);
說明:
從內核定時器目錄消除結構體。內核定時器的目錄爲連接 list 結構,不是消除結構體的內容,而是修改結構體的連接信息,因此該函數不參與結構體變量的分配和消除。
變量:
timer : 將要消除的內核定時器註冊結構體的數據地址。
返回值 :
正常運行返回 1 ,否則返回 0 。
在這裏插入圖片描述
附1:假設驅動程序裝載好了,按下一個“按鍵”後,那麼中斷處理函數“buttons_irq()”就會被調用。在中斷處理函數中,是先將哪一個按鍵“dev_id”記錄下來(“irq_pd = (struct pin_desc )dev_id;”),然後修改定時器(“mod_timer(&buttons_timer, jiffies+HZ/100);”將它 10ms“jiffies+HZ/100”再啓動“&buttons_timer”這個函數),假設 10ms 時間到了,那麼“定時器處理”函數(buttons_timer_function)初調用。
附2:buttons_timer_function()定時器處理函數的工作:
讀引腳值(pinval = s3c2410_gpio_getpin(pindesc->pin);),再確實是鬆開還是按下:
if (pinval)
{
/
鬆開:最後一參數 int value,0 表示鬆開, 1 表示按下
/
input_event(buttons_dev, pindesc->EV_KEY, 0);
}
else
{
/
按下 */
input_event(buttons_dev, pindesc->EV_KEY, 1);
}
附3:input_event()上報事件
input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)。看最後一行:
list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);
對輸入設備的“h_list” 鏈表裏的每一個成員(就是中間作連接的只有".dev"和".handler"
成員的“input_handle”結構)。把這些“input_handle”結構取出來到“handle” .
若它們是打開時,就調用這個具體“input_handle”結構變量的成員“.handler”的“event()”
函數。以前需要自已構造“open,read,write”等函數,而現在是輸入子系統框架中定義好的。
小結:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章