欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Windows XP下usbport.sys驅動(dòng)內部實(shí)現解析(二)
Windows XP下usbport.sys驅動(dòng)內部實(shí)現解析(二)
2010-01-22 18:15
(接上一篇)

4. 處理USB請求(URB)

在進(jìn)入下一個(gè)主題之前我總結幾個(gè)事實(shí)讓大家注意:

1. 對于每個(gè)usb總線(xiàn)上的設備,usbport在usbhub的幫助下為其創(chuàng )建一個(gè)device handle,并把這些device handle鏈接到一起,并為endpoint 0 創(chuàng )建一個(gè)pipe handle。

2. 在進(jìn)行select configuration的時(shí)候,usbport創(chuàng )建一個(gè)config handle結構,保存其指針到對應的device handle,然后創(chuàng )建若干個(gè)interface handle,全部鏈接到config handle上去。對于每個(gè)interface里面的全部endpoint,為其創(chuàng )建一個(gè)pipe handle,全部連接到對應的device handle上面去。對于每個(gè)pipe handle,為其創(chuàng )建一個(gè)endpoint結構,保存其指針到pipe handle,并把所有創(chuàng )建的endpoint全部鏈接到一起。

3. 客戶(hù)驅動(dòng)必須要保存由select configuration所返回的pipe handle,并在隨后的urb里面恰當的填寫(xiě)這個(gè)值。

前面的結構中的若干個(gè)LIST_ENTRY就是usbport維護管理這些結構的關(guān)鍵。維護管理用的基礎結構了解好了,接下來(lái)就是urb的處理問(wèn)題了。

說(shuō)到urb的處理,就不能不提一些internal io control的問(wèn)題。都知道urb是通過(guò)一個(gè)internal io control提交的,除了這個(gè)以外還有若干個(gè)其他的internal io control,比如用于獲取port狀態(tài)的、比如用于reset port的、等等等等。這些處理這里先不提,因為大部分的處理都是由usbhub完成的,usbport單獨完成的功能很少,還有部分是兩個(gè)配合完成的 -- 這個(gè)留到usbhub的地方再回頭來(lái)說(shuō)。

首先明白一個(gè)事實(shí),客戶(hù)驅動(dòng)把urb提交給的是自己的pdo,這個(gè)pdo作一些過(guò)濾動(dòng)作以后,直接提交給了root hub的pdo。至于是不是這樣的一個(gè)情況,等到說(shuō)起usbhub的時(shí)候就明白了,現在先假定如此。

usbport在一份數據結構的幫助下對每個(gè)urb作一些檢查,然后轉到特定的處理函數,先看這個(gè)數據結構的定義:

struct URB_DISPATCH_TABLE   // sizeof=0X14
{
    PVOID DispatchRoutine; // process routine
    USHORT           TransferLen; //
    UCHAR              reserved[2];
    UCHAR              bmRequestDirection; // setup packet
    UCHAR              bmRequestType;
    UCHAR              Recipient;
    UCHAR              bRequest;
    UCHAR              Flags;
    UCHAR              data[3];
    ULONG             FunctionCode;
};

很簡(jiǎn)單的一個(gè)結構。TransferLen用于固定大小的傳輸,用來(lái)檢查說(shuō)提交的buffer大小是否正確,如果是0,則不檢查大小信息。接下來(lái)的幾個(gè)成員用于control transfer用來(lái)填充setup packet。許多的urb都不需要你完全的填充所有的setup packet成員,usbport在這里會(huì )為你填充這些已知的固定的成員。flags則是控制usbport的操作方式的,下面會(huì )詳細的解釋。 function code則是指明這份數據是對應哪個(gè)function的。理所當然的,usbport為每個(gè)function code準備一個(gè)這樣的結構構成一個(gè)數組。

下面是處理URB的代碼:

