KVMote/CLAUDE.md
Ricardo Carneiro 91e43e73d5 fix: ajustes
2026-03-22 18:59:18 -03:00

172 lines
6.3 KiB
Markdown

# CLAUDE.md — KVMote
Arquivo de contexto para o Claude Code. Leia antes de qualquer alteração no projeto.
---
## O que é o KVMote
KVM (Keyboard/Video/Mouse) over Bluetooth. Controla um PC remoto (cliente) a partir de um PC host usando um Arduino Leonardo como dispositivo HID USB. O host captura teclado e mouse via hooks globais do Windows e retransmite os eventos ao Arduino por Bluetooth Serial (HC-06), que os injeta como HID no PC cliente.
**Sem software no PC cliente.** O Arduino aparece como teclado + mouse USB padrão.
---
## Hardware
- **Arduino Leonardo** (ATmega32U4) — único modelo com HID USB nativo
- **HC-06** módulo Bluetooth (Slave) conectado ao Serial1 do Leonardo
- **LED RGB** nos pinos: R=5, G=6, B=9 (PWM, analogWrite)
- **Baud rate:** 9600 (padrão HC-06 de fábrica)
```
Host PC ──BT SPP──► HC-06 ──Serial1──► Arduino Leonardo ──USB HID──► Cliente PC
(KVMote.exe) (COM virtual) (sem software)
```
---
## Estrutura de arquivos
| Arquivo | Função |
|---|---|
| `KVMote.ino` | Firmware Arduino: máquina de estados, HID, LED |
| `Principal.cs` | Lógica principal C#: hooks, KVM, serial, clipboard |
| `Principal.Designer.cs` | UI WinForms: layout, controles |
| `Program.cs` | Entry point: DPI + ApplicationConfiguration |
| `Form1.cs` / `Form1.Designer.cs` | Stubs vazios (manter, não remover) |
| `KVMote.csproj` | .NET 8, ImplicitUsings=disable, System.IO.Ports |
---
## Protocolo serial binário (Host → Arduino)
| Comando | Bytes | Descrição |
|---|---|---|
| `M` dx dy | 3 | Mouse move (int8 com sinal) |
| `W` delta | 2 | Mouse wheel / touchpad (int8) |
| `K` char | 2 | Keyboard.write(char) — digita caractere |
| `C` L\|R | 2 | Mouse click esquerdo ou direito |
| `P` keycode | 2 | Keyboard.press(keycode) — tecla segurada |
| `U` keycode | 2 | Keyboard.release(keycode) |
| `A` | 1 | Keyboard.releaseAll() |
| `D` L\|R | 2 | Mouse.press() — botão segurado |
| `E` L\|R | 2 | Mouse.release() |
| `O` | 1 | LED magenta (entrou no cliente) |
| `H` | 1 | LED azul (host conectado) |
| `G` | 1 | LED verde (host desconectado) |
| `~` | 1 | Ping → Arduino responde `[PONG]` |
**Arduino → Host:** apenas `[PONG]` como string ASCII.
---
## LED RGB — cores e significados
| Cor | Estado |
|---|---|
| 🟢 Verde (0,255,0) | Boot / host desconectado |
| 🔵 Azul (0,0,255) | Host conectado, mouse no host |
| 🟣 Magenta (255,0,255) | Mouse no PC cliente |
Sem flashes de tráfego — cor sólida estática.
---
## Lógica KVM (Principal.cs)
### Auto-detect de porta
`AutoDetectAsync()``ProbePorts()`: abre cada COM, envia `~`, aguarda 500ms por `[PONG]`.
### Hooks globais
- `WH_MOUSE_LL` (14) e `WH_KEYBOARD_LL` (13) via `SetWindowsHookEx`
- Instalados após conectar, removidos ao desconectar
### Entrada no modo cliente
- Mouse atinge a borda configurada (Left/Right/Above/Below)
- `EnterClientMode()`: esconde cursor, warp para centro da tela
- Técnica FPS: `SetCursorPos` para posição fixa, acumula deltas reais
### Coordenadas virtuais
- `_virtualX/_virtualY`: acumulam deltas enviados ao cliente
- Retorno ao host quando virtual cruza `-ReturnThreshold` (15px) na direção de entrada
### Saída do modo cliente
- `ExitClientMode()`: mostra cursor, reposiciona 40px dentro da borda, envia `A` + `H`
- Também chamado em `BeginReconnect()` para não deixar cursor sumido
### Throttle de mouse
- `SendMouse()` usa `Monitor.TryEnter` (lossy) — descarta se canal ocupado
- Throttle de 50ms (~20 pacotes/s) — seguro para BT 9600 baud
### Wheel / touchpad
- Acumula `_wheelAccum += rawDelta`
- Envia ao Arduino quando acumula ±120 (1 notch de mouse wheel)
- Captura smooth scroll de touchpad (deltas pequenos ±3..±15)
### Clipboard (Ctrl+V em modo cliente)
- Hook intercepta Ctrl+V e Shift+Ins em modo cliente
-`Clipboard.GetText()` do host
- Limite: `MaxClipChars = 300`
- Envia `A` (releaseAll) + 100ms antes de digitar
- Digita via `K` + byte a cada 20ms (~50 chars/s)
- Layout PT-BR ABNT2: `PtBrMap` remapeia chars via substituição de byte antes de `Keyboard.write()`
### Reconexão
- `BeginReconnect()`: chamado em timeout serial ou exceção de porta
- Retenta a cada 2500ms
- Chama `ExitClientMode()` imediatamente (cursor volta sempre)
- `!_isReconnecting` bloqueia entrada no modo cliente durante reconexão
---
## Convenções C# obrigatórias
```xml
<ImplicitUsings>disable</ImplicitUsings>
```
**Todo `using` deve ser explícito.** Faltou um → CS0103 em runtime.
**Designer file:** todos os membros de Form precisam do prefixo `this.`:
```csharp
this.btnConnect.Text = "Conectar"; // ✓
btnConnect.Text = "Conectar"; // ✗ CS0103 em ImplicitUsings=disable
```
**AutoScaleMode:** usar `Dpi` com `AutoScaleDimensions = new SizeF(96F, 96F)`. Nunca `None` (quebra DPI alto) nem `Font` (escala diferente por máquina).
**Form1.cs / Form1.Designer.cs:** manter como stubs vazios (`namespace KVMote { }`). O VS inclui no .csproj automaticamente; remover do disco pode causar erro de build.
---
## Como gerar o .exe portable
```powershell
# Self-contained (~70MB) — sem dependência de .NET no destino
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true
```
Saída: `bin\Release\net8.0-windows\win-x64\publish\KVMote.exe`
**Não usar o "Publicar" do Visual Studio** — gera ClickOnce (setup.exe + arquivos separados).
---
## Limitações conhecidas
- **Canal único 9600 baud:** mouse trava durante paste de clipboard (design proposital)
- **Chars não-ASCII** (`é`, `ã`, `ç`...): não enviáveis via clipboard (filtrados)
- **PT-BR:** `/`, `?`, `\`, `|`, `@` não mapeáveis via `Keyboard.write()` — ignorados no paste
- **Monitor único:** `Screen.PrimaryScreen` — multi-monitor não implementado
- **Um cliente por vez:** arquitetura 1:1 (um HC-06, um Arduino)
- **BT desconectado:** se Arduino perder USB, BT cai, `BeginReconnect()` age em ~3s
---
## Roadmap (não implementado)
- **Clipboard Bridge:** app separado para compartilhar clipboard via OneDrive (pasta compartilhada) entre host e cliente corporativo
- **Multi-monitor:** detectar em qual monitor o cursor está ao cruzar a borda
- **Layout US-International completo:** mapeamento de dead keys para paste
- **Baud rate configurável:** AT commands no HC-06 para 115200