天天看點

大話USB驅動之USB鍵盤

轉載請注明出處:http://blog.csdn.net/ruoyunliufeng/article/details/25040049

一.總體框圖

大話USB驅動之USB鍵盤

二.驅動代碼

三.程式分析

           上面的代碼是根據原usb鍵盤驅動代碼改寫而成,寫的比較簡單,但是有一個缺陷,不能實作重複事件(按下一個鍵不動,螢幕不會連續列印出這個鍵)。歡迎大家提供解決方法,後續有時間我還會改進,然後給大家分享。

      1.架構分析

                 a. 配置設定結構體

                  b.注冊

        2.具體分析

                  a.usb_keyboard_table

                          建立一個struct usb_device_id 的結構體,僅和usb接口的制定類型比對,例如你插入鍵盤能識别并調用probe,但是你插入個滑鼠就不能識别了(你按左鍵、右鍵什麼的基本就什麼反應也沒有)。

                  b.usb_keboard_probe(重要)

                           看代碼你會有似曾相識的感覺,沒錯相信你的感覺,usb驅動也在輸入子系統裡面(不清楚輸入子系統可以看我之前寫的觸摸屏驅動三部曲,那對輸入子系統講的比較詳細),但usb驅動也有自己與衆不同之處。

                                1. 配置設定一個input_dev

                                2. 設定

                                        2.1 能産生哪類事件

                                        2.2 能産生哪些事件

在這裡插将下簡碼表:

       君可見usb_kbd_keycode[256]  這個大數組,沒錯他就是簡碼表,他是幹啥用的?好了,讓我們想一下我們按鍵為什麼系統能夠知道,我們按下一個a,系統可不知道你按下的是啥,于是我們給鍵盤編碼,叫每一個按鍵擁有一個确定的的值,例如a就對應30這個數字。好好了解下簡碼表對後面我們分析中斷函數十分重要。具體鍵值參考(linux-2.6.22.6\linux-2.6.22.6\include\linux\input.h) 

                                3. 注冊

          程式到這裡和我們以前寫的輸入子系統的架構沒有本質差别,以前硬體相關操作我們都是去操作寄存器,現在我們隻要操作urb就行了(想操作寄存器也沒有啊,一個usb,一共四根線,還一個電源一個地

大話USB驅動之USB鍵盤

                                4. 硬體相關操作

                               c.usb_keyboard_irq(重要)

                         這個函數可以說是整個驅動的精華所在,由于程式設計能力有限,我改了很長時間才弄出來。

首先我們來看下核心自帶的源代碼是如何實作的.(我隻是拷一個片段)

下面我将用幾個問題揭開驅動這層神秘的面紗。三問驅動:

問1:第一個循環什麼意思?沒有行不行?

       答:主要是上報是否按下了29, 42, 56,125, 97, 54,100,126這幾個鍵碼對應的鍵

也就是 left control、 left shift 、left alt 、 left gui 、 right control、 right shift 、 right alt 、 right gui

這幾個鍵。因為要處理大小寫等問題。要先判斷是否按下他們,然後再判斷是否按下其餘按鍵。右移i位,再與 1就能判斷是否按下。這個和他們資料格式有關,看下個問題。沒有這個循環肯定不行,例如你想中斷某個程式要按control+c,親怎麼辦?是以這個循環是必須的。

問2:為什麼從第二個循環要從i=2開始?

       答:這個和資料的格式有關系,鍵盤發送給pc的資料每次8個位元組 data0 data1 data2 data3 data4 data5 data6 data7  ,其中data0就是我上面第一個問題将的那8個按鍵(       

|--bit0: left control是否按下,按下為1 

      |--bit1: left shift 是否按下,按下為1 

      |--bit2: left alt 是否按下,按下為1 

      |--bit3: left gui 是否按下,按下為1 

      |--bit4: right control是否按下,按下為1 

      |--bit5: right shift 是否按下,按下為1 

      |--bit6: right alt 是否按下,按下為1 

      |--bit7: right gui 是否按下,按下為1

),data1保留,data2--data7 是 普通按鍵,既然我們上面已經判斷的data0了,那我們現在理所當然要從i=2開始判斷 data2--data7了。這樣也能解決control+c的問題,先判斷control在判斷c。

問3:怎麼判斷是否按下還是松開?

        答:判斷按下:第二個for循環裡的第二個if裡面

               首先判斷new[i]是否大于3,因為由于簡碼表可知usb_kbd_keycode[0]到usb_kbd_keycode[3]都是0(key_reserved),沒有意義。并且在old[2]到old[8]中沒有出現過,也就是和上次的鍵值不一樣(memcpy函數把每次的鍵值進行拷貝,用來判斷是否按下),如果按下了,肯定值會不一樣的嘛(就是memescan沒找到)。然後再判斷一下鍵值是否為0,如何非0,則上報按鍵。如果是0,就是不知道的鍵按下(你會發現鍵碼表中除了前4個還是有許多0的)。

               判斷松開:第二個for循環裡的第一個if裡面

               和判斷按下類似,如果你松開,你的new[]數組裡面全是0,肯定和上次的old[]不一樣,是以會進入if();然後繼續判斷是否是0,如果非0,上報按鍵已經松開。注意第二次判斷用的都是old,因為你要上報的是上次是否松開,這次的new裡面全是0.

四.程式改寫

           版本v1.2:

大話USB驅動之USB鍵盤

       看了上圖你或許能夠清楚的明白程式了,但是這裡你會發現我引入了一個pre_val_change變量,因為我怕繼續循環會造成bug,因為當你上報按下還是松開的時候循環并沒有結束(調這個bug調了好久,才發現的),這将帶來備援的循環。(但對效率影響不大)

繼續閱讀