Enumeração dinâmica

A Enumeração dinâmica é a capacidade de um driver de detectar e relatar alterações no número e no tipo de dispositivos que estão conectados ao sistema enquanto o sistema está em execução.

Os drivers de barramento devem usar a enumeração dinâmica se o número ou os tipos de dispositivos conectados ao dispositivo pai dependerem da configuração de um sistema. Alguns desses dispositivos podem estar sempre conectados ao sistema e alguns podem estar conectados e desconectados enquanto o sistema está em execução.

Por exemplo, o número e o tipo de dispositivos que são conectados a um barramento PCI do sistema são dependentes do sistema, mas eles são permanentes, a menos que um usuário desligue a energia, abra o caso e adicione ou remova um dispositivo usando uma chave de fenda. Por outro lado, um usuário pode adicionar ou remover dispositivos USB conectando ou desconectando um cabo enquanto o sistema está em execução.

Listas filho dinâmicas

A estrutura permite que os drivers ofereçam suporte à enumeração dinâmica fornecendo objetos de lista de filhos da estrutura. Cada objeto de lista filho representa uma lista de dispositivos filho que estão conectados a um dispositivo pai. O driver de barramento para o dispositivo pai deve identificar os dispositivos filho do pai, adicioná-los à lista de filhos do dispositivo pai e criar um objeto de dispositivo físico (PDO) para cada filho.

Cada vez que um driver cria um objeto de dispositivo de estrutura que representa um FDO para um dispositivo, a estrutura cria uma lista filho vazia e padrão para o dispositivo. O driver pode obter um identificador para a lista filho padrão de um dispositivo chamando WdfFdoGetDefaultChildList. Normalmente, se você estiver escrevendo um driver de barramento que enumera os filhos de um dispositivo, o driver poderá adicionar filhos à lista de filhos padrão. Se você precisar criar listas filho adicionais, o driver poderá chamar WdfChildListCreate.

Antes que um driver possa usar uma lista filho, ele deve configurar o objeto de lista filho inicializando uma estrutura de WDF_CHILD_LIST_CONFIG e passando a estrutura para WdfFdoInitSetDefaultChildListConfig, para a lista filho padrão ou para WdfChildListCreate, para listas filho adicionais.

Descrições de filho dinâmicas

Cada vez que um driver de barramento identifica um dispositivo filho, ele deve adicionar a descrição do dispositivo filho a uma lista de filhos. Uma Descrição filho consiste em uma Descrição de identificação necessária e uma Descrição de endereçoopcional.

Descrição da identificação Uma descrição de identificação é uma estrutura que contém informações que identificam exclusivamente cada dispositivo enumerado pelo driver. O driver define essa estrutura, mas seu primeiro membro deve ser uma estrutura de WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER .

Normalmente, uma descrição de identificação contém cadeias de caracteres de identificação de dispositivode um dispositivo, possivelmente um número de série, e informações sobre o local do dispositivo no barramento, como um número de slot.

O driver pode fornecer o seguinte conjunto de funções de retorno de chamada, que permitem que a estrutura Manipule as informações em uma descrição de identificação:

Normalmente, você precisará fornecer essas funções de retorno de chamada se as estruturas de descrição de identificação do driver contiverem ponteiros para buffers alocados dinamicamente. Para obter mais informações sobre a finalidade dessas funções de retorno de chamada, consulte suas páginas de referência.

Descrição do endereço Uma descrição de endereço é uma estrutura que contém informações que o driver requer para que ele possa acessar o dispositivo em seu barramento, se as informações puderem ser alteradas enquanto o dispositivo estiver conectado. O driver define essa estrutura, mas seu primeiro membro deve ser uma estrutura de WDF_CHILD_ADDRESS_DESCRIPTION_HEADER .

Descrições de endereço são opcionais. Se as informações de endereço de um dispositivo não puderem ser alteradas entre a hora em que o dispositivo está conectado e a hora em que ele está desconectado, todas as informações de endereço do dispositivo poderão ser armazenadas em uma descrição de identificação. Por exemplo, controladores USB atribuem endereços a dispositivos quando os dispositivos são conectados e esses endereços não são alterados.

Por outro lado, alguns barramentos usam informações de endereçamento que podem ser alteradas. Por exemplo, o barramento IEEE 1394 usa uma "contagem de geração", que é o número de redefinições de barramento que ocorreram. Cada solicitação de e/s assíncrona para um dispositivo IEEE 1394 deve incluir a contagem de geração. Como essas informações de endereço podem ser alteradas, o driver deve armazená-la em uma descrição de endereço.

O driver pode fornecer o seguinte conjunto de funções de retorno de chamada para manipular as informações em uma descrição de endereço:

Normalmente, você precisará fornecer essas funções de retorno de chamada se as estruturas de descrição de endereço do seu driver contiverem ponteiros para buffers alocados dinamicamente. Para obter mais informações sobre a finalidade dessas funções de retorno de chamada, consulte suas páginas de referência.

Adicionando dispositivos a uma lista de filhos dinâmicos

Quando a estrutura chama uma função de retorno de chamada EvtDriverDeviceAdd do driver de barramento, a função de retorno de chamada deve chamar WdfDeviceCreate para criar um FDO para o dispositivo pai, que normalmente é um adaptador de barramento. Para obter mais informações sobre como criar um FDO, consulte criando objetos de dispositivo em um driver de função. O driver deve enumerar os filhos do dispositivo pai e adicionar os filhos a uma lista de filhos.

Opcionalmente, o driver pode chamar WdfDeviceSetBusInformationForChildren para fornecer a estrutura com informações sobre o barramento. Isso é recomendado porque torna mais fácil para os dispositivos e aplicativos filhos identificarem o barramento.

