共用方式為


如何在USB介面中選取替代設定

本主題描述發出選取介面要求以在USB介面中啟用替代設定的步驟。 選取 USB 組態之後,用戶端驅動程式必須發出此要求。 根據預設,選取組態也會啟動該組態中每個介面中的第一個替代設定。

每個USB組態都必須支援一或多個USB介面。 每個介面都會公開一或多個端點,用來將數據傳送至裝置或從裝置傳送數據。 USB 介面必須具有裝置定義的 介面索引 ,用來識別介面。 介面也必須有一或多個 替代設定 ,以群組介面的埠的連接點。 作為裝置組態的一部分,用戶端驅動程式必須在介面中選取其中一個替代設定。 因為端點可以在替代設定之間共用,所以一次只能使用一個設定。 當替代設定作用中之後,其端點就會變成可供數據傳輸使用。

對於多個介面裝置,兩個介面可以在指定時間使用。 用戶端驅動程序必須在每個介面中啟用替代設定。 端點不會在介面之間共用,因此可以在每個介面上執行每個同時的數據傳輸。

替代設定是裝置定義的,並以稱為 設定索引的數位來識別。 索引 0 的替代設定稱為本檔集中 的預設替代設定 。 替代設定會在 USB_INTERFACE_DESCRIPTOR 結構中描述。 結構包含設定相關聯的介面索引,以及設定所定義的端點數目。 它也包含介面功能符合的類別規格相關信息。 端點分組的方式取決於裝置的功能。

例如,介面會透過索引 0、1、2) ,透過三個替代設定公開兩個連續和兩個大量端點。 (索引 0、1、2) 。 替代設定 0 未定義任何端點;替代設定 1 會定義大量端點;替代設定 2 會定義連續端點。 因為替代設定 0 沒有端點,所以客戶端驅動程式可以選取此設定來停用資料傳輸,以節省頻寬。 當其中一個其他設定為使用中時,裝置已準備好進行數據傳輸。 替代設定 1 可用來傳輸大量數據。 當裝置處於串流模式時,可以選取替代設定 2。 因此,替代設定可讓用戶端驅動程序彈性地視需要變更裝置組態。 在此範例中,客戶端驅動程式只要選取替代設定,即可將裝置功能從大量傳輸切換至串流。

替代設定也可以用來設定頻寬需求。 如需範例,請參閱 USB裝置配置

Windows Driver Foundation (WDF) 提供 核心模式驅動程式架構使用者模式驅動程序架構 中的方法,讓用戶端驅動程式可以呼叫以選取不同的替代設定。 KMDF 用戶端驅動程式可以藉由指定設定索引、設定的介面描述元,或提交包含要求的 URB 來選取設定。 UMDF 用戶端驅動程式只能藉由指定其設定索引來選取替代設定。

選取組態要求成功完成之後,會停用先前作用中的替代設定。

您所需了解的事情

本文使用下列架構:

開始之前

在用戶端驅動程式可以選取替代設定之前,請確定符合這些需求:

在 KMDF 用戶端驅動程式中選取替代設定

  1. 取得具有替代設定之介面的 WDFUSBINTERFACE 句柄。

    若要取得句柄,請先呼叫 WdfUsbTargetDeviceGetNumInterfaces ,然後列舉迴圈中的介面,以取得所選組態的介面數目。 在每個反覆專案中呼叫 WdfUsbTargetDeviceGetInterface 方法,並從零開始遞增索引 () 。

    注意 在裝置列舉期間,USB 驅動程式堆疊會將數位指派給替代設定。 介面編號是以零起始且循序。 這些數位可能與裝置定義的設定索引不同。 若要取得裝置定義的設定索引,請呼叫 WdfUsbInterfaceGetInterfaceNumber 方法。

  2. 呼叫 WdfUsbInterfaceSelectSetting 方法以起始選取介面要求。 在呼叫的 Params 參數中,選擇下列其中一個選項:

    • 指定 USB 驅動程式堆疊指派的替代設定編號。 一般而言,您會傳遞您在步驟 1 中使用的相同索引來列舉設定。

    • 指定描述替代設定之介面描述項的指標。 然後,驅動程式可以藉由呼叫 WdfUsbInterfaceGetDescriptor 方法,在介面中列舉替代設定時取得介面描述元。 列舉完成之後,驅動程式會取得 USB_INTERFACE_DESCRIPTOR 結構中所有列舉的替代設定相關信息。

    • 指定 URB 的指標,其中包含選取介面要求所需的所有資訊。

      1. 配置 USBD_INTERFACE_LIST_ENTRY 結構的陣列。 此陣列中的元素數目取決於所選組態中的介面數目。 如需初始化此陣列的相關信息,請參閱 如何選取USB裝置的組態
      2. 呼叫 USBD_SelectInterfaceUrbAllocateAndBuild 例程,為選取介面要求配置 URB。 在此呼叫中,指定介面清單陣列,以及選取組態之後取得的組態句柄。 您可以呼叫 WdfUsbTargetDeviceWdmGetConfigurationHandle 方法來取得該句柄。
      3. 呼叫 WdfUsbInterfaceSelectSetting 並指定 URB。

      **WDM 驅動程式:**若要提交 URB,請將 URB 與 IRP 產生關聯,並將 IRP 提交至 USB 驅動程式堆棧。 如需詳細資訊,請參閱 如何提交 URB

    清單中的選項提供客戶端驅動程式指定選取準則的彈性。 如果您已經知道替代設定的端點功能,請選擇第一個選項 (清單中的替代設定編號) 。 否則,請選擇指定介面描述元的第二個選項。 檢查 所有 替代設定USB_INTERFACE_DESCRIPTOR結構。 針對每個設定,列舉其端點及其特性,例如端點類型、封包大小上限等等。 當您找到數據傳輸所需的端點集合時,請指定該介面描述元的指標來呼叫 WdfUsbInterfaceSelectSetting 。 一般而言,除非您是WDM型用戶端驅動程式,但只能藉由提交 URI 將要求傳送至 USB 驅動程式堆疊,否則您不需要第三個選項。

    根據客戶端驅動程式所提供的資訊,USB 驅動程式堆疊接著會建置標準控制要求, (SET INTERFACE) ,並將其傳送至裝置。 如果要求順利完成,USB 驅動程式堆疊會取得管線句柄至替代設定的端點。

    選取替代設定之後,用戶端驅動程序必須一律取得新設定中端點的管道句柄。 無法這麼做可能會導致驅動程式使用過時管道句柄來傳送數據傳輸要求。 如需擷取管道控點的相關信息,請參閱 如何列舉 USB 管道

