1. 程式人生 > >USB鍵盤背後的那些事兒--Legacy USB實現 .

USB鍵盤背後的那些事兒--Legacy USB實現 .

最近晚上閒來無事,決定寫幾篇技術文章和大家共享一下。關於議題,我想了很久,覺得還是重點寫些大家平時接觸不到,或者說不容易在其他地方見到的一些概念吧。這樣可以一方面開拓大家的知識面,另一方面我也想打破目前BIOS技術過於封閉的局面。現在的BIOS業界的確是過於封閉了,有句話說的不錯:在我們這個行業,就那麼幾個人,大家在不同的公司跳來跳去……原因就在這個行業技術上過於封閉。不是BIOS從業的工程師,很難自學BIOS程式設計的。

於是呼,我第一篇就選擇了談談Legacy USB。

1. Legacy USB是什麼?

USB我們每天都在用,那麼什麼又是Leacgy USB呢?隨便Google一下,網上什麼說法都有,但是很少有說對的。大多數朋友都知道這是一個主機板BIOS上的選項,並且幾乎都設定成了Enable,但是在問及這個東東到底是幹什麼的時候,就基本上沒人知道了。很多朋友誤認為這是USB 1.1支援選項。這是完全錯誤的,任何一項技術都應該預設做到backward compatibility(向後相容),如果USB因為升級到2.0就不再支援大量的1.1裝置,那麼我想估計就沒人用USB了。

所以Legacy USB不是USB 1.1支援選項!那麼它到底是幹什麼用的呢?我們不妨來做個實驗,現在就重啟你的電腦,進入BIOS,將這一項設定成Disable,然後進DOS,接著試試你的USB鍵盤,看看現在還能不能用呢?或者不進DOS,我們對WinXP來一次非正常關機,然後重啟,OS應該會出現一個選單,接著讀秒,提示非正常關機,按任意鍵繼續這樣的話,這個時候按下你的USB鍵盤,看看這個任意鍵能否被OS識別呢?答案勢必是不行。不過在讀秒完成後,進入OS,我們的USB鍵盤又活了。呵呵

所謂的Legacy USB是在傳統的環境下,對USB設定(主要是USB鍵盤,滑鼠)提供支援的選項。所謂的傳統的環境,是指DOS,或者那些直接去訪問8042相容鍵盤控制器的程式,或者那些使用BIOS呼叫INT 9H來取鍵盤響應的程式。這樣的程式一般都比較老,但是在某些場合他們仍然在起作用,況且在OS起來之前,幾乎100%都是Legacy USB的應用場合。

那麼為什麼會有這個問題呢?說起來就遠了,大家只要大致明白就可。之前在USB裝置出來之前,尤其是USB鍵盤出來之前,人們並沒有想象到未來的某一天還會有個USB鍵盤這個東西,那個時候我們的PC比較老實,鍵盤的工業標準是8042,同時訪問8042的程式設計標準則是兩個I/O埠,60H和64H。

本文不想變成又一篇描述如何控制8042的啟蒙文章,大家只要知道,過去我們一直是通過訪問上述兩個埠來給8042發一些指令,如讀鍵盤緩衝區,開啟/關閉鍵盤上的LED燈,來進行等等這樣的類似的操作。而8042也可以被配置成輪詢或者中斷模式,在中斷模式下,如果鍵盤緩衝區裡有足夠多的鍵,那麼8042產生一箇中斷,接著一個鍵盤驅動就會取走這些鍵,然後處理。

一切都那麼完美?不是嗎?很不幸,當我們的USB鍵盤出現後,這一切都不是那麼完美了。USB鍵盤並不歸8042管轄,當然也不可能使用60/64來通訊。這可把那些過去直接使用60/64的程式幽了一默。這些直接訪問8042的程式無法對USB鍵盤的按鍵做出任何響應。更重要的是,DOS也這麼幹。一般來說,當你新安裝一個裝置,如果不能使用,你會想到:啊,那我安裝它的驅動啊!的確是這樣,但是對於鍵盤這樣一個裝置來說,很難想象如果它不能使用還能否安裝驅動(也許使用者根本無法操作計算機)。換言之,使用者希望對自己原來的程式不加修改,就能直接使用USB鍵盤。

為了保護使用者投資,我們必須找到一個方法,使得那些老的系統,老的程式能夠能夠在不認識USB鍵盤的條件下,仍然能夠使用USB鍵盤/滑鼠。

我仍然記得,在我剛剛入行的時候,我的老闆對我說道:你知道嗎?在PC裡,什麼裝置最難程式設計?是小小的鍵盤!我當時十分不解,一個小小的鍵盤怎麼會最難呢?後來我驚訝的發現,Legacy USB竟然是各家BIOS Vendor競爭的一個焦點所在。誰能提供這個支援,誰就能競爭佔據有利地位。那都是因為這個技術太難。

從一個高層程式設計師的角度,他可能永遠都不明白為什麼這個問題如此困難。將兩完全不一樣的硬體做到軟體相容,的確有些難度。不,是很有難度。

2. Legacy USB:實現

那麼如何實現呢?問的好!答案是模擬。既然系統可以認識PS/2,那麼我們就把USB裝置模擬成PS/2裝置好了。但是如何模擬呢?

我們必須能夠截獲所有的USB中斷,然後判斷這個中斷是不是一個來自鍵盤/滑鼠的資料傳輸中斷。如果是的話,讀取USB鍵盤/滑鼠裡的資料,之後判斷一下是不是一個新按的鍵,如果是,把這個鍵譯碼成PS/2使用的Scan code Set 2.然後把這個鍵寫到8042緩衝區裡去,換言之,目前我們模擬了一次PS/2鍵盤按鍵。如果按鍵緩衝區滿,模擬程式還必須主動觸發一個IRQ1以便叫那些訪問60埠的程式能夠工作。

以上就是Legacy USB的大致實現,實際的實現要複雜的多,而且這必須被實現成SMI,一旦涉及到SMI,那麼事情將變得特別複雜。光是想想SMI能夠在記憶體裡搬來搬去就令人頭暈N次了。

請問如何模擬觸發IRQ1呢?沒有8042的時候,可以實現觸發IRQ1嗎?To wj0225:本來俺不打算在這寫個普通大眾的文章裡過多的涉及底層的實現,不過既然你問到啦,我就說說看 :)實現legacy usb,現在有很多時候系統不帶8042了。。尤其是那些legacy free的系統。Intel的ICH可以用軟體觸發IRQ1/12。方法大致是TCObase 10H有個暫存器叫SW_IRQ_GEN(某些文件,主要是BWG上,這個暫存器也叫LEGACY_ELIM)。這個暫存器就幹這個的。以ICH9為例,查閱ICH9 EDS,(這個文件過去是RS的,現在是public的,所以我可以說說它的內容了)Bit Description7:2 Reserved1 IRQ12_CAUSE — R/W. When software sets this bit to 1, IRQ12 will be asserted. Whensoftware sets this bit to 0, IRQ12 will be deasserted.0 IRQ1_CAUSE — R/W. When software sets this bit to 1, IRQ1 will be asserted. Whensoftware sets this bit to 0, IRQ1 will be deasserted.