Écrire un pilote de connecteur USB Type-C

Vous devez écrire un pilote de connecteur USB Type-C dans les scénarios suivants :

  • Si votre matériel USB Type-C a la capacité de gérer la machine d’état de distribution d’alimentation( PD). Sinon, envisagez d’écrire un pilote de contrôleur de port USB Type-C. Pour plus d’informations, consultez Écrire un pilote de contrôleur de port USB Type-C.

  • Si votre matériel n’a pas de contrôleur incorporé. Sinon, chargez le pilote intégré fourni par Microsoft, UcmUcsi.sys. (Voir Pilote UCSI) pour les transports ACPI ou écrire un pilote client UCSI pour les transports non ACPI.

Résumé

  • Objet UCM utilisé par l’extension de classe et le pilote client
  • Services fournis par l’extension de classe UCM
  • Comportement attendu du pilote client

Spécifications officielles

S’applique à

  • Windows 10

Version WDF

  • KMDF version 1.15
  • UMDF version 2.15

API importantes

Décrit le gestionnaire de connecteurs USB (UCM) qui gère un connecteur USB Type-C et le comportement attendu d’un pilote de connecteur.

UCM est conçu à l’aide du modèle de pilote client d’extension de classe WDF. L’extension de classe (UcmCx) est un pilote WDF fourni par Microsoft qui fournit des interfaces que le pilote client peut appeler pour signaler des informations sur le connecteur. Le pilote client UCM utilise les interfaces matérielles du connecteur et tient l’extension de classe informée des événements qui se produisent sur le connecteur. À l’inverse, l’extension de classe appelle des fonctions de rappel implémentées par le pilote client en réponse aux événements du système d’exploitation.

Pour activer un connecteur USB Type-C sur un système, vous devez écrire le pilote client.

gestionnaire de connecteurs usb.

Avant de commencer

  • Installez la dernière version du Kit de pilotes Windows (WDK) sur votre ordinateur de développement. Le kit contient les fichiers d’en-tête et les bibliothèques requis pour l’écriture d’un pilote client UCM. En particulier, vous aurez besoin des éléments suivants :

    • Bibliothèque stub, (UcmCxstub.lib). La bibliothèque traduit les appels effectués par le pilote client et les transmet à UcmCx.

    • Fichier d’en-tête, UcmCx.h.

      Vous pouvez écrire un pilote client UCM qui s’exécute en mode utilisateur ou en mode noyau. Pour le mode utilisateur, il est lié à la bibliothèque UMDF 2.x ; pour le mode noyau, il s’agit de KMDF 1.15. Les interfaces de programmation sont identiques pour les deux modes.

      Configuration de Visual Studio pour ucm.

  • Déterminez si votre pilote client prendra en charge les fonctionnalités avancées du connecteur USB Type-C et de la distribution d’alimentation USB.

    Cette prise en charge vous permet de créer des appareils Windows avec des connecteurs USB Type-C, des stations d’accueil et des accessoires USB Type-C et des chargeurs USB Type-C. Le pilote client signale des événements de connecteur qui permettent au système d’exploitation d’implémenter des stratégies relatives à l’USB et à la consommation d’énergie dans le système.

  • Installez Windows 10 pour les éditions de bureau (Famille, Professionnel, Entreprise et Éducation) sur votre ordinateur cible ou Windows 10 Mobile avec un connecteur USB Type-C.

  • Familiarisez-vous avec UCM et comment il interagit avec d’autres pilotes Windows. Consultez Architecture : conception USB Type-C pour un système Windows.

  • Familiarisez-vous avec Windows Driver Foundation (WDF). Lecture recommandée : Développement de pilotes avec Windows Driver Foundation, écrit par Penny Orwick et Guy Smith.

Résumé des services fournis par l’extension de classe UCM

L’extension de classe UCM tient le système d’exploitation informé des modifications apportées au rôle des données et de l’alimentation, des niveaux de charge et du contrat pdd négocié. Pendant que le pilote client interagit avec le matériel, il doit notifier l’extension de classe lorsque ces modifications se produisent. L’extension de classe fournit un ensemble de méthodes que le pilote client peut utiliser pour envoyer les notifications (décrites dans cette rubrique). Voici les services fournis :

