Gravar um driver de controlador de porta TIPO C USB

Você precisará escrever um driver de controlador de porta USB Tipo C se o hardware USB Tipo C implementar a camada física USB Tipo C ou PD (Entrega de Energia), mas não implementar os computadores de estado necessários para a Entrega de Energia.

No Windows 10, versão 1703, a arquitetura USB Type-C foi aprimorada para dar suporte a designs de hardware que implementam a camada física usb tipo C ou PD (entrega de energia), mas não têm um mecanismo de política PD correspondente ou implementação de camada de protocolo. Para esses designs, Windows 10 versão 1703 fornece um mecanismo de política PD baseado em software e um gerenciador de políticas de dispositivo por meio de uma nova extensão de classe chamada "Extensão de Classe de Interface do Controlador de Porta Tipo C do Gerenciador de Conectores USB" (UcmTcpciCx). Um driver cliente escrito por um IHV ou OEM/ODM se comunica com UcmTcpciCx para fornecer informações sobre os eventos de hardware necessários para que o mecanismo de política de PD e o gerenciador de políticas de dispositivo no UcmTcpciCx funcionem. Essa comunicação é habilitada por meio de um conjunto de interfaces de programação descritas neste artigo e na seção de referência.

Diagrama do gerenciador de conectores USB.

A extensão de classe UcmTcpciCx é, em si, um driver cliente do UcmCx. As decisões políticas sobre contratos de energia, funções de dados, são tomadas no UcmCx e encaminhadas para UcmTcpciCx. UcmTcpciCx implementa essas políticas e gerencia os computadores de estado Type-C e PD, usando a interface do controlador de porta fornecida pelo driver de cliente UcmTcpciCx.

Resumo

  • Serviços fornecidos pela extensão de classe UcmTcpci
  • Comportamento esperado do driver do cliente

Especificações oficiais

APIs importantes

Referência de extensões de classe de driver da Interface do Controlador de Porta tipo C USB

Modelo de driver de cliente UcmTcpciCx

Modelo de driver de cliente UcmTcpciCx

Antes de começar

  • Determine o tipo de driver que você precisa escrever dependendo se o hardware ou firmware implementa o computador de estado PD. Para obter mais informações, consulte Desenvolvendo drivers do Windows para conectores USB Tipo C.

  • Instale Windows 10 para edições da área de trabalho (Home, Pro, Enterprise e Education) no computador de destino ou Windows 10 Mobile com um conector USB Tipo C.

  • Instale o WDK (Kit de Driver do Windows) mais recente em seu computador de desenvolvimento. O kit tem os arquivos de cabeçalho e as bibliotecas necessários para escrever o driver cliente, especificamente, que você precisa:

    • A biblioteca stub (UcmTcpciCxStub.lib). A biblioteca converte chamadas feitas pelo driver cliente e as passa para a extensão de classe.
    • O arquivo de cabeçalho, UcmTcpciCx.h.

    O driver cliente é executado no modo kernel e é associado à biblioteca KMDF 1.15.

    Captura de tela da configuração do Visual Studio para UCM.

  • Decida se o driver do cliente dá suporte a alertas.

  • O controlador de porta não precisa estar em conformidade com TCPCI. A interface captura os recursos de qualquer controlador de porta Tipo C. Escrever um driver de cliente UcmTcpciCx para hardware que não esteja em conformidade com TCPCI envolve mapear os significados de registros e comandos na especificação TCPCI para os do hardware.

  • A maioria dos controladores TCPCI são conectados a C2. O driver cliente usa um recurso de conexão SPB (barramento periférico serial) e uma linha de interrupção para se comunicar com o hardware. O driver usa a interface de programação SpbCx (SPB Framework Extension). Familiarize-se com o SpbCx lendo estes artigos:

    • Guia de design do driver [SPB (Barramento Periférico Simples) ]
    • [Referência de programação de driver SPB]
  • Familiarize-se com o WDF (Windows Driver Foundation). Leitura recomendada: Desenvolvendo drivers com o Windows Driver Foundation, escrito por Penny Orwick e Guy Smith.