NTSTATUS  FX3SelectInterfaceSetting(  
    _In_ WDFDEVICE Device,
    _In_ UCHAR SettingIndex)

{
    NTSTATUS                 status;  
    PDEVICE_CONTEXT          pDeviceContext;  
    WDF_OBJECT_ATTRIBUTES               pipeAttributes;

    WDF_USB_INTERFACE_SELECT_SETTING_PARAMS settingParams;

    PAGED_CODE();  

    pDeviceContext = GetDeviceContext(Device);

    if (pDeviceContext->UsbInterface == NULL)
    {
        status = USBD_STATUS_BAD_NUMBER_OF_INTERFACES;
        goto Exit;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pipeAttributes, PIPE_CONTEXT);  

    pipeAttributes.EvtCleanupCallback = FX3EvtPipeContextCleanup;

    WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING (&settingParams, SettingIndex);

    status = WdfUsbInterfaceSelectSetting (
        pDeviceContext->UsbInterface,
        &pipeAttributes,
        &settingParams);

    if (status != STATUS_SUCCESS)
    {
        goto Exit;
    }

    if (WdfUsbInterfaceGetNumConfiguredPipes (pDeviceContext->UsbInterface) > 0)
    {
        status = FX3EnumeratePipes (Device);

        if (status != STATUS_SUCCESS)
        {
            goto Exit;
        }
    }

Exit:
    return status;
}

在 UMDF 用戶端驅動程式中選取替代設定

  1. 藉由呼叫 IWDFUsbTargetDevice::GetNumInterfaces 方法,取得作用中組態支援的 USB 介面數目。

  2. 取得組態中每個介面的 IWDFUsbInterface 指標。

    在迴圈中呼叫 IWDFUsbTargetDevice::RetrieveUsbInterface 方法,以列舉所有介面,直到函式傳回 NULL 為止。 每次反覆專案時, (以零起始) 遞增成員索引。 迴圈會擷取所有列舉介面的 IWDFUsbInterface 指標。

  3. 針對每個介面,呼叫 IWDFUsbInterface::GetWinUsbHandle 來取得 WinUSB 句柄。 下一個步驟需要此句柄。

  4. 呼叫 WinUsb_GetAssociatedInterface 以取得 介面的句柄。 在 AssociatedInterfaceIndex 參數中,指定步驟 2 中的索引。

  5. 決定介面中的替代設定數目。

    在迴圈中呼叫 WinUsb_QueryInterfaceSettings 函式,並在每次反覆專案中遞增索引 (以零起始的) 。 列舉所有設定時,函式會傳回ERROR_NO_MORE_ITEMS。 此函式也會傳回每個設定的介面描述元。

  6. 使用每個介面描述元 之 bNumEndpoints 成員中收到的值,並列舉其端點。 檢查端點描述項,並判斷哪個設定符合您的需求。

  7. 藉由呼叫 WinUsb_SetCurrentAlternateSetting 函式來起始選取介面要求。 在呼叫中,指定與步驟 4 中索引相關聯的替代設定編號。

  8. 藉由呼叫 WinUsb_Free 函式,釋放在步驟 4 中取得 介面句柄。

  9. 藉由呼叫 WinUsb_Free 函式,釋放在步驟 3 中取得的 WinUSB 句柄。

  10. 如果您使用 IWDFUsbInterface 方法完成,請釋放步驟 2 中擷取的所有介面指標。

備註

對於 KMDF 用戶端驅動程式,在其 WdfUsbInterfaceSelectSetting 呼叫中,驅動程式可以提供驅動程式定義管道內容的指標。 用戶端驅動程式可以將管道的相關信息儲存在管道內容中。 如需管道資訊的詳細資訊,請參閱 如何列舉 USB 管道