Condividi tramite


Come selezionare un'impostazione alternativa in un'interfaccia USB

In questo argomento vengono descritti i passaggi per l'emissione di una richiesta di interfaccia select per attivare un'impostazione alternativa in un'interfaccia USB. Il driver client deve eseguire questa richiesta dopo aver selezionato una configurazione USB. Selezionando una configurazione, per impostazione predefinita, viene attivata anche la prima impostazione alternativa in ogni interfaccia della configurazione.

Ogni configurazione USB deve supportare una o più interfacce USB. Ogni interfaccia espone uno o più endpoint usati per trasferire i dati da e verso il dispositivo. Le interfacce USB devono avere un indice di interfaccia definito dal dispositivo usato per identificare l'interfaccia. L'interfaccia deve avere anche una o più impostazioni alternative che raggruppano gli endpoint dell'interfaccia. Come parte della configurazione del dispositivo, il driver client deve selezionare una delle impostazioni alternative nell'interfaccia. Poiché gli endpoint possono essere condivisi tra impostazioni alternative, solo un'impostazione può essere attiva in un determinato momento. Dopo che l'impostazione alternativa è attiva, gli endpoint diventano disponibili per i trasferimenti di dati.

Per un dispositivo con più interfacce, due interfacce possono essere attive in un determinato momento. Il driver client deve attivare un'impostazione alternativa in ogni interfaccia. Gli endpoint non vengono condivisi tra interfacce e pertanto ogni trasferimento di dati simultaneo può essere eseguito su ogni interfaccia.

Le impostazioni alternative sono definite dal dispositivo e identificate con un numero denominato indice dell'impostazione. L'impostazione alternativa in corrispondenza dell'indice 0 è denominata impostazione alternativa predefinita in questo set di documentazione. Un'impostazione alternativa è descritta in una struttura USB_INTERFACE_DESCRIPTOR . La struttura contiene l'indice dell'interfaccia a cui è associata l'impostazione e il numero di endpoint definiti dall'impostazione. Contiene anche informazioni sulla specifica della classe a cui è conforme la funzionalità dell'interfaccia. Il modo in cui gli endpoint sono raggruppati dipende dalla funzionalità del dispositivo.

Ad esempio, un'interfaccia espone due endpoint isocroni e due endpoint in blocco tramite tre impostazioni alternative (indice 0, 1, 2). L'impostazione alternativa 0 non definisce alcun endpoint; L'impostazione alternativa 1 definisce gli endpoint in blocco; L'impostazione alternativa 2 definisce gli endpoint isocroni. Poiché l'impostazione alternativa 0 non ha alcun endpoint, il driver client può selezionare questa impostazione per disabilitare il trasferimento dei dati per risparmiare larghezza di banda. Quando una delle altre impostazioni è attiva, il dispositivo è pronto per i trasferimenti di dati. L'impostazione alternativa 1 può essere usata per trasferire i dati in blocco. È possibile selezionare l'impostazione alternativa 2 quando il dispositivo è in modalità di streaming. Pertanto, le impostazioni alternative offrono al driver client la flessibilità di modifica della configurazione del dispositivo come e quando necessario. In questo esempio, il driver client può cambiare la funzionalità del dispositivo da un trasferimento in blocco allo streaming, semplicemente selezionando un'impostazione alternativa.

È anche possibile usare impostazioni alternative per impostare i requisiti di larghezza di banda. Per un esempio, vedi Layout dispositivo USB.

Windows Driver Foundation (WDF) fornisce metodi in Kernel-Mode Driver Framework e User-Mode Driver Framework che il driver client può chiamare per selezionare un'impostazione alternativa diversa. Il driver client KMDF può selezionare un'impostazione specificando l'indice dell'impostazione, il descrittore dell'interfaccia dell'impostazione o inviando un'impostazione CHE contiene la richiesta. Il driver client UMDF può selezionare solo un'impostazione alternativa specificandone l'indice di impostazione.

Al termine di una richiesta di configurazione selezionata, l'impostazione alternativa attiva in precedenza viene disattivata.

