Compartir a través de


Recuperación de errores de canalización USB

Nota:

Este artículo es para desarrolladores de controladores de dispositivos. Si tiene dificultades con un dispositivo USB, consulte Solución de problemas comunes de USB.

En este artículo se proporciona información sobre los pasos que puede probar cuando se produce un error en una transferencia de datos a una canalización USB. En los mecanismos descritos en este artículo se tratan las operaciones de anulación, restablecimiento y ciclo de puertos en canalizaciones masivas, interrumpidas e isócrónicas.

Un controlador cliente USB se comunica con su dispositivo enviando transferencias de control al punto de conexión predeterminado; las transferencias de datos a puntos de conexión masivos, de interrupción e isócronos del dispositivo. En ocasiones, esas transferencias pueden producir un error debido a diversos motivos, como una condición de bloqueo en el punto de conexión. Si se produce un error en la transferencia, la canalización asociada no puede procesar las solicitudes hasta que se borre la condición de error.

Para las transferencias de control, la pila del controlador USB borra automáticamente las condiciones de error. En el caso de las transferencias de datos, el cliente debe realizar los pasos adecuados para recuperarse de la condición de error. Cuando se produce un error en una transferencia de datos, la pila del controlador USB notifica el error al controlador cliente a través de códigos de estado USBD con errores. En función del código de estado, el controlador puede proporcionar un mecanismo de recuperación de errores.

En este artículo se proporcionan instrucciones sobre la recuperación de errores a través de estas operaciones.

  • Restablecer la canalización USB
  • Restablecer el puerto USB al que está conectado el dispositivo
  • Ciclo del puerto USB para volver a enumerar la pila de dispositivos para el controlador de cliente

Para borrar una condición de error, comience con la operación de restablecimiento de canalización y realice operaciones más complejas, como reset-port y cycle-port, solo si es necesario.

Acerca de la coordinación de varios mecanismos de recuperación:

El controlador cliente debe coordinar las distintas operaciones para la recuperación y asegurarse de que solo se usa un método en un momento dado. Por ejemplo, considere un dispositivo con dos puntos de conexión: una interrupción masiva y otra. Después de enviar algunas solicitudes de transferencia de datos al dispositivo, el controlador observa que las solicitudes producen un error en la canalización masiva. Para recuperarse de esos errores, el controlador restablece la canalización masiva. Sin embargo, esa operación no resuelve los errores de transferencia y las transferencias masivas siguen produciendo errores. Por lo tanto, el controlador emite una solicitud para restablecer el puerto USB. Mientras tanto, las transferencias comienzan a producir un error en la canalización de interrupción y, a continuación, una solicitud de restablecimiento del dispositivo. Para recuperarse de los errores de transferencia de interrupción, el controlador emite una solicitud de restablecimiento de canalización en la canalización de interrupción. Si esas dos operaciones no están coordinadas, el controlador puede iniciar dos operaciones de restablecimiento de dispositivo simultáneamente, debido a errores en ambas canalizaciones. Esas operaciones simultáneas pueden ser problemáticas.

El controlador cliente debe asegurarse de que, en un momento dado, el controlador solo realiza una operación de puerto de restablecimiento o de ciclo. Durante esas operaciones, una operación de restablecimiento de canalización no debe estar en curso en ninguna canalización y el controlador no debe emitir una nueva solicitud de restablecimiento de canalización.

Lo que necesita saber

En este artículo se usa el marco de controlador en modo kernel (KMDF).

Requisitos previos

  • El controlador cliente debe haber creado el objeto de dispositivo de destino USB de marco.

    Si usa las plantillas USB que se proporcionan con Microsoft Visual Studio Professional 2012, el código de plantilla realiza esas tareas. El código de plantilla obtiene el identificador del objeto de dispositivo de destino y almacena en el contexto del dispositivo.

    Un controlador cliente KMDF debe obtener un identificador WDFUSBDEVICE llamando al método WdfUsbTargetDeviceCreateWithParameters . Para obtener más información, vea "Código fuente del dispositivo" en Descripción de la estructura de código del controlador de cliente USB (KMDF).

  • El controlador cliente debe tener un identificador para el objeto de canalización de destino de la plataforma. Para obtener más información, vea Cómo enumerar canalizaciones USB.

Paso 1: Determinar la causa de la condición de error

El controlador cliente inicia una transferencia de datos mediante un bloque de solicitud USB (URB). Una vez completada la solicitud, la pila del controlador USB devuelve un código de estado USBD que indica si la transferencia se realizó correctamente o si se produjo un error. En caso de error, el código USBD indica el motivo del error.

