Enumeración dinámica

La enumeración dinámica es la capacidad de un controlador para detectar y notificar los cambios en el número y el tipo de dispositivos que están conectados al sistema mientras se ejecuta el sistema.

Los controladores de bus deben usar la enumeración dinámica si el número o los tipos de dispositivos que están conectados al dispositivo primario dependen de la configuración de un sistema. Algunos de estos dispositivos pueden estar siempre conectados al sistema y algunos podrían estar conectados y desconectados mientras el sistema se está ejecutando.

Por ejemplo, el número y el tipo de dispositivos que están conectados al bus PCI de un sistema dependen del sistema, pero son permanentes a menos que un usuario apague la energía, abra la caja y agregue o quite un dispositivo mediante un destornillador. Por otro lado, un usuario puede agregar o quitar dispositivos USB conectando o desconectando un cable mientras el sistema se está ejecutando.

Listas secundarias dinámicas

El marco permite a los controladores admitir la enumeración dinámica proporcionando objetos de lista secundaria del marco. Cada objeto de lista secundaria representa una lista de dispositivos secundarios que están conectados a un dispositivo primario. El controlador de bus del dispositivo primario debe identificar los dispositivos secundarios del elemento primario, agregarlos a la lista de elementos secundarios del dispositivo primario y crear un objeto de dispositivo físico (PDO) para cada elemento secundario.

Cada vez que un controlador crea un objeto de dispositivo de marco que representa un FDO para un dispositivo, el marco crea una lista secundaria vacía y predeterminada para el dispositivo. El controlador puede obtener un identificador para la lista secundaria predeterminada de un dispositivo llamando a WdfFdoGetDefaultChildList. Normalmente, si está escribiendo un controlador de bus que enumera los elementos secundarios de un dispositivo, el controlador puede agregar elementos secundarios a la lista secundaria predeterminada. Si necesita crear listas secundarias adicionales, el controlador puede llamar a WdfChildListCreate.

Para que un controlador pueda usar una lista secundaria, debe configurar el objeto child-list inicializando una estructura de WDF_CHILD_LIST_CONFIG y pasando la estructura a WdfFdoInitSetDefaultChildListConfig, para la lista secundaria predeterminada, o a WdfChildListCreate, para listas secundarias adicionales.

Descripciones de elementos secundarios dinámicos

Cada vez que un controlador de bus identifica un dispositivo secundario, debe agregar la descripción del dispositivo secundario a una lista secundaria. Una descripción secundaria consta de una descripción de identificación necesaria y una descripción de dirección opcional.

Descripción de la identificación Una descripción de identificación es una estructura que contiene información que identifica de forma única cada dispositivo que el controlador enumera. El controlador define esta estructura, pero su primer miembro debe ser una estructura WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER .

Normalmente, una descripción de identificación contiene las cadenas de identificación del dispositivo, posiblemente un número de serie e información sobre la ubicación del dispositivo en el bus, como un número de ranura.

El controlador puede proporcionar el siguiente conjunto de funciones de devolución de llamada, que permiten al marco manipular la información en una descripción de identificación:

Normalmente, deberá proporcionar estas funciones de devolución de llamada si las estructuras de descripción de identificación del controlador contienen punteros a búferes asignados dinámicamente. Para obtener más información sobre el propósito de estas funciones de devolución de llamada, consulte sus páginas de referencia.

Descripción de la dirección Una descripción de dirección es una estructura que contiene información que requiere el controlador para que pueda acceder al dispositivo en su bus, si la información puede cambiar mientras el dispositivo está conectado. El controlador define esta estructura, pero su primer miembro debe ser una estructura WDF_CHILD_ADDRESS_DESCRIPTION_HEADER .

