Scrivere un driver del controller di porta USB Type-C

È necessario scrivere un driver del controller di porta USB Type-C se l'hardware USB Type-C implementa il livello fisico USB Type-C o Power Delivery (PD), ma non implementa i computer di stato necessari per Power Delivery.

In Windows 10 versione 1703, l'architettura USB Type-C è stata migliorata per supportare progetti hardware che implementano il livello fisico USB Type-C o Power Delivery (PD), ma non hanno un motore di criteri PD o un'implementazione del livello di protocollo corrispondente. Per queste progettazioni, Windows 10 versione 1703 fornisce un motore di criteri PD basato su software e gestione criteri del dispositivo tramite una nuova estensione di classe denominata "USB Connector Manager Type-C Port Controller Interface Extension" (UcmTcpciCx). Un driver client scritto da un IHV o OEM/ODM comunica con UcmTcpciCx per fornire informazioni sugli eventi hardware necessari per il motore di criteri PD e il gestore dei criteri di dispositivo in UcmTcpciCx per funzionare. Tale comunicazione è abilitata tramite un set di interfacce di programmazione descritte in questo articolo e nella sezione di riferimento.

Diagramma di gestione connettori USB.

L'estensione della classe UcmTcpciCx è un driver client di UcmCx. Le decisioni dei criteri sui contratti di alimentazione, sui ruoli dati, vengono prese in UcmCx e inoltrate a UcmTcpciCx. UcmTcpciCx implementa tali criteri e gestisce i computer di stato Type-C e PD usando l'interfaccia del controller di porta fornita dal driver client UcmTcpciCx.

Riepilogo

  • Servizi forniti dall'estensione della classe UcmTcpci
  • Comportamento previsto del driver client

Specifiche ufficiali

API importanti

Informazioni di riferimento sulle estensioni della classe di driver del controller di porta USB-C

Modello di driver client UcmTcpciCx

Modello di driver client UcmTcpciCx

Prima di iniziare

  • Determinare il tipo di driver necessario scrivere a seconda che l'hardware o il firmware implementi il computer con stato PD. Per altre informazioni, vedere Sviluppo di driver Windows per connettori USB Type-C.

  • Installare Windows 10 per le edizioni desktop (Home, Pro, Enterprise e Education) nel computer di destinazione o Windows 10 Mobile con un connettore USB Type-C.

  • Installare windows Driver Kit (WDK) più recente nel computer di sviluppo. Il kit include i file di intestazione e le librerie necessari per scrivere il driver client, in particolare, è necessario:

    • Libreria stub, (UcmTcpciCxStub.lib). La libreria converte le chiamate effettuate dal driver client e le passa all'estensione della classe.
    • File di intestazione, UcmTcpciCx.h.

    Il driver client viene eseguito in modalità kernel e associa alla libreria KMDF 1.15.

    Screenshot della configurazione di Visual Studio per UCM.

  • Decidere se il driver client supporta gli avvisi.

  • Il controller di porta non deve essere conforme a TCPCI. L'interfaccia acquisisce le funzionalità di qualsiasi controller di porta Type-C. La scrittura di un driver client UcmTcpciCx per l'hardware che non è conforme a TCPCI comporta il mapping dei significati dei registri e dei comandi nella specifica TCPCI a quelli dell'hardware.

  • La maggior parte dei controller TCPCI è connessa a I2C. Il driver client usa una risorsa di connessione SPB (Serial Peripheral Bus) e una linea di interruzione per comunicare con l'hardware. Il driver usa l'interfaccia di programmazione spb Framework Extension (SpbCx). Acquisire familiarità con SpbCx leggendo questi articoli:

    • [Guida alla progettazione del driver SPB (Simple Peripheral Bus) ]
    • [Informazioni di riferimento sulla programmazione del driver SPB]
  • Acquisire familiarità con Windows Driver Foundation (WDF). Lettura consigliata: Sviluppo di driver con Windows Driver Foundation, scritto da Penny Orwick e Guy Smith.

Comportamento dell'estensione della classe UcmTcpci

  • Nell'ambito dell'esecuzione del computer di stato, UcmTcpciCx invia richieste IOCTL al controller di porta. Ad esempio, nella messaggistica PD, invia una richiesta di IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER per impostare il buffer di trasmissione. La richiesta (TRANSMIT_BUFFER) viene passata al driver client. Il driver imposta quindi il buffer di trasmissione con i dettagli forniti dall'estensione della classe.

  • UcmTcpciCx implementa i criteri relativi ai contratti di alimentazione, ai ruoli dei dati e così via.

