Sie sind auf Seite 1von 8

Construir um Driver Básico

Esqueleto de driver

Desenvolvimento de drivers para


Windows
• Até 2005
– WDM (Windows Driver Model)
• Modelo?
• Resultado?
– Todo o código do driver é desenvolvido pelo programador

• A partir de 2006
– WDF (Windows Drivers Foundation)
• Framework (?)
• Construída “em cima” do WDM
• Resultado?
– Mais fácil de aprender
– Mais rápido de desenvolver

TC2 2008/09 Sérgio Lopes 2


WDM vs WDF
Driver WDM Driver WDF
Implementa de raiz um modelo Implementa apenas comportamento para os
(WDM) eventos que necessita (framework implementa
o WDM e fornece comportamento por defeito
para certos eventos)
Aceita pedidos de PnP, PM e IO, e Responde a pedidos de IO considerando apenas
decide o que fazer tendo em conta o estado das suas variáveis (PnP e PM são
o estado total implementados pela framework)
Necessita sincronizar pedidos de IO, Sincronização apenas para proteger dados
PnP e PM definidos pelo próprio driver
Comunica directamente com Tipicamente comunica com a framework, que
componentes do kernel usa interfaces WDM para falar com o SO
Acede directa/ às estruturas dos Acede aos objectos através de handles e
objectos definidos pelo WDM métodos dos objectos
Mais rápido a executar Mais rápido de programar
TC2 2008/09 Sérgio Lopes 3

KMDF vs UMDF
• WDF: KMDF UMDF

KernelͲMode UserͲMode
Driver Framework Driver Framework

– UMDF é recomendado, mas não permite DMA nem


interrupções
• KMDF
– Gigante máquina de estados WDM
– Recebe todos os pedidos de IO e do sistema (PnP, PM)
– Trata alguns pedidos (e.g. PnP) e envia outros para o driver (e.g.
reads e writes de IO)
– Garante sincronização correcta das acções
– Executa no momento certo as funções callback específicas do
driver

TC2 2008/09 Sérgio Lopes 4


Arquitectura KMDF
• Cada funcionalidade está incluída num de diferentes tipos de
objectos WDF
– Exemplos:
• driver object: representa um driver
• device object: representa um dispositivo que um driver suporta
• queue objects: representam filas de I/O que recebem os pedidos de I/O de um
dispositivo
• request objects: representam pedidos de I/O que cada fila de I/O recebe
– Ver “Summary of Framework Objects”

• Interface dos objectos é constituída por


– Métodos que o driver pode invocar para realizar uma operação sobre
o objecto
– Propriedades que o driver pode obter ou mudar
– Funções Callback associadas a Eventos que o driver pode/deve
fornecer (invocadas pela framework quando o evento ocorre)

TC2 2008/09 Sérgio Lopes 5

Objectos KMDF
• Os objectos podem ser colocados numa hierarquia paiͲfilho através do
membro ParentObject da estrutura WDF_OBJECT_ATTRIBUTES de cada
objecto
• Existe um contador de referências para cada objecto gerido pela
framework
• A framework apaga um objecto quando c.refs=0 (primeiro tenta apagar os
filhos)
• Drivers podem controlar o tempo de vida dos objectos através de
WdfObjectReference e WdfObjectDereference
• A cada objecto pode ser um atribuído um contexto próprio com
informação específica
– Criado no método que cria o objecto ou WdfObjectAllocateContext
– Tem o mesmo tempo de vida, e reside em memória não paginável
– Acessível através de um método accessor criado pela macro
WDF_DECLARE_CONTEXT_TYPE, ou através de WdfObjectGetTypedContext

TC2 2008/09 Sérgio Lopes 6


Funções típicas a implementar
• Ponto de entrada (DriverEntry)
• Adicionar um dispositivo (EvtDriverDeviceAdd)
• Acesso inicial e final ao hardware
(EvtDevicePrepareHardware e
EvtDeviceReleaseHardware)
• Entrada e saída do estado D0 do dispositivo
(EvtDeviceD0Entry e EvtDeviceD0Exit)
• Resposta aos pedidos de IO (EvtIoDefault)
TC2 2008/09 Sérgio Lopes 7

Comentar o código
• Atenção:
– Em itálico: funções cujo nome é definido pelo driver
– Distinguir o que é documentação WDM de WDF. Exemplo:
• Escrever “DriverEntry” na documentação .chm do WDK
• Ver as diferenças entre:
– DriverEntry[WDK Kernel] Ͳ> Writing a DriverEntry Routine Ͳ> AddDevice,
e
– DriverEntry[WDK KMDF] Ͳ> EvtDriverDeviceAdd
• Pistas:
– Os tipos de dados e os nomes de funções WDF
normalmente incluem o prefixo “Wdf” ou “WDF”
– Só no WDF é que se pode falar em callbacks

TC2 2008/09 Sérgio Lopes 8


Rotina DriverEntry
• Primeira função do driver a ser chamada
• Tipicamente simples:
– Inicializar o driver (e.g. alocação de variáveis globais,
ler dados do registry, etc.)
– Inicializar a estrutura de configuração do driverͲ
object, que é do tipo WDF_DRIVER_CONFIG (incluindo
o registo da callback EvtDriverDeviceAdd), antes de
invocar WdfDriverCreate
– Construir o driverͲobject WDF invocando o método
WdfDriverCreate
TC2 2008/09 Sérgio Lopes 9