Los errores de transferencia pueden deberse a un error de dispositivo, como USBD_STATUS_STALL_PID o USBD_STATUS_BABBLE_DETECTED. También pueden producirse debido a un error notificado por el controlador de host, como USBD_STATUS_XACT_ERROR.

Paso 2: Determinar si el dispositivo está conectado al puerto

Antes de emitir cualquier solicitud que restablezca la canalización o el dispositivo, asegúrese de que el dispositivo está conectado. Puede determinar el estado conectado del dispositivo llamando al método WdfUsbTargetDeviceIsConnectedSynchronous .

Paso 3: Cancelar todas las transferencias pendientes a la canalización

Antes de enviar solicitudes que restablezcan la canalización o el puerto, cancele todas las solicitudes de transferencia pendientes a la canalización, que la pila del controlador USB aún no se ha completado. Puede cancelar las solicitudes de una de estas maneras:

  • Detenga el destino de E/S llamando al método WdfIoTargetStop .

    Para detener el destino de E/S, primero obtenga el identificador WDFIOTARGET asociado al objeto de canalización de marco mediante una llamada al método WdfUsbTargetPipeGetIoTarget . Mediante el identificador, llame a WdfIoTargetStop. En la llamada, establezca la acción en WdfIoTargetCancelSentIo (consulte WDF_IO_TARGET_SENT_IO_ACTION)** para indicar al marco que cancele todas las solicitudes que la pila del controlador USB no ha completado. Para las solicitudes que se han completado, el controlador cliente debe esperar a que la devolución de llamada de finalización se invoque por el marco.

  • Enviar una solicitud de canalización de anulación. Puede enviar la solicitud llamando a uno de estos métodos:

    • Llame al método WdfUsbTargetPipeAbortSynchronously .

      La llamada es sincrónica y solo se devuelve después de cancelar todas las solicitudes pendientes. WdfUsbTargetPipeAbortSynchronousmente toma un parámetro Request opcional. Se recomienda pasar un identificador WDFREQUEST a un objeto de solicitud de marco preasignado. El parámetro habilita el marco de uso del objeto de solicitud especificado en lugar de un objeto de solicitud interno al que el controlador no puede acceder. Este valor de parámetro garantiza que WdfUsbTargetPipeAbortSynchronously no produce un error debido a una memoria insuficiente.

    • Llame al método WdfUsbTargetPipeFormatRequestForAbort para dar formato a un objeto de solicitud para una solicitud de canalización de anulación y, a continuación, envíe la solicitud mediante una llamada al método WdfRequestSend .

      Si el controlador envía la solicitud de forma asincrónica, debe especificar un puntero al EVT_WDF_REQUEST_COMPLETION_ROUTINE del controlador que implementa el controlador. Para especificar el puntero, llame al método WdfRequestSetCompletionRoutine .

      El controlador puede enviar la solicitud de forma sincrónica especificando WDF_REQUEST_SEND_OPTION_SYNCHRONOUS como una de las opciones de solicitud en WdfRequestSend. Si envía la solicitud de forma sincrónica, llame a WdfUsbTargetPipeAbortSynchronously .

Paso 4: Restablecer la canalización USB

Inicie la recuperación de errores restableciendo la canalización. Puede enviar una solicitud de restablecimiento de canalización llamando a uno de estos métodos:

  • Llame a WdfUsbTargetPipeResetSynchronously para enviar una solicitud de canalización de restablecimiento sincrónicamente.

  • Llame al método WdfUsbTargetPipeFormatRequestForReset para dar formato a un objeto de solicitud para una solicitud de canalización de restablecimiento y, a continuación, envíe la solicitud mediante una llamada al método WdfRequestSend . Esas llamadas son similares a las de la solicitud de canalización de anulación, como se describe en el paso 3.

Nota:

No envíe ninguna solicitud de transferencia nueva hasta que se complete la operación de restablecimiento de canalización.

La solicitud de restablecimiento de canalización borra la condición de error en el dispositivo y el hardware del controlador de host. Para borrar el error del dispositivo, la pila del controlador USB envía una solicitud de control CLEAR_FEATURE al dispositivo mediante el selector de características ENDPOINT_HALT. El destinatario de la solicitud es el punto de conexión asociado a la canalización. Si se produjo la condición de error en una canalización isócrónica, la pila del controlador no realiza ninguna acción para borrar el dispositivo porque, en caso de errores, los puntos de conexión isócronos se borran automáticamente.

