版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Linux下的硬件驅(qū)動USB設(shè)備(上)相關(guān)技術(shù)基礎(chǔ)模塊(驅(qū)動程序)模塊(module)是在內(nèi)核空間運行的程序,實際上是一種目標對象文件,沒有鏈接,不能獨立運行,但是可以裝載到系統(tǒng)中作為內(nèi)核的一部分運行,從而可以動態(tài)擴充內(nèi)核的功能。模塊最主要的用處就是用來實現(xiàn)設(shè)備驅(qū)動程序。Linux下對于一個硬件的驅(qū)動,可以有兩種方式:直接加載到內(nèi)核代碼中,啟動內(nèi)核時就會驅(qū)動此硬件設(shè)備。另一種就是以模塊方式,編譯生成一個.o文件。當應(yīng)用程序需要時再加載進內(nèi)核空間運行。所以我們所說的一個硬件的驅(qū)動程序,通常指的就是一個驅(qū)動模塊。設(shè)備文件對于一個設(shè)備,它可以在/dev下面存在一個對應(yīng)的邏輯設(shè)備節(jié)點,這個節(jié)點以文件的
2、形式存在,但它不是普通意義上的文件,它是設(shè)備文件,更確切的說,它是設(shè)備節(jié)點。這個節(jié)點是通過mknod命令建立的,其中指定了主設(shè)備號和次設(shè)備號。主設(shè)備號表明了某一類設(shè)備,一般對應(yīng)著確定的驅(qū)動程序;次設(shè)備號一般是區(qū)分不同屬性,例如不同的使用方法,不同的位置,不同的操作。這個設(shè)備號是從/proc/devices文件中獲得的,所以一般是先有驅(qū)動程序在內(nèi)核中,才有設(shè)備節(jié)點在目錄中。這個設(shè)備號(特指主設(shè)備號)的主要作用,就是聲明設(shè)備所使用的驅(qū)動程序。驅(qū)動程序和設(shè)備號是一一對應(yīng)的,當你打開一個設(shè)備文件時,操作系統(tǒng)就已經(jīng)知道這個設(shè)備所對應(yīng)的驅(qū)動程序。SCSI設(shè)備SCSI是有別于IDE的一個計算機標準接口?,F(xiàn)在
3、大部分平板式掃描儀、CD-R刻錄機、M0光磁盤機等漸漸趨向使用SCSI接口,加之SCSI又能提供一個高速傳送通道,所以,接觸到SCSI設(shè)備的用戶會越來越多。Linux支持很多種的SCSI設(shè)備,例如:SCSI硬盤、SCSI光驅(qū)、SCSI磁帶機。更重要的是,Linux提供了IDE設(shè)備對SCSI的模擬(ide-scsi.o模塊),我們通常會就把IDE光驅(qū)模擬為SCSI光驅(qū)進行訪問。因為在Linux中很多軟件都只能操作SCSI光驅(qū)。例如大多數(shù)刻錄軟件、一些媒體播放軟件。通常我們的USB存儲設(shè)備,也模擬為SCSI硬盤而進行訪問。Linux硬件驅(qū)動架構(gòu)對于一個硬件,Linux是這樣來進行驅(qū)動的:首先,我們
4、必須提供一個.o的驅(qū)動模塊文件(這里我們只說明模塊方式,其實內(nèi)核方式是類似的)。我們要使用這個驅(qū)動程序,首先要加載運行它(insmod*.o)。這樣驅(qū)動就會根據(jù)自己的類型(字符設(shè)備類型或塊設(shè)備類型,例如鼠標就是字符設(shè)備而硬盤就是塊設(shè)備)向系統(tǒng)注冊,注冊成功系統(tǒng)會反饋一個主設(shè)備號,這個主設(shè)備號就是系統(tǒng)對它的唯一標識(例如硬盤塊設(shè)備在/proc/devices中顯示的主設(shè)備號為3,我們用ls-l/dev/had看到的主設(shè)備就肯定是3)。驅(qū)動就是根據(jù)此主設(shè)備號來創(chuàng)建一個一般放置在/dev目錄下的設(shè)備文件(mknod命令用來創(chuàng)建它,它必須用主設(shè)備號這個參數(shù))。在我們要訪問此硬件時,就可以對設(shè)備文件通過
5、open、read、write等命令進行。而驅(qū)動就會接收到相應(yīng)的read、write操作而根據(jù)自己的模塊中的相應(yīng)函數(shù)進行了。其中還有幾個比較有關(guān)系的東西:一個是/lib/modules/2.4.XX目錄,它下面就是針對當前內(nèi)核版本的模塊。只要你的模塊依賴關(guān)系正確(可以通過depmod設(shè)置),你就可以通過modprobe命令加載而不需要知道具體模塊文件位置。另一個是/etc/modules.conf文件,它定義了一些常用設(shè)備的別名。系統(tǒng)就可以在需要此設(shè)備支持時,正確尋找驅(qū)動模塊。例如aliasethOelOO,就代表第一塊網(wǎng)卡的驅(qū)動模塊為e100.o。他們的關(guān)系圖如下:配置USB設(shè)備內(nèi)核中配置.
6、要啟用LinuxUSB支持,首先進入USBsupport節(jié)并啟用SupportforUSB選項(對應(yīng)模塊為usbcore.o)。盡管這個步驟相當直觀明了,但接下來的LinuxUSB設(shè)置步驟則會讓人感到糊涂。特別地,現(xiàn)在需要選擇用于系統(tǒng)的正確USB主控制器驅(qū)動程序。選項是EHCI(對應(yīng)模塊為ehci-hcd.o)、UHCI(對應(yīng)模塊為usb-uhci.o)、UHCI(alternatedriver)和OHCI(對應(yīng)模塊為usb-ohci.o)。這是許多人對Linux的USB開始感到困惑的地方。要理解EHCI及其同類是什么,首先要知道每塊支持插入USB設(shè)備的主板或PCI卡都需要有USB主控制器芯片
7、組。這個特別的芯片組與插入系統(tǒng)的USB設(shè)備進行相互操作,并負責(zé)處理允許USB設(shè)備與系統(tǒng)其它部分通信所必需的所有低層次細節(jié)。LinuxUSB驅(qū)動程序有三種不同的USB主控制器選項是因為在主板和PCI卡上有三種不同類型的USB芯片。EHCI驅(qū)動程序設(shè)計成為實現(xiàn)新的高速USB2.0協(xié)議的芯片提供支持。OHCI驅(qū)動程序用來為非PC系統(tǒng)上的(以及帶有SiS和ALi芯片組的PC主板上的)USB芯片提供支持。UHCI驅(qū)動程序用來為大多數(shù)其它PC主板(包括Intel和Via)上的USB實現(xiàn)提供支持。只需選擇與希望啟用的USB支持的類型對應(yīng)的?HCI驅(qū)動程序即可。如有疑惑,為保險起見,可以啟用EHCI、UHCI
8、(兩者中任選一種,它們之間沒有明顯的區(qū)別)和OHCI(趙明注:根據(jù)文檔,EHCI已經(jīng)包含了UHCI和OHCI,但目前就我個人的測試單獨加EHCI是不行的,通常我的做法是根據(jù)主板類型加載HCI或OHCI后,再加載EHCI這樣才可以支持USB2.0設(shè)備)。啟用了USBsupport和適當?shù)?HCIUSB主控制器驅(qū)動程序后,使USB啟動并運行只需再進行幾個步驟。應(yīng)該啟用“PreliminaryUSBdevicefilesystem,然后確保啟用所有特定于將與Linux一起使用的實際USB外圍設(shè)備的驅(qū)動程序。例如,為了啟用對USB游戲控制器的支持,我啟用了USBHumanInterfaceDevice
9、(fullHID)support。我還啟用了主“Inputcoresupport節(jié)下的Inputcoresupport和Joysticksupport。一旦用新的已啟用USB的內(nèi)核重新引導(dǎo)后,若/proc/bus/usb下沒有相應(yīng)USB設(shè)備信息,應(yīng)輸入以下命令將USB設(shè)備文件系統(tǒng)手動掛裝到/proc/bus/usb:#mount-tusbdevfsnone/proc/bus/usb為了在系統(tǒng)引導(dǎo)時自動掛裝USB設(shè)備文件系統(tǒng),請將下面一行添加到/etc/fstab中的/proc掛裝行之后:none/proc/bus/usbusbdevfsdefaults00模塊的配置方法.在很多時候,我們的US
10、B設(shè)備驅(qū)動并不包含在內(nèi)核中。其實我們只要根據(jù)它所需要使用的模塊,逐一加載。就可以使它啟作用。首先要確保在內(nèi)核編譯時以模塊方式選擇了相應(yīng)支持。這樣我們就應(yīng)該可以在/lib/modules/2.4.XX目錄看到相應(yīng).o文件。在加載模塊時,我們只需要運行modprobexxx.o就可以了(modprobe主要加載系統(tǒng)已經(jīng)通過depmod登記過的模塊,insmod一般是針對具體.o文件進行加載)對應(yīng)USB設(shè)備下面一些模塊是關(guān)鍵的。usbcore.o要支持usb所需要的最基礎(chǔ)模塊usb-uhci.o(已經(jīng)提過)usb-ohci.o(已經(jīng)提過)uhci.o另一個uhci驅(qū)動程序,我也不知道有什么用,一般不
11、要加載,會死機的ehci-hcd.o(已經(jīng)提過usb2.0)hid.oUSB人機界面設(shè)備,像鼠標呀、鍵盤呀都需要usb-storage.oUSB存儲設(shè)備,U盤等用到相關(guān)模塊ide-disk.oIDE硬盤ide-scsi.o把IDE設(shè)備模擬SCSI接口scsi_mod.oSCSI支持注意kernelconfig其中一項:ProbeallLUNsoneachSCSIdevice最好選上,要不某些同時支持多個口的讀卡器只能顯示一個。若模塊方式就要帶參數(shù)安裝或提前在/etc/modules.conf中加入以下項,來支持多個LUN。addoptionsscsi_modmax_scsi_luns=9sd_
12、mod.oSCSI硬盤sr_mod.oSCSI光盤sg.oSCSI通用支持(在某些探測U盤、SCSI探測中會用到)常見USB設(shè)備及其配置在Linux2.4的內(nèi)核中已經(jīng)支持不下20種設(shè)備。它支持幾乎所有的通用設(shè)備如鍵盤、鼠標、modem、打印機等,并不斷地添加廠商新的設(shè)備象數(shù)碼相機、MP3、網(wǎng)卡等。下面就是幾個最常見設(shè)備的介紹和使用方法:USB鼠標:鍵盤和鼠標屬于低速的輸入設(shè)備,對于已經(jīng)為用戶認可的PS/2接口,USB鍵盤和USB鼠標似乎并沒有太多更優(yōu)越的地方。現(xiàn)在的大部分鼠標采用了PS/2接口,不過USB接口的鼠標也越來越多,兩者相比,各有優(yōu)勢:一般來說,USB的鼠標接口的帶寬大于PS/2鼠標
13、,也就是說在同樣的時間內(nèi),USB鼠標掃描次數(shù)就要多于PS/2鼠標,這樣在定位上USB鼠標就更為精確;同時USB接口鼠標的默認采樣率也比較高,達到125HZ,而PS/2接口的鼠標僅有40HZ(Windows9x/Me)或是60HZ(WindowsNT/2000)。對于USB設(shè)備你當然必須先插入相應(yīng)的USB控制器模塊:usb-uhci.o或usbohci.omodprobeusbuhciUSB鼠標為了使其正常工作,您必須先插入模塊usbmouse.o和mousedev.omodprobeusbmousemodprobemousedev若你把HIDinputlayer支持和inputcore支持也作
14、為模塊方式安裝,那么啟動hid模塊和input模塊也是必要的。modprobehidmodprobeinputUSB鍵盤:一般的,我們現(xiàn)在使用的鍵盤大多是PS/2的,USB鍵盤還比較少見,但是下來的發(fā)展,鍵盤將向USB接口靠攏。使用USB鍵盤基本上沒有太多的要求,只需在主板的BIOS設(shè)定對USB鍵盤的支持,就可以在各系統(tǒng)中完全無障礙的使用,而且更可以真正做到在即插即用和熱插拔使用,并能提供兩個USB連接埠:讓您可以輕易地直接將具有USB接頭的裝置接在您的鍵盤上,而非計算機的后面。同樣你當然必須先插入相應(yīng)的USB控制器模塊:usb-uhci.o或usb-ohci.omodprobeusb-uhc
15、i然后您還必須插入鍵盤模塊usbkbd.o,以及keybdev.o,這樣usb鍵盤才能夠正常工作。此時,運行的系統(tǒng)命令:modprobeusbkbdmodprobekeybdev同樣若你把HIDinputlayer支持和inputcore支持也作為模塊方式安裝,那么啟動hid模塊和input模塊也是必要的。U盤和USB讀卡器:數(shù)碼存儲設(shè)備現(xiàn)在對我們來說已經(jīng)是相當普遍的了。CF卡、SD卡、MemoryStick等存儲卡已經(jīng)遍及我們的身邊,通常,他們的讀卡器都是USB接口的。另外,很多MP3、數(shù)碼相機也都是USB接口和計算機進行數(shù)據(jù)傳遞。更我們的U盤、USB硬盤,作為移動存儲設(shè)備,已經(jīng)成為我們的必
16、須裝備。在Linux下這些設(shè)備通常都是以一種叫做usb-storage的方式進行驅(qū)動。要使用他們必須加載此模塊modprobeusb-storage當然,usbcore.o和usb-uhci.o或usb-ohci也肯定是不可缺少的。另外,若你系統(tǒng)中SCSI支持也是模塊方式,那么下面的模塊也要加載modprobescsi_modmodprobesd_mod在加載完這些模塊后,我們插入U盤或存儲卡,就會發(fā)現(xiàn)系統(tǒng)中多了一個SCSI硬盤,通過正確地mount它,就可以使用了(SCSI硬盤一般為/dev/sd?,可參照文章后面的常見問題解答)。mount/dev/sdal/mntLinux支持的其他US
17、B設(shè)備。MODEM-(比較常見)網(wǎng)絡(luò)設(shè)備攝像頭一(比較常見)例如ov511.o聯(lián)機線-可以讓你的兩臺電腦用USB線實現(xiàn)網(wǎng)絡(luò)功能。usbnet.o顯示器一(我沒見過)游戲桿電視盒一(比較常見)手寫板一(比較常見)掃描儀一(比較常見)刻錄機一(比較常見)打印機一(比較常見)注意:上面所說的每個驅(qū)動模塊,并不是都要手動加載,有很多系統(tǒng)會在啟動或你的應(yīng)用需要時自動加載的,寫明這些模塊,是便于你在不能夠使用USB設(shè)備時,可以自行檢查。只要用lsmod確保以上模塊已經(jīng)被系統(tǒng)加載,你的設(shè)備就應(yīng)該可以正常工作了。當然注意有些模塊已經(jīng)以內(nèi)核方式在kernel啟動時存在了(這些模塊文件在/lib/modules/
18、2.4.XX中是找不到的)?;仨撌鬃畛S鲆姷腢SB問題有USB設(shè)備的系統(tǒng)安裝完redhat7.3啟動死機問題有USB設(shè)備,當你剛裝完redhat7.3第一次啟動時,總會死掉。主要原因是Linux在安裝時探測到有usb-uhci和ehci-hcd兩個控制器,但在啟動時,加載完usb-uhci再加載ehci-hcd就會有沖突。分析認為redhat7.3系統(tǒng)內(nèi)核在支持USB2.0標準上存在問題。在其他版本的Linux中均不存在此問題。解決辦法:在lilo或grub啟動時用命令行傳遞參數(shù)init二/sbin/init。這樣在啟動后就不運行其他服務(wù)而直接啟動shell。然后運行mount-oremoun
19、t,rw/使/可寫,init直接啟動的系統(tǒng)默認只mount/為只讀然后vi/etc/modules.config文件刪除aliasusb-controllerlehci-hcd一行。或前面加#注釋掉然后mount-oremount,ro/使/只讀,避免直接關(guān)機破壞文件系統(tǒng)然后就可以按Ctrl-Alt-Delete直接重啟了或許,你有更簡單的辦法:換USB鍵盤和鼠標為PS2接口,啟動后修改/etc/modules.config文件。我們已經(jīng)知道U盤在Linux中會模擬為SCSI設(shè)備去訪問,可怎么知道它對應(yīng)那個SCSI設(shè)備呢?方法1:推測。通常你第一次插入一個SCSI設(shè)備,它就是sda,第二個就是
20、sdb以此類推。你啟動Linux插入一個U盤,就試試sda,換了一個就可能是sdb。這里注意兩個特例:1)你用的是聯(lián)想U盤,它可能存在兩個設(shè)備區(qū)(一個用于加密或啟動電腦),這樣就可能一次用掉兩個sda、sdb,換個U盤就是sdc、sdd。2)聯(lián)想數(shù)碼電腦中,可能已經(jīng)有了六合一讀卡器。它同樣也是USB存儲設(shè)備。它會占掉一個或兩個SCSI設(shè)備號。方法2:看信息。其實,只要你提前把usb-storage.o、scsi_mod.o、sd_mod.o模塊加載(直接在kernel中也可以)了,在你插入和拔出U盤時,系統(tǒng)會自動打出信息如下:SCSIdevicesda:60928512-bytehdwrsec
21、tors(31MB)sda:WriteProtectison根據(jù)此信息,你就知道它在sda上了。當然,可能你的系統(tǒng)信息級別比較高,上述信息可能沒有打出,這時候你只要tail/var/log/messages就可以看到了。方法3:同樣,cat/proc/partitions也可以看到分區(qū)信息,其中sd?就是U盤所對應(yīng)的了。若根本沒有sd設(shè)備,就要檢查你的SCSI模塊和usb-storage模塊是否正確加載了。在使用U盤或存儲卡時,我該mount/dev/sda還是/dev/sda1呢?這是一個歷史遺留問題。存儲卡最初尺寸很小,很多廠商在使用時,就直接使用存儲,不含有分區(qū)表信息。而隨著存儲卡尺寸的
22、不斷擴大,它也就引入了類似硬盤分區(qū)的概念。例如/dev/hda你可以分成主分區(qū)hda1、hda2擴展分區(qū)hda3,然后把擴展分區(qū)hda3又分為邏輯分區(qū)hda5、hda6、hda7等。這樣,通常的U盤就被分成一個分區(qū)sda1,類似把硬盤整個分區(qū)分成一個主分區(qū)hda1。實際上,我們完全可以通過fdisk/dev/sda對存儲卡進行完全類似硬盤的分區(qū)方式分成sda1、sda2甚至邏輯分區(qū)sda5、sda6。實際上,對USB硬盤目前你的確需要這樣,因為它通常都是多少G的容量。而且通常,它里面就是筆記本硬盤。一個好玩的問題。你在Linux下用fdisk/dev/sda對U盤進行了多分區(qū),這時候到wind
23、ows下,你會發(fā)現(xiàn)怎么找,怎么格式化,U盤都只能找到第一個分區(qū)大小尺寸,而且使用看不出任何問題。這主要是windows驅(qū)動對U盤都只支持一個分區(qū)的緣故。你是不是可以利用它來進行一些文件的隱藏和保護?你是不是可以和某些人沒玩過Linux的人開些玩笑:你的U盤容量變小了J?,F(xiàn)在較多的數(shù)碼設(shè)備也和windows一樣,是把所有U盤容量分為一個,所以在對待U盤的時候,通常你mount的是sdal。但對于某些特殊的數(shù)碼設(shè)備格式化的U盤或存儲卡(目前我發(fā)現(xiàn)的是一款聯(lián)想的支持模擬USB軟盤的U盤和我的一個數(shù)碼相機),你就要mount/dev/sda。因為它根本就沒分區(qū)表(若mount/dev/sdal通常的效
24、果是死掉)。其實,這些信息,只要你注意了/proc/partitions文件,都應(yīng)該注意到的。每次插入U盤,都要尋找對應(yīng)設(shè)備文件名,都要手動mount,我能不能做到象windows那樣插入就可以使用呢。當然可以,不過你需要做一些工作。我這里只提供一些信息幫助你去嘗試完成設(shè)置:Linux內(nèi)核提供了一種叫hotplug支持的東西,它可以讓你系統(tǒng)在PCI設(shè)備、USB等設(shè)備插拔時做一些事情。而automount功能可以使你的軟驅(qū)、光盤等設(shè)備的分區(qū)自動掛載和自動卸載。你甚至可以在KDE桌面中創(chuàng)建相應(yīng)的圖標,方便你操作。具體設(shè)置方法就要你自己去嘗試了。反正我使用Linux已經(jīng)麻木了,不就是敲一行命令嘛。U
25、SB驅(qū)動開發(fā)在掌握了USB設(shè)備的配置后,對于程序員,我們就可以嘗試進行一些簡單的USB驅(qū)動的修改和開發(fā)了。這一段落,我們會講解一個最基礎(chǔ)USB框架的基礎(chǔ)上,做兩個小的USB驅(qū)動的例子。USB骨架在Linuxkernel源碼目錄中driver/usb/usb-skeleton.c為我們提供了一個最基礎(chǔ)的USB驅(qū)動程序。我們稱為USB骨架。通過它我們僅需要修改極少的部分,就可以完成一個USB設(shè)備的驅(qū)動。我們的USB驅(qū)動開發(fā)也是從她開始的。那些linux下不支持的USB設(shè)備幾乎都是生產(chǎn)廠商特定的產(chǎn)品。如果生產(chǎn)廠商在他們的產(chǎn)品中使用自己定義的協(xié)議,他們就需要為此設(shè)備創(chuàng)建特定的驅(qū)動程序。當然我們知道,有
26、些生產(chǎn)廠商公開他們的USB協(xié)議,并幫助Linux驅(qū)動程序的開發(fā),然而有些生產(chǎn)廠商卻根本不公開他們的USB協(xié)議。因為每一個不同的協(xié)議都會產(chǎn)生一個新的驅(qū)動程序,所以就有了這個通用的USB驅(qū)動骨架程序,它是以pci骨架為模板的。如果你準備寫一個linux驅(qū)動程序,首先要熟悉USB協(xié)議規(guī)范。USB主頁上有它的幫助。一些比較典型的驅(qū)動可以在上面發(fā)現(xiàn),同時還介紹了USBurbs的概念,而這個是usb驅(qū)動程序中最基本的。LinuxUSB驅(qū)動程序需要做的第一件事情就是在LinuxUSB子系統(tǒng)里注冊,并提供一些相關(guān)信息,例如這個驅(qū)動程序支持那種設(shè)備,當被支持的設(shè)備從系統(tǒng)插入或拔出時,會有哪些動作。所有這些信息都
27、傳送到USB子系統(tǒng)中,在usb骨架驅(qū)動程序中是這樣來表示的:staticstructusb_driverskel_driver=name:skeleton,probe:skel_probe,disconnect:skel_disconnect,fops:&skel_fops,minor:USB_SKEL_MINOR_BASE,id_table:skel_table,;變量name是一個字符串,它對驅(qū)動程序進行描述。probe和disconnect是函數(shù)指針,當設(shè)備與在id_table中變量信息匹配時,此函數(shù)被調(diào)用。fops和minor變量是可選的。大多usb驅(qū)動程序鉤住另外一個驅(qū)動系統(tǒng),例如S
28、CSI,網(wǎng)絡(luò)或者tty子系統(tǒng)。這些驅(qū)動程序在其他驅(qū)動系統(tǒng)中注冊,同時任何用戶空間的交互操作通過那些接口提供,比如我們把SCSI設(shè)備驅(qū)動作為我們USB驅(qū)動所鉤住的另外一個驅(qū)動系統(tǒng),那么我們此USB設(shè)備的read、write等操作,就相應(yīng)按SCSI設(shè)備的read、write函數(shù)進行訪問。但是對于掃描儀等驅(qū)動程序來說,并沒有一個匹配的驅(qū)動系統(tǒng)可以使用,那我們就要自己處理與用戶空間的read、write等交互函數(shù)。Usb子系統(tǒng)提供一種方法去注冊一個次設(shè)備號和file_operations函數(shù)指針,這樣就可以與用戶空間實現(xiàn)方便地交互。USB骨架程序的關(guān)鍵幾點如下:USB驅(qū)動的注冊和注銷Usb驅(qū)動程序在注
29、冊時會發(fā)送一個命令給usb_register,通常在驅(qū)動程序的初始化函數(shù)里。當要從系統(tǒng)卸載驅(qū)動程序時,需要注銷usb子系統(tǒng)。即需要usb_unregister函數(shù)處理:staticvoid_exitusb_skel_exit(void)/*deregisterthisdriverwiththeUSBsubsystem*/usb_deregister(&skel_driver);module_exit(usb_skel_exit);當usb設(shè)備插入時,為了使linux-hotplug(Linux中PCI、USB等設(shè)備熱插拔支持)系統(tǒng)自動裝載驅(qū)動程序,你需要創(chuàng)建一個MODULE_DEVICE_TA
30、BLE。代碼如下(這個模塊僅支持某一特定設(shè)備):/*tableofdevicesthatworkwiththisdriver*/staticstructusb_device_idskel_table=USB_DEVICE(USB_SKEL_VENDOR_ID,USB_SKEL_PRODUCT_ID),/*Terminatingentry*/;MODULE_DEVICE_TABLE(usb,skel_table);USB_DEVICE宏利用廠商ID和產(chǎn)品ID為我們提供了一個設(shè)備的唯一標識。當系統(tǒng)插入一個ID匹配的USB設(shè)備到USB總線時,驅(qū)動會在USBcore中注冊。驅(qū)動程序中probe函數(shù)也就
31、會被調(diào)用。usb_device結(jié)構(gòu)指針、接口號和接口ID都會被傳遞到函數(shù)中。staticvoid*skel_probe(structusb_device*dev,unsignedintifnum,conststructusb_device_id*id)驅(qū)動程序需要確認插入的設(shè)備是否可以被接受,如果不接受,或者在初始化的過程中發(fā)生任何錯誤,probe函數(shù)返回一個NULL值。否則返回一個含有設(shè)備驅(qū)動程序狀態(tài)的指針。通過這個指針,就可以訪問所有結(jié)構(gòu)中的回調(diào)函數(shù)。在骨架驅(qū)動程序里,最后一點是我們要注冊devfs。我們創(chuàng)建一個緩沖用來保存那些被發(fā)送給usb設(shè)備的數(shù)據(jù)和那些從設(shè)備上接受的數(shù)據(jù),同時USBu
32、rb被初始化,并且我們在devfs子系統(tǒng)中注冊設(shè)備,允許devfs用戶訪問我們的設(shè)備。注冊過程如下:/*initializethedevfsnodeforthisdeviceandregisterit*/sprintf(name,skel%d,skel-minor);skel-devfs=devfs_register(usb_devfs_handle,name,DEVFS_FL_DEFAULT,USB_MAJOR,USB_SKEL_MINOR_BASE+skel-minor,S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH,&skel_fops,N
33、ULL);如果devfs_register函數(shù)失敗,不用擔心,devfs子系統(tǒng)會將此情況報告給用戶。當然最后,如果設(shè)備從usb總線拔掉,設(shè)備指針會調(diào)用disconnect函數(shù)。驅(qū)動程序就需要清除那些被分配了的所有私有數(shù)據(jù)、關(guān)閉urbs,并且從devfs上注銷調(diào)自己。/*removeourdevfsnode*/devfs_unregister(skel-devfs);現(xiàn)在,skeleton驅(qū)動就已經(jīng)和設(shè)備綁定上了,任何用戶態(tài)程序要操作此設(shè)備都可以通過file_operations結(jié)構(gòu)所定義的函數(shù)進行了。首先,我們要open此設(shè)備。在open函數(shù)中MODULE_INC_USE_COUNT宏是一個關(guān)
34、鍵,它的作用是起到一個計數(shù)的作用,有一個用戶態(tài)程序打開一個設(shè)備,計數(shù)器就加一,例如,我們以模塊方式加入一個驅(qū)動,若計數(shù)器不為零,就說明仍然有用戶程序在使用此驅(qū)動,這時候,你就不能通過rmmod命令卸載驅(qū)動模塊了。/*incrementourusagecountforthemodule*/MOD_INC_USE_COUNT;+skel-open_count;/*saveourobjectinthefilesprivatestructure*/file-private_data=skel;當open完設(shè)備后,read、write函數(shù)就可以收、發(fā)數(shù)據(jù)了。skel的write、和read函數(shù)他們是完成
35、驅(qū)動對讀寫等操作的響應(yīng)。在skel_write中,一個FILL_BULK_URB函數(shù),就完成了urb系統(tǒng)callbak和我們自己的skel_write_bulk_callback之間的聯(lián)系。注意skel_write_bulk_callback是中斷方式,所以要注意時間不能太久,本程序中它就只是報告一些urb的狀態(tài)等。read函數(shù)與write函數(shù)稍有不同在于:程序并沒有用urb將數(shù)據(jù)從設(shè)備傳送到驅(qū)動程序,而是我們用usb_bulk_msg函數(shù)代替,這個函數(shù)能夠不需要創(chuàng)建urbs和操作urb函數(shù)的情況下,來發(fā)送數(shù)據(jù)給設(shè)備,或者從設(shè)備來接收數(shù)據(jù)。我們調(diào)用usb_bulk_msg函數(shù)并傳提一個存儲空間
36、,用來緩沖和放置驅(qū)動收到的數(shù)據(jù),若沒有收到數(shù)據(jù),就失敗并返回一個錯誤信息。usb_bulk_msg函數(shù)當對usb設(shè)備進行一次讀或者寫時,usb_bulk_msg函數(shù)是非常有用的;然而,當你需要連續(xù)地對設(shè)備進行讀/寫時,建議你建立一個自己的urbs,同時將urbs提交給usb子系統(tǒng)。skel_disconnect函數(shù)當我們釋放設(shè)備文件句柄時,這個函數(shù)會被調(diào)用。MOD_DEC_USE_COUNT宏會被用到(和MOD_INC_USE_COUNT剛好對應(yīng),它減少一個計數(shù)器),首先確認當前是否有其它的程序正在訪問這個設(shè)備,如果是最后一個用戶在使用,我們可以關(guān)閉任何正在發(fā)生的寫,操作如下:/*decrem
37、entourusagecountforthedevice*/-skel-open_count;if(skel-open_countwrite_urb);skel-open_count=0;/*decrementourusagecountforthemodule*/MOD_DEC_USE_COUNT;最困難的是,usb設(shè)備可以在任何時間點從系統(tǒng)中取走,即使程序目前正在訪問它。usb驅(qū)動程序必須要能夠很好地處理解決此問題,它需要能夠切斷任何當前的讀寫,同時通知用戶空間程序:usb設(shè)備已經(jīng)被取走。如果程序有一個打開的設(shè)備句柄,在當前結(jié)構(gòu)里,我們只要把它賦值為空,就像它已經(jīng)消失了。對于每一次設(shè)備讀寫等
38、其它函數(shù)操作,我們都要檢查usb_device結(jié)構(gòu)是否存在。如果不存在,就表明設(shè)備已經(jīng)消失,并返回一個-ENODEV錯誤給用戶程序。當最終我們調(diào)用release函數(shù)時,在沒有文件打開這個設(shè)備時,無論usb_device結(jié)構(gòu)是否存在、它都會清空skel_disconnect函數(shù)所作工作。Usb骨架驅(qū)動程序,提供足夠的例子來幫助初始人員在最短的時間里開發(fā)一個驅(qū)動程序。更多信息你可以到linuxusb開發(fā)新聞組去尋找。U盤、USB讀卡器、MP3、數(shù)碼相機驅(qū)動對于一款windows下用的很爽的U盤、USB讀卡器、MP3或數(shù)碼相機,可能Linux下卻不能支持。怎么辦?其實不用傷心,也許經(jīng)過一點點的工作,
39、你就可以很方便地使用它了。通常是此U盤、USB讀卡器、MP3或數(shù)碼相機在WindowsXP中不需要廠商專門的驅(qū)動就可以識別為移動存儲設(shè)備,這樣的設(shè)備才能保證成功,其他的就看你的運氣了。USB存儲設(shè)備,他們的read、write等操作都是通過上章節(jié)中提到的鉤子,把自己的操作鉤到SCSI設(shè)備上去的。我們就不需要對其進行具體的數(shù)據(jù)讀寫處理了。第一步:我們通過cat/proc/bus/usb/devices得到當前系統(tǒng)探測到的USB總線上的設(shè)備信息。它包括Vendor、ProdID、Product等。下面是我買的一款雜牌CF卡讀卡器插入后的信息片斷:T:Bus=01Lev=01Prnt=01Port=
40、01Cnt=02Dev#=5Spd=12MxCh=0D:Ver=1.10Cls=00(ifc)Sub=00Prot=00MxPS=8#Cfgs=1P:Vendor=07c4ProdID=a400Rev=1.13S:Manufacturer=USBS:Product=MassStorageC:*#Ifs=1Cfg#=1Atr=80MxPwr=70mAI:If#=0Alt=0#EPs=2Cls=08(vend.)Sub=06Prot=50Driver=usb-storageE:Ad=81(I)Atr=02(Bulk)MxPS=64Ivl=0msE:Ad=02(O)Atr=02(Bulk)MxPS=
41、64Ivl=0ms其中,我們最關(guān)心的是Vendor=07c4ProdID=a400和Manufacturer二USB(果然是雜牌,廠商名都看不到)Product二MassStorage。對于這些移動存儲設(shè)備,我們知道Linux下都是通過usb-storage.o驅(qū)動模擬成scsi設(shè)備去支持的,之所以不支持,通常是usb-storage驅(qū)動未包括此廠商識別和產(chǎn)品識別信息(在類似skel_probe的USB最初探測時被屏蔽了)。對于USB存儲設(shè)備的硬件訪問部分,通常是一致的。所以我們要支持它,僅需要修改usb-storage中關(guān)于廠商識別和產(chǎn)品識別列表部分。第二部,打開drivers/usb/st
42、orage/unusual_devs.h文件,我們可以看到所有已知的產(chǎn)品登記表,都是以UNUSUAL_DEV(idVendor,idProduct,bcdDeviceMin,bcdDeviceMax,vendor_name,product_name,use_protocol,use_transport,init_function.Flags)方式登記的。其中相應(yīng)的涵義,你就可以根據(jù)命名來判斷了。所以只要我們?nèi)缦绿钊胛覀冏约旱淖?,就可以讓usb-storage驅(qū)動去認識和發(fā)現(xiàn)它。UNUSUAL_DEV(07c4,a400,0 x0000,0 xffff,USB,MassStorage,US_S
43、C_SCSI,US_PR_BULK,NULL,US_FL_FIX_INQUIRY|US_FL_START_STOP|US_FL_MODE_XLATE)注意:添加以上幾句的位置,一定要正確。比較發(fā)現(xiàn),usb-storage驅(qū)動對所有注冊都是按idVendor,idProduct數(shù)值從小到大排列的。我們也要放在相應(yīng)位置。最后,填入以上信息,我們就可以重新編譯生成內(nèi)核或usb-storage.o模塊。這時候插入我們的設(shè)備就可以跟其他U盤一樣作為SCSI設(shè)備去訪問了。鍵盤飛梭支持目前很多鍵盤都有飛梭和手寫板,下面我們就嘗試為一款鍵盤飛梭加入一個驅(qū)動。在通常情況,當我們插入USB接口鍵盤時,在/proc
44、/bus/usb/devices會看到多個USB設(shè)備。比如:你的USB鍵盤上的飛梭會是一個,你的手寫板會是一個,若是你的USB鍵盤有USB擴展連接埠,也會看到。下面是具體看到的信息T:Bus=02Lev=00Prnt=00Port=00Cnt=00Dev#=1Spd=12MxCh=2B:Alloc=11/900us(1%),#Int=1,#Iso=0D:Ver=1.00Cls=09(hub)Sub=00Prot=00MxPS=8#Cfgs=1P:Vendor=0000ProdID=0000Rev=0.00S:Product=USBUHCIRootHubS:SerialNumber=d800C:
45、*#Ifs=1Cfg#=1Atr=40MxPwr=0mAI:If#=0Alt=0#EPs=1Cls=09(hub)Sub=00Prot=00Driver=hubE:Ad=81(I)Atr=03(Int.)MxPS=8Ivl=255msT:Bus=02Lev=01Prnt=01Port=01Cnt=01Dev#=3Spd=12MxCh=3D:Ver=1.10Cls=09(hub)Sub=00Prot=00MxPS=8#Cfgs=1P:Vendor=07e4ProdID=9473Rev=0.02S:Manufacturer=ALCORS:Product=MovadoUSBKeyboardC:*#I
46、fs=1Cfg#=1Atr=e0MxPwr=100mAI:If#=0Alt=0#EPs=1Cls=09(hub)Sub=00Prot=00Driver=hubE:Ad=81(I)Atr=03(Int.)MxPS=1Ivl=255ms找到相應(yīng)的信息后就可開始工作了。實際上,飛梭的定義和鍵盤鍵碼通常是一樣的,所以我們參照drivers/usb/usbkbd.c代碼進行一些改動就可以了。因為沒能拿到相應(yīng)的硬件USB協(xié)議,我無從知道飛梭在按下時通訊協(xié)議眾到底發(fā)什么,我只能把它的信息打出來進行分析。幸好,它比較簡單,在下面代碼的usb_kbd_irq函數(shù)中if(kbd-newO=(char)OxO1)和
47、if(kbd-newl4)&0 x0f)!=0 x7)就是判斷飛梭左旋。usb_kbd_irq函數(shù)就是鍵盤中斷響應(yīng)函數(shù)。他的掛接,就是在usb_kbd_probe函數(shù)中FILL_INT_URB(&kbd-irq,dev,pipe,kbd-new,maxp8?8:maxp,usb_kbd_irq,kbd,endpoint-bInterval);一句中實現(xiàn)。從usb骨架中我們知道,usb_kbd_probe函數(shù)就是在USB設(shè)備被系統(tǒng)發(fā)現(xiàn)是運行的。其他部分就都不是關(guān)鍵了。你可以根據(jù)具體的探測值(Vendor=07e4ProdID=9473等)進行一些修改就可以了。值得一提的是,在鍵盤中斷中,我們的做
48、法是收到USB飛梭消息后,把它模擬成左方向鍵和右方向鍵,在這里,就看你想怎么去響應(yīng)它了。當然你也可以響應(yīng)模擬成F14、F15等擴展鍵碼。在了解了此基本的驅(qū)動后,對于一個你已經(jīng)拿到通訊協(xié)議的鍵盤所帶手寫板,你就應(yīng)該能進行相應(yīng)驅(qū)動的開發(fā)了吧。程序見附錄1:鍵盤飛梭驅(qū)動。使用此驅(qū)動要注意的問題:在加載此驅(qū)動時你必須先把hid設(shè)備卸載,加載完usbhkey.o模塊后再加載hid.o。因為若hid存在,它的probe會屏蔽系統(tǒng)去利用我們的驅(qū)動發(fā)現(xiàn)我們的設(shè)備。其實,飛梭本來就是一個hid設(shè)備,正確的方法,或許你應(yīng)該修改hid的probe函數(shù),然后把我們的驅(qū)動融入其中?;仨撌讌⒖假Y料LINUX設(shè)備驅(qū)動程序A
49、LESSANDRORUBINI著LIS0LEG譯紅inux系統(tǒng)分析與高級編程技術(shù)周巍松編著LinuxKernel-2.4.20源碼和文檔說明回頁首附錄1:鍵盤飛梭驅(qū)動#include#include#include#include#include#include#include/*VersionInformation*/#defineDRIVER_VERSION#defineDRIVER_AUTHORTGEHOTKEY#defineDRIVER_DESCUSBHIDTgehotkeydriver#defineUSB_HOTKEY_VENDOR_ID0 x07e4#defineUSB_HOTKE
50、Y_PRODUCT_ID0 x9473/廠商和產(chǎn)品ID信息就是/proc/bus/usb/devices中看到的值MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);structusb_kbdstructinput_devdev;structusb_device*usbdev;unsignedcharnew8;unsignedcharold8;structurbirq,led;/devrequestdr;/這一行和下一行的區(qū)別在于kernel2.4.20版本對usb_kbd鍵盤結(jié)構(gòu)定義發(fā)生了變化structusb_ctrlr
51、equestdr;unsignedcharleds,newleds;charname128;intopen;/此結(jié)構(gòu)來自內(nèi)核中drivers/usb/usbkbd.cstaticvoidusb_kbd_irq(structurb*urb)structusb_kbd*kbd=urb-context;int*new;new=(int*)kbd-new;if(kbd-new0=(char)0 x01)if(kbd-new14)&0 x0f)!=0 x7)handle_scancode(0 xe0,1);handle_scancode(0 x4b,1);handle_scancode(0 xe0,0)
52、;handle_scancode(0 x4b,0);elsehandle_scancode(0 xe0,1);handle_scancode(0 x4d,1);handle_scancode(0 xe0,0);handle_scancode(0 x4d,0);printk(new=%x%x%x%x%x%x%x%x,kbd-new0,kbd-new1,kbd-new2,kbd-new3,kbd-new4,kbd-new5,kbd-new6,kbd-new7);staticvoid*usb_kbd_probe(structusb_device*dev,unsignedintifnum,conststructusb_device_id*id)structusb_interface*iface;structusb_interface_descriptor*interface;structusb_endpoint_descriptor*endpoint;structusb_kbd*kbd;intpipe,maxp;iface=&dev-actconfig-int
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度消防清包工合同范本:消防設(shè)施維修與技術(shù)支持3篇
- 二零二五年度葡萄酒年份酒拍賣會合作合同4篇
- 二零二五年度航空航天產(chǎn)業(yè)勞動合同范本
- 二零二五年度環(huán)保項目投資顧問聘用合同范本4篇
- 二零二五年度氣體消防系統(tǒng)安全技術(shù)研發(fā)與產(chǎn)業(yè)化合同
- 2025-2030全球電源鋁支架行業(yè)調(diào)研及趨勢分析報告
- 2025年全球及中國介入穿刺針行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 二零二五年度水泥涵管生產(chǎn)自動化改造合同
- 二零二五年度私人租房租賃續(xù)約合同
- 化肥銷售居間服務(wù)合同
- 電力溝施工組織設(shè)計-電纜溝
- 《法律援助》課件
- 小兒肺炎治療與護理
- 《高處作業(yè)安全》課件
- 春節(jié)后收心安全培訓(xùn)
- 小學(xué)教師法制培訓(xùn)課件
- 電梯操作證及電梯維修人員資格(特種作業(yè))考試題及答案
- 市政綠化養(yǎng)護及市政設(shè)施養(yǎng)護服務(wù)方案(技術(shù)方案)
- SLT824-2024 水利工程建設(shè)項目文件收集與歸檔規(guī)范
- 鍋爐本體安裝單位工程驗收表格
- 報價單(產(chǎn)品報價單)
評論
0/150
提交評論