237 lines
9.7 KiB
Markdown
237 lines
9.7 KiB
Markdown
# 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 |
|