Para adicionar filhos a uma lista de filhos, o driver deve chamar WdfChildListAddOrUpdateChildDescriptionAsPresent para cada dispositivo filho que encontrar. Essa chamada informa à estrutura que um driver descobriu um dispositivo filho que está conectado a um dispositivo pai. Quando o driver chama WdfChildListAddOrUpdateChildDescriptionAsPresent, ele fornece uma descrição de identificação e, opcionalmente, uma descrição de endereço.

Depois que o driver chama WdfChildListAddOrUpdateChildDescriptionAsPresent para relatar um novo dispositivo, a estrutura informa o gerenciador PnP de que o novo dispositivo existe. Em seguida, o Gerenciador de PnP cria uma pilha de dispositivos e uma pilha de drivers para o novo dispositivo. Como parte desse processo, a estrutura chama a função de retorno de chamada EvtChildListCreateDevice do driver de barramento. Essa função de retorno de chamada deve chamar WdfDeviceCreate para criar um PDO para o novo dispositivo.

Normalmente, vários dispositivos filho são conectados a um pai, portanto, o driver de barramento precisará chamar WdfChildListAddOrUpdateChildDescriptionAsPresent várias vezes. A maneira mais eficiente de fazer isso é a seguinte:

  1. Chame WdfChildListBeginScan.

  2. Chame WdfChildListAddOrUpdateChildDescriptionAsPresent para cada dispositivo filho.

  3. Chame WdfChildListEndScan.

Se você envolver a enumeração dinâmica do driver com chamadas para WdfChildListBeginScan e WdfChildListEndScan, a estrutura armazenará todas as alterações na lista de filhos e notificará o Gerenciador de PNP das alterações quando o driver chamar WdfChildListEndScan. Em algum momento posterior, a estrutura chama a função de retorno de chamada EvtChildListCreateDevice do driver de barramento para cada dispositivo na lista de filhos. Essa função de retorno de chamada chama WdfDeviceCreate para criar um PDO para cada novo dispositivo.

Quando o driver chama WdfChildListBeginScan, a estrutura marca todos os dispositivos anteriormente relatados como não estando mais presentes. Portanto, o driver deve chamar WdfChildListAddOrUpdateChildDescriptionAsPresent para todos os filhos que o driver pode detectar, não apenas os filhos recém-descobertos. Para adicionar um único filho a uma lista filho, o driver pode fazer uma única chamada para WdfChildListUpdateAllChildDescriptionsAsPresent sem primeiro chamar WdfChildListBeginScan.

Atualizando uma lista de filhos dinâmicas

Há duas maneiras comuns de atualizar as informações em uma lista de filhos dinâmicos:

  1. Quando um dispositivo pai recebe uma interrupção que indica a chegada ou a remoção de um filho, a função de retorno de chamada EvtInterruptDpc do driver chama WdfChildListAddOrUpdateChildDescriptionAsPresent se um dispositivo tiver sido conectado ou WdfChildListUpdateChildDescriptionAsMissing se um dispositivo tiver sido desconectado.

  2. O driver pode fornecer uma função de retorno de chamada EvtChildListScanForChildren , que a estrutura chama toda vez que o dispositivo pai entra em seu estado de trabalho (D0). Essa função de retorno de chamada deve enumerar todos os dispositivos filho chamando WdfChildListBeginScan, WdfChildListAddOrUpdateChildDescriptionAsPresent (ou WdfChildListUpdateAllChildDescriptionsAsPresent) e WdfChildListEndScan.

Você pode usar uma ou ambas as técnicas em seu driver.

Atravessando uma lista de filhos dinâmicas

Se você quiser que o driver examine o conteúdo de uma lista de filhos, ele poderá atravessar a lista usando uma das seguintes técnicas:

  • Para obter o conteúdo de cada descrição de dispositivo filho, um de cada vez, o driver pode:

    1. Chame WdfChildListBeginIteration.
    2. Chame WdfChildListRetrieveNextDevice, quantas vezes forem necessárias.
    3. Chame WdfChildListEndIteration.

    Ao chamar WdfChildListBeginIteration, o driver especifica um sinalizador de tipo WDF_RETRIEVE_CHILD_FLAGSque indica se a estrutura deve recuperar todas as descrições de dispositivo ou apenas um subconjunto. Quando o WdfChildListRetrieveNextDevice encontra uma correspondência, ele recupera as descrições de identificação e endereço do dispositivo filho, além de um identificador para seu objeto de dispositivo.

  • Se você precisar obter a descrição de endereço que está contida atualmente em uma descrição de dispositivo filho, o driver poderá chamar WdfChildListRetrieveAddressDescription, especificando uma descrição de identificação. A estrutura percorre a lista de filhos até encontrar um dispositivo filho com uma descrição de identificação correspondente e, em seguida, recupera a descrição do endereço.

  • Se você precisar obter um identificador para o objeto de dispositivo do Framework que está associado a um dispositivo filho específico, o driver poderá chamar WdfChildListRetrievePdo. A estrutura percorre a lista filho até encontrar um dispositivo filho com uma descrição de identificação correspondente e, em seguida, retornar um identificador de objeto de dispositivo. Certifique-se de encapsular a chamada com WdfChildListBeginIteration e WdfChildListEndIteration para proteger o chamador de uma remoção REPENTINA de PnP do PDO em outro thread.

Acessando as descrições de identificação e endereço de PDO

O driver pode chamar os seguintes métodos para acessar a descrição de identificação ou de endereço de PDO:

Manipulando solicitações de reenumeração

Drivers de barramento baseados em estrutura que suportam enumeração dinâmica podem receber uma solicitação para reaumerar um dispositivo filho específico por meio da interface REENUMERATE_SELF_INTERFACE_STANDARD . Para obter mais informações, consulte Tratamento de solicitações de enumeração