Las descripciones de direcciones son opcionales. Si la información de dirección de un dispositivo no puede cambiar entre el momento en que se conecta el dispositivo y la hora en que está desconectada, toda la información de dirección del dispositivo se puede almacenar en una descripción de identificación. Por ejemplo, los controladores USB asignan direcciones a los dispositivos cuando los dispositivos están conectados y estas direcciones no cambian.

Por otro lado, algunos autobuses usan información de direccionamiento que puede cambiar. Por ejemplo, el bus IEEE 1394 usa un "recuento de generación", que es el número de restablecimientos de bus que se han producido. Cada solicitud de E/S asincrónica a un dispositivo IEEE 1394 debe incluir el recuento de generación. Dado que esta información de dirección puede cambiar, el controlador debe almacenarla en una descripción de dirección.

El controlador puede proporcionar el siguiente conjunto de funciones de devolución de llamada para manipular la información en una descripción de dirección:

Normalmente, deberá proporcionar estas funciones de devolución de llamada si las estructuras de descripción de direcciones del controlador contienen punteros a búferes asignados dinámicamente. Para obtener más información sobre el propósito de estas funciones de devolución de llamada, consulte sus páginas de referencia.

Agregar dispositivos a una lista secundaria dinámica

Cuando el marco llama a la función de devolución de llamada EvtDriverDeviceAdd del controlador de bus, la función de devolución de llamada debe llamar a WdfDeviceCreate para crear un FDO para el dispositivo primario, que suele ser un adaptador de bus. Para obtener más información sobre cómo crear un FDO, consulte Creating Device Objects in a Function Driver. A continuación, el controlador debe enumerar los elementos secundarios del dispositivo primario y agregar los elementos secundarios a una lista secundaria.

Opcionalmente, el controlador puede llamar a WdfDeviceSetBusInformationForChildren para proporcionar al marco información sobre el bus. Se recomienda hacerlo porque facilita que los dispositivos secundarios y las aplicaciones identifiquen el bus.

Para agregar elementos secundarios a una lista secundaria, el controlador debe llamar a WdfChildListAddOrUpdateChildDescriptionAsPresent para cada dispositivo secundario que encuentre. Esta llamada informa al marco de trabajo de que un controlador ha detectado un dispositivo secundario que está conectado a un dispositivo primario. Cuando el controlador llama a WdfChildListAddOrUpdateChildDescriptionAsPresent, proporciona una descripción de identificación y, opcionalmente, una descripción de dirección.

Una vez que el controlador llama a WdfChildListAddOrUpdateChildDescriptionAsPresent para notificar un nuevo dispositivo, el marco informa al administrador de PnP de que existe el nuevo dispositivo. A continuación, el administrador de PnP crea una pila de dispositivos y una pila de controladores para el nuevo dispositivo. Como parte de este proceso, el marco llama a la función de devolución de llamada EvtChildListCreateDevice del controlador de bus. Esta función de devolución de llamada debe llamar a WdfDeviceCreate para crear un PDO para el nuevo dispositivo.

Normalmente, varios dispositivos secundarios están conectados a un elemento primario, por lo que el controlador de bus tendrá que llamar a WdfChildListAddOrUpdateChildDescriptionAsPresent varias veces. La manera más eficaz de hacerlo es la siguiente:

  1. Llame a WdfChildListBeginScan.

  2. Llame a WdfChildListAddOrUpdateChildDescriptionAsPresent para cada dispositivo secundario.

  3. Llame a WdfChildListEndScan.

Si rodea la enumeración dinámica del controlador con llamadas a WdfChildListBeginScan y WdfChildListEndScan, el marco almacena todos los cambios en la lista secundaria y notifica al administrador de PnP los cambios cuando el controlador llama a WdfChildListEndScan. Más adelante, el marco llama a la función de devolución de llamada EvtChildListCreateDevice del controlador de bus para cada dispositivo de la lista secundaria. Esta función de devolución de llamada llama a WdfDeviceCreate para crear un PDO para cada dispositivo nuevo.

