Utilisation de canaux USB

L’infrastructure représente chaque canal d’une interface USB en tant qu’objet de canal USB framework. Lorsqu’un pilote configure un périphérique USB, l’infrastructure crée un objet de canal USB framework pour chaque canal dans chaque interface sélectionnée. Les méthodes d’objet pipe permettent à un pilote d’effectuer les opérations suivantes :

Obtention d’informations sur le canal

Après avoir appelé WdfUsbInterfaceGetConfiguredPipe pour obtenir un handle sur un objet de canal USB framework, votre pilote peut appeler les méthodes suivantes définies par l’objet de canal USB pour obtenir des informations sur le canal USB :

WdfUsbTargetPipeGetIoTarget
Retourne un handle à l’objet cible d’E/S associé à un canal USB. Le pilote peut passer cette poignée à WdfRequestSend.

WdfUsbTargetPipeGetInformation
Récupère des informations sur un canal USB et son point de terminaison.

WdfUsbTargetPipeGetType
Retourne le type d’un canal USB.

WdfUsbTargetPipeIsInEndpoint
Détermine si un canal USB est connecté à un point de terminaison d’entrée.

WdfUsbTargetPipeIsOutEndpoint
Détermine si un canal USB est connecté à un point de terminaison de sortie.

WDF_USB_PIPE_DIRECTION_IN
Détermine si un point de terminaison USB est un point de terminaison d’entrée.

WDF_USB_PIPE_DIRECTION_OUT
Détermine si un point de terminaison USB est un point de terminaison de sortie.

Pour plus d’informations, consultez Guide pratique pour énumérer des canaux USB.

Lecture à partir d’un canal

Pour lire des données à partir d’un canal d’entrée USB, votre pilote peut utiliser l’une ou l’autre des trois techniques suivantes :

  • Lire les données de manière synchrone

    Pour lire des données de manière synchrone à partir d’un canal d’entrée USB, votre pilote peut appeler la méthode WdfUsbTargetPipeReadSynchronously . Cette méthode génère et envoie une demande de lecture, et elle retourne une fois l’opération d’E/S terminée.

  • Lire les données de manière asynchrone

    Pour lire des données de manière asynchrone à partir d’un canal d’entrée USB, votre pilote peut appeler la méthode WdfUsbTargetPipeFormatRequestForRead pour générer une demande de lecture. Ensuite, le pilote peut appeler WdfRequestSend pour envoyer la requête de manière asynchrone (ou synchrone).

  • Lire des données de manière asynchrone et continue

    Un lecteur continu est un mécanisme fourni par l’infrastructure qui permet de s’assurer qu’une demande de lecture est toujours disponible pour un canal USB. Ce mécanisme garantit que le pilote sera toujours prêt à recevoir des données d’un appareil qui fournit un flux d’entrée asynchrone et non sollicité. Par exemple, un pilote pour une interface réseau carte peut utiliser un lecteur continu pour recevoir des données d’entrée.

    Pour configurer un lecteur continu pour un canal d’entrée, la fonction de rappel EvtDevicePrepareHardware du pilote doit appeler la méthode WdfUsbTargetPipeConfigContinuousReader . Cette méthode met en file d’attente un ensemble de demandes de lecture vers la cible d’E/S de l’appareil.

    En outre, la fonction de rappel EvtDeviceD0Entry du pilote doit appeler WdfIoTargetStart pour démarrer le lecteur continu et la fonction de rappel EvtDeviceD0Exit du pilote doit appeler WdfIoTargetStop pour arrêter le lecteur continu.

    Chaque fois que les données sont disponibles à partir de l’appareil, la cible d’E/S termine une demande de lecture et l’infrastructure appelle l’une des deux fonctions de rappel : EvtUsbTargetPipeReadComplete, si la cible E/S a correctement lu les données, ou EvtUsbTargetPipeReadersFailed, si la cible d’E/S signale une erreur.

    Si vous ne fournissez pas le rappel facultatif EvtUsbTargetPipeReadersFailed , le framework répond à une tentative de lecture ayant échoué en envoyant une autre demande de lecture. Par conséquent, si le bus est dans un état où il n’accepte pas de lectures, l’infrastructure envoie continuellement de nouvelles demandes pour récupérer après un échec de lecture.

    Une fois qu’un pilote a appelé WdfUsbTargetPipeConfigContinuousReader, le pilote ne peut pas utiliser WdfUsbTargetPipeReadSynchronously ou WdfRequestSend pour envoyer des demandes d’E/S au canal, sauf si la fonction de rappel EvtUsbTargetPipeReadersFailed du pilote est appelée et retourne FALSE.

Par défaut, l’infrastructure signale une erreur si votre pilote spécifie une mémoire tampon de lecture qui n’est pas un multiple de la taille maximale des paquets du canal. Votre pilote peut appeler WdfUsbTargetPipeSetNoMaximumPacketSizeCheck pour désactiver ce test des tailles de mémoire tampon de lecture.