Comportamento previsto del driver client

Il driver client al UcmTcpciCx è previsto:

  • Essere il proprietario dei criteri di alimentazione. UcmTcpciCx non partecipa alla gestione della potenza del controller di porta.

  • Tradurre le richieste, ricevute da UcmTcpciCx, in comandi di lettura o scrittura hardware. I comandi devono essere asincroni perché DPM non può bloccare l'attesa del completamento di un trasferimento hardware.

  • Specificare un oggetto coda del framework che contiene oggetti richiesta framework. Per ogni richiesta che l'estensione della classe UcmTcpci vuole inviare al driver client, l'estensione aggiunge un oggetto request nell'oggetto coda del driver. Al termine dell'elaborazione della richiesta, il driver chiama WdfRequestComplete. È responsabilità del driver client completare le richieste in modo tempestivo.

  • Individuare e segnalare le funzionalità del controller di porta. Queste funzionalità includono informazioni quali i ruoli in cui il controller di porta può operare (ad esempio Solo origine, sink-only, DRP). Tuttavia, esistono altre funzionalità del connettore (vedere la nota su Capability Store) e del sistema nel suo complesso, che DPM è necessario sapere per implementare correttamente i criteri USB Type-C e PD. Ad esempio, DPM deve conoscere le funzionalità di origine del sistema/connettore per annunciarlo al partner della porta.

    Archivio funzionalità

    Oltre alle funzionalità correlate al driver client, le informazioni aggiuntive provengono da una posizione globale di sistema denominata Capability Store. Questo Archivio funzionalità globale del sistema viene archiviato in ACPI. È una descrizione statica delle funzionalità del sistema e di ognuno dei relativi connettori USB Type-C usati da DPM per determinare i criteri da implementare.

    Separando la descrizione delle funzionalità di sistema dal driver client per i controller di porta, la progettazione consente l'uso di un driver in sistemi diversi di diverse funzionalità. UcmCx, non UcmTcpciCx, interfacce con l'Archivio funzionalità. UcmTcpciCx (o il relativo driver client) non interagisce con l'Archivio funzionalità.

    Se applicabile, le informazioni dell'archivio funzionalità eseguono l'override delle informazioni provenienti direttamente dal driver client del controller di porta. Ad esempio, un controller di porta è in grado di eseguire operazioni solo sink e il driver client segnala tali informazioni. Tuttavia, il resto del sistema potrebbe non essere configurato correttamente per l'operazione di sola sink. In tal caso, il produttore del sistema può segnalare che i connettori sono in grado di eseguire l'operazione di sola origine nell'Archivio funzionalità. L'impostazione in Capability Store ha la precedenza sulle informazioni segnalate dal driver.

  • Notifica UcmTcpciCx con tutti i dati pertinenti correlati agli avvisi.

  • facoltativo. Eseguire un'elaborazione aggiuntiva dopo l'immissione/uscita di una modalità alternativa. Il driver viene informato di questi stati dall'estensione della classe tramite richieste IOCTL.

Registrare il driver client con UcmTcpciCx

Riferimento di esempio: vedere EvtPrepareHardware in Device.cpp.

  1. Nell'implementazione EVT_WDF_DRIVER_DEVICE_ADD chiamare UcmTcpciDeviceInitInitialize per inizializzare la struttura WDFDEVICE_INIT opaca. La chiamata associa il driver client al framework.

  2. Dopo aver creato l'oggetto dispositivo framework (WDFDEVICE), chiamare UcmTcpciDeviceInitialize per registrare il client diver con UcmTcpciCx.

Inizializzare il canale di comunicazione I2C nell'hardware del controller di porta

Riferimento di esempio: vedere EvtCreateDevice in Device.cpp.

Nell'implementazione EVT_WDF_DEVICE_PREPARE_HARDWARE leggere le risorse hardware per aprire un canale di comunicazione. Questa operazione è necessaria per recuperare le funzionalità PD e ricevere notifiche sugli avvisi.

La maggior parte dei controller TCPCI è connessa a I2C. Nell'esempio di riferimento, il driver client apre un canaleI2 usando l'interfaccia di programmazione Spb Framework Extension (SpbCx).

Il driver client enumera le risorse hardware chiamando WdfCmResourceListGetDescriptor.

Gli avvisi vengono ricevuti come interruzioni. Pertanto, il driver crea un oggetto di interruzione del framework e registra l'ISR che gestisce gli avvisi. L'ISR esegue operazioni di lettura e scrittura hardware, che bloccano fino al completamento dell'accesso hardware. Poiché l'attesa è inaccettabile a DIRQL, il driver esegue l'ISR in PASSIVE_LEVEL.