Configuration du rôle de données

Sur les systèmes USB Type-C, le rôle de données (hôte ou fonction) dépend de la status des broches CC du connecteur. Votre pilote client lit la ligne CC (voir Architecture : Conception USB Type-C pour un système Windows) status à partir de votre contrôleur de port pour déterminer si le port a été résolu en port UFP (Upstream Facing Port) ou En aval (UFP). Il signale ces informations à l’extension de classe afin qu’elle puisse signaler le rôle actuel aux pilotes de commutateur de rôle USB.

Notes

Les pilotes de commutateur de rôle USB sont utilisés sur les systèmes Windows 10 Mobile. Sur Windows 10 pour les systèmes d’éditions de bureau, la communication entre l’extension de classe et les pilotes de commutateur de rôle est facultative. Ces systèmes peuvent ne pas utiliser de contrôleur à double rôle, auquel cas les pilotes de commutateur de rôle ne sont pas utilisés.

Rôle d’alimentation et chargement

Votre pilote client lit la publication usb type-C actuelle ou négocie un contrat d’alimentation PD avec le connecteur partenaire.

  • Sur un système Windows 10 Mobile, la décision de choisir le chargeur approprié est assistée par logiciel. Le pilote client signale les informations de contrat à l’extension de classe afin qu’il puisse envoyer les niveaux de facturation au pilote d’arbitrage de facturation (CAD.sys). LA CAO sélectionne le niveau actuel à utiliser et transfère les informations de niveau de charge au sous-système de batterie.
  • Sur un système Windows 10 pour les éditions de bureau, le chargeur approprié est sélectionné par le matériel. Le pilote client peut choisir d’obtenir ces informations et de les transférer à l’extension de classe. Cette logique peut également être implémentée par un autre pilote.

Changements de rôle de données et d’alimentation

Une fois qu’un contrat pdD a été négocié, les rôles de données et les rôles d’alimentation peuvent changer. Cette modification peut être initiée par votre pilote client ou le connecteur partenaire. Le pilote client signale ces informations à l’extension de classe, afin qu’il puisse reconfigurer les éléments en conséquence.

Mise à jour du rôle de données et/ou d’alimentation

Le système d’exploitation peut décider que le rôle de données actuel n’est pas correct. Dans ce cas, l’extension de classe appelle la fonction de rappel de votre pilote pour effectuer les opérations d’échange de rôle nécessaires.

Le Gestionnaire de stratégie USB Type-C fourni par Microsoft surveille les activités des connecteurs USB Type-C. Windows, version 1809, présente un ensemble d’interfaces de programmation que vous pouvez utiliser pour écrire un pilote client dans Policy Manager. Le pilote client peut participer aux décisions de stratégie pour les connecteurs USB Type-C. Avec cet ensemble, vous pouvez choisir d’écrire un pilote d’exportation en mode noyau ou un pilote en mode utilisateur. Pour plus d’informations, consultez Écrire un pilote client USB Type-C Policy Manager.

Comportement attendu du pilote client

Votre pilote client est responsable des tâches suivantes :

  • Détectez les modifications sur la ligne CC et déterminez le type de partenaire, tel que UFP, DFP, etc. Pour ce faire, le pilote doit implémenter la machine à états Type C complète, comme défini dans la spécification USB Type-C.
  • Configurez votre Mux en fonction de l’orientation détectée sur la ligne CC. Cela inclut l’activation de votre émetteur/récepteur pd et la gestion et la réponse aux messages pdd. Pour ce faire, le pilote doit implémenter les machines d’état complètes du récepteur pd et de l’émetteur, comme défini dans la spécification USB Power Delivery 2.0.
  • Prenez des décisions en matière de stratégie de pdD, telles que la négociation d’un contrat (en tant que source ou récepteur), les échanges de rôles, etc. Le pilote client est chargé de déterminer le contrat le plus approprié.
  • Publiez et négociez d’autres modes, puis configurez le Mux si un autre mode est détecté. Le pilote client est chargé de décider du mode alternatif à négocier.
  • Contrôle de VBus/VConn sur le connecteur.

