USB HID – Human Interface Device Class: Exemplo com a placa FRDM-KL25Z

A classe de dispositivos USB HID foi inicialmente criada para que dispositivos de entrada de dados pudessem ser adicionados facilmente em um computador. Alguns exemplos são: teclados, mouse, joystick, entre outros. Essa classe será tomada como exemplo por ser a mais simples.

O artigo apresenta algumas definições gerais do protocolo USB. No final, um exemplo de aplicação executado no PC para controlar um LED da placa Freedom Board KL25Z é demonstrado. Em cada tópico algumas referências serão citadas para consulta.

Introdução ao protocolo USB

Quando conectamos um dispositivo USB no computador, o SO se encarrega de exportar as informações sobre o dispositivo. Essas informações são obtidas a partir dos descritores USB.

Propriedades de um dispositivo USB.
Figura 1: Propriedades de um dispositivo USB.

Essas informações são obtidas com o dispositivo conectado, utilizando requisições do tipo GetDescriptor definidas no protocolo USB. Essa requisição é estruturada por uma operação de controle chamada de Setup que é enviada para o dispositivo USB. Os elementos que compõe essa operação são ilustrados abaixo.

bmRequestTypebRequestwValuewIndexwLengthData

Esses campos especificam uma operação de controle. Por exemplo, os campos bmRequestType e bRequest indicam a operação GetDescriptor quando os respectivos valores são: 0x80 e 0x06. Outras operações são apresentadas neste link: Setup Packet.

OffsetCampoTamanho em bytesTipoDescrição
0bmRequestType1Bit-MapD7 Data Phase Transfer Direction
0 = Host to Device
1 = Device to Host
D6..5 Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved
D4..0 Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other
4..31 = Reserved
1bRequest1Value

Request

2wValue2Value

Value

4wIndex2Index or Offset

Index

6wLength2Count

Number of bytes to transfer if there is a data phase

Alguns campos dos descritores podem especificar uma referência para outro descritor. Por exemplo, algumas configurações são apenas mensagens (strings), como o nome do dispositivo que foi conectado. Para tal, existem descritores de string.

O tipo do descritor é indicado pelo campo wValue. Já o campo wIndex é utilizado conforme o descritor solicitado. Uma requisição desse tipo com wValue e wIndex iguais a 0x03 e 0x01, respectivamente, indica uma operação de leitura do descritor de string 1.

Transferência de dados

No tópico anterior foi apresentada a operação de controle chamada Setup. A partir da operação de Setup, o host consegue enviar e receber informações do dispositivo USB. A informação apresentada é apenas uma parte do protocolo USB. Na verdade, os campos apresentados formam um pacote de dados, denominado Setup Packet.

Um pacote é um conjunto de bytes.

Em geral, a transferência de dados entre os dois elementos ocorre em pacotes – seguindo o formato especificado no protocolo de comunicação -, sendo que cada pacote tem uma função específica. De modo geral, são definidos três tipos de transferências, com o seguinte formato: TOKEN + DATA + HANDSHAKE.

O Setup é uma exemplo da informação enviada em DATA.

Idependente do pacote, o primeiro byte enviado é um número de identificação PID (Packet Identifier) que tem apenas um byte (somente os primeiros quatro bits são utilizados para definir o tipo do pacote, o restante dos bits são espelhados). Na tabela abaixo são destacados os tipos de pacote e as respectivas funções. Os dois primeiros bits determinam o tipo e o restante é utilizado para definir a função/operação.

PID TypePID NamePID<3:0>
TokenOUT0001
IN1001
SOF0101
SETUP1101
DataDATA00011
DATA11011
DATA20111
MDATA1111
HandshakeACK0010
NAK1010
STALL1110
NYET0110
SpecialPRE1100
ERR1100
SPLIT1000
PING0100
Reserved0000

Operações de Controle

Toda transferência é iniciada enviando um pacote TOKEN. Para operação de Setup, o PID do pacote deve ser 1101. A estrutura desse pacote é ilustrada abaixo (Sync e EOP indicam o início e o fim da transferência de um pacote).

Sync
PID
ADDR
ENDP
CRC5
EOP
 
8 bits
7 bits
4 bits
5 bits
 