Comportamento da extensão da classe UcmTcpci

  • Como parte da execução da máquina de estado, UcmTcpciCx envia solicitações IOCTL para o controlador de porta. Por exemplo, no sistema de mensagens PD, ele envia uma solicitação IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER para definir o buffer de transmissão. Essa solicitação (TRANSMIT_BUFFER) é entregue ao driver cliente. Em seguida, o driver define o buffer de transmissão com os detalhes fornecidos pela extensão de classe.

  • UcmTcpciCx implementa políticas sobre contratos de energia, funções de dados e assim por diante.

Comportamento esperado do driver do cliente

Espera-se que o driver do cliente para o UcmTcpciCx:

  • Seja o proprietário da política de energia. UcmTcpciCx não participa do gerenciamento de energia do controlador de porta.

  • Traduza solicitações, recebidas de UcmTcpciCx, em comandos de leitura ou gravação de hardware. Os comandos devem ser assíncronos porque o DPM não pode bloquear a espera pela conclusão de uma transferência de hardware.

  • Forneça um objeto de fila de estrutura que contém objetos de solicitação de estrutura. Para cada solicitação que a extensão de classe UcmTcpci deseja enviar ao driver cliente, a extensão adiciona um objeto de solicitação no objeto de fila do driver. Quando o driver terminar de processar a solicitação, ele chamará WdfRequestComplete. É responsabilidade do driver do cliente concluir as solicitações em tempo hábil.

  • Descubra e relate os recursos do controlador de porta. Esses recursos incluem informações como as funções em que o controlador de porta pode operar (como somente origem, somente coletor, DRP). No entanto, há outras funcionalidades do conector (consulte a Observação sobre o Repositório de Funcionalidades) e do sistema como um todo, que o DPM precisa saber para implementar corretamente a política USB Tipo C e PD. Por exemplo, o DPM precisa saber os recursos de origem do sistema/conector para anunciá-lo ao parceiro de porta.

    Repositório de Recursos

    Além dos recursos relacionados ao driver do cliente, informações adicionais vêm de um local global do sistema conhecido como Repositório de Funcionalidades. Esse Repositório de Funcionalidades global do sistema é armazenado no ACPI. É uma descrição estática dos recursos do sistema e de cada um de seus conectores USB Tipo C que o DPM usa para determinar as políticas a serem implementadas.

    Ao separar a descrição dos recursos do sistema do driver cliente para os controladores de porta, o design permite que um driver seja usado em diferentes sistemas de funcionalidades variadas. UcmCx, não UcmTcpciCx, faz interfaces com o Repositório de Funcionalidades. UcmTcpciCx (ou seu driver cliente) não interage com o Repositório de Recursos.

    Sempre que aplicável, as informações do Repositório de Funcionalidades substituem as informações provenientes diretamente do driver cliente do controlador de porta. Por exemplo, um controlador de porta é capaz de executar a operação somente coletor e o driver cliente relata essas informações. No entanto, o restante do sistema pode não estar configurado corretamente para a operação somente coletor. Nesse caso, o fabricante do sistema pode relatar que os conectores são capazes de operação somente origem no Repositório de Recursos. A configuração no Repositório de Funcionalidades tem precedência sobre as informações relatadas pelo driver.

  • Notifique UcmTcpciCx com todos os dados relevantes relacionados aos alertas.

  • Opcional. Execute algum processamento extra depois que um modo alternativo for inserido/encerrado. O driver é informado sobre esses estados pela extensão de classe por meio de solicitações IOCTL.

Registrar o driver cliente com UcmTcpciCx

Referência de exemplo: consulte EvtPrepareHardware em Device.cpp.

  1. Em sua implementação de EVT_WDF_DRIVER_DEVICE_ADD, chame UcmTcpciDeviceInitInitialize para inicializar a estrutura opaca WDFDEVICE_INIT. A chamada associa o driver do cliente à estrutura .

  2. Depois de criar o objeto de dispositivo de estrutura (WDFDEVICE), chame UcmTcpciDeviceInitialize para registrar o mergulhador do cliente com UcmTcpciCx.

Inicializar o canal de comunicações I2C para o hardware do controlador de porta

Referência de exemplo: consulte EvtCreateDevice em Device.cpp.

Na implementação do EVT_WDF_DEVICE_PREPARE_HARDWARE, leia os recursos de hardware para abrir um canal de comunicação. Isso é necessário para recuperar recursos de PD e ser notificado sobre alertas.

A maioria dos controladores TCPCI são conectados a C2. No exemplo de referência, o driver do cliente abre um canal I2 usando a interface de programação SpbCx (SPB Framework Extension).