1. Initialiser l’objet connecteur UCM (UCMCONNECTOR)

L’objet de connecteur UCM (UCMCONNECTOR) représente le connecteur USB Type-C et est le handle main entre l’extension de classe UCM et le pilote client. L’objet suit les modes de fonctionnement et les fonctionnalités d’approvisionnement en alimentation du connecteur.

Voici le résumé de la séquence dans laquelle le pilote client récupère un handle UCMCONNECTOR pour le connecteur. Effectuer ces tâches dans votre pilote

  1. Appelez UcmInitializeDevice en passant la référence à une structure UCM_MANAGER_CONFIG . Le pilote doit appeler cette méthode dans la fonction de rappel EVT_WDF_DRIVER_DEVICE_ADD avant d’appeler WdfDeviceCreate.

  2. Spécifiez les paramètres d’initialisation du connecteur USB Type-C dans une structure de UCM_CONNECTOR_TYPEC_CONFIG . Cela inclut le mode de fonctionnement du connecteur, qu’il s’agisse d’un port orienté vers l’aval, d’un port amont orienté vers l’amont ou d’un double rôle. Il spécifie également les niveaux actuels USB Type-C lorsque le connecteur est une source d’alimentation. Un connecteur USB Type-C peut être conçu de telle sorte qu’il puisse agir sur une prise audio de 3,5 mm. Si le matériel prend en charge la fonctionnalité, l’objet connecteur doit être initialisé en conséquence.

    Dans la structure, vous devez également inscrire la fonction de rappel du pilote client pour la gestion des rôles de données.

    Cette fonction de rappel est associée à l’objet connecteur, qui est appelé par l’extension de classe UCM. Cette fonction doit être implémentée par le pilote client.

    EVT_UCM_CONNECTOR_SET_DATA_ROLE Échange le rôle de données du connecteur vers le rôle spécifié lorsqu’il est attaché à un connecteur partenaire.

  3. Si votre pilote client souhaite être compatible pd, c’est-à-dire gérer l’implémentation matérielle Power Delivery 2.0 du connecteur, vous devez également initialiser une structure de UCM_CONNECTOR_PD_CONFIG qui spécifie les paramètres d’initialisation pd. Cela inclut le flux d’alimentation, que le connecteur soit un récepteur d’alimentation ou une source d’alimentation.

    Dans la structure, vous devez également inscrire la fonction de rappel du pilote client pour la gestion des rôles d’alimentation.

    Cette fonction de rappel est associée à l’objet connecteur, qui est appelé par l’extension de classe UCM. Cette fonction doit être implémentée par le pilote client.

    EVT_UCM_CONNECTOR_SET_POWER_ROLE Définit le rôle d’alimentation du connecteur sur le rôle spécifié lorsqu’il est attaché à un connecteur partenaire.

  4. Appelez UcmConnectorCreate et récupérez un handle UCMCONNECTOR pour le connecteur. Veillez à appeler cette méthode une fois que le pilote client a créé l’objet de périphérique framework en appelant WdfDeviceCreate. Un endroit approprié pour cet appel peut se trouver dans le EVT_WDF_DEVICE_PREPARE_HARDWARE du conducteur ou EVT_WDF_DEVICE_D0_ENTRY.

EVT_UCM_CONNECTOR_SET_DATA_ROLE     EvtSetDataRole;