Inizializzare le funzionalità Type-C e PD del controller di porta

Riferimento di esempio: vedere EvtDeviceD0Entry in Device.cpp.

Nell'implementazione di EVT_WDF_DEVICE_D0_EXIT,

  1. Comunicare con l'hardware del controller di porta e recuperare l'identificazione e le funzionalità del dispositivo leggendo vari registri.

  2. Inizializzare UCMTCPCI_PORT_CONTROLLER_IDENTIFICATION e UCMTCPCI_PORT_CONTROLLER_CAPABILITIES con le informazioni recuperate.

  3. Inizializzare UCMTCPCI_PORT_CONTROLLER_CONFIG struttura con le informazioni precedenti passando le strutture inizializzate alla UCMTCPCI_PORT_CONTROLLER_CONFIG_INIT.

  4. Chiamare UcmTcpciPortControllerCreare per creare l'oggetto controller di porta e recuperare l'handle UCMTCPCIPORTCONTROLLER.

Configurare un oggetto coda del framework per la ricezione di richieste da UcmTcpciCx

Riferimento di esempio: vedere EvtDeviceD0Entry in Device.cpp e HardwareRequestQueueInitialize in Queue.cpp.

  1. Nell'implementazione di EVT_WDF_DEVICE_D0_EXIT creare un oggetto coda del framework chiamando WdfIoQueueCreate. In tale chiamata è necessario registrare l'implementazione del callback per gestire le richieste IOCTL inviate da UcmTpciCx. Il driver client può usare una coda gestita da energia.

    Durante l'esecuzione dei computer di stato Type-C e PD, UcmTpciCx invia comandi al driver client da eseguire. UcmTcpciCx garantisce al massimo una richiesta di controller porta in sospeso in qualsiasi momento.

  2. Chiamare UcmTcpciPortControllerSetHardwareRequestQueue per registrare il nuovo oggetto coda del framework con UcmTpciCx. Dopo aver completato la chiamata, UcmTcpciCx inserisce gli oggetti della coda del framework (WDFREQUEST) in questa coda quando richiede un'azione dal driver.

  3. Implementare la funzione di callback EvtIoDeviceControl per gestire questi IOCTLs.

Codice di controllo Descrizione
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_STATUS Ottiene i valori di tutti i registri di stato in base alla specifica dell'interfaccia dell'interfaccia del controller di porta seriale universale-C. Il driver client deve recuperare i valori del CC_STATUS, POWER_STATUS e FAULT_STATUS registri.
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_CONTROL Ottiene i valori di tutti i registri di controllo definiti in base alla specifica dell'interfaccia del controller di porta del bus seriale universale-C.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONTROL Imposta il valore di un registro di controllo definito in base alla specifica dell'interfaccia del controller di porta del bus seriale universale-C.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT Imposta il registro DI TRASMISSIONE definito come per la specifica dell'interfaccia dell'interfaccia del controller di porta del bus seriale universale-C.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER Imposta il TRANSMIT_BUFER Register definito come per la specifica dell'interfaccia dell'interfaccia del controller di porta seriale universale.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_RECEIVE_DETECT Imposta il RECEIVE_DETECT Register definito come per la specifica dell'interfaccia del controller di porta del bus seriale universale.Set the RECEIVE_DETECT Register defined as per the Universal Serial Bus Type-C Port Interface Specification.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONFIG_STANDARD_OUTPUT Imposta la CONFIG_STANDARD_OUTPUT Register definita in base alla specifica dell'interfaccia del controller di porta del bus seriale universale.Set the CONFIG_STANDARD_OUTPUT Register defined as per the Universal Serial Bus Type-C Port Interface Specification.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_COMMAND Imposta il valore di un registro dei comandi definito in base alla specifica dell'interfaccia del controller di porta del bus seriale universale.Set the value of a command register defined as per the Universal Serial Bus Type-C Port Interface Specification.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_MESSAGE_HEADER_INFO Imposta il valore del MESSAGE_HEADER_INFO Register definito come per la specifica dell'interfaccia del controller di porta del bus seriale universale-C.
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_ENTERED Notifica al driver client che viene immessa una modalità alternativa in modo che il driver possa eseguire altre attività.
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_EXITED Notifica al driver client che viene chiusa una modalità alternativa in modo che il driver possa eseguire altre attività.
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_CONFIGURED Notifica al driver client che la modalità alternativa DisplayPort nel dispositivo partner è stata configurata con l'assegnazione di pin in modo che il driver possa eseguire altre attività.
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_HPD_STATUS_CHANGED Notifica al driver client che lo stato di rilevamento del plug-hot della connessione DisplayPort è cambiato in modo che il driver possa eseguire altre attività.
  1. Chiamare UcmTcpciPortControllerStart per indicare a UcmTcpciCx di avviare il controller di porta. UcmTcpciCx presuppone il controllo di USB Type-C e Power Delivery. Dopo l'avvio del controller di porta, UcmTcpciCx può iniziare a inserire le richieste nella coda della richiesta hardware.

