# 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 - Lê `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 disable ``` **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