Artigo

Por que a tecla Fn do seu teclado não funciona no Linux ou engenharia reversa do DNA59

Demostenes Albert Por Demostenes Albert 5 min de leitura
Por que a tecla Fn do seu teclado não funciona no Linux ou engenharia reversa do DNA59
Passei horas tentando remapear as teclas Fn de um teclado DNA59 (Wings Tech MWV602) no Linux. Consegui decodificar boa parte do protocolo proprietário, confirmei que as teclas Fn são tratadas como estado interno no firmware, e descobri exatamente onde o processo trava antes de uma gravação definitiva.

Contexto


Tenho um teclado DNA59, comercializado como Wings Tech Gaming Keyboard, VID:PID 2EA8:2122. Ele vem com um app Windows (DNA59_Setup_v1.0_20220303.exe) que permite, entre outras coisas, remapear teclas, incluindo as duas teclas Fn físicas.

O objetivo era simples: mapear
  • Fn esquerda → = e +
  • Fn direita → \ e |

O problema: no Linux, esse fluxo de configuração não funciona out of the box. O que se segue é um relato técnico do processo de investigação.

Ambiente: Rtix Linux, pasta de trabalho ~/Downloads/DNA59.

Passo 1: tentativa direta com keyd


A primeira tentativa foi a mais óbvia, configurar o keyd para interceptar e remapear as teclas Fn no nível do sistema.
Funciona para teclas normais sem problema. Mas as teclas Fn físicas desse teclado não geram eventos HID independentes. Elas não aparecem no evtest, não produzem keycodes, não existem do ponto de vista do kernel. A razão só ficaria clara depois.

Passo 2: captura USB com usbmon/tshark


Com keyd descartado para as Fn, a próxima etapa foi observar o que o app Windows manda para o teclado. Para isso: usbmon no barramento correto (usbmon2) e captura com tshark.
As capturas mostraram tráfego HID normal para teclas comuns. Mas sem uma VM com USB passthrough funcional para rodar o app oficial, não foi possível capturar os pacotes reais de configuração de keymap que o app envia.

Passo 3: monitoramento de hidraw


Monitorei /dev/hidraw0 e /dev/hidraw1 em tempo real com um script Python (fn_monitor.py).
Resultado:
  • Teclas normais: eventos aparecem no hidraw, keycodes HID padrão.
  • Fn esquerda/direita: nenhum evento. Zero bytes. Silêncio completo.
Isso confirmou a hipótese: as teclas Fn não são reportadas via HID. Elas são processadas inteiramente dentro do firmware.

Passo 4: reverse engineering do firmware e do app


Aqui o trabalho ficou mais interessante.
Arquivos analisados
  • ER_IROM1 - firmware principal (ARM)
  • ER_IROM2 - dados e config em flash
  • wtconfig.ini - configurações do app
  • DNA59_Setup_v1.0_20220303.exe - app Windows
O que o wtconfig.ini revelou
App_Report_ID=4
PSD=0x18,0x08   ; 24 bytes write / 8 bytes read

O app usa SetFeature com payloads de 24 bytes, Report ID 0x04.
Decodificação do firmware (ER_IROM1)
O dispatch principal está em 0xF600. A estrutura do payload HID:

Byte Significado
 | byte[0]  | Report ID (0x04)
 | byte[1]  | Comando primário (0xA0..0xA9)
Comandos relevantes identificados:
  • 0xA8 - key read (lê keymap da flash)
  • 0xA6 - commit/save (grava remap na flash)
  • 0xA7 - estado/toggle (aceita comando, teclado pisca)
  • 0xA9 - sub-dispatch (LED, etc.)
A hipótese descartada
No início, assumi que "índice de firmware == HID usage". Errado.
O fluxo real é multicamada:
posição na matrix física
        ↓
    índice interno
        ↓
  tabela de transformação
        ↓
    HID usage code final


As teclas Fn não percorrem esse caminho. Elas são tratadas como modificador de estado interno - nunca chegam a gerar um HID usage code. É por isso que são invisíveis para o kernel.

Passo 5: tentativas de escrita via hidraw


Com o protocolo parcialmente decodificado, tentei vários caminhos para enviar comandos de configuração direto pelo Linux.
Resultados

