天天看點

大話USB驅動之總線驅動程式

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

           總線驅動是不用改的,核心都幫我們做好了,為了了解整個USB驅動的體系,我們來分析一下總線驅動程式。

一.總線框圖

大話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總線驅動提供的讀寫等接口進行操作。

參考:韋東山視訊第二期

繼續閱讀