Pour plus d’informations, consultez :

Écriture dans un canal

Pour écrire des données dans un canal de sortie USB, votre pilote peut utiliser l’une des techniques suivantes (ou les deux) :

  • Écrire des données de manière synchrone

    Pour écrire des données de manière synchrone dans un canal de sortie USB, votre pilote peut appeler la méthode WdfUsbTargetPipeWriteSynchronously . Cette méthode génère et envoie une demande d’écriture, et elle retourne une fois l’opération d’E/S terminée.

  • Écrire des données de manière asynchrone

    Pour écrire des données de manière asynchrone dans un canal d’entrée USB, votre pilote peut appeler la méthode WdfUsbTargetPipeFormatRequestForWrite pour générer une demande d’écriture. Ensuite, le pilote peut appeler WdfRequestSend pour envoyer la requête de manière asynchrone.

Pour plus d’informations, consultez Comment envoyer des demandes de transfert USB en bloc.

Arrêt et réinitialisation d’un canal

Votre pilote peut appeler les méthodes suivantes pour arrêter ou réinitialiser un canal USB :

WdfUsbTargetPipeAbortSynchronously
Envoie de manière synchrone une demande d’arrêt d’un canal USB.

WdfUsbTargetPipeFormatRequestForAbort
Met en forme une demande d’arrêt d’un canal USB. Le pilote peut appeler WdfRequestSend pour envoyer la requête de manière synchrone ou asynchrone.

WdfUsbTargetPipeResetSynchronously
Envoie de manière synchrone une demande de réinitialisation d’un canal USB.

WdfUsbTargetPipeFormatRequestForReset
Met en forme une demande de réinitialisation d’un canal USB. Le pilote doit appeler WdfRequestSend pour envoyer la requête de manière synchrone ou asynchrone.

Si la cible USB de votre pilote effectue une demande d’E/S avec une valeur d’erreur status, votre pilote doit effectuer les opérations suivantes :

  1. Arrêtez le canal et annulez toutes les demandes d’E/S supplémentaires que le pilote a envoyées à la cible USB, si la cible n’a pas terminé les requêtes.

    Appelez WdfIoTargetStop avec l’indicateur WdfIoTargetCancelSentIo défini.

  2. Envoyez de manière synchrone une demande d’abandon au canal.

    Appelez WdfUsbTargetPipeAbortSynchronously ou appelez WdfUsbTargetPipeFormatRequestForAbort suivi de WdfRequestSend avec l’indicateur WDF_REQUEST_SEND_OPTION_SYNCHRONOUS défini.

  3. Envoyez de manière synchrone une demande de réinitialisation au canal.

    Appelez WdfUsbTargetPipeResetSynchronously ou appelez WdfUsbTargetPipeFormatRequestForReset suivi de WdfRequestSend avec l’indicateur WDF_REQUEST_SEND_OPTION_SYNCHRONOUS défini.

  4. Redémarrez le canal.

    Appelez WdfIoTargetStart.

  5. Renvoyez à nouveau la demande d’E/S qui a échoué et toutes les demandes d’E/S qui ont suivi la demande ayant échoué.

Après un nombre important de défaillances multiples, le pilote doit tenter de réinitialiser le port USB en procédant comme suit :

  1. Arrêtez tous les canaux actifs et annulez toutes les demandes d’E/S supplémentaires que le pilote a envoyées à la cible USB de chaque canal, si la cible ne les a pas terminées.

    Pour chaque canal actif, appelez WdfIoTargetStop avec l’indicateur WdfIoTargetCancelSentIo défini.

  2. Envoyez de façon synchrone une demande de réinitialisation du port USB.

    Appelez WdfUsbTargetDeviceResetPortSynchronously.

  3. Redémarrez les canaux.

    Appelez WdfIoTargetStart pour chaque canal que le pilote a arrêté.

  4. Renvoyez la dernière demande d’E/S qui a échoué et toutes les demandes d’E/S qui ont suivi la demande ayant échoué.

Pour plus d’informations, consultez Comment récupérer à partir d’erreurs de canal USB.

Envoi d’un URB à un canal

Si votre pilote KMDF communique avec un canal USB en envoyant des demandes d’E/S qui contiennent des URB, le pilote peut appeler les méthodes suivantes :

WdfUsbTargetPipeSendUrbSynchronously (KMDF uniquement)
Envoie de façon synchrone une demande d’E/S qui contient un URB.

WdfUsbTargetPipeFormatRequestForUrb (KMDF uniquement)
Met en forme une demande d’E/S qui contient un URB. Le pilote peut appeler WdfRequestSend pour envoyer la requête de manière synchrone ou asynchrone.

WdfUsbTargetPipeWdmGetPipeHandle (KMDF uniquement)
Retourne la poignée de canal USBD d’un appareil. Certains URB nécessitent ce handle.