Utilisation des canaux USB

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

Obtention d’informations de canal

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

WdfUsbTargetPipeGetIoTarget
Retourne un handle vers l’objet cible d’e/s associé à un canal USB. Le pilote peut passer ce handle à 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 obtenir des informations connexes, consultez comment énumérer les canaux USB.

Lire à partir d’un canal

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

  • Lire des données de façon synchrone

    Pour lire des données de façon 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 retourne une fois l’opération d’e/s terminée.

  • Lire des données de façon asynchrone

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

  • Lire des données de façon 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 à partir d’un appareil qui fournit un flux d’entrée asynchrone et non sollicité. Par exemple, un pilote pour une carte d’interface réseau (NIC) peut utiliser un lecteur continu pour recevoir les 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 sur 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 des 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 d’e/s a lu les données, ou EvtUsbTargetPipeReadersFailed, si la cible d’e/s signale une erreur.

    Si vous ne fournissez pas le rappel EvtUsbTargetPipeReadersFailed facultatif, 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 les lectures, l’infrastructure envoie continuellement de nouvelles demandes pour récupérer à partir d’un échec de lecture.

    Une fois que le pilote a appelé WdfUsbTargetPipeConfigContinuousReader, il 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, le Framework signale une erreur si votre pilote spécifie un tampon de lecture qui n’est pas un multiple de la taille de paquet maximale du canal. Votre pilote peut appeler WdfUsbTargetPipeSetNoMaximumPacketSizeCheck pour désactiver ce test de 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 façon synchrone

    Pour écrire des données de façon synchrone sur 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 retourne une fois l’opération d’e/s terminée.

  • Écrire des données de façon asynchrone

    Pour écrire des données de façon asynchrone dans un canal d’entrée USB, votre pilote peut appeler la méthode WdfUsbTargetPipeFormatRequestForWrite pour générer une demande d’écriture. Le pilote peut ensuite appeler WdfRequestSend pour envoyer la demande de façon asynchrone.

Pour obtenir des informations connexes, consultez la page envoi de demandes de transfert en bloc USB.

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 façon 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 demande de façon synchrone ou asynchrone.

WdfUsbTargetPipeResetSynchronously
Envoie de façon 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 demande de façon synchrone ou asynchrone.

Si la cible USB de votre pilote termine une requête d’e/s avec une valeur d’état d’erreur, 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 demandes.

    Appelez WdfIoTargetStop avec l’indicateur WdfIoTargetCancelSentIo défini.

  2. Envoie de façon synchrone une demande d’abandon au canal.

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

  3. Envoie de façon synchrone une demande de réinitialisation au canal.

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

  4. Redémarrez le canal.

    Appelez WdfIoTargetStart.

  5. Renvoyez la requête d’e/s qui a échoué, ainsi que toutes les demandes d’e/s qui ont suivi la requête ayant échoué.

Après un nombre significatif 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 l’a pas terminée.

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

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

    Appelez WdfUsbTargetDeviceResetPortSynchronously.

  3. Redémarrez les canaux.

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

  4. Renvoyer la dernière demande d’e/s qui a échoué, ainsi que toutes les demandes d’e/s qui ont suivi la requête ayant échoué.

Pour obtenir des informations connexes, consultez Comment récupérer des 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 URBs, le pilote peut appeler les méthodes suivantes :

WdfUsbTargetPipeSendUrbSynchronously (KMDF uniquement)
Envoie de façon synchrone une requête d’e/s qui contient un URB.

WdfUsbTargetPipeFormatRequestForUrb (KMDF uniquement)
Met en forme une requête d’e/s qui contient un URB. Le pilote peut appeler WdfRequestSend pour envoyer la demande de façon synchrone ou asynchrone.

WdfUsbTargetPipeWdmGetPipeHandle (KMDF uniquement)
Retourne le handle du canal USBD d’un appareil. Certains URBs nécessitent ce handle.