2007年11月1日 星期四

USB 韌體解析-1

回想一下我去公所辦事的狀況:當一踏進大門,義工媽媽就馬上問"帥哥,請問要來辦什麼事情?"(純屬事實,絕無虛構)並且引導我去抽號碼牌。然後坐著等待叫號之後再去櫃台填表辦事。這就是一個典型的官僚系統。



原始的USB界面(也就是非OTG的USB)就像現實世界的官僚系統一樣,全部都是PC(host 端)主導一切的動作,甚至連上傳資料都不能裝置端自己要傳就傳,一定要host叫你傳才能傳。所以實作上就非常簡單,不會發生其他網路界面那種搶頻寬的問題。



接下來的解說需要去usb.org下載USB2.0規格書配合來看。



裝置插入

我們可以看看剛才下載的USB_20.pdf 的7.1.5.1。根據USB 2.0的規範,USB的裝置端需要如下圖所示依裝置的速度並聯一個電阻在D+或D-與3.3V間。









看到這裡,我們就可以知道在自製USB滑鼠裡畫的電路圖是一個低速的USB裝置,也知道PC怎樣知道有個有個"帥哥"進來而該派"義工媽媽"去幫忙抽號碼牌了。可是電阻的接法好像跟上面的圖不太一樣也跟USB 2.0規範不太一樣耶?這個部份先保留,等到USB高級心法再詳細解說。



Device Request



再來也跟現實狀況一樣,在抽號碼牌前都是由義工媽媽來服務,等到抽完號碼牌後就要等到叫到號碼後才去櫃台由小姐服務。USB裝置在剛被RESET或是接到PC時都是固定為0號,等到PC下了一個Set Address的Request後變成由HOST指定的號碼了。



在USB的世界裡一切就是很官僚,一切都只有填充題。所有要填的表格和該填什麼都在USB_20.pdf的9.3和9.4裡。



韌體解析-1

經過前面的解說和參考資料的研讀後,我們可以知道USB韌體最重要的部份就是在處理request表格。以我們一直當範例的EasyLogger來說,在usbdrv.c的347行附近像下面這樣就是在處理request表格。




}else if(rq->bRequest == USBRQ_SET_ADDRESS){ /* 5 */
usbNewDeviceAddr = rq->wValue.bytes[0];
}else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */
flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW;
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ /* 1 */

//
//
//




不過這個程式不太好閱讀,有興趣者可以參考Silicon LabsUSB Firmware Programmer's Guide 第34頁開始的程式碼,這份文件寫得很工整很容易閱讀。



今天就暫時在這裡告一段落。

沒有留言:

張貼留言