Essa operação de controle deve ser realizada em um dispositivo específico, sendo determinado pelo campo ADDR. Toda comunicação está relacionada a um local em que os dados são armazenados, denominado endpoint (ENDP). Um dispositivo USB pode apresentar até 16 endpoints para função de entrada (IN), e outros 16 para saída (OUT) de dados. A direção indica:

  • IN: do dispositivo para o host;
  • OUT: do host para o dispositivo.

Cabe ressaltar que somente o endpoint 0 é utilizado para as operações de controle.

Na sequência, as informações da operação de Setup são enviadas dentro do pacote DATA. 

Sync
PID
DATA
CRC16
EOP
 
8 bits
(0-1024)
x 8 bits
16 bits
 

Por fim, a conexão é finalizada com um pacote HANDSHAKE. Note que o campo PID define a operação: ACK, NAK, STALL ou NYET.

Sync
PID
EOP
 
8 bits
 

Fluxo de comunicação e descritores

A primeira comunicação servirá para descobrir o tamanho máximo do pacote que o dispositivo está configurado para operar. Os pacotes de configuração (SETUP) sempre serão enviados ao endpoint 0. Como destacado, o Setup possui 8 bytes para especificar a operação de controle. A estrutura que representa esse bloco de dados é mostrada abaixo.

Os descritores USB também podem ser implementados como estruturas. A definição de cada campo pode ser vista neste link.

Reports

Os dados que o dispositivos USB-HID exporta são transferidos por estruturas chamadas de reports. A estrutura do relatório é transformada em uma tabela de valores e armazenada em um descritor. Esse descritor é utilizado para informar o host sobre a estrutura do report.

Nesse exemplo, o dispositivo será utilizado somente para controlar um LED. Para construir a estrutura de um report foi utilizada a ferramenta HID Descriptor. Mais detalhes dos campos do report podem ser obtidos no mesmo link.

Ferramenta HID Descriptor para listar dispositivos USB HID.
Figura 2: Ferramenta HID Descriptor.

Configurando USB- HID no microcontrolador KL25Z

O código apresentado é uma modificação deste projeto: Minimal USB HID example for Kinetis L.

A configuração do controlador USB é realizada a partir de registradores e estruturas de dados armazenados em memória. O periférico controla toda recepção de pacotes e notifica a aplicação usando interrupções, facilitando o desenvolvimento da aplicação.

Recepção de pacotes e notificação.
Figura 3: Recepção de pacotes e notificação.

Quando um dispositivo é conectado no barramento USB, ocorre a condição de RESET. Nesse momento, o dispositivo deve habilitar o endpoint 0 e configurar o endereço com o valor 0. Isso é necessário, pos o host iniciará uma comunicação com o dispositivo de endereço 0 no endpoint 0. 

Como dito, a comunicação ocorre entre o host e um endpoint. Para facilitar tal operação, o periférico USB da KL25Z conta com uma estrutura chamada Buffer Descriptor Table (BDT) que é armazenada na memória. Nessa tabela são armazenados os descritores (BD) de cada endpoint.

Buffer Descriptor

O Buffer Descriptor (BD) é utilizado para controlar as operações em um endpoint. Cada endpoint possui uma configuração de 8 bytes. Considerando que cada endpoint possui um canal de entrada e outro saída, são necessários 16 bytes.

Para possibilitar que um endpoint possa operar enquanto os dados são processados, existe um mecanismo de double buffer. Considerando isso, o BD é utilizado para:

  • Indicar quem tem acesso ao buffer do endpoint na memória (bit OWN);
  • Determinar qual buffer está sendo utilizado (bit DATA0/1);
  • Apontar para o endereço base do endpoint na memória (32 bits);
  • Definir quantos bytes serão transferidos (campo BC de 10 bits).

O formato do BD é ilustrado na figura abaixo. Para mais informações, consulte o documento do microcontrolador, na página 617.

Estrutura do Buffer Descriptor.
Figura 4: Estrutura do Buffer Descriptor. Fonte: KL25 Sub-Family Reference Manual.

Para representar o BD, a seguinte estrutura foi criada.

Buffer Descriptor Table

Tal estrutura é organizada em 512 bytes na memória, sendo referenciada a partir de um conjunto de registradores chamados de BDT Page Registers.

A USB possui um controlador DMA dedicado que é usado para acessar o BDT. Esse mecanismo é utilizado para acessar tal região de memória quando um token é recebido. Os dados indicados no BDT serão utilizados para acessar o buffer referente ao endpoint utilizado na comunicação.