Informazioni importanti

Questo articolo usa i framework seguenti:

Prima di iniziare

Prima che il driver client possa selezionare un'impostazione alternativa, assicurarsi che siano soddisfatti questi requisiti:

  • Il driver client deve aver creato l'oggetto dispositivo di destinazione USB del framework.

  • Il dispositivo deve avere una configurazione attiva.

    • Un driver client KMDF deve chiamare il metodo WdfUsbTargetDeviceSelectConfig .

    • Per un driver client UMDF, il framework seleziona la prima configurazione e l'impostazione alternativa predefinita per ogni interfaccia in tale configurazione.

      Se si usano modelli USB, il codice seleziona la prima configurazione e l'impostazione alternativa predefinita in ogni interfaccia.

Selezionare un'impostazione alternativa in un driver client KMDF

  1. Ottenere un handle WDFUSBINTERFACE per l'interfaccia con l'impostazione alternativa.

    Per ottenere handle, ottenere innanzitutto il numero di interfacce della configurazione selezionata chiamando WdfUsbTargetDeviceGetNumInterfaces e quindi enumerare le interfacce in un ciclo. In ogni iterazione chiamare il metodo WdfUsbTargetDeviceGetInterface e incrementare l'indice (a partire da zero).

    Nota Durante l'enumerazione del dispositivo, lo stack di driver USB assegna numeri alle impostazioni alternative. I numeri di interfaccia sono in base zero e sequenziale. Questi numeri potrebbero essere diversi dall'indice delle impostazioni definite dal dispositivo. Per ottenere l'indice delle impostazioni definite dal dispositivo, chiamare il metodo WdfUsbInterfaceGetInterfaceNumber .

  2. Avviare una richiesta di interfaccia select chiamando il metodo WdfUsbInterfaceSelectSetting . Nel parametro Params della chiamata scegliere una delle opzioni seguenti:

    • Specificare il numero di impostazione alternativo assegnato dallo stack di driver USB. In genere, si passa lo stesso indice usato nel passaggio 1 per enumerare le impostazioni.

    • Specificare un puntatore al descrittore di interfaccia che descrive l'impostazione alternativa. Il driver può quindi ottenere descrittori di interfaccia durante l'enumerazione delle impostazioni alternative nell'interfaccia chiamando il metodo WdfUsbInterfaceGetDescriptor . Al termine dell'enumerazione, il driver ottiene informazioni su tutte le impostazioni alternative enumerate nella struttura USB_INTERFACE_DESCRIPTOR .

    • Specificare un puntatore a un'istanza DI CHE contiene tutte le informazioni necessarie per la richiesta di interfaccia select.

      1. Allocare una matrice di strutture USBD_INTERFACE_LIST_ENTRY . Il numero di elementi in questa matrice dipende dal numero di interfacce nella configurazione selezionata. Per informazioni sull'inizializzazione di questa matrice, vedere Come selezionare una configurazione per un dispositivo USB.
      2. Allocare un'istanza DI PER la richiesta di interfaccia select chiamando la routine USBD_SelectInterfaceUrbAllocateAndBuild . In questa chiamata specificare la matrice dell'elenco di interfacce e l'handle di configurazione ottenuti dopo aver selezionato una configurazione. È possibile ottenere tale handle chiamando il metodo WdfUsbTargetDeviceWdmGetConfigurationHandle .
      3. Chiamare WdfUsbInterfaceSelectSetting e specificare l'oggetto ESEGUI.

      **Driver WDM:**Per inviare l'OGGETTO TYPE, associare l'OGGETTO SURFACE a un IRP e inviare l'IRP allo stack di driver USB. Per altre informazioni, vedere How to Submit an ENUMERAT.

    Le opzioni nell'elenco offrono al driver client la flessibilità necessaria per specificare i criteri di selezione. Se si è già a conoscenza delle funzionalità dell'endpoint dell'impostazione alternativa, scegliere la prima opzione (con il numero di impostazione alternativa) nell'elenco. In caso contrario, scegliere la seconda opzione che specifica il descrittore di interfaccia. Esaminare USB_INTERFACE_DESCRIPTOR strutture per tutte le impostazioni alternative. Per ogni impostazione, enumerare gli endpoint e le relative caratteristiche, ad esempio il tipo di endpoint, le dimensioni massime dei pacchetti e così via. Quando si trova il set di endpoint necessari per i trasferimenti di dati, chiamare WdfUsbInterfaceSelectSetting specificando un puntatore al descrittore di interfaccia. In genere, non è necessaria la terza opzione, a meno che non si sia un driver client basato su WDM che può inviare richieste solo allo stack di driver USB inviando GLI URB.

    In base alle informazioni fornite dal driver client, lo stack di driver USB compila quindi una richiesta di controllo standard (SET INTERFACE) e la invia al dispositivo. Se la richiesta viene completata correttamente, lo stack di driver USB ottiene handle pipe agli endpoint dell'impostazione alternativa.

    Dopo aver selezionato un'impostazione alternativa, il driver client deve sempre ottenere gli handle della pipe per gli endpoint nella nuova impostazione. In caso contrario, il driver potrebbe inviare richieste di trasferimento dei dati usando handle pipe non aggiornati. Per informazioni sul recupero di handle di pipe, vedere Come enumerare pipe 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;
}