Callback EvtDriverDeviceAdd
• Invocada sempre que o PnP manager detecte a ligação de um novo
dispositivo (e.g., várias portas USB)
• Obrigatória para drivers que suportem dispositivos PnP
• Declarada usando o tipo EVT_WDF_DRIVER_DEVICE_ADD
• Registada através de WDF_DRIVER_CONFIG_INIT em DriverEntry
• Reponsabilidade fundamental – criar e inicializar o deviceͲobject:
– Create a framework device object to represent the device.
– Create I/O queues so the driver can receive I/O requests.
– Create device interfaces that applications use to communicate with the
device.
– Create driverͲdefined interfaces that other drivers can use.
– Initialize Windows Management Instrumentation (WMI) support.
– Create interrupt objects, if the driver handles device interrupts.
– Enable direct memory access (DMA) transactions, if the driver handles DMA
operations.

TC2 2008/09 Sérgio Lopes 10


Callbacks EvtDevice????Hardware
• EvtDevicePrepareHardware()
– Declarada usando o tipo EVT_WDF_DEVICE_PREPARE_HARDWARE
– Se necessário, realiza operações para que o driver possa aceder ao
dispositivo (nomeadamente mapear endereços físicos em virtuais, obter
interfaces de outros drivers, determinar o revision number do dispositivo)
– Garante que o driver consegue aceder ao dispositivo
– Invocada antes de EvtDeviceD0Entry

• EvtDeviceReleaseHardware
– Declarada usando o tipo EVT_WDF_DEVICE_RELEASE_HARDWARE
– Realiza as operações de quando o dispositivo já não está acessível (mas a
configuração PCI sim) desfazendo o mapeamento feito na de cima
– Invocada após EvtDeviceD0Exit

• Registadas através de WdfDeviceInitSetPnpPowerEventCallbacks


em EvtDriverDeviceAdd

TC2 2008/09 Sérgio Lopes 11

Callbacks EvtDeviceD0????
• EvtDeviceD0Entry
– Declarada usando o tipo EVT_WDF_DEVICE_D0_ENTRY
– Realiza as operações necessárias quando o dispositivo entra no estado de energia D0 (working
state)
– Inicializações necessárias ao funcionamento do driver (e.g., lançar o timer de acções
periodicas)
– Operações podem depender do estado energia anterior

• EvtDeviceD0Exit
– Declarada usando o tipo EVT_WDF_DEVICE_D0_EXIT
– Realiza as operações necessárias quando o dispositivo sai de D0 para um estado de menor
consumo de energia
– Terminar ou suspender operações de IO pendentes e guardar o estado do dispositivo para
poder ser utilizado na callback acima (para repor o estado D0)
– Operações podem depender do estado energia seguinte

• Registadas através de WdfDeviceInitSetPnpPowerEventCallbacks em


EvtDriverDeviceAdd
• Ver “Device Power States”

TC2 2008/09 Sérgio Lopes 12


Callback EvtIoDefault
• Declarada usando o tipo EVT_WDF_IO_QUEUE_IO_DEFAULT
• Processa os pedidos de IO recebidos numa fila (ver “Processing I/O
Requests”)
• Recebe todos os pedidos de IO da respectiva fila que não têm
callbacks especificas registadas (ver “Request Handlers”)
• Normalmente envolvem buffers de entrada e de saída (ver
“Accessing Data Buffers in FrameworkͲBased Drivers”)
• Registada através de WdfIoQueueCreate
• Pode ser invocada com IRQL <= DISPATCH_LEVEL (excepto se o
valor do membro ExecutionLevel da estrutura
WDF_OBJECT_ATTRIBUTES do driver ou do dispositivo é
WdfExecutionLevelPassive, e para drivers do topo da stack que é
PASSIVE_LEVEL)

TC2 2008/09 Sérgio Lopes 13

Trabalho prático
• Comentar o código do driver “basic”
• Com base na aplicação EchoApp.c do exemplo de driver ECHO, construir
uma aplicação que envie pedidos de IO para o driver “basic”, com os
seguintes requisitos:
– receba um primeiro parâmetro opcional que defina o número de pedidos a
enviar (por defeito 10)
– receba um segundo parâmetro opcional que determina se o o pedido é
Read/Write/DeviceIoControl (Read por defeito)
– receba um terceiro parâmetro opcional da linha de comandos que seleciona o
envie de forma síncrona/ assíncrona (síncrona por defeito)
• Ciclos do Desenvolvimento Iterativo
– Enviar 10 pedidos Read de modo síncrono
– Suportar o parâmetro de escolha do número de pedidos e acrescentar o envio
de pedidos Write e DeviceIoControl em sequencia
– Suportar a escolha dos 2 ultimos parâmetros e acrescentar o envio assíncrono
Pistas
• Utilize a função GetDevicePath() fornecida no exemplo,
documentandoͲa com base nas seguintes secções da
documentação do WDK:
– “Device Information Sets”
– “Using Device Installation Functions”, nomeadamente:
• SetupDiGetClassDevs e SetupDiDestroyDeviceInfoList
• SetupDiEnumDeviceInterfaces e SetupDiGetDeviceInterfaceDetail
• Pesquise na documentação do API Win32 do Windows
(http://msdn.microsoft.com/enͲ
us/library/cc433218(VS.85).aspx) os comandos
– CreateFile e CloseHandle
– DeviceIoControl
– ReadFile e WriteFile
– CreateIoCompletionPort e GetQueuedCompletionStatus

Das könnte Ihnen auch gefallen