轉載注明出處:http://blog.csdn.net/ruoyunliufeng/article/details/25040009
總線驅動是不用改的,核心都幫我們做好了,為了了解整個USB驅動的體系,我們來分析一下總線驅動程式。
一.總線框圖

總線的圖畫的已經非常清楚了,這篇部落格我們分析的是左邊的程式,在下篇我們想通過USB鍵盤這一實際例子來講解。
二.程式實作
1. 由于代碼太多且關系複雜這裡隻列出調用的函數(沒有寫參數)。從插入USB裝置,到調用USB裝置驅動程式,這一過程。
hub_irq() //當我們接上USB的時候,由于硬體上會産生一個高電平,是以主機控制器會産生中斷
kick_khubd() //喚醒線程
hub_thread() //線程
hub_events() //事件
hub_port_connect_change() //端口連接配接發生變化
udev = usb_alloc_dev(hdev, hdev->bus, port1); // 配置設定一個udev結構體
dev->dev.bus = &usb_bus_type; //USB總線
choose_address(udev); // 給新裝置配置設定編号(位址)
hub_port_init() //端口初始化
hub_set_address // 把編号(位址)告訴USB裝置
usb_get_device_descriptor(udev, 8); // 擷取裝置描述符
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);//再次獲得一次
usb_new_device(udev) //建立USB裝置
err = usb_get_configuration(udev); //獲得配置,把所有描述符都讀出來并解析
usb_parse_configuration() //解析
device_add() // 把device放入usb_bus_type的dev連結清單,
// 從usb_bus_type的driver連結清單裡取出usb_driver,
// 把usb_interface和usb_driver的id_table比較
// 如果能比對,調用usb_driver的.probe
2.總線驅動程式都做了什麼
a. 識别USB裝置
1. 配置設定位址
choose_address(udev); // 給新裝置配置設定編号(位址)
2. 并告訴USB裝置(set address)
hub_set_address // 把編号(位址)告訴USB裝置
3. 發出指令擷取描述符(描述符的資訊可以在include\linux\usb\Ch9.h看到)
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
b. 查找并安裝對應的裝置驅動程式
device_add();
c. 提供USB讀寫函數
盡管USB本身所屬裝置驅動的結構與不挂在USB總線上時完全相同,但是在通路方式上卻發生了很大的變化。例如,對于字元裝置驅動而言,盡管仍然是write(), read(), ioctl()這些函數,但是在這些函數中,與USB裝置通信時不再是I/O記憶體和I/O端口的通路,而貫穿始終的是稱為URB的USB請求塊,這些請求塊通過USB總線驅動提供的讀寫等接口進行操作。
參考:韋東山視訊第二期