# KVMote — Conhecimento do Projeto Documento de referência técnica e histórico de decisões do projeto KVMote. --- ## O que é KVMote é um KVM (Keyboard, Video, Mouse) over Bluetooth que permite controlar um PC remoto usando o teclado e mouse do seu PC principal, sem instalar nenhum software no PC controlado. **Inspirado em:** Barrier / InputLeap / Mouse Without Borders — mas funciona em ambientes corporativos restritivos porque o PC cliente enxerga apenas um teclado e mouse USB comuns (Arduino). --- ## Como funciona ``` ┌─────────────────────┐ Bluetooth SPP ┌──────────────────┐ │ PC Host │ ◄────── (COM virtual) ────────► │ HC-06 │ │ KVMote.exe │ │ (Bluetooth) │ │ - captura mouse │ └──────┬───────────┘ │ - captura teclado │ │ Serial 9600 │ - detecta borda │ ┌──────▼───────────┐ └─────────────────────┘ │ Arduino Leonardo │ │ (USB HID) │ └──────┬────────────┘ │ USB ┌──────▼───────────┐ │ PC Cliente │ │ (sem software) │ └───────────────────┘ ``` 1. O **KVMote.exe** roda no PC host (onde estão teclado e mouse físicos) 2. O mouse chega na borda da tela configurada → cursor some → modo cliente ativo 3. Movimentos de mouse e teclas são capturados por hooks globais do Windows 4. Enviados via **Bluetooth Serial** ao HC-06 → Arduino Leonardo 5. O Arduino injeta os eventos como **USB HID** no PC cliente 6. Para voltar: mova o mouse ~15px de volta na direção do host --- ## Hardware necessário | Componente | Modelo | Observação | |---|---|---| | Microcontrolador | **Arduino Leonardo** | Obrigatório — único com HID USB nativo (ATmega32U4) | | Bluetooth | **HC-06** | Módulo slave, 9600 baud padrão | | LED indicador | LED RGB catodo comum | Pinos R=5, G=6, B=9 (PWM) | | Resistores | ~100Ω por canal | Proteção do LED | **Arduino Uno não funciona** — não tem suporte HID nativo. --- ## Instalação e configuração ### PC Cliente (onde o Arduino fica conectado) 1. Conectar o Arduino Leonardo via USB (aparece como teclado + mouse) 2. Verificar que o HC-06 está pareado com o PC Host via Bluetooth Windows 3. Nenhum software adicional necessário ### PC Host (onde o KVMote.exe roda) 1. Parear o HC-06 no Bluetooth do Windows → anota a porta COM gerada 2. Rodar `KVMote.exe` (portable, sem instalação) 3. Selecionar a posição do PC cliente (Esquerda / Direita / Acima / Abaixo) 4. Clicar **Detectar** → aguarda auto-detecção da porta COM 5. Selecionar o layout do teclado do PC cliente (US ou PT-BR ABNT2) 6. Clicar **Conectar** --- ## Indicadores LED do Arduino | Cor | Significado | |---|---| | 🟢 Verde | Arduino ligado, aguardando conexão do host | | 🔵 Azul | Host conectado, mouse no PC host | | 🟣 Magenta | Mouse no PC cliente (modo ativo) | --- ## Protocolo serial binário Comunicação Host → Arduino a 9600 baud: | Comando | Bytes | Ação | |---|---|---| | `M` + dx + dy | 3 | Mover mouse (valores int8 com sinal) | | `W` + delta | 2 | Roda do mouse / scroll touchpad | | `K` + char | 2 | Digitar caractere (Keyboard.write) | | `P` + keycode | 2 | Pressionar tecla (mantém pressionada) | | `U` + keycode | 2 | Soltar tecla | | `A` | 1 | Soltar todas as teclas | | `C` + L/R | 2 | Clique do mouse | | `D` + L/R | 2 | Pressionar botão do mouse (arrastar) | | `E` + L/R | 2 | Soltar botão do mouse | | `O` | 1 | LED magenta (entrou no cliente) | | `H` | 1 | LED azul (host conectado) | | `G` | 1 | LED verde (host desconectado) | | `~` | 1 | Ping → Arduino responde `[PONG]` | --- ## Funcionalidades implementadas ### KVM básico - ✅ Controle de mouse (move, clique, arraste, scroll) - ✅ Controle de teclado (todas as teclas, modificadores, F-keys, numpad) - ✅ Detecção de borda (Left, Right, Above, Below) - ✅ Retorno ao host por coordenadas virtuais (threshold 15px) - ✅ Cursor escondido durante modo cliente ### Conexão - ✅ Auto-detecção de porta COM por PONG handshake - ✅ Heartbeat a cada 3s (PONG timeout = 9s) - ✅ Reconexão automática em loop - ✅ Saída do modo cliente ao perder conexão (cursor sempre volta) ### Scroll - ✅ Mouse wheel físico - ✅ Touchpad dois dedos (acumulador de delta para smooth scroll) ### Clipboard - ✅ Ctrl+V (ou Shift+Ins) em modo cliente envia texto do host como digitação - ✅ Limite de 300 caracteres - ✅ Suporte a layout PT-BR ABNT2 (remapeamento de pontuação) - ✅ ReleaseAll antes de digitar (evita Ctrl+letra indesejado) ### Layout de teclado (clipboard) | Layout | Chars problemáticos corrigidos | |---|---| | US / Internacional | — (padrão) | | PT-BR ABNT2 | `;` `:` `[` `]` `{` `}` mapeados corretamente | Chars não mapeáveis em PT-BR (ignorados no paste): `/` `?` `\` `|` `@` --- ## Arquitetura do código C# ### Principal.cs — seções 1. **P/Invoke** — SetWindowsHookEx, ClipCursor, SetCursorPos 2. **Auto-detect** — ProbePorts, PONG handshake 3. **Position selector** — botões Acima/Esquerda/Direita/Abaixo 4. **Connect/Disconnect** — abertura de porta, timers, hooks 5. **Port management** — OpenPort, ClosePort, OnDataReceived 6. **Watchdog + Heartbeat + Reconnect** — saúde da conexão 7. **Global Hooks** — instala/remove WH_MOUSE_LL e WH_KEYBOARD_LL 8. **Mouse Hook Callback** — edge detection, warp, virtual coords, scroll 9. **Keyboard Hook Callback** — Ctrl+V intercept, P/U por VK code 10. **VK → Arduino keycode mapping** — tabela + ranges (a-z, 0-9, numpad) 11. **Send methods** — Send (blocking+lock), SendMouse (lossy TryEnter) 12. **Utilities** — SetStatus, SetPortInfo, Log 13. **Clipboard send + layout** — TranslateChar, SendClipboardToClient ### Técnica de mouse (FPS warp) - `ClipCursor` não é usado — causava problemas - Em vez disso: cursor fica em posição fixa no centro (`_lastRawPos`) - A cada WM_MOUSEMOVE: calcula delta, acumula em `_pendingDX/_pendingDY`, faz warp de volta - Throttle de 50ms antes de enviar ao Arduino --- ## Decisões de projeto | Decisão | Alternativa considerada | Motivo | |---|---|---| | Arduino Leonardo | Arduino Uno | Uno não tem HID nativo | | 9600 baud | 115200 baud | HC-06 padrão de fábrica, simples | | WH_MOUSE_LL hook | Raw Input API | Mais simples, suficiente | | Monitor.TryEnter para mouse | Queue assíncrona | Lossy é OK para mouse, não bloqueia | | Coordenadas virtuais para retorno | Timer de inatividade | Mais natural, sem delay artificial | | AutoScaleMode.Dpi | AutoScaleMode.None | None quebrava em telas de alta resolução | | TCP não usado | TCP local seria mais rápido | Corporativo bloqueia portas | --- ## Limitações conhecidas - **Velocidade:** 9600 baud limita a ~50 teclas/s no clipboard; mouse trava durante paste - **Chars acentuados:** `é`, `ã`, `ç` etc. não enviáveis via clipboard (não-ASCII) - **Monitor único:** sem suporte a multi-monitor no host - **Um cliente:** arquitetura 1:1 - **PT-BR parcial:** `/`, `?`, `\`, `|`, `@` não mapeáveis via Keyboard.write() - **Tela do cliente:** não capturada (KV sem o V — só K e M) --- ## Roadmap ### Clipboard Bridge (próximo projeto) App separado para compartilhar clipboard entre host e cliente. Transporte via: 1. **OneDrive pasta compartilhada** — funciona em corporativo (Microsoft 365 whitelisted) 2. **TCP/IP local** — rápido, para redes domésticas 3. **Bluetooth RFCOMM** — PC a PC direto, sem rede Suporte planejado: texto (qualquer tamanho), imagens PNG (comprimidas), não arquivos. ### Melhorias futuras - Baud rate configurável (AT commands HC-06) - Multi-monitor - Layout US-International completo com dead keys - Indicador visual de latência BT --- ## Como gerar o executável portable ```powershell # Na pasta do projeto: # Self-contained (~70MB) — roda sem .NET instalado dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true # Dependente do runtime (~2MB) — requer .NET 8 Desktop Runtime dotnet publish -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true ``` Saída: `bin\Release\net8.0-windows\win-x64\publish\KVMote.exe` > ⚠️ Não usar o botão "Publicar" do Visual Studio — gera ClickOnce (múltiplos arquivos). --- ## Troubleshooting | Sintoma | Causa provável | Solução | |---|---|---| | Porta não detectada | HC-06 não pareado | Parear BT no Windows antes | | Cursor some e não volta | Conexão caiu em modo cliente | Mover mouse — reconexão automática restaura cursor | | Teclas erradas no cliente | Layout diferente | Ajustar "Layout do cliente" no app | | Scroll não funciona | Apenas no touchpad? | Acumulador captura, mas pode ser lento | | Mouse lento no cliente | Throttle 50ms | Normal — limitação do BT 9600 baud | | Texto colado com chars errados | Layout PT-BR | Selecionar PT-BR ABNT2 no app | | App muito pequeno no notebook | Tela alta resolução | App já corrigido com AutoScaleMode.Dpi |