Cuando el controlador llama a WdfChildListBeginScan, el marco marca todos los dispositivos notificados anteriormente como ya no están presentes. Por lo tanto, el controlador debe llamar a WdfChildListAddOrUpdateChildDescriptionAsPresent para todos los elementos secundarios que el controlador pueda detectar, no solo los elementos secundarios recién detectados. Para agregar un único elemento secundario a una lista secundaria, el controlador puede realizar una sola llamada a WdfChildListUpdateAllChildDescriptionsAsPresent sin llamar primero a WdfChildListBeginScan.

Actualización de una lista secundaria dinámica

Hay dos maneras comunes de actualizar la información en una lista secundaria dinámica:

  1. Cuando un dispositivo primario recibe una interrupción que indica la llegada o eliminación de un elemento secundario, la función de devolución de llamada EvtInterruptDpc del controlador llama a WdfChildListAddOrUpdateChildDescriptionAsPresent si se ha conectado un dispositivo o WdfChildListUpdateUpdateDescriptionAsMissing si un dispositivo se ha desconectado.

  2. El controlador puede proporcionar una función de devolución de llamada EvtChildListScanForChildren , que el marco llama cada vez que el dispositivo primario entra en su estado de trabajo (D0). Esta función de devolución de llamada debe enumerar todos los dispositivos secundarios llamando a WdfChildListBeginScan, WdfChildListAddOrUpdateChildDescriptionAsPresent (o WdfChildListUpdateAllChildDescriptionsAsPresent) y WdfChildListEndScan.

Puede usar una o ambas técnicas en el controlador.

Recorrer una lista de elementos secundarios dinámicos

Si desea que el controlador examine el contenido de una lista secundaria, puede recorrer la lista mediante una de las técnicas siguientes:

  • Para obtener el contenido de cada descripción del dispositivo secundario, de uno en uno, el controlador puede:

    1. Llame a WdfChildListBeginIteration.
    2. Llame a WdfChildListRetrieveNextDevice, tantas veces como sea necesario.
    3. Llame a WdfChildListEndIteration.

    Al llamar a WdfChildListBeginIteration, el controlador especifica una marca con tipo WDF_RETRIEVE_CHILD_FLAGS que indica si el marco debe recuperar todas las descripciones del dispositivo o solo un subconjunto. Cuando WdfChildListRetrieveNextDevice encuentra una coincidencia, recupera la identificación y las descripciones de direcciones del dispositivo secundario, además de un identificador para su objeto de dispositivo.

  • Si necesita obtener la descripción de la dirección que se encuentra actualmente en una descripción del dispositivo secundario, el controlador puede llamar a WdfChildListRetrieveAddressDescription, especificando una descripción de identificación. El marco recorre la lista secundaria hasta que encuentra un dispositivo secundario con una descripción de identificación coincidente y, a continuación, recupera la descripción de la dirección.

  • Si necesita obtener un identificador para el objeto de dispositivo de marco asociado a un dispositivo secundario determinado, el controlador puede llamar a WdfChildListRetrievePdo. El marco recorre la lista secundaria hasta que encuentra un dispositivo secundario con una descripción de identificación coincidente y, a continuación, devuelve un identificador de objeto de dispositivo. Asegúrese de encapsular la llamada con WdfChildListBeginIteration y WdfChildListEndIteration para proteger al autor de la llamada de la eliminación repentina de PnP del PDO en otro subproceso.

Acceso a las descripciones de identificación y dirección de un PDO

El controlador puede llamar a los métodos siguientes para acceder a la descripción de identificación o la descripción de la dirección de un PDO:

Control de solicitudes de volver a enumerar

Los controladores de bus basados en marco que admiten la enumeración dinámica pueden recibir una solicitud para volver a enumerar un dispositivo secundario determinado a través de la interfaz REENUMERATE_SELF_INTERFACE_STANDARD . Para obtener más información, consulta Control de solicitudes de enumeración.