LINUX下USB1.1設備學習小記(3)_host與device

 
LINUX下USB1.1設備學習小記(3)_host與device
 
 
 
各位還記得”任何傳輸都是由host發起的”這句話麼~
在usb設備插入pc中到拔出usb設備,都是由host進行詢問的
一個usb鼠標的工作流程可以表達如下:
usb鼠標插入pc中:
主機詢問設備:給我你的設備信息(控制傳輸)
主機根據usb鼠標的設備信息進行驅動配置,配置結束後
主機詢問設備:給我你的數據信息(中斷傳輸)
一定的時間間隔之後....
主機詢問設備:給我你的數據信息(中斷傳輸)
一定的時間間隔之後...
主機詢問設備:給我你的數據信息(中斷傳輸)
.................
直到這個設備被拔出,主機不斷要求設備提供鼠標的按鍵和移動數據
 
因爲任何傳輸都是由host發起的,所以host是我解析的第一對象,而UHCI這個host是我將介紹的對象,目前PC上有3類主機控制器,分別爲UHCI,OHCI和EHCI
UHCI和OHCI是低速和全速USB設備的主機控制器,所有高速設備都是EHCI這個主機控制器管理的
爲什麼選擇UHCI而不是OHCI呢~ 很簡單,因爲我是參考fudan_abc的BLOG進行解析的,他寫的是關於UHCI的,呢麼我只有寫UHCI的,因爲很多技術規範只有UHCI的生產商英特爾才知道,包括他的BUG
下面我先簡短的介紹一下UHCI
UHCI全稱Universal Host Controller Interface,也就是通用主機控制器接口,他的一個重要責任就是發送USB通信中最關鍵的令牌包,下面我們就看看他是怎麼發送令牌包的
在UHCI的軟件控制中,最小的處理爲一個叫Transfer Descriptor的結構,這個結構爲16字節

黃色區域表示主機控制器硬件可以讀寫的,白色表示主機控制器硬件只能讀,不能寫
所有字段都能由主機控制器驅動,也就是軟件來寫
td的這4個字段從上倒下分別爲連接字段,控制字段,令牌字段和緩衝字段
呢麼這個TD完成一個什麼樣的功能呢?~
很可惜,從軟件上看,這個TD負責完成一個事務的傳輸,也就是令牌包,數據包和握手包這3個包的傳輸都由TD來描述,所以單獨令牌包的發送是硬件自動完成的,軟件是參與不到的,所以我們只能從一個控制傳輸來看看UHCI是如何完成事務傳輸的
不過在這之前還需要介紹1個知識,Frame List
Frame List是一個由1024個Frame組成的幀列表,幹嘛用呢?~很簡單,所有的td都是掛載在Frame上的,然後UHCI分配給每幀1ms的時間做傳輸,執行Frame上的td隊列,
1ms到期後就處理下一幀的td隊列
現在我們假定設備的地址爲20,使用0號端點,發送一個setup事務,任務爲取得大小爲18字節的設備描述符
這個setup事務使用一個setup事務,數據階段使用一個in事務,狀態階段使用一個out事務, 好,現在開始構建td隊列

第一個事務爲setup事務
1. 首先填充 td令牌字段中的pid字段,setup事務中的令牌包爲setup包,setup包的pid爲1101,pid效驗爲0010,則pid字段爲0x2D
2. 填充td令牌字段中的地址字段,這裏我們使用的地址爲20,則填充0x14
3. 填充td令牌字段中的端點字段,這裏我們使用的端點爲0,則填充0x0
4. 填充td令牌字段中的數據長度字段,setup事務中data的數據大小爲8字節,則填充0x8
5. 填充td令牌字段中的數據包類型字段,setup默認爲0,這裏填充爲0
6. 填充td的緩衝字段,這個緩衝字段是一個指針,指向一個DMA地址,UHCI硬件根據事務是寫還是讀來直接讀寫這個地址上的數據,不需要CPU的參與,假設我已經爲8字節的數據申請了一個DMA地址,爲0xFFFF,則填充0xFFFF到緩衝字段
7. 填充td的連接字段,因爲還有一個數據階段的in事務和狀態階段的out事務,這裏連接數據階段的in事務所使用的td地址