NTSTATUS
EvtDevicePrepareHardware(
    WDFDEVICE Device,
    WDFCMRESLIST ResourcesRaw,
    WDFCMRESLIST ResourcesTranslated
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_CONTEXT devCtx;
    UCM_MANAGER_CONFIG ucmCfg;
    UCM_CONNECTOR_CONFIG connCfg;
    UCM_CONNECTOR_TYPEC_CONFIG typeCConfig;
    UCM_CONNECTOR_PD_CONFIG pdConfig;
    WDF_OBJECT_ATTRIBUTES attr;
    PCONNECTOR_CONTEXT connCtx;

    UNREFERENCED_PARAMETER(ResourcesRaw);
    UNREFERENCED_PARAMETER(ResourcesTranslated);

    TRACE_FUNC_ENTRY();

    devCtx = GetDeviceContext(Device);

    if (devCtx->Connector)
    {
        goto Exit;
    }

    //
    // Initialize UCM Manager
    //
    UCM_MANAGER_CONFIG_INIT(&ucmCfg);

    status = UcmInitializeDevice(Device, &ucmCfg);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(
            "UcmInitializeDevice failed with %!STATUS!.",
            status);
        goto Exit;
    }

    TRACE_INFO("UcmInitializeDevice() succeeded.");

    //
    // Create a USB Type-C connector #0 with PD
    //
    UCM_CONNECTOR_CONFIG_INIT(&connCfg, 0);

    UCM_CONNECTOR_TYPEC_CONFIG_INIT(
        &typeCConfig,
        UcmTypeCOperatingModeDrp,
        UcmTypeCCurrentDefaultUsb | UcmTypeCCurrent1500mA | UcmTypeCCurrent3000mA);

    typeCConfig.EvtSetDataRole = EvtSetDataRole;

    UCM_CONNECTOR_PD_CONFIG_INIT(&pdConfig, UcmPowerRoleSink | UcmPowerRoleSource);

    connCfg.TypeCConfig = &typeCConfig;
    connCfg.PdConfig = &pdConfig;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CONNECTOR_CONTEXT);

    status = UcmConnectorCreate(Device, &connCfg, &attr, &devCtx->Connector);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(
            "UcmConnectorCreate failed with %!STATUS!.",
            status);
        goto Exit;
    }

    connCtx = GetConnectorContext(devCtx->Connector);

    UcmEventInitialize(&connCtx->EventSetDataRole);

    TRACE_INFO("UcmConnectorCreate() succeeded.");

Exit:

    TRACE_FUNC_EXIT();
    return status;
}

2. Signaler l’événement d’attachement du connecteur partenaire

Le pilote client doit appeler UcmConnectorTypeCAttach lorsqu’une connexion à un connecteur partenaire est détectée. Cet appel avertit l’extension de classe UCM, qui avertit davantage le système d’exploitation. À ce stade, le système peut commencer à charger au niveau USB Type-C.

L’extension de classe UCM avertit également les pilotes de commutateur de rôle (URS) USB. En fonction du type de partenaire, URS configure le contrôleur dans le rôle hôte ou le rôle de fonction. Avant d’appeler cette méthode, assurez-vous que le Mux sur votre système est configuré correctement. Sinon, si le système est en rôle de fonction, il se connecte à une vitesse incorrecte (vitesse élevée au lieu de SuperSpeed).

        UCM_CONNECTOR_TYPEC_ATTACH_PARAMS attachParams;

        UCM_CONNECTOR_TYPEC_ATTACH_PARAMS_INIT(
            &attachParams,
            UcmTypeCPortStateDfp);
        attachParams.CurrentAdvertisement = UcmTypeCCurrent1500mA;

        status = UcmConnectorTypeCAttach(
                    Connector,
                    &attachParams);
        if (!NT_SUCCESS(status))
        {
            TRACE_ERROR(
                "UcmConnectorTypeCAttach() failed with %!STATUS!.",
                status);
            goto Exit;
        }

        TRACE_INFO("UcmConnectorTypeCAttach() succeeded.");

3. Signaler les modifications de publicité USB Type-C

Dans l’événement d’attachement initial, le connecteur partenaire envoie une publicité actuelle. Si la publicité spécifie le niveau actuel du connecteur partenaire lorsque le partenaire est un port USB Type C en aval. Sinon, la publicité spécifie le niveau actuel du connecteur local, représenté par le handle UCMCONNECTOR (connecteur local). Cette publicité initiale peut changer pendant la durée de vie de la connexion. Ces modifications doivent être surveillées par le pilote client.