processurb(pUrb)
{
     檢查FunctionCode
     檢查pUrb->DeviceHandle
     if(UrbDispatchTable[FunCode].Flags & 4)
     {
         // force usbport to use default pipe
         get pipe handle from device handle
         save it to pUrb
     }

     if(UrbDispatchTable[FunCode].Flags & 1)
    {
        // actual transfer needed
        if(UrbDispatchTable[FunCode].Flags & 8)
        {
            // no transfer buffer needed
            pUrb->TransferBuffer = 0
            pUrb->TransferBufferLength = 0
            pUrb->TransferBufferMdl = 0
        }
        validate pipe handle
        if(pUrb->TransferBufferLength !=0 && pUrb->TransferBufferMdl == 0)
        {
            IoAllocateMdl();
            MmBuildMdlForNonPagedPool();
            set a flag in UrbHeader,indicates that when we complete this urb,we must free the mdl
        }
        allocate a transfer struct
    }

    check transfer length

    status = call UrbDispatchTable[FunCode]->DispatchRoutine(...);

    if(status != pending)
        complete the urb

    return status;
}

proccess urb是一個(gè)公共的處理函數,他根據dispatch table的flags成員作一些有限度的處理,然后交給真正的dispatch routine處理。

這個(gè)dispatch routine就各式各樣了,大致分成4類(lèi):

1類(lèi)就是不需要transfer結構了,參考上flags & 1非0的分支。這類(lèi)urb大多直接完成了,比如select configuration,比如get frame length。

2類(lèi)屬于control 傳輸,這類(lèi)就根據dispatch table里面的那些setup packet成員填充自己的setup pack結構,然后將transfer排隊。

3類(lèi)屬于interrupt or bulk 傳輸,直接排隊transfer。

4類(lèi)屬于iso transfer,最主要的是要檢查各個(gè)Packet,而且要設置start frame number,最后還是要排隊transfer。

不需要排隊的urb大多是一些沒(méi)有實(shí)現的urb,比如set frame length,或者是一些要特別處理的,比如select configuration。其他的最終都是要排隊transfer的。特別注意參加排隊的是transfer結構,而不是irp或者其他。對照 endpoint結構的那些成員PendingTransferList等等就能明白,排隊的對象并不是irp。

transfer 也是一個(gè)不小的結構:

struct TRANSFER // sizeof=0XC0
{
    ULONG Direction;
    ULONG TimeoutInterval;
    LARGE_INTEGER SubmitTime;
    ULONG TransferedLen;
    ULONG Status;
    ULONG Irp;
    PKEVENT pEvent;
    PURB UrbPointer;
    LIST_ENTRY TransferListEntry; // link entry
    ULONG MappedRegisterBase; // for dma
    ULONG NumberOfMappedRegister; //
    ULONG TransferDirection;
    ULONG TransferBufferLen;
    URB_SETUP_PACKET SetupPacket;
    PMDL TransferMdl;
    LIST_ENTRY AdapterDBList; // for double buffer
    PVOID ParentPointer; // split
    PVOID EndpointPointer;
    PVOID ClientTransferPointer; // passed to miniport
    LIST_ENTRY ChildTransferListHead;
    LIST_ENTRY SplitTransferListEntry;
    PVOID IsoTransferInfo; // iso
    SG_LIST sgList; // scatter-gather list
};

留下了一些分析相關(guān)的成員:其中如果這個(gè)transfer對應有irp則會(huì )設置Irp成員,這個(gè)是可以選的。如果沒(méi)有對應irp也是可以的,那么怎么知道這個(gè)transfer完成了呢?用irp的話(huà)還可以使用complete routine,要是沒(méi)有irp呢?這就是下面的那個(gè)pEvent成員的作用了,他指向一個(gè)event,完成的時(shí)候會(huì )設置這個(gè)event。

還有幾個(gè)list entry,存在的主要原因就是允許傳輸大于MaxTransferLength的數據,那么就必須把原來(lái)的buffer切割成小的buffer,為每個(gè)buffer創(chuàng )建一個(gè)child transfer,這些list entry就是用來(lái)管理這個(gè)的。

至于A(yíng)dapterDBList,則是上面說(shuō)的某個(gè)buffer跨越了非連續的兩個(gè)物理頁(yè)的情況下,用于miniport通知的。 miniport必須要使用額外的緩沖而不是transfer所提供的緩沖,所以usbport必須要提供空間來(lái)保存這些額外的緩沖信息。

最后的是sgList,usbport把要傳輸的buffer映射成一個(gè)一個(gè)的物理頁(yè),用sgList這個(gè)結構來(lái)描述,這個(gè)結構會(huì )傳遞給miniport driver使用。

好了,來(lái)看真實(shí)的排隊情況:usbport通過(guò)調用_USBPORT_QueueTransferUrb函數來(lái)排隊某個(gè)urb,這個(gè)函數很簡(jiǎn)單。