O driver cliente enumera os recursos de hardware chamando WdfCmResourceListGetDescriptor.

Os alertas são recebidos como interrupções. Portanto, o driver cria um objeto de interrupção de estrutura e registra o ISR que manipula os alertas. O ISR executa operações de leitura e gravação de hardware, que bloqueiam até que o acesso ao hardware seja concluído. Como a espera é inaceitável no DIRQL, o driver executa o ISR em PASSIVE_LEVEL.

Inicializar os recursos type-C e PD do controlador de porta

Referência de exemplo: consulte EvtDeviceD0Entry em Device.cpp.

Em sua implementação de EVT_WDF_DEVICE_D0_EXIT,

  1. Comunique-se com o hardware do controlador de porta e recupere a identificação e os recursos do dispositivo lendo vários registros.

  2. Inicialize UCMTCPCI_PORT_CONTROLLER_IDENTIFICATION e UCMTCPCI_PORT_CONTROLLER_CAPABILITIES com as informações recuperadas.

  3. Inicialize UCMTCPCI_PORT_CONTROLLER_CONFIG estrutura com as informações anteriores passando as estruturas inicializadas para UCMTCPCI_PORT_CONTROLLER_CONFIG_INIT.

  4. Chame UcmTcpciPortControllerCreate para criar o objeto do controlador de porta e recuperar o identificador UCMTCPCIPORTCONTROLLER.

Configurar um objeto de fila de estrutura para receber solicitações do UcmTcpciCx

Referência de exemplo: consulte EvtDeviceD0Entry em Device.cpp e HardwareRequestQueueInitialize em Queue.cpp.

  1. Em sua implementação de EVT_WDF_DEVICE_D0_EXIT, crie um objeto de fila de estrutura chamando WdfIoQueueCreate. Nessa chamada, você precisará registrar sua implementação de retorno de chamada para lidar com solicitações IOCTL enviadas por UcmTpciCx. O driver do cliente pode usar uma fila gerenciada por energia.

    Durante a execução dos computadores de estado Tipo C e PD, o UcmTpciCx envia comandos para o driver cliente a ser executado. UcmTcpciCx garante no máximo uma solicitação de controlador de porta pendente a qualquer momento.

  2. Chame UcmTcpciPortControllerSetHardwareRequestQueue para registrar o novo objeto de fila de estrutura com UcmTpciCx. Depois que essa chamada for bem-sucedida, UcmTcpciCx colocará objetos de fila de estrutura (WDFREQUEST) nessa fila quando exigir a ação do driver.

  3. Implemente a função de retorno de chamada EvtIoDeviceControl para lidar com essas IOCTLs.

Código de controle Descrição
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_STATUS Obtém valores de todos os registros de status de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal. O driver do cliente deve recuperar os valores dos registros CC_STATUS, POWER_STATUS e FAULT_STATUS.
IOCTL_UCMTCPCI_PORT_CONTROLLER_GET_CONTROL Obtém os valores de todos os registros de controle definidos de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONTROL Define o valor de um registro de controle definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT Define o Registro DE TRANSMISSÃO definido de acordo com a Especificação da Interface do Controlador de Porta do Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_TRANSMIT_BUFFER Define o registro de TRANSMIT_BUFER definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_RECEIVE_DETECT Define o registro de RECEIVE_DETECT definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_CONFIG_STANDARD_OUTPUT Define o registro de CONFIG_STANDARD_OUTPUT definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_COMMAND Define o valor de um registro de comando definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_SET_MESSAGE_HEADER_INFO Define o valor do registro de MESSAGE_HEADER_INFO definido de acordo com a Especificação da Interface do Controlador de Porta Tipo C do Barramento Serial Universal.
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_ENTERED Notifica o driver cliente de que um modo alternativo é inserido para que o driver possa executar outras tarefas.
IOCTL_UCMTCPCI_PORT_CONTROLLER_ALTERNATE_MODE_EXITED Notifica o driver cliente de que um modo alternativo é encerrado para que o driver possa executar outras tarefas.
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_CONFIGURED Notifica o driver cliente de que o modo alternativo DisplayPort no dispositivo parceiro foi configurado com atribuição de pino para que o driver possa executar outras tarefas.
IOCTL_UCMTCPCI_PORT_CONTROLLER_DISPLAYPORT_HPD_STATUS_CHANGED Notifica o driver do cliente de que o hot-plug detecta status da conexão DisplayPort foi alterado para que o driver possa executar outras tarefas.
  1. Chame UcmTcpciPortControllerStart para instruir UcmTcpciCx a iniciar o controlador de porta. UcmTcpciCx assume o controle de USB Tipo C e Entrega de Energia. Depois que o controlador de porta for iniciado, UcmTcpciCx poderá começar a colocar solicitações na fila de solicitações de hardware.