Si le connecteur local est le récepteur d’alimentation et que la publicité actuelle change, le pilote client doit détecter les modifications dans la publicité actuelle et les signaler à l’extension de classe. Sur Windows 10 Mobile systèmes, ces informations sont utilisées par CAD.sys et le sous-système de batterie pour ajuster la quantité de courant qu’elles utilisent à partir de la source. Pour signaler la modification du niveau actuel à l’extension de classe, le pilote client doit appeler UcmConnectorTypeCCurrentAdChanged.

4. Signaler le nouveau contrat de pdd négocié

Si votre connecteur prend en charge la PD, après l’événement d’attachement initial, des messages PD sont transférés entre le connecteur et son connecteur partenaire. Entre les deux partenaires, un contrat pdd est négocié qui détermine les niveaux actuels que le connecteur peut dessiner ou permettre au partenaire de dessiner. Chaque fois que le contrat PD change, le pilote client doit appeler ces méthodes pour signaler la modification à l’extension de classe.

  • Le pilote client doit appeler ces méthodes chaque fois qu’il obtient une publication de fonctionnalités sources (non sollicitée ou non) du partenaire. Le connecteur local (récepteur) reçoit une publicité non sollicitée du partenaire uniquement lorsque le partenaire est la source. En outre, le connecteur local peut demander explicitement des fonctionnalités source au partenaire capable d’être la source (même lorsque le partenaire est actuellement le récepteur). Cet échange s’effectue en envoyant un message Get_Source_Caps au partenaire.
  • À l’inverse, le pilote client doit appeler ces méthodes chaque fois que le connecteur local (source) publie des fonctionnalités sources auprès du partenaire. En outre, lorsque le connecteur local reçoit un message Get_Source_Caps du partenaire, il doit répondre avec les fonctionnalités sources du connecteur local.

5. Rapport de charge de la batterie status

Le pilote client peut notifier l’extension de classe UCM si le niveau de charge n’est pas adéquat. L’extension de classe signale ces informations au système d’exploitation. Le système utilise ces informations pour afficher une notification de l’utilisateur indiquant que le chargeur ne charge pas le système de manière optimale. Les status de charge peuvent être signalées par les méthodes suivantes :

Ces méthodes spécifient l’état de charge. Si les niveaux signalés sont UcmChargingStateSlowCharging ou UcmChargingStateTrickleCharging ( voir UCM_CHARGING_STATE), le système d’exploitation affiche la notification utilisateur.

6. Signaler des événements PR_Swap/DR_Swap

Si le connecteur reçoit un message d’échange de rôle d’alimentation (PR_Swap) ou de rôle de données (DR_Swap) du partenaire, le pilote client doit notifier l’extension de classe UCM.

  • UcmConnectorDataDirectionChanged

    Appelez cette méthode après qu’un message de DR_Swap pdD a été traité. Après cet appel, le système d’exploitation signale le nouveau rôle à URS, qui supprime les pilotes de rôle existants et charge les pilotes pour le nouveau rôle.

  • UcmConnectorPowerDirectionChanged

    Appelez cette méthode après qu’un message de PR_Swap pdD a été traité. Après un PR_Swap, le contrat pdd doit être renégocié. Le pilote client doit signaler cette négociation de contrat PD en appelant les méthodes décrites à l’étape 4.

7. Implémenter des fonctions de rappel pour gérer les demandes d’échange de rôle d’alimentation et de données

L’extension de classe UCM peut recevoir des demandes de modification des données ou de direction d’alimentation du connecteur. Dans ce cas, il appelle l’implémentation du pilote client de EVT_UCM_CONNECTOR_SET_DATA_ROLE et EVT_UCM_CONNECTOR_SET_POWER_ROLE fonctions de rappel (si le connecteur implémente pdd). Le pilote client a précédemment inscrit ces fonctions dans son appel à UcmConnectorCreate.

