Gravar um driver de cliente do controlador de funções
Este artigo descreve as várias tarefas que um driver cliente do controlador de funções executa ao interagir com a EXTENSÃO do controlador de função USB (UFX).
APIs importantes
Descreve as várias tarefas executadas por um driver cliente do controlador de funções ao interagir com a EXTENSÃO do controlador de função USB (UFX). O UFX e o driver cliente se comunicam entre si usando métodos de exportação e funções de retorno de chamada de evento. Os métodos de exportação ( chamados UfxDeviceXxx ou UfxEndpointXxx) são exportados pelo UFX e invocados pelo driver cliente. As funções de retorno de chamada ( nomeadas EVT_UFX_Xxx)são implementadas no driver do cliente e invocadas pela UFX.
A UFX chama todas as funções de retorno de chamada do driver cliente de forma assíncrona e um retorno de chamada por vez por objeto. Por exemplo, há um objeto de dispositivo USB e três objetos de ponto de extremidade. No máximo quatro funções de retorno de chamada (uma para o dispositivo e outra para cada ponto de extremidade) podem ser chamadas por vez. Para cada método de retorno de chamada, o UFX aguarda até que o driver do cliente chame UfxDeviceEventComplete para indicar que o driver concluiu a solicitação. O único outro método de exportação que o UFX escuta enquanto aguarda essas exportações é UfxDeviceNotifyHardwareFailure. Muitas funções de retorno de chamada do cliente são opcionais. As funções necessárias são as seguintes:
- EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD
- EVT_UFX_DEVICE_ENDPOINT_ADD
- EVT_UFX_DEVICE_HOST_CONNECT
- EVT_UFX_DEVICE_HOST_DISCONNECT
- EVT_UFX_DEVICE_ADDRESSED
Inicialização
- O driver cliente do controlador de funções inicia o processo de inicialização quando o WDF (Windows Driver Foundation) invoca a implementação do driver cliente do retorno de chamada EVT_WDF_DRIVER_DEVICE_ADD . Nessa implementação, espera-se que o driver cliente chame UfxFdoInit e crie o objeto do dispositivo chamando WdfDeviceCreate.
- O driver do cliente chama UfxDeviceCreate para criar o objeto de dispositivo USB e recuperar o identificador UFXDEVICE.
- O driver do cliente chama UfxDeviceNotifyHardwareReady para indicar à UFX que agora ele pode invocar as funções de retorno de chamada do driver de cliente.
- O UFX executa tarefas de inicialização como:
- A UFX chama a implementação de EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD do driver cliente para criar o ponto de extremidade padrão.
- O UFX cria PDOs (objetos de dispositivo físico) filho para interfaces compatíveis com o dispositivo.
- A UFX aguarda a ativação do driver de classe de dispositivo quando envia a solicitação de IOCTL_INTERNAL_USBFN_ACTIVATE_USB_BUS . Ele também aguarda o driver do cliente chamar UfxDeviceNotifyAttach que indica que o dispositivo foi anexado.
Notificação do driver de classe
Para ser notificado sobre pacotes de instalação e o status do barramento, um driver de classe deve enviar uma IOCTL_INTERNAL_USBFN_ACTIVATE_USB_BUS solicitações. O UFX enfileira essas solicitações em filas de notificação específicas do driver de classe. Ao receber uma notificação sobre um evento de barramento do driver cliente, o UFX aparece de cada fila apropriada e conclui a solicitação. Para evitar que os drivers de classe não sejam notificados, a UFX mantém uma fila de notificações de tamanho fixo para o driver de classe.
Eventos de anexação e desanexação do dispositivo
A UFX pressupõe que o dispositivo seja desanexado até que o driver do cliente do controlador de funções chame UfxDeviceNotifyAttach.
Após essa chamada, o UFX define o estado do dispositivo como Alimentado conforme definido na especificação USB. Para notificar o driver cliente sobre a alteração de estado, o UFX invoca a implementação de EVT_UFX_DEVICE_USB_STATE_CHANGE do driver cliente.
A UFX notifica o driver do carregador (Cad.sys) para ajudar a carregar o dispositivo. A UFX também notifica os drivers de classe concluindo IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION solicitações enviadas anteriormente por drivers de classe.
O driver do cliente deve chamar UfxDeviceNotifyDetach quando o barramento for desanexado. O cliente só deve chamar desanexar uma vez após cada chamada para UfxDeviceNotifyAttach. Após a chamada UfxDeviceNotifyDetach , o UFX chama EVT_UFX_DEVICE_HOST_DISCONNECT (se isso não for uma alteração de interface). Em seguida, o UFX continua com todas as tarefas limpo, como limpar todas as filas de ponto de extremidade e iniciar a fila de ponto de extremidade padrão. As chamadas UFX EVT_UFX_DEVICE_USB_STATE_CHANGE e notificam os drivers de classe concluindo IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION solicitações.
Falha de hardware
Se ocorrer um erro de hardware, espera-se que o driver cliente chame UfxDeviceNotifyHardwareFailure. Em resposta, a UFX derrubará a pilha do dispositivo e poderá tentar se recuperar dessa situação chamando a EVT_UFX_DEVICE_CONTROLLER_RESET do driver do cliente. O cliente deve redefinir o controlador para seu estado inicial. Se ocorrer outra falha de hardware, o cliente deverá chamar UfxDeviceNotifyHardwareFailure novamente. Na segunda chamada, a UFX registrará seu estado e marcar de bugs.
Detecção de porta
A detecção de porta é executada pelo UFX. Ele chama a função de retorno de chamada EVT_UFX_DEVICE_PORT_DETECT do driver de cliente do controlador de funções para determinar o tipo de porta à qual o dispositivo está anexado. O cliente responde chamando UfxDevicePortDetectComplete ou UfxDevicePortDetectCompleteEx com um dos tipos de porta definidos em USBFN_PORT_TYPE.
Se o cliente não puder determinar o tipo de porta, o cliente deverá relatar UsbfnUnknownPort. Se a porta for desconhecida ou uma porta downstream, a UFX chamará a função EVT_UFX_DEVICE_HOST_CONNECT do driver cliente. A UFX escuta o ônibus por algum tempo. Se a porta for desconhecida, mas houver tráfego, como um pacote de instalação, UFX assumirá UsbfnStandardDownstreamPort. Caso contrário, o UFX atribuirá a porta a usbfnInvalidDedicatedChargingPort. Depois que um tipo de porta for determinado, o UFX notificará Cad.sys e chamará a função de EVT_UFX_DEVICE_PORT_CHANGE do driver cliente. Na função, espera-se que o driver do cliente altere o estado do hardware para corresponder ao tipo de porta UFX.
Criação de ponto de extremidade
O UFX cria o ponto de extremidade padrão (ponto de extremidade 0) chamando o EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD do driver cliente para que ele possa lidar com pacotes de instalação enviados pelo host. A UFX cria outros pontos de extremidade chamando EVT_UFX_DEVICE_ENDPOINT_ADD. O UFX só cria pontos de extremidade depois que o driver do cliente chama UfxDeviceNotifyHardwareReady. Nessas funções de retorno de chamada, espera-se que o driver cliente chame UfxEndpointCreate para o objeto de ponto de extremidade e obtenha seu identificador UFXENDPOINT. O UFX define o pai como o PDO do driver de classe associado à interface à qual o ponto de extremidade pertence. Pai do ponto de extremidade padrão é o objeto de dispositivo USB. Um ponto de extremidade contém dois objetos de fila de estrutura: uma fila de transferência e uma fila de comandos, que só podem ser acessados quando o dispositivo está no estado Configurado (com exceção do Ponto de Extremidade 0, que pode ser acessado após chamadas UFX EVT_UFX_DEVICE_HOST_CONNECT).
- Solicitações de fila de comandos
- IOCTL_INTERNAL_USBFN_GET_PIPE_STATE
- IOCTL_INTERNAL_USBFN_SET_PIPE_STATE
- IOCTL_INTERNAL_USBFN_DESCRIPTOR_UPDATE
- Solicitações de fila de transferência
- IOCTL_INTERNAL_USBFN_TRANSFER_IN
- IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT
- IOCTL_INTERNAL_USBFN_TRANSFER_OUT
- IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_IN
- IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_OUT
Enumeração do dispositivo
O driver do cliente não deve permitir conexões com um host antes que o UFX chame o EVT_UFX_DEVICE_HOST_CONNECT do driver. A enumeração do dispositivo começa quando o driver do cliente chama UfxDeviceNotifyReset. No estado Padrão , o UFX manipula pacotes de configuração padrão.
Redefinir
O UFX limpa todas as filas de ponto de extremidade e envia uma solicitação IOCTL_INTERNAL_USBFN_DESCRIPTOR_UPDATE ao driver cliente para atualizar o wMaxPacketSize do ponto de extremidade 0. O UFX inicia a fila do ponto de extremidade padrão e define o estado como Padrão.
Default
A UFX chama a função de EVT_UFX_DEVICE_USB_STATE_CHANGE do driver cliente. Ele também notifica os drivers de classe do estado. Depois que o UFX recebe o pacote de configuração padrão SET_ADDRESS, o UFX define o estado como Endereçado.
Abordados
A UFX chama a função EVT_UFX_DEVICE_ADDRESSED do driver cliente para indicar ao cliente qual endereço ele deve usar. - Se o endereço for 0, o UFX definirá o estado como Padrão e chamaráEVT_UFX_DEVICE_USB_STATE_CHANGE e notificará os drivers de classe. Ao receber o pacote de configuração padrão SET_CONFIGURATION, o UFX define o estado como Configurado.
Configurado
Se a configuração selecionada for 0, o UFX limpará os pontos de extremidade da interface e definirá o estado como Endereçado. A UFX envia uma solicitação IOCTL_INTERNAL_USBFN_DESCRIPTOR_UPDATE ao driver cliente para atualizar o wMaxPacketSize dos pontos de extremidade da interface. A UFX garante que todas as filas de ponto de extremidade de interface tenham terminado de limpar e iniciar filas de ponto de extremidade da interface. Se o tipo de porta não for UsbfnStandardDownstreamPort ou UsbfnChargingDownstreamPort, o UFX alterará o tipo de porta para UsbfnStandardDownstreamPort e informará Cad.sys; o driver do cliente chamando EVT_UFX_DEVICE_PORT_CHANGE e EVT_UFX_DEVICE_USB_STATE_CHANGE para atualizar o estado; os drivers de classe do estado configurado.
Transferências de controle padrão
A UFX pode lidar com transferências de controle no ponto de extremidade padrão a qualquer momento depois de chamar EVT_UFX_DEVICE_DEFAULT_ENDPOINT_ADD, na qual o driver cliente cria o ponto de extremidade padrão usando. Todas as transferências de controle começam com um pacote de instalação de 8 bytes. Para enviar um pacote de instalação para o host, o driver do cliente deve chamar UfxEndpointNotifySetup. As transferências de controle padrão são concluídas pela UFX. Se houver dados associados à transferência de controle, o UFX lerá e gravará no ponto de extremidade de controle padrão conforme apropriado.
Transferências de controle não padrão
Se o UFX não puder lidar com uma transferência de controle, a transferência será encaminhada para o driver de classe apropriado concluindo uma solicitação de IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION . As transferências de controle podem ocorrer em qualquer ponto de extremidade definido como um ponto de extremidade de controle no descritor de ponto de extremidade. As transferências de controle em pontos de extremidade diferentes do ponto de extremidade de controle padrão são sempre transferências de controle não padrão. Se o ponto de extremidade de controle for o ponto de extremidade de controle padrão, a UFX notificará um drivers de classe de pacotes de instalação marcados como solicitações de classe para esse driver de classe. Se o ponto de extremidade de controle pertencer a uma interface, o UFX notificará o driver de classe associado a essa interface. Se necessário, espera-se que os drivers de classe leiam e escrevam no ponto de extremidade de controle.
Transferências de dados
As transferências de dados são iniciadas por drivers de classe enviando solicitações de IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT ou IOCTL_INTERNAL_USBFN_TRANSFER_OUT . Depois de validar cada uma dessas solicitações, a UFX encaminha-a para a fila de ponto de extremidade apropriada a ser manipulada pelo driver cliente. Espera-se que o driver do cliente execute uma validação adicional. O driver cliente recebe solicitações de transferência em filas de ponto de extremidade. O driver cliente pode recuperar quantas solicitações dessa fila precisar para maximizar a utilização do barramento. O driver do cliente deve concluir solicitações bem-sucedidas com STATUS_SUCCESS. O driver deve fazer uma tentativa de melhor esforço para cancelar solicitações e concluir solicitações canceladas com STATUS_CANCELLED se canceladas. Se parâmetros inválidos forem passados, o driver do cliente concluirá a solicitação com STATUS_INVALID_PARAMETER.
Transferências de controle
As transferências de controle começam com um pacote de instalação de 8 bytes. Para enviar um pacote de instalação para o host, o driver do cliente deve chamar UfxEndpointNotifySetup. O UFX notifica os drivers de classe de transferências de controle não padrão concluindo solicitações de notificação. Os clientes e o UFX usam IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT ou IOCTL_INTERNAL_USBFN_TRANSFER_OUT para ler e gravar no ponto de extremidade de controle padrão. No entanto, uma interface pode definir outros pontos de extremidade de controle, que somente o driver de classe correspondente pode usar. Os pontos de extremidade de controle podem ser paralisados em resposta a um pacote de instalação. Os drivers de classe enviam a solicitação IOCTL_INTERNAL_USBFN_SET_PIPE_STATE para paralisar o ponto de extremidade. Espera-se que o hardware ou o driver cliente retomem imediatamente o tráfego no ponto de extremidade após o envio da parada. Os pontos de extremidade de controle também podem enviar e receber pacotes de comprimento zero (ZLP) sem dados anteriores. O driver do cliente e o UFX podem fazer isso usando IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_IN e IOCTL_INTERNAL_USBFN_CONTROL_STATUS_HANDSHAKE_OUT.
Transferências em massa e interrupção
As transferências em massa garantem a entrega de dados e são usadas para enviar grandes quantidades de dados. As transferências podem ser enviadas em um ponto de extremidade em massa usando IOCTL_INTERNAL_USBFN_TRANSFER_IN, IOCTL_INTERNAL_USBFN_TRANSFER_IN_APPEND_ZERO_PKT ou IOCTL_INTERNAL_USBFN_TRANSFER_OUT. Os pontos de extremidade em massa podem ser paralisados da mesma forma para controlar pontos de extremidade usando IOCTL_INTERNAL_USBFN_SET_PIPE_STATE. Espera-se que o driver do cliente envie um pacote STALL em resposta a todas as solicitações de host e mantenha as solicitações IOCTL. Ao contrário dos pontos de extremidade de controle, um ponto de extremidade em massa paralisado permanece paralisado até que o estado da parada seja explicitamente limpo.
Transferências de interrupção As transferências de interrupção são como transferências em massa, mas têm uma latência garantida. As transferências de interrupção têm a mesma interface que as transferências em massa, mas não têm recursos de streaming.
Transferências isocronas
Não se espera que o driver do cliente dê suporte a transferências isócronas nesta versão.
Gerenciamento de Energia
O driver do cliente possui todos os aspectos do gerenciamento de energia. Como as funções de retorno de chamada são assíncronas, espera-se que o driver do cliente volte para um estado de energia apropriado e conclua a solicitação antes de chamar a função de exportação apropriada, como UfxDeviceEventComplete.
O UFX estará em um estado de trabalho se o estado do dispositivo (definido em USBFN_DEVICE_STATE) for UsbfnDeviceStateSuspended e UsbfnDeviceStateAttached e não tiver relatado um tipo de porta. Como alternativa, a UFX relatou o tipo de porta (definido em USBFN_PORT_TYPE) UsbfnStandardDownstreamPort ou UsbfnChargingDownstreamPort.
O UFX entra e sai de um estado de trabalho chamando EVT_UFX_DEVICE_USB_STATE_CHANGE ou implementações de EVT_UFX_DEVICE_PORT_CHANGE . A transição de ou para um estado De trabalho é concluída quando o driver do cliente chama UfxDeviceEventComplete.
Em um estado de trabalho, o UFX pode chamar qualquer retorno de chamada. Embora não esteja no estado De trabalho, o UFX chama apenas EVT_UFX_DEVICE_USB_STATE_CHANGE para inserir um estado de trabalho; EVT_UFX_DEVICE_REMOTE_WAKEUP_SIGNAL emitir um velório remoto durante a suspensão (se houver suporte).
Suspensão do dispositivo
A suspensão do dispositivo ocorre quando não há tráfego no ônibus por 3 milissegundos. Nesse caso, o driver cliente deve informar a UFX quando detectar suspensão e retomada chamando UfxDeviceNotifySuspend e UfxDeviceNotifyResume. Ao receber essas chamadas, o UFX chama EVT_UFX_DEVICE_USB_STATE_CHANGE e notifica os drivers de classe ao concluir IOCTL_INTERNAL_USBFN_BUS_EVENT_NOTIFICATION solicitações. Se o velório remoto for compatível com o dispositivo e habilitado pelo host, o UFX poderá chamar chamadas EVT_UFX_DEVICE_USB_STATE_CHANGE enquanto estiver suspenso para emitir um sinal de ativação remota.