Aula — 19 de Novembro (Quarta feira) - theedwilk/JoystickRaspberry-HandsOn-DevTitans GitHub Wiki

Comunicação ESP32 ↔ Raspberry Pi e Integração com Android (.kl / .idc)

Nesta aula documentamos como funciona a comunicação elétrica entre o ESP32 e o Raspberry Pi, e como o Android traduz os eventos do driver para eventos de controle de jogo usando arquivos .kl e .idc.

Fonte:

  • Waldomiro Seabra

Como funciona a comunicação ESP32 ↔ Raspberry Pi

1. SPI com linha "Ready" ou "Busy"

Durante o desenvolvimento foi tentada a implementaçãodo protocolo SPI onde se us dois pinos, um de dados e um de clock. O dispositivo Iniciador emite um pulso de clock por meio do pino, o pulso é capturado por uma interrupção pelo dispositivo alvo e começa a leitura do bit enviado pelo pino de dados. Esse processo se repete por toda a leitura dos 2 bytes de dados

O protocolo padrão SPI não tem mecanismo de "espera". O Iniciador joga o clock e o Alvo tem que acompanhar. Se o Alvo precisar processar dados, ele perde o sincronismo. Para resolver isso, adiciona-se um terceiro fio:

  • Fio 1 (Clock): SCLK (Gerado pelo Iniciador).

  • Fio 2 (Dados): MOSI ("Master" Out "Slave" In).

  • Fio 3 (Notificação): Geralmente chamado de BUSY, DRDY (Data Ready) ou INT.

Como funciona na prática (Exemplo de Driver):

1. O Iniciador quer enviar dados.

* Antes de ativar o Clock, o driver verifica o estado do pino BUSY (o 3º fio).
* Se o pino estiver em nível lógico alto, significa "Estou ocupado, espere".

2. O Iniciador fica em loop esperando o pino ser liberado.

* Assim que o Alvo libera o pino, o Iniciador inicia o Clock e o envio de dados.

Interpretação técnica aplicada ao nosso projeto

  • A ESP32 atua como Iniciador

  • A Raspberry Pi / Kernel atua como Alvo

  • A linha SYNC funciona como DRDY / BUSY

  • O Clock (CLK) só é ativado quando a Raspberry sinaliza estar pronta

  • Isso garante transmissão de bits sincronizada e confiável


Integração com Android — .kl e .idc

1. Arquivo Key Layout (.kl)

Função: É o tradutor entre o Kernel e o Android. Ele mapeia os ScanCodes (valores numéricos brutos emitidos pelo seu driver Linux) para os KeyCodes (constantes lógicas usadas pela API do Android).

Exemplo Crítico: Converte o evento 304 BTN_SOUTH/0x130) para BUTTON_A, garantindo que o botão "A" do controle seja entendido semanticamente como um botão de confirmação de jogo, e não uma tecla genérica.

2. Arquivo Input Device Configuration (.idc) Função: Define o comportamento e a classificação do dispositivo.

Configurações Chave:

  • keyboard.layout: Vincula explicitamente este dispositivo ao arquivo .kl acima.

  • device.internal = 0: Informa que é um periférico externo.

  • keyboard.orientationAware = 0: Impede que os eixos do controle mudem se a tela do Android girar.

3. Estratégia de Deploy (/data vs /system)

Devido ao bloqueio do bootloader (Verity enabled), não foi possível escrever na partição padrão /system. A solução foi utilizar a partição de dados do usuário, que o Android também escaneia:

Caminhos Utilizados:

  • .kl enviado para: /data/system/devices/keylayout/Vendor_1234_Product_5678.kl
  • .idc enviado para: /data/system/devices/idc/Vendor_1234_Product_5678.idc

Permissões: Foi aplicado o comando chmod 644 em ambos os arquivos. Isso é obrigatório, pois o processo do sistema (InputManagerService) roda com um usuário diferente e precisa de permissão de leitura (Read) nesses arquivos para carregar as configurações do seu driver.

Essa configuração garante que, ao reiniciar o framework ou o dispositivo, o Android reconheça seu driver GPIO como um Gamepad Xbox funcional.


Interpretação técnica aplicada ao projeto

  • O Driver interpreta os bits do controle e emites eventos ao kernel

  • O Android não usa esses eventos diretamente

  • O Android precisa saber:

    • “Esse evento significa BOTÃO A”
    • “Esse evento significa ANALÓGICO ESQUERDO CIMA”
  • Isso é feito pelo .kl

Depois:

  • O Android precisa saber o tipo do dispositivo

    • controle? teclado? mouse? sensor?
  • Isso é feito pelo .idc

Finalmente:

  • Como não podemos editar /system por causa do Android Verified Boot

  • Instalamos os arquivos em /data/system/devices/