Enumeración dinámica

La enumeración dinámica es la capacidad de un controlador para detectar y notificar 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 conectados al dispositivo primario dependen de la configuración de un sistema. Algunos de estos dispositivos pueden estar siempre conectados al sistema y otros 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 alimentación, abra el caso y agrega 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 de trabajo 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 mediante una llamada a WdfFdoGetDefaultChildList. Normalmente, si escribe 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 de lista secundaria inicializando una estructura WDF_CHILD_LIST_CONFIG y pasando la estructura a WdfFdoInitSetDefaultChildListConfig, para la lista secundaria predeterminada o a WdfChildListCreate, para listas secundarias adicionales.

Descripciones secundarias dinámicas

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 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 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER estructura.

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, vea 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 el controlador requiere 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 WDF_CHILD_ADDRESS_DESCRIPTION_HEADER estructura.

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 el momento en que se desconecta, 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 buses usan información de direccionamiento que puede cambiar. Por ejemplo, el IEEE 1394 bus 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 IEEE 1394 dispositivo 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 la 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, vea 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 de un controlador de bus, la función de devolución de llamada debe llamar a WdfDeviceCreate para crear un FDO para el dispositivo primario, que normalmente es un adaptador de bus. Para obtener más información sobre cómo crear un FDO, vea Crear objetos de dispositivo en un controlador de función. A continuación, el controlador debe enumerar los elementos secundarios del dispositivo primario y agregarlos a una lista de elementos secundarios.

Opcionalmente, el controlador puede llamar a WdfDeviceSetBusInformationForChildren para proporcionar al marco información sobre el bus. Se recomienda hacerlo porque facilita a los dispositivos y aplicaciones secundarios identificar 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 la dirección.

Después de que el controlador llame a WdfChildListAddOrUpdateChildDescriptionAsPresent para notificar un nuevo dispositivo, el marco informa al administrador de PnP de que el nuevo dispositivo existe. A continuación, el administrador de PnP compila 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 varias veces a WdfChildListAddOrUpdateChildDescriptionAsPresent . 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 nuevo dispositivo.

Cuando el controlador llama a WdfChildListBeginScan, el marco marca todos los dispositivos notificados anteriormente como que ya no están presentes. Por lo tanto, el controlador debe llamar a WdfChildListAddOrUpdateChildDescriptionAsPresent para todos los secundarios que el controlador pueda detectar, no solo los 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.

Actualizar 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 WdfChildListUpdateChildDescriptionAsMissing si se ha desconectado un dispositivo.

  2. El controlador puede proporcionar una función de devolución de llamada EvtChildListScanForChildren , a la que el marco llama cada vez que el dispositivo primario entra en su estado de funcionamiento (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 de estas técnicas en el controlador.

Recorrer una lista secundaria dinámica

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 la descripción de cada 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 de dispositivos o solo un subconjunto. Cuando WdfChildListRetrieveNextDevice encuentra una coincidencia, recupera las descripciones de identificación y dirección 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 correspondiente y, a continuación, recupera la descripción de la dirección.

  • Si necesita obtener un identificador para el objeto de dispositivo del 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 correspondiente 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 REENUMERATE_SELF_INTERFACE_STANDARD interfaz. Para más información, consulte Control de solicitudes de enumeración.