O endereço acessado na tabela é formado pelos elementos ilustrados na Figura abaixo.

Composição do endereço para acessar um BD.
Figura 5: Composição do endereço para acessar um BD. Fonte: KL25 Sub-Family Reference Manual.

Abaixo é mostrado a definição do BDT com um vetor de estruturas do tipo BD. Como dito, para cada endpoint existem dois buffer duplicados para entrada e saída. Logo, são quatro buffers por enpoint.

Endpoint

Para representar o endpoint, foi criada a seguinte estrutura:

O handler é utilizado para definir a rotina de tratamento da transação conforme o PID recebido. Já o membro data foi utilizado para apontar para o buffer utilizado (BD que está sendo usado no momento).

Configuração inicial do periférico

Para operar no modo FullSpeed é necessário que a USB opere em 48 MHz. Tal configuração é realizada na função de inicialização do sistema. Abaixo são mostrados os procedimentos de configuração da USB.

No início somente a interrupção por Reset é ativada. A rotina de tratamento é mostrada a seguir:

  • Reset: Habilita o endpoint 0, determina o endereço do dispositivo igual a zero e habilita outras interrupções;
  • Token: Ocorre sempre que uma transação é finalizada. Obtém o endpoint, a operação e os dados envolvidos na transação.

Operações de controle

As operações realizadas no endpoint 0 são para obter informações do dispositivo e também configurá-lo. Nessa aplicação, somente os comandos SetAddress, SetConfiguration, GetDescriptor e GetInterface foram implementados. A seguir é mostrado um exemplo de operação do Setup. A partir dos dados é determinado qual requisição será processada.

Descritores

Dispositivos HID utilizam apenas transferências de controle e de interrupção. Nessas transferências, um pacote de dados pode conter até 64 bytes. Interrupção significa que o endpoint é utilizado para transferir poucos dados rapidamente. Nesse caso, o dispositivo USB deve ser reativo. Para tal, o endpoint é usado somente em uma direção.

Essas configurações são realizadas com o preenchimento das estruturas de dados mostradas a seguir.

Note que no descritor HID existe uma referência para estrutura do report.

Exemplo

A seguir é mostrado um exemplo de operação no endpoint 1, controlando o estado do LED RGB conectado no pino PB19. A aplicação verifica dois bytes recebidos para definir qual operação será realizada. O primeiro byte é utilizado para definir o LED e o segundo para determinar o estado.

Enviando informações para um dispositivo

Para enviar dados ao dispositivo foi criada uma aplicação em C#, utilizando a biblioteca HIDInterface.

Aplicação para enviar comandos de controle do LED.
Figura 6: Aplicação para enviar comandos de controle do LED.

O dispositivo é localizado utilizando as informações do PID e VID.

Por fim, os dados são enviados para o dispositivo conforme a operação solicitada.

Para saber mais

Algumas partes do projeto não foram apresentadas no artigo. O projeto completo pode ser acessado no github.

Para conhecer mais sobre o protocolo USB acesse os materiais:

Para descrição dos reports:

Para descrição do periférico, acesse o datasheet no microcontrolador:

Outros artigos do Embarcados:

Raspberry Pi Zero W – Utilizando placa de som USB

Usando FreeRTOS para aplicações com a Freescale FRDM KL25z

Conheça a FRDM KL25Z da NXP

Vale conferir o livro Tecnologia ARM escrito pelo Fábio Pereira. Esse livro possui uma seção com muita informação sobre o protocolo USB.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Software » USB HID - Human Interface Device Class: Exemplo com a placa FRDM-KL25Z
Comentários:
Notificações
Notificar
guest
1 Comentário
recentes
antigos mais votados
Inline Feedbacks
View all comments
Leonardo Miguel
Miguel
20/04/2019 20:38

Olá Fernando, seu artigo realmente foi um show de conhecimento sobre o protocolo USB.
Tenho uma duvida, eu consigo enviar comando “bytes” para um dispositivo USB HID Keybord, para fazer determinadas alterações?

Talvez você goste:

Séries

Menu

WEBINAR
 

BlueNRG-LP – Bluetooth 5.2 de longo alcance para aplicações industriais

Data: 05/11 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link