Le pilote client effectue des opérations d’échange de rôle à l’aide d’interfaces matérielles.

  • EVT_UCM_CONNECTOR_SET_DATA_ROLE

    Dans l’implémentation du rappel, le pilote client est censé :

    1. Envoyez un message pd DR_Swap au partenaire de port.
    2. Appelez UcmConnectorDataDirectionChanged pour informer l’extension de classe que la séquence de messages s’est terminée avec succès ou a échoué.
    EVT_UCM_CONNECTOR_SET_DATA_ROLE     EvtSetDataRole;
    
    NTSTATUS
    EvtSetDataRole(
        UCMCONNECTOR  Connector,
        UCM_TYPE_C_PORT_STATE DataRole
        )
    {
        PCONNECTOR_CONTEXT connCtx;
    
        TRACE_INFO("EvtSetDataRole(%!UCM_TYPE_C_PORT_STATE!) Entry", DataRole);
    
        connCtx = GetConnectorContext(Connector);
    
        TRACE_FUNC_EXIT();
    
        return STATUS_SUCCESS;
    }
    
  • EVT_UCM_CONNECTOR_SET_POWER_ROLE

    Dans l’implémentation du rappel, le pilote client est censé :

    1. Envoyez un message pd PR_Swap au port-partner.
    2. Appelez UcmConnectorPowerDirectionChanged pour informer l’extension de classe que la séquence de messages s’est terminée avec succès ou sans succès.
    EVT_UCM_CONNECTOR_SET_POWER_ROLE     EvtSetPowerRole;
    
    NTSTATUS
    EvtSetPowerRole(
        UCMCONNECTOR Connector,
        UCM_POWER_ROLE PowerRole
        )
    {
        PCONNECTOR_CONTEXT connCtx;
    
        TRACE_INFO("EvtSetPowerRole(%!UCM_POWER_ROLE!) Entry", PowerRole);
    
        connCtx = GetConnectorContext(Connector);
    
        //PR_Swap operation.
    
        TRACE_FUNC_EXIT();
    
        return STATUS_SUCCESS;
    }
    

Notes

Le pilote client peut appeler UcmConnectorDataDirectionChanged et UcmConnectorPowerDirectionChanged de manière asynchrone, ce qui n’est pas à partir du thread de rappel. Dans une implémentation classique, l’extension de classe appelle les fonctions de rappel qui amènent le pilote client à lancer une transaction matérielle pour envoyer le message. Une fois la transaction terminée, le matériel avertit le pilote. Le pilote appelle ces méthodes pour notifier l’extension de classe.

8. Signaler l’événement de détachement du connecteur partenaire

Le pilote client doit appeler UcmConnectorTypeCDetach lorsque la connexion à un connecteur partenaire se termine. Cet appel avertit l’extension de classe UCM, qui avertit davantage le système d’exploitation.

Exemple de cas d’usage : Appareil mobile connecté à un PC

Lorsqu’un appareil exécutant Windows 10 Mobile est connecté à un PC exécutant Windows 10 pour les éditions de bureau via une connexion USB Type C, le système d’exploitation s’assure que l’appareil mobile est le port UFP (Upstream Face Port), car MTP fonctionne uniquement dans cette direction. Dans ce scénario, voici la séquence de correction de rôle de données :

  1. Le pilote client, en cours d’exécution sur l’appareil mobile, signale un événement d’attachement en appelant UcmConnectorTypeCAttach et signale le connecteur partenaire en tant que port UFP (Downstream Facing Port).
  2. Le pilote client signale le contrat PD en appelant UcmConnectorPdPartnerSourceCaps et UcmConnectorPdConnectionStateChanged.
  3. L’extension de classe UCM avertit les pilotes côté périphérique USB, ce qui entraîne la réponse de ces pilotes à l’énumération à partir de l’hôte. Les informations du système d’exploitation sont échangées via USB.
  4. L’extension de classe UCM UcmCx appelle les fonctions de rappel du pilote client pour modifier les rôles : EVT_UCM_CONNECTOR_SET_DATA_ROLE et EVT_UCM_CONNECTOR_SET_POWER_ROLE.

Notes

Si deux appareils Windows 10 Mobile sont connectés l’un à l’autre, un échange de rôle n’est pas effectué et l’utilisateur est averti que la connexion n’est pas valide.