版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
《通信嵌入式系統(tǒng)技術(shù)
與應(yīng)用》第6講第四章ARMLinux設(shè)備驅(qū)動程序開發(fā)一.設(shè)備驅(qū)動概述1.設(shè)備驅(qū)動簡介及驅(qū)動模塊2.設(shè)備文件分類 3.設(shè)備號 4.驅(qū)動層次結(jié)構(gòu) 5.設(shè)備驅(qū)動程序與外界的接口 6.設(shè)備驅(qū)動程序的特點(diǎn)1.設(shè)備驅(qū)動簡介及驅(qū)動模塊操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設(shè)備的,它為用戶屏蔽了各種各樣的設(shè)備,驅(qū)動硬件是操作系統(tǒng)最基本的功能,并且提供統(tǒng)一的操作方式。設(shè)備驅(qū)動程序是內(nèi)核的一部分,硬件驅(qū)動程序是操作系統(tǒng)最基本的組成部分,在Linux內(nèi)核源程序中也占有60%以上。因此,熟悉驅(qū)動的編寫是很重要的。Linux內(nèi)核中采用可加載的模塊化設(shè)計(jì)(LKMs,LoadableKernelModules),一般情況下編譯的Linux內(nèi)核是支持可插入式模塊的,也就是將最基本的核心代碼編譯在內(nèi)核中,其他的代碼可以選擇在內(nèi)核中,或者編譯為內(nèi)核的模塊文件。常見的驅(qū)動程序也是作為內(nèi)核模塊動態(tài)加載的,比如聲卡驅(qū)動和網(wǎng)卡驅(qū)動等,而Linux最基礎(chǔ)的驅(qū)動,如CPU、PCI總線、TCP/IP協(xié)議、APM(高級電源管理)、VFS等驅(qū)動程序則直接編譯在內(nèi)核文件中。有時(shí)也把內(nèi)核模塊叫做驅(qū)動程序,只不過驅(qū)動的內(nèi)容不一定是硬件罷了,比如ext3文件系統(tǒng)的驅(qū)動。因此,加載驅(qū)動時(shí)就是加載內(nèi)核模塊。2.設(shè)備文件分類在前面提到過,Linux的一個(gè)重要特點(diǎn)就是將所有的設(shè)備都當(dāng)做文件進(jìn)行處理,這一類特殊文件就是設(shè)備文件,它們可以使用前面提到的文件、I/O相關(guān)函數(shù)進(jìn)行操作,這樣就大大方便了對設(shè)備的處理。它通常在/dev下面存在一個(gè)對應(yīng)的邏輯設(shè)備節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)以文件的形式存在。Linux系統(tǒng)的設(shè)備文件分為三類:塊設(shè)備文件、字符設(shè)備文件和網(wǎng)絡(luò)設(shè)備文件。塊設(shè)備文件通常指一些需要以塊(如512字節(jié))的方式寫入的設(shè)備,如IDE硬盤、SCSI硬盤、光驅(qū)等。字符型設(shè)備文件通常指可以直接讀寫,沒有緩沖區(qū)的設(shè)備,如并口、虛擬控制臺等。網(wǎng)絡(luò)設(shè)備文件通常是指網(wǎng)絡(luò)設(shè)備訪問的BSDsocket接口,如網(wǎng)卡等。3.設(shè)備號設(shè)備號是一個(gè)數(shù)字,它是設(shè)備的標(biāo)志。一個(gè)設(shè)備文件(也就是設(shè)備節(jié)點(diǎn))可以通過mknod命令來創(chuàng)建,其中指定了主設(shè)備號和次設(shè)備號。主設(shè)備號表明某一類設(shè)備,一般對應(yīng)著確定的驅(qū)動程序;次設(shè)備號一般是用于區(qū)分標(biāo)明不同屬性,例如不同的使用方法,不同的位置,不同的操作等,它標(biāo)志著某個(gè)具體的物理設(shè)備。高字節(jié)為主設(shè)備號和底字節(jié)為次設(shè)備號。例如,在系統(tǒng)中的塊設(shè)備IDE硬盤的主設(shè)備號是3,而多個(gè)IDE硬盤及其各個(gè)分區(qū)分別賦予次設(shè)備號1、2、3……4.驅(qū)動層次結(jié)構(gòu)Linux下的設(shè)備驅(qū)動程序是內(nèi)核的一部分,運(yùn)行在內(nèi)核模式,也就是說設(shè)備驅(qū)動程序?yàn)閮?nèi)核提供了一個(gè)I/O接口,用戶使用這個(gè)接口實(shí)現(xiàn)對設(shè)備的操作。下圖顯示了典型的Linux輸入/輸出系統(tǒng)中各層次結(jié)構(gòu)和功能。4.驅(qū)動層次結(jié)構(gòu)Linux設(shè)備驅(qū)動程序包含中斷處理程序和設(shè)備服務(wù)子程序兩部分。設(shè)備服務(wù)子程序包含了所有與設(shè)備操作相關(guān)的處理代碼。它從面向用戶進(jìn)程的設(shè)備文件系統(tǒng)中接受用戶命令,并對設(shè)備控制器執(zhí)行操作。這樣,設(shè)備驅(qū)動程序屏蔽了設(shè)備的特殊性,使用戶可以像對待文件一樣操作設(shè)備。設(shè)備控制器需要獲得系統(tǒng)服務(wù)時(shí)有兩種方式:查詢和中斷。因?yàn)長inux下的設(shè)備驅(qū)動程序是內(nèi)核的一部分,在設(shè)備查詢期間系統(tǒng)不能運(yùn)行其他代碼,查詢方式的工作效率較低,所以只有少數(shù)設(shè)備如軟盤驅(qū)動程序采取這種方式,大多設(shè)備以中斷方式向設(shè)備驅(qū)動程序發(fā)出輸入/輸出請求。5.設(shè)備驅(qū)動程序與外界的接口每種類型的驅(qū)動程序,不管是字符設(shè)備還是塊設(shè)備都為內(nèi)核提供相同的調(diào)用接口,因此內(nèi)核能以相同的方式處理不同的設(shè)備。Linux為每種不同類型的設(shè)備驅(qū)動程序維護(hù)相應(yīng)的數(shù)據(jù)結(jié)構(gòu),以便定義統(tǒng)一的接口并實(shí)現(xiàn)驅(qū)動程序的可裝載性和動態(tài)性。Linux設(shè)備驅(qū)動程序與外界的接口可以分為如下三個(gè)部分。驅(qū)動程序與操作系統(tǒng)內(nèi)核的接口:這是通過數(shù)據(jù)結(jié)構(gòu)file_operations來完成的。驅(qū)動程序與系統(tǒng)引導(dǎo)的接口:這部分利用驅(qū)動程序?qū)υO(shè)備進(jìn)行初始化。驅(qū)動程序與設(shè)備的接口:這部分描述驅(qū)動程序如何與設(shè)備交互,與具體設(shè)備密切相關(guān)。它們之間的相互關(guān)系如下圖所示。6.設(shè)備驅(qū)動程序的特點(diǎn)(1)內(nèi)核代碼:設(shè)備驅(qū)動程序是內(nèi)核的一部分,如果驅(qū)動程序出錯(cuò),則可能導(dǎo)致系統(tǒng)崩潰。(2)內(nèi)核接口:設(shè)備驅(qū)動程序必須為內(nèi)核或者其子系統(tǒng)提供一個(gè)標(biāo)準(zhǔn)接口。比如,一個(gè)終端驅(qū)動程序必須為內(nèi)核提供一個(gè)文件I/O接口;一個(gè)SCSI設(shè)備驅(qū)動程序應(yīng)該為SCSI子系統(tǒng)提供一個(gè)SCSI設(shè)備接口,同時(shí)SCSI子系統(tǒng)也必須為內(nèi)核提供文件的I/O接口及緩沖區(qū)。(3)內(nèi)核機(jī)制和服務(wù):設(shè)備驅(qū)動程序使用一些標(biāo)準(zhǔn)的內(nèi)核服務(wù),如內(nèi)存分配等。(4)可裝載:大多數(shù)的Linux操作系統(tǒng)設(shè)備驅(qū)動程序都可以在需要時(shí)裝載進(jìn)內(nèi)核,在不需要時(shí)從內(nèi)核中卸載。(5)可設(shè)置:Linux操作系統(tǒng)設(shè)備驅(qū)動程序可以集成為內(nèi)核的一部分,并可以根據(jù)需要把其中的某一部分集成到內(nèi)核中,這只需要在系統(tǒng)編譯時(shí)進(jìn)行相應(yīng)的設(shè)置即可。(6)動態(tài)性:在系統(tǒng)啟動且各個(gè)設(shè)備驅(qū)動程序初始化后,驅(qū)動程序?qū)⒕S護(hù)其控制的設(shè)備。如果該設(shè)備驅(qū)動程序控制的設(shè)備不存在也不影響系統(tǒng)的運(yùn)行,那么此時(shí)的設(shè)備驅(qū)動程序只是多占用了一點(diǎn)系統(tǒng)內(nèi)存罷了。二.字符設(shè)備驅(qū)動編寫1.字符設(shè)備驅(qū)動編寫流程說明 2.重要數(shù)據(jù)結(jié)構(gòu) 3.設(shè)備驅(qū)動程序主要組成 4.proc文件系統(tǒng)1.字符設(shè)備驅(qū)動編寫流程說明在上一節(jié)中已經(jīng)提到,設(shè)備驅(qū)動程序可以使用模塊的方式動態(tài)加載到內(nèi)核中去。加載模塊的方式與以往的應(yīng)用程序開發(fā)有很大的不同。以往在開發(fā)應(yīng)用程序時(shí)都有一個(gè)main函數(shù)作為程序的入口點(diǎn),而在驅(qū)動開發(fā)時(shí)卻沒有main函數(shù),模塊在調(diào)用insmod命令時(shí)被加載,此時(shí)的入口點(diǎn)是init_module函數(shù),通常在該函數(shù)中完成設(shè)備的注冊。同樣,模塊在調(diào)用rmmod函數(shù)時(shí)被卸載,此時(shí)的入口點(diǎn)是cleanup_module函數(shù),在該函數(shù)中完成設(shè)備的卸載。在設(shè)備完成注冊加載之后,用戶的應(yīng)用程序就可以對該設(shè)備進(jìn)行一定的操作,如read、write等,而驅(qū)動程序就是用于實(shí)現(xiàn)這些操作,在用戶應(yīng)用程序調(diào)用相應(yīng)入口函數(shù)時(shí)執(zhí)行相關(guān)的操作,init_module入口點(diǎn)函數(shù)則不需要完成其他如read、write之類功能。1.字符設(shè)備驅(qū)動編寫流程說明上述函數(shù)之間的關(guān)系如圖所示2.重要數(shù)據(jù)結(jié)構(gòu)用戶應(yīng)用程序調(diào)用設(shè)備的一些功能是在設(shè)備驅(qū)動程序中定義的,也就是設(shè)備驅(qū)動程序的入口點(diǎn),它是一個(gè)在<linux/fs.h>中定義的structfile結(jié)構(gòu),這是一個(gè)內(nèi)核結(jié)構(gòu),不會出現(xiàn)在用戶空間的程序中,它定義了常見文件I/O函數(shù)的入口。每個(gè)設(shè)備的驅(qū)動程序不一定要實(shí)現(xiàn)其中所有的函數(shù)操作,若不需要定義實(shí)現(xiàn)時(shí),則只需將其設(shè)為NULL即可。其中,structinode提供了關(guān)于設(shè)備文件/dev/driver(假設(shè)此設(shè)備名為driver)的信息。structfile提供關(guān)于被打開的文件信息,主要用于與文件系統(tǒng)對應(yīng)的設(shè)備驅(qū)動程序使用。structfile較為重要3.設(shè)備驅(qū)動程序主要組成(1)設(shè)備注冊設(shè)備注冊使用函數(shù)register_chrdev,調(diào)用該函數(shù)后就可以向系統(tǒng)申請主設(shè)備號,如果register_chrdev操作成功,設(shè)備名就會出現(xiàn)在/proc/devices文件里。register_chrdev函數(shù)格式如表所示。所需頭文件#include<linux/fs.h>函數(shù)原型intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops)函數(shù)傳入值major設(shè)備驅(qū)動程序向系統(tǒng)申請的主設(shè)備號,如果為0則系統(tǒng)為此驅(qū)動程序動態(tài)地分配一個(gè)主設(shè)備號name設(shè)備名fops對各個(gè)調(diào)用的入口點(diǎn)函數(shù)返回值成功:如果是動態(tài)分配主設(shè)備號,此返回所分配的主設(shè)備號。且設(shè)備名就會出現(xiàn)在函數(shù)返回值/proc/devices文件里出錯(cuò):-13.設(shè)備驅(qū)動程序主要組成打開設(shè)備的接口函數(shù)是open,根據(jù)設(shè)備的不同,open函數(shù)完成的功能也有所不同,但通常情況下在open函數(shù)中要完成如下工作。遞增計(jì)數(shù)器。檢查特定設(shè)備的特殊情況。初始化設(shè)備。識別次設(shè)備號。其中遞增計(jì)數(shù)器是用于設(shè)備計(jì)數(shù)的。由于設(shè)備在使用時(shí)通常會打開較多次數(shù),也可以由不同的進(jìn)程所使用,所以若有一進(jìn)程想要關(guān)閉該設(shè)備,則必須保證其他設(shè)備沒有使用該設(shè)備。因此使用計(jì)數(shù)器就可以很好地完成這項(xiàng)功能。這里,實(shí)現(xiàn)計(jì)數(shù)器操作的是用在<linux/module.h>中定義的3個(gè)宏如下。MOD_INC_USE_COUNT:計(jì)數(shù)器加一。MOD_DEC_USE_COUNT:計(jì)數(shù)器減一。MOD_IN_USE:計(jì)數(shù)器非零時(shí)返回真。另外,當(dāng)有多個(gè)物理設(shè)備時(shí),就需要識別次設(shè)備號來對各個(gè)不同的設(shè)備進(jìn)行不同的操作,在有些驅(qū)動程序中并不需要用到。注意:雖然這是對設(shè)備文件執(zhí)行的第一個(gè)操作,但卻不是驅(qū)動程序一定要聲明的操作。若這個(gè)函數(shù)的入口為NULL,那么設(shè)備的打開操作將永遠(yuǎn)成功,但系統(tǒng)不會通知驅(qū)動程序。3.設(shè)備驅(qū)動程序主要組成(4)釋放設(shè)備釋放設(shè)備的接口函數(shù)是release。要注意釋放設(shè)備和關(guān)閉設(shè)備是完全不同的。當(dāng)一個(gè)進(jìn)程釋放設(shè)備時(shí),其他進(jìn)程還能繼續(xù)使用該設(shè)備,只是該進(jìn)程暫時(shí)停止對該設(shè)備的使用;而當(dāng)一個(gè)進(jìn)程關(guān)閉設(shè)備時(shí),其他進(jìn)程必須重新打開此設(shè)備才能使用。釋放設(shè)備時(shí)要完成的工作如下。遞減計(jì)數(shù)器MOD_DEC_USE_COUNT。在最后一次釋放設(shè)備操作時(shí)關(guān)閉設(shè)備。3.設(shè)備驅(qū)動程序主要組成(5)讀寫設(shè)備讀寫設(shè)備的主要任務(wù)就是把內(nèi)核空間的數(shù)據(jù)復(fù)制到用戶空間,或者從用戶空間復(fù)制到內(nèi)核空間,也就是將內(nèi)核空間緩沖區(qū)里的數(shù)據(jù)復(fù)制到用戶空間的緩沖區(qū)中或者相反。雖然這個(gè)過程看起來很簡單,但是內(nèi)核空間地址和應(yīng)用空間地址是有很大區(qū)別的,其中之一就是用戶空間的內(nèi)存是可以被換出的,因此可能會出現(xiàn)頁面失效等情況。所以就不能使用諸如memcpy之類的函數(shù)來完成這樣的操作。在這里就要使用copy_to_user或copy_from_user函數(shù),它們就是用來實(shí)現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)交換的。要注意,這兩個(gè)函數(shù)不僅實(shí)現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)轉(zhuǎn)換,而且還會檢查用戶空間指針的有效性。如果指針無效,那么就不進(jìn)行復(fù)制3.設(shè)備驅(qū)動程序主要組成(6)獲取內(nèi)存在應(yīng)用程序中獲取內(nèi)存通常使用函數(shù)malloc,但在設(shè)備驅(qū)動程序中動態(tài)開辟內(nèi)存可以有基于內(nèi)存地址和基于頁面為單位兩類。其中,基于內(nèi)存地址的函數(shù)有kmalloc,注意的是,kmalloc函數(shù)返回的是物理地址,而malloc等返回的是線性地址,因此在驅(qū)動程序中不能使用malloc函數(shù)。與malloc()不同,kmalloc()申請空間有大小限制。長度是2的整次方,并且不會對所獲取的內(nèi)存空間清零。基于頁為單位的內(nèi)存函數(shù)族有:get_zeroed_page:獲得一個(gè)已清零頁面。get_free_page:獲得一個(gè)或幾個(gè)連續(xù)頁面。get_dma_pages:獲得用于DMA傳輸?shù)捻撁?。與之相對應(yīng)的釋放內(nèi)存用也有kfree或free_pages族。3.設(shè)備驅(qū)動程序主要組成(7)打印信息就如同在編寫用戶空間的應(yīng)用程序,打印信息有時(shí)是很好的調(diào)試手段,也是在代碼中很常用的組成部分。但是與用戶空間不同,在內(nèi)核空間要用函數(shù)printk而不能用平常的函數(shù)printf。printk和printf很類似,都可以按照一定的格式打印消息,printk還可以定義打印消息的優(yōu)先級。這些不同優(yōu)先級的信息可以輸出到控制臺上、/var/log/messages里。其中,對輸出給控制臺的信息有一個(gè)特定的優(yōu)先級console_loglevel。若優(yōu)先級小于這個(gè)整數(shù)值時(shí),則消息才能顯示到控制臺上,否則,消息會顯示在/var/log/messages里。若不加任何優(yōu)先級選項(xiàng),則消息默認(rèn)輸出到/var/log/messages文件中。注意:要開啟klogd和syslogd服務(wù),消息才能正常輸出。4.proc文件系統(tǒng)/proc文件系統(tǒng)是一個(gè)偽文件系統(tǒng),它是一種內(nèi)核和內(nèi)核模塊用來向進(jìn)程發(fā)送信息的機(jī)制。這個(gè)偽文件系統(tǒng)讓用戶可以和內(nèi)核內(nèi)部數(shù)據(jù)結(jié)構(gòu)進(jìn)行交互,獲取有關(guān)進(jìn)程的有用信息,在運(yùn)行時(shí)通過改變內(nèi)核參數(shù)改變設(shè)置。與其他文件系統(tǒng)不同,/proc存在于內(nèi)存之中而不是硬盤上。讀者可以通過“l(fā)s”查看/proc文件系統(tǒng)的內(nèi)容。三.塊設(shè)備驅(qū)動編寫1.塊設(shè)備驅(qū)動程序描述符2.塊設(shè)備驅(qū)動編寫流程1.塊設(shè)備驅(qū)動程序描述符塊設(shè)備文件通常指一些需要以塊(如512字節(jié))的方式寫入的設(shè)備,如IDE硬盤、SCSI硬盤、光驅(qū)等。它的驅(qū)動程序的編寫過程與字符型設(shè)備驅(qū)動程序的編寫有很大的區(qū)別。塊設(shè)備驅(qū)動程序描述符是一個(gè)包含在<linux/blkdev.h>中的blk_dev_struct類型的數(shù)據(jù)結(jié)構(gòu),其定義如下所示:structblk_dev_struct{request_queue_trequest_queue;queue_proc*queue;void*date;};1.塊設(shè)備驅(qū)動程序描述符在這個(gè)結(jié)構(gòu)中,請求隊(duì)列request_queue是主體,包含了初始化之后的I/O請求隊(duì)列。對于函數(shù)指針queue,當(dāng)其為非0時(shí),就調(diào)用這個(gè)函數(shù)來找到具體設(shè)備的請求隊(duì)列,這是為考慮具有同一主設(shè)備號的多種同類設(shè)備而設(shè)的一個(gè)域,該指針也在初始化時(shí)就設(shè)置好。指針data是輔助queue函數(shù)找到特定設(shè)備的請求隊(duì)列,保存一些私有的數(shù)據(jù)。所有塊設(shè)備的描述符都存放在blk_dev表structblk_dev_structblk_dev[MAX_BLKDEV]中;每個(gè)塊設(shè)備都對應(yīng)著數(shù)組中的一項(xiàng),可以使用主設(shè)備號進(jìn)行檢索。每當(dāng)用戶進(jìn)程對一個(gè)塊設(shè)備發(fā)出一個(gè)讀寫請求時(shí),首先調(diào)用塊設(shè)備所公用的函數(shù)generic_file_read()和generic_file_write()。如果數(shù)據(jù)存在在緩沖區(qū)中或緩沖區(qū)還可以存放數(shù)據(jù),那么就同緩沖區(qū)進(jìn)行數(shù)據(jù)交換。否則,系統(tǒng)會將相應(yīng)的請求隊(duì)列結(jié)構(gòu)添加到其對應(yīng)項(xiàng)的blk_dev_struct中,如下圖所示。1.塊設(shè)備驅(qū)動程序描述符2.塊設(shè)備驅(qū)動編寫流程流程說明塊設(shè)備驅(qū)動程序的編寫流程同字符設(shè)備驅(qū)動程序的編寫流程很類似,也包括了注冊和使用兩部分。但與字符驅(qū)動設(shè)備所不同的是,塊設(shè)備驅(qū)動程序包括一個(gè)request請求隊(duì)列。它是當(dāng)內(nèi)核安排一次數(shù)據(jù)傳輸時(shí)在列表中的一個(gè)請求隊(duì)列,用以最大化系統(tǒng)性能為原則進(jìn)行排序。在后面的讀寫操作時(shí)會詳細(xì)講解這個(gè)函數(shù),下圖給出了塊設(shè)備驅(qū)動程序的流程圖,請注意與字符設(shè)備驅(qū)動程序的區(qū)別。四.中斷編程四.中斷編程前面所講述的驅(qū)動程序中都沒有涉及到中斷處理,而實(shí)際上,有很多Linux的驅(qū)動都是通過中斷的方式來進(jìn)行內(nèi)核和硬件的交互。這是驅(qū)動程序申請中斷和釋放中斷的調(diào)用。在include/linux/sched.h里聲明。request_irq()調(diào)用的定義:intrequest_irq(unsignedintirq,void(*handler)(intirq,void*dev_id,structpt_regs*regs),unsignedlongirqflags,constchar*devname,oid*dev_id);irq是要申請的硬件中斷號。在Intel平臺,范圍是0~15。handler是向系統(tǒng)登記的中斷處理函數(shù)。這是一個(gè)回調(diào)函數(shù),中斷發(fā)生時(shí),系統(tǒng)調(diào)用這個(gè)函數(shù),傳入的參數(shù)包括硬件中斷號,deviceid,寄存器值。dev_id就是下面的request_irq時(shí)傳遞給系統(tǒng)的參數(shù)dev_id。irqflags是中斷處理的一些屬性。比較重要的有SA_INTERRUPT,標(biāo)明中斷處理程序是快速處理程序(設(shè)置SA_INTERRUPT)還是慢速處理程序(不設(shè)置SA_INTERRUPT)??焖偬幚沓绦虮徽{(diào)用時(shí)屏蔽所有中斷。慢速處理程序不屏蔽。還有一個(gè)SA_SHIRQ屬性,設(shè)置了以后運(yùn)行多個(gè)設(shè)備共享中斷。dev_id在中斷共享時(shí)會用到。一般設(shè)置為這個(gè)設(shè)備的device結(jié)構(gòu)本身或者NULL。中斷處理程序可以用dev_id找到相應(yīng)的控制這個(gè)中斷的設(shè)備,或者用irq2dev_map找到中斷對應(yīng)的設(shè)備。voidfree_irq(unsignedintirq,void*dev_id);五.鍵盤驅(qū)動實(shí)現(xiàn)1.鍵盤工作原理 2.鍵盤驅(qū)動綜述 3.鍵盤驅(qū)動流程1.鍵盤工作原理(1)原理簡介在鍵盤產(chǎn)生按鍵動作之后,鍵盤上的掃描芯片(一般為8048)獲得鍵盤的掃描碼,并將其發(fā)送到主機(jī)端。在主機(jī)端的處理過程為是端口讀取掃描碼之后,對鍵盤模式作一個(gè)判斷,如果是RAW模式,則直接將鍵盤掃描碼發(fā)送給應(yīng)用程序;如果是其他模式,則就將掃描碼轉(zhuǎn)化成為鍵盤碼,然后再判斷模式以決定是否將鍵盤碼直接發(fā)送給應(yīng)用程序;如果是XLATE或Unicod。模式,則將鍵盤碼再次轉(zhuǎn)化成為符號碼,然后根據(jù)對符號碼解析,獲得相應(yīng)的處理函數(shù),并將其送到TY設(shè)備的緩存中。鍵盤模式有4種,這4種模式的對應(yīng)關(guān)系如圖所示。Scancodemode(RAW)模式:將鍵盤端口上讀出的掃描碼放入緩沖區(qū),通過參數(shù)s設(shè)置。Keycodemode(MEDIUMRAW)模式:將掃描碼過濾為鍵盤碼放入緩沖區(qū),通過參數(shù)k設(shè)置。ASCIImode(XLATE)模式:識別各種鍵盤碼的組合,轉(zhuǎn)換為TTY終端代碼放入緩沖區(qū),通過參數(shù)a可以設(shè)置。UTF-8mode(Unicode)模式:Unicode模式基本上與XLATE相同,只不過可以通過數(shù)字小鍵盤I旬接槍入U(xiǎn)nicode代碼,通過參數(shù)u可以設(shè)置。1.鍵盤工作原理(2)掃描碼一個(gè)基本按鍵的掃描碼由3個(gè)字節(jié)組成:1個(gè)字節(jié)的接通掃描碼和2個(gè)字節(jié)的斷開掃描碼。其中第1和第2個(gè)字節(jié)相同,中間字節(jié)是斷開標(biāo)志F0H。例如B鍵的接通掃描碼是32H,斷開掃描碼是F0H32H,B鍵被按下時(shí),32H被發(fā)送出去,如果移植按住不放,則鍵盤將以按鍵重復(fù)率不停地發(fā)送32H,直到該鍵釋放,才發(fā)出斷開掃描碼F0H32H。掃描碼與按鍵的位置有關(guān),與該鍵的ASCII碼并無對應(yīng)關(guān)系。鍵盤上還有部分?jǐn)U展鍵(功能鍵和控制鍵等),這些鍵的掃描碼由5個(gè)字節(jié)組成,與基本鍵的掃描碼相比,接通掃描碼與斷開掃描碼前各多了一個(gè)固定值字節(jié)E0H。例如Home鍵的接通掃描碼是E0H70H,斷開掃描碼是E0HF0H70H。還有兩個(gè)特殊鍵,PrintScreen鍵的接通掃描碼是E0H12HE0H7CH;斷開掃描碼是E0HF0H7CHE0HF0H77H,無斷開掃描碼。1.鍵盤工作原理(3)鍵盤碼由前面的分析可見,單單一個(gè)鍵的按下與斷開,鍵盤最多要產(chǎn)生一系列多達(dá)6個(gè)字節(jié)的掃描碼序列,而內(nèi)核必須解析掃描碼序列從而定位某個(gè)鍵被按下與釋放的事件。為達(dá)到這個(gè)目的,每一個(gè)鍵被分配一個(gè)鍵盤碼k(k的范圍1-127)如果按鍵按下產(chǎn)生的鍵盤碼為k,則釋放該鍵產(chǎn)生的鍵盤碼為k+128。按照鍵盤碼的分配規(guī)則,對于產(chǎn)生單個(gè)掃描碼范圍0x0l~0x58的鍵,其鍵盤碼與掃描碼相同。而對于0x59~0x71范圍的鍵,可以查表獲得其掃描碼與鍵盤碼對應(yīng)。1.鍵盤工作原理(4)符號碼符號碼(keysym)最終是用來標(biāo)志一個(gè)按鍵事件的惟一值;根據(jù)上面的分析,它由鍵盤碼經(jīng)過Keymap表映射而來。它包括2個(gè)字節(jié),高8位表示type,根據(jù)type的不同,我們最終選擇不同的處理函數(shù)來處理不同類型的事件,type相同的事件由同一個(gè)函數(shù)來處理。Type包括一般鍵、方向鍵、字母鍵、函數(shù)鍵等。在<linux/keyboard.h>中可以找到13種鍵類型的宏定義。1.鍵盤工作原理(5)Keymap表在使用鍵盤時(shí)常常使用組合鍵,而組合鍵的意義通常是系統(tǒng)另外賦予的,所以從鍵盤碼向TY輸入符的轉(zhuǎn)換需要借助Keymap表來索引。intshift_final=shiftstate^kbd-Aockstate;ushort'keymap=keymaps[shiftfinall];keysym=key_map[keycodel];由于共計(jì)有8個(gè)修飾符(modifier),即Shift,AitGr,Control,Alt,ShiftL,ShiftR,CtrIL和CtrlR,因此共有256張可能的Keymap,而在實(shí)際使用時(shí),內(nèi)核缺省只分配7張Keymap:plain,Shift,AltR,Ctrl,Ctrl+Shift,AItL和Ctrl+AitL。1.鍵盤工作原理Keymap表是一張二維表,結(jié)構(gòu)圖如圖所示。通過這張Keymap表,就能完成鍵盤碼到符號碼的轉(zhuǎn)化,獲得相應(yīng)的符號碼。Ctrl...shift......鍵盤碼排序:符號碼Keysym2.鍵盤驅(qū)動綜述Linux中的大多數(shù)驅(qū)動程序都采用了層次型的體系結(jié)構(gòu),鍵盤驅(qū)動程序也不例外。在Linux中,鍵盤驅(qū)動被劃分成兩層來實(shí)現(xiàn)。其中,上層是一個(gè)通用的鍵盤抽象層,完成鍵盤驅(qū)動中不依賴于底層具
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年金融服務(wù)采購合同創(chuàng)新金融產(chǎn)品合作協(xié)議2篇
- 導(dǎo)演與發(fā)行方2025年度合同3篇
- 二零二五年度餐飲泔水處理與環(huán)保設(shè)施運(yùn)營管理合同6篇
- 二零二五年度高校畢業(yè)生就業(yè)見習(xí)實(shí)踐基地建設(shè)合作合同3篇
- 二零二五年度航空航天設(shè)備維修承包合同樣本3篇
- 二零二五年高性能混凝土委托加工合同范本3篇
- 碎石買賣合同(二零二五年度)2篇
- 二零二五年度藥品質(zhì)量第三方檢測合同范本6篇
- 二零二五版國際貿(mào)易中貨物所有權(quán)轉(zhuǎn)移與國際貿(mào)易政策研究合同3篇
- 2025年度電力設(shè)施租賃合同標(biāo)的轉(zhuǎn)讓協(xié)議3篇
- 課題申報(bào)書:大中小學(xué)鑄牢中華民族共同體意識教育一體化研究
- 巖土工程勘察課件0巖土工程勘察
- 《腎上腺腫瘤》課件
- 2024-2030年中國典當(dāng)行業(yè)發(fā)展前景預(yù)測及融資策略分析報(bào)告
- 《乘用車越野性能主觀評價(jià)方法》
- 幼師個(gè)人成長發(fā)展規(guī)劃
- 2024-2025學(xué)年北師大版高二上學(xué)期期末英語試題及解答參考
- 批發(fā)面包采購合同范本
- 乘風(fēng)化麟 蛇我其誰 2025XX集團(tuán)年終總結(jié)暨頒獎(jiǎng)盛典
- 2024年大數(shù)據(jù)分析公司與中國政府合作協(xié)議
- 一年級數(shù)學(xué)(上)計(jì)算題專項(xiàng)練習(xí)匯編
評論
0/150
提交評論