keybird


Namekeybird JSON
Version 1.0.4 PyPI version JSON
download
home_pageNone
SummaryTurn a Raspberry Pi into a USB HID keyboard/mouse bridge with web-based control
upload_time2025-10-26 00:48:40
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords raspberry-pi hid usb-gadget keyboard mouse kvm
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Keybird v1.0.4

**Transform your Raspberry Pi into a professional USB keyboard, mouse, and media controller with web-based management.**

Control a computer from another computer, customize per-keyboard mappings, suppress keys or functions that auto-enter, and manage everything through a modern Bootstrap 5 dark theme web interface. But why does this exist [BHB.bzz](https://bhb.buzz/keybird.html)

**🔗 GitHub:** [github.com/mcyork/keybird](https://github.com/mcyork/keybird)

---

## 🎯 What Is This?

The Pi HID Bridge turns a Raspberry Pi into a **composite USB HID device** that emulates:
- ⌨️ **Keyboard** with 100+ mapped keys
- 🖱️ **Mouse** with 3 buttons + scroll wheel
- 🎵 **Media keys** (volume, play/pause, etc.)

**Plus unique features:**
- 🎹 **Multi-keyboard pass-through** - Monitor YubiKey, Dell, Apple, Microsoft keyboards simultaneously
- 🔧 **Per-keyboard custom mappings** - YubiKey Enter suppression, key remapping, text macros
- 📋 **Emulation profile switching** - Pretend to be different keyboard models
- 🖱️ **Web trackpad** with automatic calibration for different displays
- 🌐 **Web UI** - Control from laptop, phone, or tablet

---

## ⚡ Quick Start (2 Minutes)

### Prerequisites

- **Raspberry Pi 4 Model B** (tested and validated)
  - Full functionality including keyboard pass-through
- **Raspberry Pi Zero 2 W** (tested and validated)
  - ⚠️ Keyboard functionality only - no pass-through capability due to single USB port hardware limitation
- ⚠️ **NOT compatible with Pi 5** (USB gadget mode unresolved issues)
- **USB-C data cable** - Must support data, not just charging (Pi 4B)
- **Micro-USB data cable** - Must support data, not just charging (Pi Zero 2 W)
  - Pi connected to network (WiFi or Ethernet)
  - Pi has SSH enabled (default on Raspberry Pi OS)

### Deploy from Your Computer (No SSH login needed!)

```bash
# 1. Install pi-shell and keybird on YOUR COMPUTER
pip install pi-shell keybird

# 2. Add your Pi (one-time setup with password-less SSH)
pi-shell add mypi --host 192.168.1.50 --user pi --password raspberry --push-key

# 3. Deploy to Pi (single command!)
keybird-deploy mypi
```

**Done!** 🎉 Access web UI at `http://192.168.1.50:8080`

> **📦 Note:** Keybird not yet on PyPI. For now, install from source:
> ```bash
> pip install pi-shell
> git clone https://github.com/mcyork/keybird.git
> cd keybird
> pip install .
> pi-shell add mypi --host 192.168.1.50 --user pi --password raspberry --push-key
> keybird-deploy mypi
> ```

### What Gets Installed

✅ **Flask web app** with Bootstrap 5 dark theme UI  
✅ **USB HID gadget** (keyboard + mouse + media keys)  
✅ **Systemd services** (auto-start on boot)  
✅ **Boot configuration** (enables USB gadget mode)  
✅ **Dependencies** (flask, evdev)

### Manual Deployment (See Under the Hood)

Want transparency? See **[manual-deploy/README.md](manual-deploy/README.md)** for step-by-step SSH deployment.

---

## Post-Installation

### Connect Hardware

Connect your Pi's **USB-C port** to your target computer's USB port.

### Access Web UI

```bash
open http://<pi-ip>:8080
```

**Done!** 🎉

---

## 🎹 Core Features

### Multi-Keyboard Pass-Through

> **Note:** This feature requires **Raspberry Pi 4 Model B** (Pi Zero 2 W lacks physical USB host ports for keyboards)

**Monitor all keyboards at once:**
- YubiKey NEO
- Dell WK636 Wireless Keyboard  
- Apple Magic Keyboard
- Microsoft keyboards
- Any USB keyboard

Each keyboard can have its own custom key mappings!

**Example:** Suppress YubiKey's auto-Enter key while keeping Enter normal on other keyboards.

### Emulation Profile Switching

**Pretend to be different keyboards:**
- Dell WK636 (VID: 046d, PID: c52b)
- Apple Magic Keyboard (VID: 05ac, PID: 029f)
- Logitech Unifying Receiver (VID: 046d, PID: 4049)
- Any keyboard you clone!

**Why?** Some software only works with specific keyboard models. Clone the required keyboard and switch profiles as needed.

### Mouse Control

**Two ways to control the mouse:**

1. **Web Trackpad** - Beautiful 500x350px trackpad in browser
   - Click on trackpad → sends click to target PC
   - Move in trackpad → cursor moves
   - Right-click → context menu
   - Scroll wheel → page scrolling
   - Auto-calibration for your display size

2. **Physical Mouse Pass-Through** - Plug real mice into Pi
   - Forwards all movements and clicks
   - Multi-mouse support
   - Zero latency

### Per-Keyboard Custom Mappings

**Three mapping types:**

1. **HID Remap** - Map key X to key Y
   - Example: Map F13 to Print Screen

2. **Text Replacement** - Map key to type text
   - Example: Map F14 to type "show ip interface brief"

3. **Suppress** - Ignore specific keys
   - Example: Suppress Enter key on YubiKey only

**Management UI:**
- Select keyboard from dropdown
- View all mappings in table
- Add/Edit/Delete mappings
- Export/Import for backup

---

## 📱 Web Interface

Access at `http://<pi-ip>:8080`

**Modern Bootstrap 5 dark theme with tabbed interface:**

### Header Controls (Always Visible)
- **Status Bar:** USB connection and emulation profile status
- **Mode Toggles:** Keyboard and mouse pass-through switches
- **Quick Actions:** Reboot button

### Tab 1: Control (Default)
- **Send Text:** Batch send text as keystrokes to connected computer
- **Trackpad:** Interactive mouse control with sensitivity and calibration

### Tab 2: Learning
- **Unmapped Keys:** Auto-detected unknown keys with one-click mapping
- **HID Reference:** Quick lookup for common HID codes

### Tab 3: Mappings
- **Keyboard Management:** Select any connected keyboard
- **Custom Mappings:** Suppress keys, remap, or send text macros
- **Per-Keyboard Rules:** Different mappings for each physical device

### Tab 4: Settings
- **Emulation Profiles:** Switch which keyboard device the Pi pretends to be
- **Detected Keyboards:** See all physically connected keyboards
- **Export/Import:** Backup your profiles and mappings

---

## 🚀 Advanced Usage

### YubiKey Integration

**Problem:** YubiKey OTP mode sends Enter after password  
**Solution:** Suppress Enter key on YubiKey only

```
1. Go to Mappings tab
2. Select "Yubico Yubikey NEO OTP+U2F+CCID"
3. Add Mapping:
   - Key Code: 28 (Enter)
   - Action Type: 🚫 Suppress
4. Done! YubiKey outputs password without auto-submit
```

### Trackpad Calibration

**Problem:** Different screens need different sensitivities  
**Solution:** Calibrate for each display

```
1. Enable Mouse Pass-through toggle in header
2. Go to Control tab → Click 🎯 Calibrate button
3. Use physical mouse to click 4 corners of screen
4. Save as "Windows Desktop" or "MacBook Pro"
5. Disable mouse pass-through toggle
6. Use web trackpad with perfect sensitivity!
```

### Profile Switching

**Problem:** Some software requires specific keyboard models  
**Solution:** Clone and switch profiles

```
1. Plug target keyboard into Pi
2. Go to Settings tab → Detected Physical Keyboards
3. Click "Clone" button next to the keyboard
4. Pi reboots as that keyboard
5. Use Emulation Profile dropdown to switch between saved profiles anytime
```

### Multi-Computer Setup

**Best Practice with KVM:**

```
[Powered USB Hub] ← Constant power
      ↓
   [KVM] ← Switches USB data
      ↓
[Computer A] [Computer B] [Computer C]

Connected to hub:
- Raspberry Pi (via USB-C data cable)
  - Your keyboards
  - Your mice
- Microphone
- Other USB devices

Benefits:
- Pi stays powered (no reboot when switching)
- All devices switch together
- Web UI always accessible
- Different calibrations per computer
```

---

## 📦 What Gets Installed

### On the Pi

**Application Files:**
```
/home/pi/pi-hid-bridge/
├── app/pi_kb.py              # Flask app (2,850+ lines)
├── scripts/
│   ├── setup_gadget_composite.sh  # Creates USB gadget
│   ├── cleanup_gadget.sh          # Removes USB gadget
│   └── gadget.conf                # VID/PID configuration
├── systemd/
│   ├── hid-gadget.service         # Auto-start gadget
│   └── pi-hid-bridge.service      # Auto-start Flask
└── requirements.txt               # Python deps
```

**Runtime Data Files:**
```
/home/pi/
├── keyboard_profiles.json         # Emulation profiles
├── keyboard_mappings.json         # Per-keyboard custom mappings
└── trackpad_calibrations.json     # Trackpad calibrations
```

**System Configuration:**
```
/boot/firmware/config.txt          # dtoverlay=dwc2 added
/boot/firmware/cmdline.txt         # modules-load=dwc2 added
/etc/systemd/system/               # Services installed
```

**USB Devices Created:**
```
/dev/hidg0                         # Keyboard
/dev/hidg1                         # Consumer Control (media keys)
/dev/hidg2                         # Mouse
```

---

## 🛠️ Pi Shell CLI

This project uses **Pi Shell** - a pip-installable CLI tool for managing Raspberry Pis via SSH.

**Install:** `pip install pi-shell`  
**GitHub:** [github.com/mcyork/pi-shell](https://github.com/mcyork/pi-shell)

### Essential Commands

After adding your Pi with `pi-shell add mypi ...`, you can use the symlink:

```bash
# Check status
pi-shell status mypi

# Execute commands (streaming output)
mypi run-stream "command"

# Send files
mypi send /local/file /remote/path

# Read files
mypi read /remote/file > local-file

# List all Pis
pi-shell list
```

### Deployment Commands

```bash
# Deploy from scratch
keybird-deploy mypi

# Quick restart (already deployed)
cd keybird/manual-deploy
./quick-start.sh mypi
```

---

## 🔌 Hardware Setup

### Raspberry Pi 4 Model B

**USB Ports:**
- **USB-C port** 
  - USB gadget output (connects to target computer)
- **4× USB-A ports** - Connect keyboards, mice, YubiKey, etc.
- **Ethernet** - Management network
- **Wi-Fi** - Wireless management (optional)

**Wiring:**
```
Target Computer USB Port
         ↓
    [USB-C Cable] ← Data + Power
         ↓
    Pi USB-C Port
    
Pi USB-A Ports:
    ├─ Keyboard 1 (Dell)
    ├─ Keyboard 2 (YubiKey)
    ├─ Mouse 1 (Logitech)
    └─ Mouse 2 (Microsoft)
```

**Power Options:**
1. **Via USB-C from target** - If target provides enough power
2. **Via GPIO pins** - 5V to pins 2/4, GND to pin 6
3. **PoE HAT** - Power over Ethernet

---

## 📚 Documentation

### Getting Started
- **[Manual Deployment README](manual-deploy/README.md)** - Deploy without pip install
- **[Manual Deployment Guide](manual-deploy/MANUAL_DEPLOY.md)** - Step-by-step SSH deployment

### Maintenance
- **[Uninstall Guide](docs/UNINSTALL.md)** - Complete removal instructions

---

## 🐛 Troubleshooting

### USB Not Connecting

**Check USB status:**
```bash
mypi run-stream 'cat /sys/class/udc/*/state'
```

**Should show:** `configured`  
**If shows:** `not attached` → Check USB cable is data-capable

**Manually recreate gadget:**
```bash
mypi run-stream 'sudo systemctl restart hid-gadget.service'
```

### Services Won't Start

**Check logs:**
```bash
mypi run-stream 'sudo journalctl -u pi-hid-bridge.service -n 50'
mypi run-stream 'sudo journalctl -u hid-gadget.service -n 50'
```

**Manual restart:**
```bash
mypi run-stream 'sudo systemctl restart hid-gadget.service'
mypi run-stream 'sudo systemctl restart pi-hid-bridge.service'
```

### Keyboard Pass-Through Not Working

**Check keyboards detected:**
```bash
curl http://<pi-ip>:8080/detected_keyboards
```

**Enable pass-through:**
- Open web UI
- Toggle "Keyboard Pass-through" in header

**Check logs:**
```bash
mypi run-stream 'sudo journalctl -u pi-hid-bridge.service -f'
```

### Mouse Not Working

**Check mouse devices exist:**
```bash
mypi run-stream 'ls -la /dev/hidg*'
```

**Should see:** `/dev/hidg0`, `/dev/hidg1`, `/dev/hidg2`

**If missing hidg2:**
```bash
mypi run-stream 'sudo systemctl restart hid-gadget.service'
```

### Web UI Not Loading

**Check Flask is running:**
```bash
mypi run-stream 'sudo systemctl status pi-hid-bridge.service'
```

**Check it's listening:**
```bash
mypi run-stream 'sudo ss -tlnp | grep 8080'
```

**View live logs:**
```bash
mypi run-stream 'sudo journalctl -u pi-hid-bridge.service -f'
```

---

## 🔄 Updating & Backup

### Update Python Backend

```bash
mypi send app/pi_kb.py /home/pi/pi-hid-bridge/app/pi_kb.py
mypi run-stream 'sudo systemctl restart pi-hid-bridge.service'
```

### Update Web UI (No Restart Needed)

```bash
mypi send templates/index.html /home/pi/pi-hid-bridge/templates/index.html
mypi send static/css/style.css /home/pi/pi-hid-bridge/static/css/style.css
mypi send static/js/app.js /home/pi/pi-hid-bridge/static/js/app.js
# Just refresh browser
```

### Backup Profiles and Mappings

```bash
# Download from Pi
mypi read /home/pi/keyboard_profiles.json > backup_profiles.json
mypi read /home/pi/keyboard_mappings.json > backup_mappings.json
mypi read /home/pi/trackpad_calibrations.json > backup_calibrations.json
```

Or use Web UI → Export buttons.

### Restore Backups

```bash
# Upload to Pi
mypi send backup_profiles.json /home/pi/keyboard_profiles.json
mypi send backup_mappings.json /home/pi/keyboard_mappings.json
mypi send backup_calibrations.json /home/pi/trackpad_calibrations.json

# Restart service
mypi run-stream 'sudo systemctl restart pi-hid-bridge.service'
```

### Full Re-Deploy

```bash
keybird-deploy mypi
```

---

## 🌐 API Reference

### Health Check
```bash
GET /health
```

### USB Status
```bash
GET /usb_status
# Returns: {"state": "configured", "attached": true}
```

### Keyboard Pass-Through
```bash
GET /passthrough
# Check status

POST /passthrough
# Body: {"enabled": true}
# Toggle on/off
```

### Mouse Pass-Through
```bash
GET /mouse_passthrough
POST /mouse_passthrough
# Body: {"enabled": true}
```

### Mouse Control
```bash
POST /mouse_move
# Body: {"dx": 10, "dy": -5, "buttons": 0, "wheel": 0}

POST /mouse_click
# Body: {"button": "left"}  # or "right", "middle"
```

### Send Text
```bash
POST /send_text
# Body: {"text": "Hello, world!"}
```

### Detected Keyboards
```bash
GET /detected_keyboards
# Returns list of physical keyboards with VID/PID
```

### Detected Mice
```bash
GET /detected_mice
# Returns list of physical mice
```

### Emulation Profiles
```bash
GET /emulation_profiles
# List all saved profiles

POST /emulation_profiles/switch
# Body: {"profile_id": "logitech_4049"}
```

### Keyboard Mappings
```bash
GET /keyboard_mappings/all
# List all keyboards with mappings

GET /keyboard_mappings/<kbd_id>
# Get specific keyboard's mappings

POST /keyboard_mappings/<kbd_id>/mapping
# Body: {"code": 28, "type": "suppress"}

DELETE /keyboard_mappings/<kbd_id>/mapping/<code>
```

### Trackpad Calibration
```bash
POST /calibration/start
# Start calibration process

GET /calibration/status
# Check calibration progress

POST /calibration/save
# Body: {"name": "Windows Desktop", "sensitivity": 3.2, "points": [...]}

GET /calibrations
# List all saved calibrations

POST /calibrations/<cal_id>/activate
# Activate a calibration profile
```

### System Control
```bash
POST /reboot
# Reboot the Pi
```

---

## 📖 Detailed Documentation

### Getting Started
- Read **DEPLOYMENT_QUICK_REFERENCE.md** for deployment cheat sheet
- Read **DEPLOYMENT_GUIDE.md** for detailed manual deployment

### Feature Guides
- **LEARNING_MODE_GUIDE.md** - Map unknown keys interactively
- **YUBIKEY_SUPPRESS_EXAMPLE.md** - Suppress YubiKey Enter key
- **MOUSE_CONTROL_GUIDE.md** - Use the web trackpad
- **TRACKPAD_CALIBRATION_GUIDE.md** - Calibrate for your display
- **PROFILES_AND_MAPPINGS.md** - Understand emulation vs mappings

### Advanced Topics
- **KEYBOARD_VENDOR_NOTES.md** - Why Dell keyboards show as Logitech
- **MOUSE_PASSTHROUGH_GUIDE.md** - Physical mouse forwarding
- **FINDINGS.md** - Pi 5 USB gadget investigation

---

## 🏗️ Architecture

### Components

```
┌─────────────────────────────────────────────────┐
│           Target Computer (Windows/Mac/Linux)    │
│                        ▲                         │
│                        │ USB HID                 │
└────────────────────────┼─────────────────────────┘
                         │
                    USB-C Cable
                         │
┌────────────────────────▼─────────────────────────┐
│              Raspberry Pi 4 Model B              │
│  ┌───────────────────────────────────────────┐  │
│  │  Composite USB HID Gadget                 │  │
│  │  - /dev/hidg0 (Keyboard)                  │  │
│  │  - /dev/hidg1 (Consumer Control)          │  │
│  │  - /dev/hidg2 (Mouse)                     │  │
│  └───────────────────────────────────────────┘  │
│                      ▲                           │
│                      │                           │
│  ┌───────────────────┴───────────────────────┐  │
│  │         Flask Web App (pi_kb.py)          │  │
│  │  - Keyboard pass-through                  │  │
│  │  - Mouse pass-through                     │  │
│  │  - Custom mappings engine                 │  │
│  │  - Profile management                     │  │
│  │  - Calibration system                     │  │
│  │  - Web UI server                          │  │
│  └───────────────────┬───────────────────────┘  │
│                      │                           │
│                      │ evdev                     │
│                      ▼                           │
│  ┌──────────────────────────────────────────┐   │
│  │     Physical Input Devices               │   │
│  │  - Keyboards (YubiKey, Dell, Apple...)   │   │
│  │  - Mice (Logitech, Microsoft...)         │   │
│  └──────────────────────────────────────────┘   │
│                                                  │
│  Network: Ethernet + Wi-Fi ◄─── Web Browser     │
└──────────────────────────────────────────────────┘
```

### Data Flow

**Keyboard Pass-Through:**
```
Physical Keyboard → evdev → Pi → Custom Mappings → HID Report → Target PC
```

**Web Trackpad:**
```
Browser → HTTP → Pi → Calibration → HID Report → Target PC
```

**Profile Switching:**
```
User Selection → Update gadget.conf → Reboot → New VID/PID → Target PC sees different keyboard
```

---

## 🤝 Contributing

This is a personal project, but suggestions welcome!

**Areas for improvement:**
- Additional mapping types (delays, sequences)
- Drag-and-drop mouse support
- Encrypted macro implementation
- AI command generation
- GamePad emulation

---

## 📜 License

Personal project - use at your own risk!

---

## 🙏 Acknowledgments

Built with:
- **Flask** - Web framework
- **evdev** - Linux input device interface
- **Python** - Glue holding it all together
- **Pi Shell** - Pi management CLI ([github.com/mcyork/pi-shell](https://github.com/mcyork/pi-shell))

Inspired by Black Hat Booze (https://bhb.buzz) and the deep obsession with the distilation process - be it for spirits or code.
---

## 🗑️ Uninstalling

Keybird makes system-level changes that need proper cleanup:

```bash
# Complete removal (cleans everything)
sudo keybird-uninstall

# Then remove Python package
sudo pip uninstall keybird

# Reboot to apply boot config changes
sudo reboot
```

The uninstall script removes:
- ✅ USB gadget configuration (boot files)
- ✅ Systemd services  
- ✅ Installed files in `/opt/keybird/`

**Preserves** (in case you reinstall):
- 💾 Saved profiles, mappings, calibrations in `/home/pi/`

See **[UNINSTALL.md](docs/UNINSTALL.md)** for manual uninstall steps.

---

## 🆘 Support

**Check logs:**
```bash
sudo journalctl -u pi-hid-bridge.service -f
```

**Reset everything (pip install users):**
```bash
sudo systemctl restart hid-gadget.service
sudo systemctl restart pi-hid-bridge.service
```

**Reset everything (manual deploy users):**
```bash
cd keybird/manual-deploy
./quick-start.sh mypi
```

---

## 🚀 Version History

- **v1.0.4** (Oct 2025) - **PyPI Fix**: Corrected package build to include touch support for iPhone/iPad trackpad
- **v1.0.3** (Oct 2025) - **Mobile Support**: Added touch support for iPhone/iPad trackpad - touch to move cursor, tap to click, two-finger right-click
- **v1.0.2** (Oct 2025) - **Modernization**: Updated to Python 3.10+, replaced deprecated pkg_resources with importlib.resources
- **v1.0.1** (Oct 2025) - **Bug fix**: Fixed silent crash in keyboard pass-through mode
- **v1.0** (Oct 2025) - Initial release with keyboard pass-through, web UI, mouse control, trackpad calibration, multi-keyboard support, profiles, per-keyboard mappings, and YubiKey support
- **v0.1** (Oct 2025) - Initial prototype

---

**Ready to control your computers like a pro? Deploy and enjoy!** 🎮

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "keybird",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "raspberry-pi, hid, usb-gadget, keyboard, mouse, kvm",
    "author": null,
    "author_email": "Ian McCutcheon <ian@mcyork.com>",
    "download_url": "https://files.pythonhosted.org/packages/95/a1/bfcdab0f91404168c29779f5d84d6c6431a214928b3af3bf5d41bf1d7926/keybird-1.0.4.tar.gz",
    "platform": null,
    "description": "# Keybird v1.0.4\n\n**Transform your Raspberry Pi into a professional USB keyboard, mouse, and media controller with web-based management.**\n\nControl a computer from another computer, customize per-keyboard mappings, suppress keys or functions that auto-enter, and manage everything through a modern Bootstrap 5 dark theme web interface. But why does this exist [BHB.bzz](https://bhb.buzz/keybird.html)\n\n**\ud83d\udd17 GitHub:** [github.com/mcyork/keybird](https://github.com/mcyork/keybird)\n\n---\n\n## \ud83c\udfaf What Is This?\n\nThe Pi HID Bridge turns a Raspberry Pi into a **composite USB HID device** that emulates:\n- \u2328\ufe0f **Keyboard** with 100+ mapped keys\n- \ud83d\uddb1\ufe0f **Mouse** with 3 buttons + scroll wheel\n- \ud83c\udfb5 **Media keys** (volume, play/pause, etc.)\n\n**Plus unique features:**\n- \ud83c\udfb9 **Multi-keyboard pass-through** - Monitor YubiKey, Dell, Apple, Microsoft keyboards simultaneously\n- \ud83d\udd27 **Per-keyboard custom mappings** - YubiKey Enter suppression, key remapping, text macros\n- \ud83d\udccb **Emulation profile switching** - Pretend to be different keyboard models\n- \ud83d\uddb1\ufe0f **Web trackpad** with automatic calibration for different displays\n- \ud83c\udf10 **Web UI** - Control from laptop, phone, or tablet\n\n---\n\n## \u26a1 Quick Start (2 Minutes)\n\n### Prerequisites\n\n- **Raspberry Pi 4 Model B** (tested and validated)\n  - Full functionality including keyboard pass-through\n- **Raspberry Pi Zero 2 W** (tested and validated)\n  - \u26a0\ufe0f Keyboard functionality only - no pass-through capability due to single USB port hardware limitation\n- \u26a0\ufe0f **NOT compatible with Pi 5** (USB gadget mode unresolved issues)\n- **USB-C data cable** - Must support data, not just charging (Pi 4B)\n- **Micro-USB data cable** - Must support data, not just charging (Pi Zero 2 W)\n  - Pi connected to network (WiFi or Ethernet)\n  - Pi has SSH enabled (default on Raspberry Pi OS)\n\n### Deploy from Your Computer (No SSH login needed!)\n\n```bash\n# 1. Install pi-shell and keybird on YOUR COMPUTER\npip install pi-shell keybird\n\n# 2. Add your Pi (one-time setup with password-less SSH)\npi-shell add mypi --host 192.168.1.50 --user pi --password raspberry --push-key\n\n# 3. Deploy to Pi (single command!)\nkeybird-deploy mypi\n```\n\n**Done!** \ud83c\udf89 Access web UI at `http://192.168.1.50:8080`\n\n> **\ud83d\udce6 Note:** Keybird not yet on PyPI. For now, install from source:\n> ```bash\n> pip install pi-shell\n> git clone https://github.com/mcyork/keybird.git\n> cd keybird\n> pip install .\n> pi-shell add mypi --host 192.168.1.50 --user pi --password raspberry --push-key\n> keybird-deploy mypi\n> ```\n\n### What Gets Installed\n\n\u2705 **Flask web app** with Bootstrap 5 dark theme UI  \n\u2705 **USB HID gadget** (keyboard + mouse + media keys)  \n\u2705 **Systemd services** (auto-start on boot)  \n\u2705 **Boot configuration** (enables USB gadget mode)  \n\u2705 **Dependencies** (flask, evdev)\n\n### Manual Deployment (See Under the Hood)\n\nWant transparency? See **[manual-deploy/README.md](manual-deploy/README.md)** for step-by-step SSH deployment.\n\n---\n\n## Post-Installation\n\n### Connect Hardware\n\nConnect your Pi's **USB-C port** to your target computer's USB port.\n\n### Access Web UI\n\n```bash\nopen http://<pi-ip>:8080\n```\n\n**Done!** \ud83c\udf89\n\n---\n\n## \ud83c\udfb9 Core Features\n\n### Multi-Keyboard Pass-Through\n\n> **Note:** This feature requires **Raspberry Pi 4 Model B** (Pi Zero 2 W lacks physical USB host ports for keyboards)\n\n**Monitor all keyboards at once:**\n- YubiKey NEO\n- Dell WK636 Wireless Keyboard  \n- Apple Magic Keyboard\n- Microsoft keyboards\n- Any USB keyboard\n\nEach keyboard can have its own custom key mappings!\n\n**Example:** Suppress YubiKey's auto-Enter key while keeping Enter normal on other keyboards.\n\n### Emulation Profile Switching\n\n**Pretend to be different keyboards:**\n- Dell WK636 (VID: 046d, PID: c52b)\n- Apple Magic Keyboard (VID: 05ac, PID: 029f)\n- Logitech Unifying Receiver (VID: 046d, PID: 4049)\n- Any keyboard you clone!\n\n**Why?** Some software only works with specific keyboard models. Clone the required keyboard and switch profiles as needed.\n\n### Mouse Control\n\n**Two ways to control the mouse:**\n\n1. **Web Trackpad** - Beautiful 500x350px trackpad in browser\n   - Click on trackpad \u2192 sends click to target PC\n   - Move in trackpad \u2192 cursor moves\n   - Right-click \u2192 context menu\n   - Scroll wheel \u2192 page scrolling\n   - Auto-calibration for your display size\n\n2. **Physical Mouse Pass-Through** - Plug real mice into Pi\n   - Forwards all movements and clicks\n   - Multi-mouse support\n   - Zero latency\n\n### Per-Keyboard Custom Mappings\n\n**Three mapping types:**\n\n1. **HID Remap** - Map key X to key Y\n   - Example: Map F13 to Print Screen\n\n2. **Text Replacement** - Map key to type text\n   - Example: Map F14 to type \"show ip interface brief\"\n\n3. **Suppress** - Ignore specific keys\n   - Example: Suppress Enter key on YubiKey only\n\n**Management UI:**\n- Select keyboard from dropdown\n- View all mappings in table\n- Add/Edit/Delete mappings\n- Export/Import for backup\n\n---\n\n## \ud83d\udcf1 Web Interface\n\nAccess at `http://<pi-ip>:8080`\n\n**Modern Bootstrap 5 dark theme with tabbed interface:**\n\n### Header Controls (Always Visible)\n- **Status Bar:** USB connection and emulation profile status\n- **Mode Toggles:** Keyboard and mouse pass-through switches\n- **Quick Actions:** Reboot button\n\n### Tab 1: Control (Default)\n- **Send Text:** Batch send text as keystrokes to connected computer\n- **Trackpad:** Interactive mouse control with sensitivity and calibration\n\n### Tab 2: Learning\n- **Unmapped Keys:** Auto-detected unknown keys with one-click mapping\n- **HID Reference:** Quick lookup for common HID codes\n\n### Tab 3: Mappings\n- **Keyboard Management:** Select any connected keyboard\n- **Custom Mappings:** Suppress keys, remap, or send text macros\n- **Per-Keyboard Rules:** Different mappings for each physical device\n\n### Tab 4: Settings\n- **Emulation Profiles:** Switch which keyboard device the Pi pretends to be\n- **Detected Keyboards:** See all physically connected keyboards\n- **Export/Import:** Backup your profiles and mappings\n\n---\n\n## \ud83d\ude80 Advanced Usage\n\n### YubiKey Integration\n\n**Problem:** YubiKey OTP mode sends Enter after password  \n**Solution:** Suppress Enter key on YubiKey only\n\n```\n1. Go to Mappings tab\n2. Select \"Yubico Yubikey NEO OTP+U2F+CCID\"\n3. Add Mapping:\n   - Key Code: 28 (Enter)\n   - Action Type: \ud83d\udeab Suppress\n4. Done! YubiKey outputs password without auto-submit\n```\n\n### Trackpad Calibration\n\n**Problem:** Different screens need different sensitivities  \n**Solution:** Calibrate for each display\n\n```\n1. Enable Mouse Pass-through toggle in header\n2. Go to Control tab \u2192 Click \ud83c\udfaf Calibrate button\n3. Use physical mouse to click 4 corners of screen\n4. Save as \"Windows Desktop\" or \"MacBook Pro\"\n5. Disable mouse pass-through toggle\n6. Use web trackpad with perfect sensitivity!\n```\n\n### Profile Switching\n\n**Problem:** Some software requires specific keyboard models  \n**Solution:** Clone and switch profiles\n\n```\n1. Plug target keyboard into Pi\n2. Go to Settings tab \u2192 Detected Physical Keyboards\n3. Click \"Clone\" button next to the keyboard\n4. Pi reboots as that keyboard\n5. Use Emulation Profile dropdown to switch between saved profiles anytime\n```\n\n### Multi-Computer Setup\n\n**Best Practice with KVM:**\n\n```\n[Powered USB Hub] \u2190 Constant power\n      \u2193\n   [KVM] \u2190 Switches USB data\n      \u2193\n[Computer A] [Computer B] [Computer C]\n\nConnected to hub:\n- Raspberry Pi (via USB-C data cable)\n  - Your keyboards\n  - Your mice\n- Microphone\n- Other USB devices\n\nBenefits:\n- Pi stays powered (no reboot when switching)\n- All devices switch together\n- Web UI always accessible\n- Different calibrations per computer\n```\n\n---\n\n## \ud83d\udce6 What Gets Installed\n\n### On the Pi\n\n**Application Files:**\n```\n/home/pi/pi-hid-bridge/\n\u251c\u2500\u2500 app/pi_kb.py              # Flask app (2,850+ lines)\n\u251c\u2500\u2500 scripts/\n\u2502   \u251c\u2500\u2500 setup_gadget_composite.sh  # Creates USB gadget\n\u2502   \u251c\u2500\u2500 cleanup_gadget.sh          # Removes USB gadget\n\u2502   \u2514\u2500\u2500 gadget.conf                # VID/PID configuration\n\u251c\u2500\u2500 systemd/\n\u2502   \u251c\u2500\u2500 hid-gadget.service         # Auto-start gadget\n\u2502   \u2514\u2500\u2500 pi-hid-bridge.service      # Auto-start Flask\n\u2514\u2500\u2500 requirements.txt               # Python deps\n```\n\n**Runtime Data Files:**\n```\n/home/pi/\n\u251c\u2500\u2500 keyboard_profiles.json         # Emulation profiles\n\u251c\u2500\u2500 keyboard_mappings.json         # Per-keyboard custom mappings\n\u2514\u2500\u2500 trackpad_calibrations.json     # Trackpad calibrations\n```\n\n**System Configuration:**\n```\n/boot/firmware/config.txt          # dtoverlay=dwc2 added\n/boot/firmware/cmdline.txt         # modules-load=dwc2 added\n/etc/systemd/system/               # Services installed\n```\n\n**USB Devices Created:**\n```\n/dev/hidg0                         # Keyboard\n/dev/hidg1                         # Consumer Control (media keys)\n/dev/hidg2                         # Mouse\n```\n\n---\n\n## \ud83d\udee0\ufe0f Pi Shell CLI\n\nThis project uses **Pi Shell** - a pip-installable CLI tool for managing Raspberry Pis via SSH.\n\n**Install:** `pip install pi-shell`  \n**GitHub:** [github.com/mcyork/pi-shell](https://github.com/mcyork/pi-shell)\n\n### Essential Commands\n\nAfter adding your Pi with `pi-shell add mypi ...`, you can use the symlink:\n\n```bash\n# Check status\npi-shell status mypi\n\n# Execute commands (streaming output)\nmypi run-stream \"command\"\n\n# Send files\nmypi send /local/file /remote/path\n\n# Read files\nmypi read /remote/file > local-file\n\n# List all Pis\npi-shell list\n```\n\n### Deployment Commands\n\n```bash\n# Deploy from scratch\nkeybird-deploy mypi\n\n# Quick restart (already deployed)\ncd keybird/manual-deploy\n./quick-start.sh mypi\n```\n\n---\n\n## \ud83d\udd0c Hardware Setup\n\n### Raspberry Pi 4 Model B\n\n**USB Ports:**\n- **USB-C port** \n  - USB gadget output (connects to target computer)\n- **4\u00d7 USB-A ports** - Connect keyboards, mice, YubiKey, etc.\n- **Ethernet** - Management network\n- **Wi-Fi** - Wireless management (optional)\n\n**Wiring:**\n```\nTarget Computer USB Port\n         \u2193\n    [USB-C Cable] \u2190 Data + Power\n         \u2193\n    Pi USB-C Port\n    \nPi USB-A Ports:\n    \u251c\u2500 Keyboard 1 (Dell)\n    \u251c\u2500 Keyboard 2 (YubiKey)\n    \u251c\u2500 Mouse 1 (Logitech)\n    \u2514\u2500 Mouse 2 (Microsoft)\n```\n\n**Power Options:**\n1. **Via USB-C from target** - If target provides enough power\n2. **Via GPIO pins** - 5V to pins 2/4, GND to pin 6\n3. **PoE HAT** - Power over Ethernet\n\n---\n\n## \ud83d\udcda Documentation\n\n### Getting Started\n- **[Manual Deployment README](manual-deploy/README.md)** - Deploy without pip install\n- **[Manual Deployment Guide](manual-deploy/MANUAL_DEPLOY.md)** - Step-by-step SSH deployment\n\n### Maintenance\n- **[Uninstall Guide](docs/UNINSTALL.md)** - Complete removal instructions\n\n---\n\n## \ud83d\udc1b Troubleshooting\n\n### USB Not Connecting\n\n**Check USB status:**\n```bash\nmypi run-stream 'cat /sys/class/udc/*/state'\n```\n\n**Should show:** `configured`  \n**If shows:** `not attached` \u2192 Check USB cable is data-capable\n\n**Manually recreate gadget:**\n```bash\nmypi run-stream 'sudo systemctl restart hid-gadget.service'\n```\n\n### Services Won't Start\n\n**Check logs:**\n```bash\nmypi run-stream 'sudo journalctl -u pi-hid-bridge.service -n 50'\nmypi run-stream 'sudo journalctl -u hid-gadget.service -n 50'\n```\n\n**Manual restart:**\n```bash\nmypi run-stream 'sudo systemctl restart hid-gadget.service'\nmypi run-stream 'sudo systemctl restart pi-hid-bridge.service'\n```\n\n### Keyboard Pass-Through Not Working\n\n**Check keyboards detected:**\n```bash\ncurl http://<pi-ip>:8080/detected_keyboards\n```\n\n**Enable pass-through:**\n- Open web UI\n- Toggle \"Keyboard Pass-through\" in header\n\n**Check logs:**\n```bash\nmypi run-stream 'sudo journalctl -u pi-hid-bridge.service -f'\n```\n\n### Mouse Not Working\n\n**Check mouse devices exist:**\n```bash\nmypi run-stream 'ls -la /dev/hidg*'\n```\n\n**Should see:** `/dev/hidg0`, `/dev/hidg1`, `/dev/hidg2`\n\n**If missing hidg2:**\n```bash\nmypi run-stream 'sudo systemctl restart hid-gadget.service'\n```\n\n### Web UI Not Loading\n\n**Check Flask is running:**\n```bash\nmypi run-stream 'sudo systemctl status pi-hid-bridge.service'\n```\n\n**Check it's listening:**\n```bash\nmypi run-stream 'sudo ss -tlnp | grep 8080'\n```\n\n**View live logs:**\n```bash\nmypi run-stream 'sudo journalctl -u pi-hid-bridge.service -f'\n```\n\n---\n\n## \ud83d\udd04 Updating & Backup\n\n### Update Python Backend\n\n```bash\nmypi send app/pi_kb.py /home/pi/pi-hid-bridge/app/pi_kb.py\nmypi run-stream 'sudo systemctl restart pi-hid-bridge.service'\n```\n\n### Update Web UI (No Restart Needed)\n\n```bash\nmypi send templates/index.html /home/pi/pi-hid-bridge/templates/index.html\nmypi send static/css/style.css /home/pi/pi-hid-bridge/static/css/style.css\nmypi send static/js/app.js /home/pi/pi-hid-bridge/static/js/app.js\n# Just refresh browser\n```\n\n### Backup Profiles and Mappings\n\n```bash\n# Download from Pi\nmypi read /home/pi/keyboard_profiles.json > backup_profiles.json\nmypi read /home/pi/keyboard_mappings.json > backup_mappings.json\nmypi read /home/pi/trackpad_calibrations.json > backup_calibrations.json\n```\n\nOr use Web UI \u2192 Export buttons.\n\n### Restore Backups\n\n```bash\n# Upload to Pi\nmypi send backup_profiles.json /home/pi/keyboard_profiles.json\nmypi send backup_mappings.json /home/pi/keyboard_mappings.json\nmypi send backup_calibrations.json /home/pi/trackpad_calibrations.json\n\n# Restart service\nmypi run-stream 'sudo systemctl restart pi-hid-bridge.service'\n```\n\n### Full Re-Deploy\n\n```bash\nkeybird-deploy mypi\n```\n\n---\n\n## \ud83c\udf10 API Reference\n\n### Health Check\n```bash\nGET /health\n```\n\n### USB Status\n```bash\nGET /usb_status\n# Returns: {\"state\": \"configured\", \"attached\": true}\n```\n\n### Keyboard Pass-Through\n```bash\nGET /passthrough\n# Check status\n\nPOST /passthrough\n# Body: {\"enabled\": true}\n# Toggle on/off\n```\n\n### Mouse Pass-Through\n```bash\nGET /mouse_passthrough\nPOST /mouse_passthrough\n# Body: {\"enabled\": true}\n```\n\n### Mouse Control\n```bash\nPOST /mouse_move\n# Body: {\"dx\": 10, \"dy\": -5, \"buttons\": 0, \"wheel\": 0}\n\nPOST /mouse_click\n# Body: {\"button\": \"left\"}  # or \"right\", \"middle\"\n```\n\n### Send Text\n```bash\nPOST /send_text\n# Body: {\"text\": \"Hello, world!\"}\n```\n\n### Detected Keyboards\n```bash\nGET /detected_keyboards\n# Returns list of physical keyboards with VID/PID\n```\n\n### Detected Mice\n```bash\nGET /detected_mice\n# Returns list of physical mice\n```\n\n### Emulation Profiles\n```bash\nGET /emulation_profiles\n# List all saved profiles\n\nPOST /emulation_profiles/switch\n# Body: {\"profile_id\": \"logitech_4049\"}\n```\n\n### Keyboard Mappings\n```bash\nGET /keyboard_mappings/all\n# List all keyboards with mappings\n\nGET /keyboard_mappings/<kbd_id>\n# Get specific keyboard's mappings\n\nPOST /keyboard_mappings/<kbd_id>/mapping\n# Body: {\"code\": 28, \"type\": \"suppress\"}\n\nDELETE /keyboard_mappings/<kbd_id>/mapping/<code>\n```\n\n### Trackpad Calibration\n```bash\nPOST /calibration/start\n# Start calibration process\n\nGET /calibration/status\n# Check calibration progress\n\nPOST /calibration/save\n# Body: {\"name\": \"Windows Desktop\", \"sensitivity\": 3.2, \"points\": [...]}\n\nGET /calibrations\n# List all saved calibrations\n\nPOST /calibrations/<cal_id>/activate\n# Activate a calibration profile\n```\n\n### System Control\n```bash\nPOST /reboot\n# Reboot the Pi\n```\n\n---\n\n## \ud83d\udcd6 Detailed Documentation\n\n### Getting Started\n- Read **DEPLOYMENT_QUICK_REFERENCE.md** for deployment cheat sheet\n- Read **DEPLOYMENT_GUIDE.md** for detailed manual deployment\n\n### Feature Guides\n- **LEARNING_MODE_GUIDE.md** - Map unknown keys interactively\n- **YUBIKEY_SUPPRESS_EXAMPLE.md** - Suppress YubiKey Enter key\n- **MOUSE_CONTROL_GUIDE.md** - Use the web trackpad\n- **TRACKPAD_CALIBRATION_GUIDE.md** - Calibrate for your display\n- **PROFILES_AND_MAPPINGS.md** - Understand emulation vs mappings\n\n### Advanced Topics\n- **KEYBOARD_VENDOR_NOTES.md** - Why Dell keyboards show as Logitech\n- **MOUSE_PASSTHROUGH_GUIDE.md** - Physical mouse forwarding\n- **FINDINGS.md** - Pi 5 USB gadget investigation\n\n---\n\n## \ud83c\udfd7\ufe0f Architecture\n\n### Components\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502           Target Computer (Windows/Mac/Linux)    \u2502\n\u2502                        \u25b2                         \u2502\n\u2502                        \u2502 USB HID                 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                         \u2502\n                    USB-C Cable\n                         \u2502\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502              Raspberry Pi 4 Model B              \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2502\n\u2502  \u2502  Composite USB HID Gadget                 \u2502  \u2502\n\u2502  \u2502  - /dev/hidg0 (Keyboard)                  \u2502  \u2502\n\u2502  \u2502  - /dev/hidg1 (Consumer Control)          \u2502  \u2502\n\u2502  \u2502  - /dev/hidg2 (Mouse)                     \u2502  \u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2502\n\u2502                      \u25b2                           \u2502\n\u2502                      \u2502                           \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2502\n\u2502  \u2502         Flask Web App (pi_kb.py)          \u2502  \u2502\n\u2502  \u2502  - Keyboard pass-through                  \u2502  \u2502\n\u2502  \u2502  - Mouse pass-through                     \u2502  \u2502\n\u2502  \u2502  - Custom mappings engine                 \u2502  \u2502\n\u2502  \u2502  - Profile management                     \u2502  \u2502\n\u2502  \u2502  - Calibration system                     \u2502  \u2502\n\u2502  \u2502  - Web UI server                          \u2502  \u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2502\n\u2502                      \u2502                           \u2502\n\u2502                      \u2502 evdev                     \u2502\n\u2502                      \u25bc                           \u2502\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510   \u2502\n\u2502  \u2502     Physical Input Devices               \u2502   \u2502\n\u2502  \u2502  - Keyboards (YubiKey, Dell, Apple...)   \u2502   \u2502\n\u2502  \u2502  - Mice (Logitech, Microsoft...)         \u2502   \u2502\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518   \u2502\n\u2502                                                  \u2502\n\u2502  Network: Ethernet + Wi-Fi \u25c4\u2500\u2500\u2500 Web Browser     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### Data Flow\n\n**Keyboard Pass-Through:**\n```\nPhysical Keyboard \u2192 evdev \u2192 Pi \u2192 Custom Mappings \u2192 HID Report \u2192 Target PC\n```\n\n**Web Trackpad:**\n```\nBrowser \u2192 HTTP \u2192 Pi \u2192 Calibration \u2192 HID Report \u2192 Target PC\n```\n\n**Profile Switching:**\n```\nUser Selection \u2192 Update gadget.conf \u2192 Reboot \u2192 New VID/PID \u2192 Target PC sees different keyboard\n```\n\n---\n\n## \ud83e\udd1d Contributing\n\nThis is a personal project, but suggestions welcome!\n\n**Areas for improvement:**\n- Additional mapping types (delays, sequences)\n- Drag-and-drop mouse support\n- Encrypted macro implementation\n- AI command generation\n- GamePad emulation\n\n---\n\n## \ud83d\udcdc License\n\nPersonal project - use at your own risk!\n\n---\n\n## \ud83d\ude4f Acknowledgments\n\nBuilt with:\n- **Flask** - Web framework\n- **evdev** - Linux input device interface\n- **Python** - Glue holding it all together\n- **Pi Shell** - Pi management CLI ([github.com/mcyork/pi-shell](https://github.com/mcyork/pi-shell))\n\nInspired by Black Hat Booze (https://bhb.buzz) and the deep obsession with the distilation process - be it for spirits or code.\n---\n\n## \ud83d\uddd1\ufe0f Uninstalling\n\nKeybird makes system-level changes that need proper cleanup:\n\n```bash\n# Complete removal (cleans everything)\nsudo keybird-uninstall\n\n# Then remove Python package\nsudo pip uninstall keybird\n\n# Reboot to apply boot config changes\nsudo reboot\n```\n\nThe uninstall script removes:\n- \u2705 USB gadget configuration (boot files)\n- \u2705 Systemd services  \n- \u2705 Installed files in `/opt/keybird/`\n\n**Preserves** (in case you reinstall):\n- \ud83d\udcbe Saved profiles, mappings, calibrations in `/home/pi/`\n\nSee **[UNINSTALL.md](docs/UNINSTALL.md)** for manual uninstall steps.\n\n---\n\n## \ud83c\udd98 Support\n\n**Check logs:**\n```bash\nsudo journalctl -u pi-hid-bridge.service -f\n```\n\n**Reset everything (pip install users):**\n```bash\nsudo systemctl restart hid-gadget.service\nsudo systemctl restart pi-hid-bridge.service\n```\n\n**Reset everything (manual deploy users):**\n```bash\ncd keybird/manual-deploy\n./quick-start.sh mypi\n```\n\n---\n\n## \ud83d\ude80 Version History\n\n- **v1.0.4** (Oct 2025) - **PyPI Fix**: Corrected package build to include touch support for iPhone/iPad trackpad\n- **v1.0.3** (Oct 2025) - **Mobile Support**: Added touch support for iPhone/iPad trackpad - touch to move cursor, tap to click, two-finger right-click\n- **v1.0.2** (Oct 2025) - **Modernization**: Updated to Python 3.10+, replaced deprecated pkg_resources with importlib.resources\n- **v1.0.1** (Oct 2025) - **Bug fix**: Fixed silent crash in keyboard pass-through mode\n- **v1.0** (Oct 2025) - Initial release with keyboard pass-through, web UI, mouse control, trackpad calibration, multi-keyboard support, profiles, per-keyboard mappings, and YubiKey support\n- **v0.1** (Oct 2025) - Initial prototype\n\n---\n\n**Ready to control your computers like a pro? Deploy and enjoy!** \ud83c\udfae\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Turn a Raspberry Pi into a USB HID keyboard/mouse bridge with web-based control",
    "version": "1.0.4",
    "project_urls": {
        "Homepage": "https://github.com/mcyork/keybird",
        "Issues": "https://github.com/mcyork/keybird/issues",
        "Repository": "https://github.com/mcyork/keybird"
    },
    "split_keywords": [
        "raspberry-pi",
        " hid",
        " usb-gadget",
        " keyboard",
        " mouse",
        " kvm"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d2e125ac7b0a51b23adca63bf4a8cfd87fecbebae70523798c18b96d85ab9cf9",
                "md5": "d60ef26ca2a8c4ae70f281ac5ab44735",
                "sha256": "14eeb4a6cddfc7b7e3d8ee579f77c25877f295d0b13cf608cc8a828ea7655e28"
            },
            "downloads": -1,
            "filename": "keybird-1.0.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d60ef26ca2a8c4ae70f281ac5ab44735",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 48303,
            "upload_time": "2025-10-26T00:48:39",
            "upload_time_iso_8601": "2025-10-26T00:48:39.429792Z",
            "url": "https://files.pythonhosted.org/packages/d2/e1/25ac7b0a51b23adca63bf4a8cfd87fecbebae70523798c18b96d85ab9cf9/keybird-1.0.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "95a1bfcdab0f91404168c29779f5d84d6c6431a214928b3af3bf5d41bf1d7926",
                "md5": "40023c1094e250eb7385b7467d12278d",
                "sha256": "042d0486e78526760f3aad573e882bed25e3f00a6fe878268e5e0768f9574b53"
            },
            "downloads": -1,
            "filename": "keybird-1.0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "40023c1094e250eb7385b7467d12278d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 52214,
            "upload_time": "2025-10-26T00:48:40",
            "upload_time_iso_8601": "2025-10-26T00:48:40.686255Z",
            "url": "https://files.pythonhosted.org/packages/95/a1/bfcdab0f91404168c29779f5d84d6c6431a214928b3af3bf5d41bf1d7926/keybird-1.0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-26 00:48:40",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mcyork",
    "github_project": "keybird",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "keybird"
}
        
Elapsed time: 3.87570s