欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
PC鍵盤(pán)驅動(dòng)程序源碼分析
一.   編寫(xiě)目的:
描述uclinux內核中pc機鍵盤(pán)驅動(dòng)的體系結構和工作原理,用于指導針對具體的嵌入式鍵盤(pán)的驅動(dòng)程序的編寫(xiě)。
二.   參考資料:
1.《Linux內核源代碼情景分析(下冊)》第8.7和8.8章節,page330~412
2.內核源代碼文件:
../linux-2.4.x/drivers/char/keyboard.c
../linux-2.4.x/include/asm-i386/keyboard.h
../linux-2.4.x/drivers/char/pc_keyb.c
../linux-2.4.x/drivers/input/*.*
../linux-2.0.x/drivers/char/keyboard.c
3.網(wǎng)絡(luò )文章:《書(shū)寫(xiě)基于內核的linux鍵盤(pán)記錄器》
三.   pc鍵盤(pán)驅動(dòng)工作流程:
1.  鍵盤(pán)初始化
該工作主要是由tty初始化函數tty_init()調用鍵盤(pán)驅動(dòng)程序模塊的初始化函數kbd_init()實(shí)現。Kbd_init()函數主要調用initialize_kbd()函數完成工作。
主要完成工作為,鍵盤(pán)的自檢,檢測,啟動(dòng),寄存器設置等;并且向系統注冊鍵盤(pán)中斷服務(wù)函數。
2.  鍵盤(pán)中斷響應過(guò)程
當用戶(hù)按鍵或者釋放鍵時(shí),鍵盤(pán)向系統產(chǎn)生中斷信號,系統自動(dòng)進(jìn)入鍵盤(pán)中斷服務(wù)函數處理,該部分工作主要由鍵盤(pán)中斷服務(wù)函數keyboard_interrupt()完成。
主要完成工作為:從鍵盤(pán)狀態(tài)寄存器讀取鍵盤(pán)狀態(tài),從鍵盤(pán)緩沖區讀取數據,根據讀取的狀態(tài)和數據,進(jìn)行鍵碼轉換等工作,將結果存入一個(gè)tty的“flip_buffer”的數據緩沖區。在中斷服務(wù)函數最后,進(jìn)行鍵盤(pán)后端處理函數(其實(shí)是控制臺終端的tasklet,即console_tasklet())調度。
3.  鍵盤(pán)后端處理(不屬于鍵盤(pán)驅動(dòng)程序處理范疇)
在鍵盤(pán)中斷服務(wù)函數結束之前,會(huì )將鍵盤(pán)后端處理函數(其實(shí)是控制臺終端的tasklet,即console_tasklet())掛入后端處理隊列,系統在調度的時(shí)候最終執行該函數。
在該函數中將完成一些鍵盤(pán)的相關(guān)工作,例如將flip_buffer中的鍵盤(pán)數據加以處理,將結果存入tty的read_buffer數據緩沖區。
4.  鍵盤(pán)數據最終結果傳遞到用戶(hù)進(jìn)程(不屬于鍵盤(pán)驅動(dòng)程序處理范疇)
在tty的file_operations數據結構的read函數指針指向read_charn()函數,該函數從read_buffer數據緩沖區獲取數據,返回給用戶(hù)進(jìn)程。
如此一次鍵盤(pán)回話(huà)完成。
5.  
四.   源文件具體分析:
有一點(diǎn)必須注意,在linux-2.0.x的內核中,鍵盤(pán)驅動(dòng)主要工作都是在
../linux-2.0.x/drivers/char/keyboard.c
文件中完成,而沒(méi)有別的文件,不象linux-2.4.x內核除了文件:
../linux-2.4.x/drivers/char/keyboard.c
還有以下這些文件:
../linux-2.4.x/drivers/char/pc_keyb.c
../linux-2.4.x/include/asm-i386/keyboard.h
我們這里主要分析的時(shí)候linux-2.4.x內核的鍵盤(pán)驅動(dòng)程序。
另外還有一些相關(guān)代碼:
../linux-2.4.x/drivers/char/vt.c
../linux-2.4.x/drivers/char/tty_io.c
../linux-2.4.x/drivers/char/tty_ioctl.c
../linux-2.4.x/drivers/input/*.*
../linux-2.4.x/include/linux/kbd_kern.h
../linux-2.4.x/drivers/char/console.c
1.../linux-2.4.x/drivers/char/pc_keyb.c
(1)      void __init pckbd_init_hw(void)
鍵盤(pán)初始化函數,該函數由Kbd_init()調用(Kbd_init()調用的是kbd_init_hw(),但是在i386中,kbd_init_hw被#define為pckbd_init_hw)。
主要完成工作:
a.  根據kbd_controller_present判斷鍵盤(pán)控制器是否存在
b.  調用kbd_request_region()分配資源
c.  調用kbd_clear_input()清除鍵盤(pán)控制器緩沖區數據
d.  鍵盤(pán)如果未復位初始化,則調用函數initialize_kbd()進(jìn)行初始化
e.  設置kbd_rate函數指針為pckbd_rate()函數
f.   調用kbd_request_irq(),將鍵盤(pán)中斷服務(wù)函數keyboard_interrupt()注冊到系統。
(2)      static char * __init initialize_kbd(void)
鍵盤(pán)初始化函數,該函數由pckbd_init_hw()調用。
主要完成工作:
a.  調用kbd_write_command_w(KBD_CCMD_SELF_TEST),進(jìn)行鍵盤(pán)自檢
b.  調用kbd_write_command_w(KBD_CCMD_KBD_TEST),進(jìn)行鍵盤(pán)檢測
c.  調用kbd_write_command_w(KBD_CCMD_KBD_ENABLE),使能鍵盤(pán)
d.  調用kbd_write_output_w(KBD_CMD_RESET)復位鍵盤(pán),并且調用函數kbd_wait_for_input()接受復位狀態(tài)字節并且判斷復位是否成功,如果復位成功,繼續,否則函數返回
e.  調用kbd_write_output_w(KBD_CMD_DISABLE),在設置鍵盤(pán)工作模式之前,停止鍵盤(pán)工作。調用kbd_wait_for_input()接受停止鍵盤(pán)狀態(tài),如果停止成功,繼續,否則函數返回
f.   調用kbd_write_command_w(KBD_CCMD_WRITE_MODE)和kbd_write_output_w(…)設置鍵盤(pán)工作模式。
g.  對于powerpc鍵盤(pán)的一些模式設置
h.  調用kbd_write_output_w_and_wait(KBD_CMD_ENABLE),在完成鍵盤(pán)工作模式設置之后,使能鍵盤(pán)工作
i.    最后調用kbd_write_output_w_and_wait(KBD_CMD_SET_RATE),set the typematic rate to maximum
(3)      static int kbd_write_output_w_and_wait(int data)
發(fā)送數據到鍵盤(pán)數據端口函數
主要完成工作:
a.  調用kbd_write_output_w(data)函數,往鍵盤(pán)數據端口發(fā)送數據
b.  調用kbd_wait_for_input()等待鍵盤(pán)的回應數據。
(4)      static int kbd_write_command_w_and_wait(int data)
發(fā)送命令到鍵盤(pán)數據端口函數
主要完成工作:
a.  調用kbd_write_command_w(data)函數,往鍵盤(pán)命令(控制)端口發(fā)送命令
b.  調用kbd_wait_for_input()等待鍵盤(pán)的回應數據
(5)      static void kbd_write_output_w(int data)
發(fā)送數據到鍵盤(pán)的數據端口函數,主要由kbd_write_output (data)完成工作,kbd_write_output (data)函數和體系結構非常密切,一般由匯編代碼實(shí)現
(6)      static void kbd_write_command_w(int data)
發(fā)送命令到鍵盤(pán)的命令(控制)端口函數,主要由kbd_write_command(data)完成工作,kbd_write_command(data)函數和體系結構非常密切,一般由匯編代碼實(shí)現。
(7)      static int __init kbd_wait_for_input(void)
延時(shí)等待鍵盤(pán)返回數據函數,即循環(huán)等待的時(shí)候kbd_read_data()調用函數從鍵盤(pán)的讀取數據。
(8)      static void __init kbd_clear_input(void)
發(fā)送清除鍵盤(pán)數據,即調用函數kbd_read_data()不停地從鍵盤(pán)讀取數據,知道沒(méi)有數據為止。
(9)      static int __init kbd_read_data(void)
從鍵盤(pán)讀取數據
主要完成工作:
a.  調用kbd_read_status()函數從鍵盤(pán)狀態(tài)寄存器讀取鍵盤(pán)地狀態(tài),該函數和體系結構關(guān)系密切,一般由匯編代碼實(shí)現
b.  判斷鍵盤(pán)緩沖區是否有數據,如果有則調用函數kbd_read_input()從鍵盤(pán)數據寄存器讀取數據,該函數和體系結構關(guān)系密切,一般由匯編代碼實(shí)現
c.  判斷讀取地數據是否有效
(10)   line657~679不懂
(11)  static int pckbd_rate(struct kbd_repeat *rep)
在pckbd_init_hw()函數中被賦值給函數指針kbd_rate,被../linux-2.4.x/drivers/char/vt.c 文件vt_ioctl()調用
(12)  static int write_kbd_rate(unsigned char r)
被函數pckbd_rate(),是一個(gè)內部函數
(13)   static unsigned char parse_kbd_rate(struct kbd_repeat *r)
被函數pckbd_rate(),是一個(gè)內部函數
(14)  void pckbd_leds(unsigned char leds)
在文件../linux-2.4.x/include/asm-i386/keyboard.h被定義成宏:kbd_leds()。被鍵盤(pán)中斷后端處理函數kbd_bh()函數調用。
主要功能:
       調用函數send_data()設置鍵盤(pán)的led燈,如果失敗設置鍵盤(pán)不存在。
(15)   static int send_data(unsigned char data)
發(fā)送字節data到鍵盤(pán),并且等待鍵盤(pán)的回應。
(16)  static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
鍵盤(pán)中斷服務(wù)函數(最關(guān)鍵),主要是調用函數handle_kbd_event()完成工作。在整個(gè)函數執行過(guò)程必須關(guān)閉中斷。
注意:ps鼠標和鍵盤(pán)共用鍵盤(pán)中斷服務(wù)函數
(17)  static unsigned char handle_kbd_event(void)
中斷事件處理函數,該函數由keyboard_interrupt()調用
主要完成以下工作:
a.  調用kbd_read_status()讀取鍵盤(pán)狀態(tài)端口
b.  循環(huán)執行以下操作,知道根據狀態(tài)寄存器判斷沒(méi)有數據,或者已經(jīng)讀取了1000個(gè)數據:
調用kbd_read_input()讀取數據
根據狀態(tài)寄存器的值,判斷是ps鼠標中斷,則調用鼠標中斷事件處理函數handle_mouse_event(),如果是鍵盤(pán)中斷,則調用handle_keyboard_event(unsigned char scancode)。
重新讀取狀態(tài)寄存器
c.  
(18)  static inline void handle_keyboard_event(unsigned char scancode)
該函數為鍵盤(pán)中斷事件處理函數,由handle_kbd_event()函數調用,主要工作由handle_scancode()函數實(shí)現。
主要完成工作:
a.  調用do_acknowledge(scancode)發(fā)送通知數據收到信息給鍵盤(pán)
b.  調用handle_scancode()函數處理scancode。Handle_scancode()函數在文件../linux-2.4.x/drivers/char/keyboard.c中實(shí)現
c.  調用函數tasklet_schedule(&keyboard_tasklet),將剩余工作放到bh,即將鍵盤(pán)后端函數keyboard_tasklet掛入tasklet,系統自動(dòng)會(huì )調度運行該函數。
(19)  static inline void handle_mouse_event(unsigned char scancode)
由于ps鼠標不在該范疇內,在此不加以分析。
(20)  static int do_acknowledge(unsigned char scancode)
該函數處理當從鍵盤(pán)接收到一個(gè)數據時(shí),往鍵盤(pán)發(fā)送ACK信息。
主要完成工作:
a.  根據reply_expected判斷是否需要往鍵盤(pán)發(fā)送ACK信息
b.  如果需要,根據具體的scancode進(jìn)行處理
(21)  int pckbd_pm_resume(struct pm_dev *dev, pm_request_t rqst, void *data)
該函數是關(guān)于PS鼠標的函數,在此不分析
(22)  char pckbd_unexpected_up(unsigned char keycode)
進(jìn)行一些不預期的按鍵釋放等處理,相應清除一些標志
(23)   int pckbd_translate(unsigned char scancode, unsigned char *keycode,char raw_mode)
將scancode轉換為keycode,該函數在../linux-2.4.x/include/asm-i386/keyboard.h 文件中被定義成kbd_translate,在handle_scancode()函數中被調用。具體實(shí)現參考源代碼
(24)  int pckbd_getkeycode(unsigned int scancode)
根據scancode和keycode數組e0_keys[128]或者high_keys[]數組獲取keycode,該函數在../linux-2.4.x/include/asm-i386/keyboard.h中被定義為宏kbd_getkeycode,在文件../linux-2.4.x/drivers/char/keyboard.c中被getkeycode()函數調用。
主要功能:
       根據scancode獲取pc鍵盤(pán)的功能鍵碼
(25)  int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
根據scancode將eo_keys[128]或者high_keys[]對應項的值設置為keycode,該函數在../linux-2.4.x/include/asm-i386/keyboard.h中北定義為宏kbd_getsetkeycode,在文件../linux-2.4.x/drivers/char/keyboard.c中被getsetkeycode()函數調用。
主要功能:
根據設置pc鍵盤(pán)的功能鍵碼為scancode
(26)  static void kb_wait(void)
循環(huán)等待,在等待的時(shí)候調用函數handle_kbd_event()監視鍵盤(pán)狀態(tài),超時(shí)或者狀態(tài)滿(mǎn)足則退出循環(huán)等待。
(27)   
2.../linux-2.4.x/drivers/char/keyboard.c
(1)            void handle_scancode(unsigned char scancode, int down)
該函數在pc鍵盤(pán)驅動(dòng)中是非常關(guān)鍵的一個(gè)函數,主要是將scancode轉換為tty所能接受的碼制,例如ascii碼,unicode等,具體根據需求而定。并且將轉換結果存入flip_buffer;在控制臺的后端處理函數將從flip_buffer讀取數據到read_buffer;而tty驅動(dòng)程序的讀取函數(read:read_chan())從read_buffer讀取數據,從而完成鍵盤(pán)的一個(gè)回話(huà)。
具體實(shí)現請參考《linux內核源代碼情景分析(下冊)》的page375開(kāi)始的內容
(2)            int __init kbd_init(void)
該函數在pc鍵盤(pán)驅動(dòng)中也是非常關(guān)鍵的一個(gè)函數,鍵盤(pán)驅動(dòng),鍵盤(pán)的初始化都由該函數實(shí)現,主要功能通過(guò)調用函數kbd_init_hw()實(shí)現,而kbd_init_hw()是一個(gè)宏,具體實(shí)現函數為pckbd_init_hw()。
該函數被tty驅動(dòng)的初始化函數即../linux-2.4.x/drivers/char/tty_io.c文件中的tty_init()函數調用。
具體實(shí)現:
a.  初始化kbd_table數組,即每個(gè)控制臺的鍵盤(pán)狀態(tài)。
b.  獲取ttytab指針(也可以說(shuō)是一個(gè)數組,數組成員為每個(gè)控制臺對應的tty)。
c.  調用kbd_init_hw()函數,實(shí)現初始化
d. 使能鍵盤(pán)中斷服務(wù)后端函數運行,并且掛接keyboard_tasklet()(其實(shí)就是kbd_bh()函數)為鍵盤(pán)中斷服務(wù)后端執行函數
e. 調用函數pm_register()將鍵盤(pán)注冊到電源管理設備列表,最后一個(gè)參數為回調函數,在此好像是NULL
(3)            static void kbd_bh(unsigned long dummy)
鍵盤(pán)中斷服務(wù)程序的后端服務(wù)函數,主要完成console changing, led setting and copy_to_cooked等比較花時(shí)間的工作。
主要功能:
 完成鍵盤(pán)的numlock,capslock和scrolllock的led指示燈設置。
(4)            int getkeycode(unsigned int scancode)
該函數在../linux-2.4.x/drivers/char/vt.c文件line255處被do_kbkeycode_ioctl()調用。
(5)            int setkeycode(unsigned int scancode, unsigned int keycode)
該函數在../linux-2.4.x/drivers/char/vt.c文件line262處被do_kbkeycode_ioctl()調用。
(6)            static inline unsigned char getleds(void)
該函數被鍵盤(pán)中斷后端處理函數kbd_bh()調用
(7) void register_leds(int console, unsigned int led,unsigned int *addr, unsigned int mask)
(8)            void setledstate(struct kbd_struct *kbd, unsigned int led)
該函數在../linux-2.4.x/drivers/char/vt.c文件Line690的vt_ioctl()函數中被調用。
具體功能:
       設置鍵盤(pán)NumLock, CapsLock,或ScrollLock的led燈的狀態(tài)。
(9)            unsigned char getledstate(void)
該函數在../linux-2.4.x/drivers/char/vt.c文件Line683的vt_ioctl()函數中被調用。
具體功能:
       讀取鍵盤(pán)NumLock, CapsLock,或ScrollLock的led燈的狀態(tài)。
以下函數都是handle_scancode()函數處理scancode的時(shí)候調用的內部函數:
(10)        void put_queue(int ch)
(11)        static void puts_queue(char *cp)
上面這兩個(gè)函數(8),(9)比較關(guān)鍵,因為就是由這兩個(gè)函數將轉換結果存入flip_buffer,并且將控制臺的后端服務(wù)函數,即bh函數掛入tasklet。
(12)        void compute_shiftstate(void)
該函數被許多地方調用,例如:
../linux-2.4.x/drivers/char/console.c
../linux-2.4.x/drivers/char/vt.c
主要功能:
       設置shift_state全局變量,該變量是應該是和pc鍵盤(pán)上的“shift”鍵的狀態(tài)相關(guān)聯(lián)。
(13)         unsigned char handle_diacr(unsigned char ch)
(14)         static void SAK(void)
(15)         static void spawn_console(void)
(16)         static void compose(void)
(17)         static void boot_it(void)
(18)         static void scroll_back(void)
(19)         static void scroll_forw(void)
(20)         static void send_intr(void)
(21)         static void incr_console(void)
(22)         static void decr_console(void)
(23)         static void lastcons(void)
(24)         static void bare_num(void)
(25)         static void num(void)
(26)         static void hold(void)
(27)         static void show_ptregs(void)
(28)         static void caps_on(void)
(29)         static void caps_toggle(void)
(30)         static void enter(void)
(31)         static void applkey(int key, char mode)
(32)         void to_utf8(ushort c)
(33)         static void do_slock(unsigned char value, char up_flag)
(34)         static void do_lock(unsigned char value, char up_flag)
(35)         static void do_ascii(unsigned char value, char up_flag)
(36)         static void do_meta(unsigned char value, char up_flag)
(37)         static void do_dead2(unsigned char value, char up_flag)
(38)         static void do_shift(unsigned char value, char up_flag)
(39)         static void do_cur(unsigned char value, char up_flag)
(40)         static void do_pad(unsigned char value, char up_flag)
(41)         static void do_fn(unsigned char value, char up_flag)
(42)         static void do_cons(unsigned char value, char up_flag)
(43)         static void do_dead(unsigned char value, char up_flag)
(44)         static void do_self(unsigned char value, char up_flag)
(45)         static void do_spec(unsigned char value, char up_flag)
(46)         static void do_ignore(unsigned char value, char up_flag)
五.   鍵盤(pán)驅動(dòng)和系統上層的接口,以下函數就是在根據具體硬件的時(shí)候特別關(guān)注的函數:
鍵盤(pán)驅動(dòng)和系統上層的接口主要就是和tty驅動(dòng)的接口,用戶(hù)和鍵盤(pán)打交道一般都是通過(guò)tty的接口函數進(jìn)行。
1.  kbd_init()-鍵盤(pán)初始化函數:tty驅動(dòng)程序的初始化函數tty_init()調用鍵盤(pán)初始化函數kbd_init()函數
2.  Put_queue()或者puts_queue()函數:數據緩沖區和tty的接口,鍵盤(pán)驅動(dòng)(具體地說(shuō)是鍵盤(pán)中斷服務(wù)函數)將從鍵盤(pán)讀取地數據存入flip_buffer數據緩沖區,而用戶(hù)調用tty驅動(dòng)的read函數(即read_chan())則從flip_buffer讀取數據。
3.  ../linux-2.4.x/drivers/char/tty_ioctl.c 文件n_tty_ioctl()函數調用的地方。
4.  ../linux-2.4.x/drivers/char/vt.c 文件vt_ioctl()調用的地方。
(1)       void setledstate(struct kbd_struct *kbd, unsigned int led)
(2)       unsigned char getledstate(void)
(3)       int getkeycode(unsigned int scancode)
(4)       int setkeycode(unsigned int scancode, unsigned int keycode)
(5)       void compute_shiftstate(void)
(6)       static int pckbd_rate(struct kbd_repeat *rep)
5.  ../linux-2.4.x/drivers/chr/console.c文件redraw_screen()調用的地方
(1)       void compute_shiftstate(void)
(2)       
6.  另外注意的函數:
(1)       static void kbd_bh(unsigned long dummy)
(2)       void pckbd_leds(unsigned char leds)
7.  
六.   
 
本文來(lái)自CSDN博客,轉載請標明出處:http://blog.csdn.net/houen_study/archive/2004/11/29/197638.aspx
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
usb鍵鼠標驅動(dòng)分析
Linux設備驅動(dòng)入門(mén)
一個(gè)嵌入式Linux系統的鍵盤(pán)驅動(dòng)實(shí)現
linux_davinci按鍵驅動(dòng)
設備驅動(dòng)程序設計
s3c2440 Linux驅動(dòng)之 觸摸屏驅動(dòng)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久