第二個事務爲數據階段的in事務
1. 首先填充首先填充 td令牌字段中的pid字段,in事務中的令牌包爲in包,in包的pid爲1001,pid效驗爲0110,則pid字段爲0x69
2. 填充td令牌字段中的地址字段,這裏我們使用的地址爲20,則填充0x14
3. 填充td令牌字段中的端點字段,這裏我們使用的端點爲0,則填充0x0
4. 填充td令牌字段中的數據長度字段,我們所需要的設備描述符的大小爲18字節,則這裏填寫爲0x12
5. 填充td令牌字段中的數據包類型字段,因爲這是第一個數據包,第一個數據包所使用的類型爲data1,這裏填充爲1
6. 填充td的緩衝字段,這個緩衝字段是一個指針,指向一個DMA地址,UHCI硬件根據事務是寫還是讀來直接讀寫這個地址上的數據,不需要CPU的參與,假設我已經爲18字節的數據申請了一個DMA地址,爲0xCCCC,則填充0xCCCC到緩衝字段
7. 填充td的連接字段,因爲還有一個狀態階段的out事務,這裏連接狀態階段out事務所使用的td地址

第三個事務爲狀態階段所使用的out事務
1. 首先填充首先填充 td令牌字段中的pid字段,out事務中的令牌包爲out包,out包的pid爲0001,pid效驗爲1110,則pid字段爲0xE1
2. 填充td令牌字段中的地址字段,這裏我們使用的地址爲20,則填充0x14
3. 填充td令牌字段中的端點字段,這裏我們使用的端點爲0,則填充0x0
4. 填充td令牌字段中的數據長度字段,狀態階段的數據包中的數據長度爲0,這裏填充爲0x0
5. 填充td令牌字段中的數據包類型字段,因爲這是狀態階段的數據包,規定使用的數據包類型爲data1,這裏填充爲1
6. 填充td的緩衝字段,因爲該數據包的數據爲0,這裏填充0
7. 填充td的連接字段,因爲後面沒有事務了,這裏填充停止標誌
現在把這3個事務連接到幀上,
形成下圖

UHCI如何進行操作呢?~  我形象的比喻一下
1號td(setup事務)-setup階段
1. 主機:我發setup包了,等一下我還要發個數據包
2. 主機:我發數據包了
3. 設備:我收到了
2號td(in事務)-數據階段
1:主機:我發in包了,你給我返還一個數據包
2:設備:我發數據包了
3:主機:我收到了
3號td(out事務)-狀態階段
1. 主機:我發out包了,等一下我還要發個數據包
2. 主機:我發數據包了
3. 設備:我收到了
這樣,一個控制傳輸就完成了
是不是覺得很簡單呢?~
其實USB真正複雜的地方在於休眠和恢復,這些都是由主機控制器來完成的,平時USB驅動程序是不會接觸到的,但在之後的UHCI在LINUX中的驅動中我將盡自己的能力分析,畢竟我的數模電路基礎幾乎爲0,大家多包涵 = 3=

瞭解了主機端,我們再看看設備端,設備端的工作相對較少,爲什麼呢?看看前面控制傳輸的圖,可以發現,所有的事務的第一個包都是黃色的,也就是都是由主機發送的,設備所要發送的包類型只有兩種,數據包和握手包,處理流程如下
在PDIUSBD12中,應答包是由硬件自動判斷的,剩下給軟件編程人員的就只剩根據令牌包是否發數據包的權利了,真是悲慘啊~
 
 
 
= 3= 轉載請註明轉自個人BLOG http://blog.chinaunix.net/u1/57901/
發佈了48 篇原創文章 · 獲贊 15 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章