Manipular alertas do hardware do controlador de porta

Referência de exemplo: consulte ProcessAndSendAlerts em Alert.cpp

O driver do cliente deve lidar com alertas (ou eventos) recebidos do hardware do controlador de porta e enviá-los para UcmTcpciCx com dados relacionados ao evento.

Quando ocorre um alerta de hardware, o hardware do controlador de porta aciona o pino DE ALERTA alto. Isso faz com que o ISR do driver do cliente (registrado na etapa 2) seja invocado. A rotina atende à interrupção de hardware em PASSIVE_LEVEL. A rotina determina se uma interrupção é um alerta do hardware do controlador de porta; nesse caso, ele conclui o processamento do alerta e notifica UcmTcpciCx chamando UcmTcpciPortControllerAlert.

Antes de chamar UcmTcpciPortControllerAlert, o cliente é responsável por incluir todos os dados relevantes relacionados ao alerta em uma estrutura de UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. O cliente fornece uma matriz de todos os alertas que estão ativos porque há a possibilidade de que o hardware possa declarar vários alertas simultaneamente.

Aqui está um exemplo de fluxo de tarefas para relatar a alteração no Status do CC.

  1. O cliente recebe um alerta de hardware.

  2. O cliente lê o registro de ALERTA e determina os alertas de tipo que estão ativos.

  3. O cliente lê o registro CC STATUS e descreve o conteúdo do registro CC STATUS no UCMTCPCI_PORT_CONTROLLER_ALERT_DATA. O driver define o membro AlertType como UcmTcpciPortControllerAlertCCStatus e membro CCStatus do registro.

  4. O cliente chama UcmPortControllerAlert para enviar os alertas de hardware da matriz para UcmTcpciCx.

  5. O cliente limpa o alerta (isso pode acontecer a qualquer momento depois que o cliente recupera as informações de alerta)

Solicitações de processo recebidas de UcmTcpciCx

Referência de exemplo: consulte PortControllerInterface.cpp

Como parte da execução do computador de estado, o UcmTcpciCx precisa enviar solicitações para o controlador de porta. Por exemplo, ele precisa definir o TRANSMIT_BUFFER. Essa solicitação é entregue ao driver do cliente. O driver define o buffer de transmissão com os detalhes fornecidos por UcmTcpciCx. A maioria dessas solicitações se traduz em uma leitura ou gravação de hardware pelo driver cliente. Os comandos devem ser assíncronos porque o DPM não pode bloquear a espera da conclusão de uma transferência de hardware.

UcmTcpciCx envia os comandos como Código de Controle de E/S que descrevem a operação get/set necessária do driver cliente. Na configuração da fila do driver cliente, o driver registrou sua fila com UcmTcpciCx. UcmTcpciCx começa a colocar objetos de solicitação de estrutura na fila que requer operação do driver. Os códigos de Controle de E/S são listados na tabela na etapa 4.

É responsabilidade do driver cliente concluir solicitações em tempo hábil.

O driver do cliente chama WdfRequestComplete no objeto de solicitação de estrutura com um status de conclusão quando tiver terminado a operação solicitada.

O driver do cliente pode precisar enviar uma solicitação de E/S para outro driver para executar a operação de hardware. Por exemplo, no exemplo, o driver envia uma solicitação SPB para o controlador de porta conectado a C I2. Nesse caso, o driver não pode encaminhar o objeto de solicitação de estrutura que recebeu de UcmTcpciCx porque o objeto de solicitação pode não ter o número correto de locais de pilha no WDM IRP. O driver do cliente deve criar outro objeto de solicitação de estrutura e encaminhá-lo para outro driver. O driver do cliente pode pré-alocar objetos de solicitação necessários durante a inicialização, em vez de criar um sempre que recebe uma solicitação de UcmTcpciCx. Isso é possível porque UcmTcpciCx garante que haverá apenas uma solicitação pendente a qualquer momento.

Consulte Também