Gestire gli avvisi dall'hardware del controller di porta

Riferimento di esempio: Vedere ProcessAndSendAlerts in Alert.cpp

Il driver client deve gestire gli avvisi (o gli eventi) ricevuti dall'hardware del controller di porta e inviarli a UcmTcpciCx con dati correlati all'evento.

Quando si verifica un avviso hardware, l'hardware del controller di porta determina l'altezza del pin ALERT. In questo modo, l'ISR del driver client (registrato nel passaggio 2) viene richiamato. La routine consente di interrompere l'hardware in PASSIVE_LEVEL. La routine determina se un interruzione è un avviso dall'hardware del controller di porta; in tal caso, completa l'elaborazione dell'avviso e notifica a UcmTcpciCx chiamando UcmTcpciPortControllerAlert.

Prima di chiamare UcmTcpciPortControllerAlert, il client è responsabile dell'inclusione di tutti i dati pertinenti correlati all'avviso in una struttura di UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. Il client fornisce una matrice di tutti gli avvisi attivi perché è possibile che l'hardware possa affermare più avvisi contemporaneamente.

Ecco un flusso di esempio di attività per segnalare la modifica dello stato cc.

  1. Il client riceve un avviso hardware.

  2. Il client legge il registro ALERT e determina gli avvisi di tipo attivi.

  3. Il client legge il registro CC STATUS e descrive il contenuto del registro CC STATUS in UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. Il driver imposta il membro AlertType su UcmTcpciPortControllerAlertCCStatus e membro CCStatus del registro.

  4. Il client chiama UcmPortControllerAlert per inviare gli avvisi hardware della matrice a UcmTcpciCx.

  5. Il client cancella l'avviso (questo può verificarsi in qualsiasi momento dopo che il client recupera le informazioni sull'avviso)

Elaborare le richieste ricevute da UcmTcpciCx

Riferimento di esempio: Vedere PortControllerInterface.cpp

Nell'ambito dell'esecuzione del computer in stato, UcmTcpciCx deve inviare richieste al controller di porta. Ad esempio, deve impostare la TRANSMIT_BUFFER. Questa richiesta viene passata al driver client. Il driver imposta il buffer di trasmissione con i dettagli forniti da UcmTcpciCx. La maggior parte di queste richieste si traduce in una lettura hardware o in scrittura dal driver client. I comandi devono essere asincroni perché DPM non può bloccare l'attesa del completamento di un trasferimento hardware.

UcmTcpciCx invia i comandi come codice di controllo I/O che descrive l'operazione get/set richiesta dal driver client. Nella configurazione della coda del driver client il driver ha registrato la coda con UcmTcpciCx. UcmTcpciCx avvia l'inserimento di oggetti richiesta framework nella coda che richiede l'operazione dal driver. I codici di controllo I/O sono elencati nella tabella nel passaggio 4.

È responsabilità del conducente del client completare le richieste in modo tempestivo.

Il driver client chiama WdfRequestComplete nell'oggetto richiesta framework con stato di completamento al termine dell'operazione richiesta.

Il driver client potrebbe dover inviare una richiesta di I/O a un altro driver per eseguire l'operazione hardware. Nell'esempio, ad esempio, il driver invia una richiesta SPB al controller di porta connesso I2C. In tal caso, il driver non può inoltrare l'oggetto richiesta del framework ricevuto da UcmTcpciCx perché l'oggetto richiesta potrebbe non avere il numero corretto di posizioni dello stack in WDM IRP. Il driver client deve creare un altro oggetto richiesta framework e inoltrarlo a un altro driver. Il driver client può preallocare gli oggetti richiesti durante l'inizializzazione, anziché crearne uno ogni volta che ottiene una richiesta da UcmTcpciCx. Ciò è possibile perché UcmTcpciCx garantisce che vi sarà una sola richiesta in sospeso in qualsiasi momento.

Vedere anche