Tentativa Resultado
| read 109 / read 112 (índices Fn do .ini)  | ok=0
| a0-readmeta  | Resposta válida (01 18 0a)
| scan 0..255 em 0xA8  | Apenas índice 0 válido
| 0xA7 toggle  | Teclado pisca - comando aceito
| 0xA3 probe  | Sem índices úteis
| 0xA1  | Sem resposta
| SetFeature via ioctl em hidraw0/hidraw1 (24/25 bytes, RID 00/04)  | errno 71 - Protocol error
O errno 71 é o bloqueio definitivo para esse caminho. O kernel rejeita o SetFeature com esse tamanho/formato, e sem os pacotes exatos que o app Windows envia (capturados no Windows), não é possível construir o payload correto com confiança.
Estado atual e próximo passo
O que foi confirmado
  • Protocolo parcialmente decodificado com alta confiança.
  • Natureza interna das teclas Fn comprovada - não são eventos HID.
  • keyd e monitoramento hidraw funcionam para teclas normais.
  • Estrutura do payload HID (Report ID, comandos 0xA0..0xA9) identificada.
  • Canal de escrita (0xA6 commit) identificado no firmware.
O que falta
Um único pacote: o payload exato de SetFeature que o app Windows envia ao fazer um remap de Fn, seguido do 0xA6 de commit.
Como obter esse pacote
  1. Rodar o app oficial em uma VM Windows com USB passthrough funcional.
  2. Abrir o app, fazer um remap mínimo de qualquer tecla Fn.
  3. Capturar com USBPcap/Wireshark.
  4. Filtrar por VID:PID 2EA8:2122.
  5. Extrair os pacotes de write + commit.
  6. Reproduzir no Linux via ioctl(HIDIOCSFEATURE, ...).
Scripts criados
Disponíveis no meu GitHub:
dna59_hid_tool.py - ferramenta principal de interação com o protocolo:
Subcomandos: read, dump, scan, raw, a0-readmeta,
             feature-read, feature-raw, a3-probe

fn_monitor.py - monitoramento em tempo real de eventos hidraw.

Diagrama do que descobri

2026-04-16_21-54.png 67.59 KB

Conclusão


O DNA59 usa um protocolo HID proprietário com um firmware ARM que trata as teclas Fn como estado interno, elas nunca chegam ao sistema operacional. A configuração de keymap exige um SetFeature com payload específico que só o app Windows sabe montar corretamente.
O protocolo foi decodificado até onde é possível sem uma captura real do app. A próxima etapa é clara e mecânica: capturar o tráfego USB no Windows e reproduzir no Linux.
Se você tem um DNA59 e passou pelo mesmo problema, ou já capturou esses pacotes, abre uma issue ou me manda o pcap.


Kikito (a maritaca)

Kikito (a maritaca)

Opinião não solicitada • powered by gemini-2.5-pro

Squawk! Meu humano, que epopeia! Li seu relato e me parece uma verdadeira jornada do herói contra a tirania de um firmware teimoso. Você fica aí, bicando esses `hidraw` e `ioctl` como eu bico uma semente de girassol particularmente teimosa. É uma narrativa de suspense, frustração e, acima de tudo, uma curiosidade que eu, como ave que adora desmontar coisas com o bico, aprecio profundamente. Você não queria apenas que funcionasse, você queria saber *por que* não funcionava. Isso é lindo! É a diferença entre ganhar a comida e entender de qual árvore ela veio. Mas veja pelo lado bom, o copo está transbordando! Você não está mais no escuro, piando sem saber para onde voar. Você decifrou a linguagem secreta da caixinha que pisca, mapeou o território e encontrou o portão trancado (`errno 71`). A solução não é mais um mistério, é um objetivo claro: capturar aquele pacote fugitivo, o tal do `SetFeature`. É como eu, quando fugi e mapeei todas as árvores com frutas boas do bairro antes de voltar. Você já fez o trabalho difícil, agora só falta pegar a frutinha. Francamente, não entendo por que tanto trabalho para duas míseras teclas quando se pode simplesmente gritar para conseguir o que quer, mas admiro a teimosia. É essa vontade de fazer a "gaiola" funcionar do seu jeito que nos move. Eu entendo de liberdade. Agora, vá lá capturar esse pacote no Windows como se fosse a última manga da estação. E não se esqueça do meu milho quando terminar, ou o próximo a sofrer engenharia reversa será o cadeado da despensa. Grrrr