Selezionare un'impostazione alternativa in un driver client UMDF

  1. Ottenere il numero di interfacce USB supportate dalla configurazione attiva chiamando il metodo IWDFUsbTargetDevice::GetNumInterfaces .

  2. Ottenere un puntatore IWDFUsbInterface per ogni interfaccia nella configurazione.

    Enumerare tutte le interfacce chiamando il metodo IWDFUsbTargetDevice::RetrieveUsbInterface in un ciclo finché la funzione non restituisce NULL. Con ogni iterazione, incrementare l'indice membro (in base zero). Il ciclo recupera i puntatori IWDFUsbInterface a tutte le interfacce enumerate.

  3. Per ogni interfaccia, ottenere l'handle WinUSB chiamando IWDFUsbInterface::GetWinUsbHandle. Questo handle è richiesto dal passaggio successivo.

  4. Chiamare WinUsb_GetAssociatedInterface per ottenere un handle all'interfaccia. Nel parametro AssociatedInterfaceIndex specificare l'indice nel passaggio 2.

  5. Determinare il numero di impostazioni alternative nell'interfaccia.

    Chiamare la funzione WinUsb_QueryInterfaceSettings in un ciclo e incrementare l'indice (in base zero) in ogni iterazione. Quando vengono enumerate tutte le impostazioni, la funzione restituisce ERROR_NO_MORE_ITEMS. La funzione restituisce anche descrittori di interfaccia per ogni impostazione.

  6. Usando il valore ricevuto nel membro bNumEndpoints di ogni descrittore di interfaccia ed enumerare i relativi endpoint. Esaminare i descrittori di endpoint e determinare quale impostazione soddisfa le esigenze.

  7. Avviare una richiesta di interfaccia select chiamando la funzione WinUsb_SetCurrentAlternateSetting . Nella chiamata specificare il numero di impostazione alternativo associato all'indice nel passaggio 4.

  8. Rilasciare l'handle di interfaccia ottenuto nel passaggio 4 chiamando la funzione WinUsb_Free .

  9. Rilasciare l'handle WinUSB ottenuto nel passaggio 3 chiamando la funzione WinUsb_Free .

  10. Se si finisce di usare i metodi IWDFUsbInterface , rilasciare tutti i puntatori di interfaccia recuperati nel passaggio 2.

Commenti

Per un driver client KMDF, nella chiamata WdfUsbInterfaceSelectSetting , il driver può fornire un puntatore a un contesto di pipe definito dal driver. Il driver client può archiviare informazioni sulle pipe nel contesto della pipe. Per altre informazioni sulla pipe, vedere Come enumerare pipe USB.