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 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 conectados ao barramento PCI de um sistema são dependentes do sistema, mas são permanentes, a menos que um usuário desligue a energia, abra a caixa 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 deem suporte à enumeração dinâmica fornecendo objetos de lista filho da estrutura. Cada objeto de lista filho representa uma lista de dispositivos filho conectados a um dispositivo pai. O driver de barramento do dispositivo pai deve identificar os dispositivos filho do pai, adicioná-los à lista filho do dispositivo pai e criar um PDO (objeto de dispositivo físico) para cada filho.

Sempre 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 motorista de ônibus que enumera os filhos de um dispositivo, seu motorista 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 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 filho dinâmicas

Sempre que um motorista de ônibus identifica um dispositivo filho, ele deve adicionar a descrição do dispositivo filho a uma lista filho. Uma descrição filho consiste em uma descrição de identificação necessária e uma descrição de endereço opcional.

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

Normalmente, uma descrição de identificação contém as cadeias de caracteres de identificação do dispositivo de um dispositivo, possivelmente um número de série e informações sobre a localização 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 WDF_CHILD_ADDRESS_DESCRIPTION_HEADER .

As 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 estiver conectado e a hora em que ele estiver desconectado, todas as informações de endereço do dispositivo poderão ser armazenadas em uma descrição de identificação. Por exemplo, os controladores USB atribuem endereços a dispositivos quando os dispositivos estão conectados e esses endereços não são alterados.

Por outro lado, alguns ônibus 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 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 filho dinâmica

Quando a estrutura chama a função de retorno de chamada EvtDriverDeviceAdd de um 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. Em seguida, o driver deve enumerar os filhos do dispositivo pai e adicionar os filhos a uma lista filho.

Opcionalmente, o driver pode chamar WdfDeviceSetBusInformationForChildren para fornecer à estrutura informações sobre o barramento. Isso é recomendado porque facilita a identificação do barramento por dispositivos e aplicativos filho.

Para adicionar filhos a uma lista filho, o driver deve chamar WdfChildListAddOrUpdateChildDescriptionAsPresent para cada dispositivo filho que encontrar. Essa chamada informa à estrutura que um driver descobriu um dispositivo filho 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 ao gerenciador PnP que o novo dispositivo existe. Em seguida, o gerenciador PnP cria uma pilha de dispositivos e uma pilha de driver 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 motorista do 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ê cercar a enumeração dinâmica do driver com chamadas para WdfChildListBeginScan e WdfChildListEndScan, a estrutura armazenará todas as alterações na lista filho e notificará o gerenciador PnP das alterações quando o driver chamar WdfChildListEndScan. Posteriormente, a estrutura chama a função de retorno de chamada EvtChildListCreateDevice do driver de barramento para cada dispositivo na lista filho. 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 relatados anteriormente como não mais presentes. Portanto, o driver deve chamar WdfChildListAddOrUpdateChildDescriptionAsPresent para todos os filhos que o driver pode detectar, não apenas 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 filho dinâmica

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

  1. Quando um dispositivo pai recebe uma interrupção que indica a chegada ou 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 sempre 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 essas técnicas em seu driver.

Percorrendo uma lista filho dinâmica

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

  • Para obter o conteúdo de cada descrição de dispositivo filho, uma 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_FLAGS que indica se a estrutura deve recuperar todas as descrições do dispositivo ou apenas um subconjunto. Quando 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 do endereço atualmente contida em uma descrição do dispositivo filho, seu driver poderá chamar WdfChildListRetrieveAddressDescription, especificando uma descrição de identificação. A estrutura percorre a lista filho 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 de estrutura associado a um dispositivo filho específico, seu 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, retorna um identificador de objeto do dispositivo. Lembre-se de encapsular a chamada com WdfChildListBeginIteration e WdfChildListEndIteration para proteger o chamador contra a remoção repentina de PnP do PDO em outro thread.

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

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

Manipulando solicitações de renumeração

Os drivers de barramento baseados em estrutura que dão suporte à enumeração dinâmica podem receber uma solicitação para reenumerar um dispositivo filho específico por meio da interface REENUMERATE_SELF_INTERFACE_STANDARD . Para obter mais informações, consulte Manipulando solicitações de enumeração