Para borrar el error del controlador de host, la pila del controlador borra el estado HALT de la canalización y restablece el botón de alternancia de datos de la canalización en 0.

Paso 5: Restablecer el puerto USB

Si una operación de restablecimiento de canalización no borra la condición de error y las transferencias de datos siguen fallando, envíe una solicitud de restablecimiento de puerto.

  1. Cancela todas las transferencias al dispositivo. Para ello, enumere todas las canalizaciones de la configuración actual y cancele las solicitudes pendientes programadas para cada canalización.

  2. Detenga el destino de E/S para el dispositivo.

    Llame al método WdfUsbTargetDeviceGetIoTarget para obtener un identificador WDFIOTARGET asociado al objeto de dispositivo de destino de la plataforma. A continuación, llame a WdfIoTargetStop y especifique el identificador WDFIOTARGET. En la llamada, establezca la acción en WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION).

  3. Envíe una solicitud reset-port llamando al método WdfUsbTargetDeviceResetPortSynchronously .

Una operación de restablecimiento de puerto hace que el dispositivo se vuelva a enumerar en el bus USB. La pila del controlador USB conserva la configuración del dispositivo después de la enumeración. El controlador cliente puede usar los identificadores de canalización obtenidos anteriormente porque la pila de controladores garantiza que los identificadores de canalización existentes permanezcan válidos.

No se puede restablecer una función individual de un dispositivo compuesto. En el caso de un dispositivo compuesto, cuando el controlador cliente de una función determinada envía una solicitud de restablecimiento de puerto, se restablece todo el dispositivo. Si el dispositivo USB mantiene el estado, esa solicitud de restablecimiento de puerto puede afectar a los controladores de cliente de otras funciones. Por lo tanto, es importante que el controlador cliente intente restablecer la canalización antes de restablecer el puerto.

Paso 6: Ciclo del puerto USB

Una operación de puerto de ciclo es similar al dispositivo que está desconectado y conectado de nuevo al puerto, excepto que el dispositivo no está desconectado eléctricamente. El dispositivo está desconectado y se vuelve a conectar en software. Esta operación conduce al restablecimiento y la enumeración del dispositivo. Como resultado, el Administrador de PnP vuelve a generar el nodo del dispositivo.

Si una operación de restablecimiento de puerto no borra la condición de error y las transferencias de datos siguen fallando, envíe una solicitud de puerto de ciclo.

  1. Cancele todas las transferencias al dispositivo. Asegúrese de cancelar la solicitud pendiente programada para cada canalización en la configuración actual (consulte el paso 3).

  2. Detenga el destino de E/S para el dispositivo.

    Llame al método WdfUsbTargetDeviceGetIoTarget para obtener un identificador WDFIOTARGET asociado al objeto de dispositivo de destino de la plataforma. A continuación, llame a WdfIoTargetStop y especifique el identificador WDFIOTARGET. En la llamada, establezca la acción en WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION).

  3. Envíe una solicitud cycle-port llamando a uno de estos métodos:

El controlador cliente puede enviar solicitudes de transferencia al dispositivo solo después de que se haya completado la solicitud de puerto de ciclo. Esto se debe a que el nodo del dispositivo se quita mientras la pila del controlador USB procesa la solicitud de puerto de ciclo.

La solicitud cycle-port hace que el dispositivo se vuelva a enumerar. La pila del controlador USB informa al Administrador de PnP de que el dispositivo se ha desconectado. El administrador de PnP desglosa la pila de dispositivos asociada al controlador cliente. La pila de controladores restablece el dispositivo, vuelve a enumerarlo en el bus USB e informa al Administrador de PnP de que se ha conectado un dispositivo. PnP Manager vuelve a generar la pila de dispositivos para el dispositivo USB.

Como resultado de la operación de puerto de ciclo, cualquier aplicación que tenga un identificador abierto al dispositivo obtiene una notificación de eliminación de dispositivos (si la aplicación se registró para dicha notificación). En respuesta, la aplicación podría notificar un mensaje desconectado del dispositivo al usuario. Dado que afecta a la experiencia del usuario, el controlador cliente debe optar por una solicitud de puerto de ciclo solo si otros mecanismos de recuperación no resuelven la condición de error.

De forma similar a la operación reset-port (descrita en el paso 6), para un dispositivo compuesto, la operación cycle-port afecta a todo el dispositivo y no a funciones individuales del dispositivo.