_USBPORT_QueueTransferUrb(pUrb,pEndpoint)
{
    do some check
    update some fields in transfer struct
    if(transfer associates with an irp)
        call _USBPORT_QueuePendingTransferIrp
    else
        call _USBPORT_QueuePendingUrbToEndpoint

    call _USBPORT_FlushPendingList
}

根據transfer是否關(guān)聯(lián)有irp調用不同的函數,在有irp的情況下首先是要設置irp的cancel routine,然后再調用_USBPORT_QueuePendingUrbToEndpoint函數。也其實(shí)就是多一個(gè)設置cancel routine的步驟,至于cancel部分后面會(huì )有專(zhuān)門(mén)的講解,先放一放。主要來(lái)看后面這個(gè)函數,更是非常簡(jiǎn)單:

_USBPORT_QueuePendingUrbToEndpoint(pTransfer,pEndpoint)
{
    link transfer->TransferListEntry to Endpoint->PendingTransfer
}

接下來(lái)當然是_USBPORT_FlushPendingList函數了,看他的名字都知道是在干什么。這個(gè)函數顯得很復雜,因為是幾個(gè)很關(guān)鍵的函數之一。

_USBPORT_FlushPendingList(pEndpoint)
{
    bContinue = TRUE
    do
    {
        if(Endpoint is not root hub\'s endpoint)
        {
            check Endpoint->ActiveTransfer list
            if(is not empty)
            {
                get a transfer from active list
                bContinue = FALSE
                call _USBPORT_CoreEndpointWorker
                if return != 0
                    call _USBPORT_InvalidateEndpoint
            }
        }
        if(bContinue == FALSE)
            break;

        check Endpoint->PendingTransfer
        if(is not empty)
        {
            reset canel routine
            if(irp has not been canceled)
            {
                bContinue = FALSE
                call _USBPORT_QueueActiveUrbToEndpoint
                if( return != 0 )
                    call _USBPORT_FlushMapTransferList
                else
                {
                    call _USBPORT_CoreEndpointWorker
                    if return != 0
                        call _USBPORT_InvalidateEndpoint
                }
         }
    } while( bContinue );
}

或者看了會(huì )很奇怪,先不管,我把全部代碼流程都列出來(lái),然后再總體討論。

_USBPORT_QueueActiveUrbToEndpoint(pTransfer,pEndpoint)
{
    bNeedMap = FALSE
    if(Endpoint is stopped || Transfer is aborted)
        link transfer to pEndpoint->CancelTransfer
    else
    {
        if(Transfer\'s length != 0)
        {
            link transfer to fdo\'s MapTransferList
            bNeedMap = TRUE;
        }
        else
        {
            link transfer to pEndpoint->ActiveTransfer
        }
    }
    return bNeedMap
}

這個(gè)函數比較簡(jiǎn)單,作作判斷決定transfer該進(jìn)入什么樣子的list,然后返回一個(gè)標記表明是否需要進(jìn)行map,只有在transfer的 transfer length也就是pUrb->TransferBufferLength非0的時(shí)候,才需要進(jìn)行Map。

_USBPORT_FlushMapTransferList
{
    while(!pFdoExt->DoMapping)
    {
        if(pFdoExt->MapTransferList is not empty)
        {
            pFdoExt->DoMapping = TRUE;
            get a transfer from the list
            AllocateAdapterChannel(_USBPORT_MapTransfer);
        }
        else break;
    }
}

也是一個(gè)不算復雜的函數:首先檢查當前是否在map,如果為false,然后檢查map transfer list是否是空,不空則取一個(gè)處理調用AllocateAdapterChannel,傳遞的參數是_USBPORT_MapTransfer,在這個(gè)函數里面會(huì )重新設置pFdo->DoMapping = FALSE。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
WDM驅動(dòng)程序設計之USB總線(xiàn)支持類(lèi):KUsbLowerDevice類(lèi)
Linux設備驅動(dòng)程序學(xué)習(18)-USB 驅動(dòng)程序(三)
usb中urb相關(guān)接口函數
usb trace/monitor
利用偽造內核文件來(lái)繞過(guò)IceSword的檢測
如何獲取 PCI 設備的配置和位置信息
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久