Key Mime Pi:將你的 Raspberry Pi 變成遠端鍵盤
近年版本的 Raspberry Pi 支援 USB on-the-go (USB OTG)(隨身傳輸),可讓它們模擬鍵盤、隨身碟和麥克風等 USB 裝置。為了善用這項功能,我製作了一個開源網頁應用程式,能將我的 Pi 變成虛擬鍵盤。我稱它為 Key Mime Pi。
這篇文章將示範 Key Mime Pi 的運作方式,以及如何自行打造一個。
示範
所需材料
- 一部支援 USB OTG 的 Raspberry Pi:
- Raspberry Pi 4(所有型號)
- Raspberry Pi Zero W
- Raspberry Pi A 與 A+ (尚待驗證)
- 此來源聲稱早期 Raspberry Pi 支援 USB OTG,但我尚未親自測試這些裝置。
- Raspberry Pi OS(原名 Raspbian)
- Stretch 或更新版本
- 一條 USB 傳輸線
- 適用於 Pi 4:USB-C 轉 USB-A(公對公)
- 適用於 Pi Zero W:Micro-USB 轉 USB-A(公對公)
安裝 Raspberry Pi OS Lite
首先,請在 microSD 卡上安裝 Raspberry Pi OS Lite(前身為 Raspbian)。

我使用 Rufus 來燒錄 Pi 的 microSD 卡,但任何整碟映像工具皆可使用。
在 microSD 卡的 boot 分割區放置一個名為 ssh 的檔案以啟用 SSH 存取,然後將 microSD 卡插入 Pi 裝置。若要透過無線網路連線,還需在 boot 分割區建立 wpa_supplicant.conf 檔案。
連接你的 Pi
將 USB 傳輸線連接至 Pi 的 USB OTG 連接埠。在 Pi 4 上,即為 USB-C 連接埠;對於 Pi Zero,則是標示為「USB」的 Micro-USB 連接埠。


對於 Raspberry Pi 4(左),請連接至 USB-C 連接埠;對於 Raspberry Pi Zero W(右),請連接至 Micro-USB 資料傳輸埠。
將 USB 傳輸線的另一端連接至你想以鍵盤身分連接的電腦。USB 3.0 連接埠效果較佳,因為其供電量較大,不過我測試過的所有 USB 2.0 連接埠也都能正常運作。
你的 Pi 應該會透過電腦的 USB 連接埠取得電力並開機。
安裝 Key Mime Pi
安裝 Key Mime Pi 有兩種方式。你可以使用傳統的 bash,無需任何額外工具;或者,若想更優雅地安裝,也可透過我最喜愛的開源組態管理工具 Ansible 來安裝。
選項一:純 bash 方式
在 bash 終端機中輸入下列指令,以連線至你的 Pi 並將其設定為 USB device emulation(USB 裝置模擬):
# SSH into your Pi
PI_HOSTNAME="raspberrypi" # Change to your pi's hostname
PI_SSH_USERNAME="pi" # Change to your Pi username
# Connect to the Pi (default password is "raspberry")
ssh "${PI_SSH_USERNAME}@${PI_HOSTNAME}"
# Install pre-requisites
sudo apt-get update && \
sudo apt-get install -y \
git \
python-pip \
python3-venv
# Install Key Mime Pi
git clone https://github.com/mtlynch/key-mime-pi.git
cd key-mime-pi
sudo ./enable-usb-hid
sudo reboot等待 Pi 重新啟動後,再次透過 SSH 連線並啟動 Key Mime Pi 網頁伺服器:
ssh "${PI_SSH_USERNAME}@${PI_HOSTNAME}"
cd key-mime-pi
python3 -m venv venv
. venv/bin/activate
pip install --requirement requirements.txt
PORT=8000 ./app/main.py選項二:Ansible 方式
如果你是 Ansible 使用者,可以使用我的 Key Mime Pi Ansible role 來達到更好的自動化。下列指令會將 Key Mime Pi 以 systemd service(系統服務) 的形式安裝至你的裝置:
PI_HOSTNAME="raspberrypi" # Change to your pi's hostname
PI_SSH_USERNAME="pi" # Change to your Pi username
# Install the Key Mime Pi Ansible role
ansible-galaxy install mtlynch.keymimepi
# Create a minimal Ansible playbook to configure your Pi
echo "- hosts: $PI_HOSTNAME
roles:
- role: mtlynch.keymimepi" > install.yml
# Install all software (default password is "raspberry")
ansible-playbook \
--inventory "$PI_HOSTNAME", \
--user "$PI_SSH_USERNAME" \
--become \
--become-method sudo \
--ask-pass \
install.yml
# Reboot the Pi
ansible \
"$PI_HOSTNAME" \
-m reboot \
--inventory "$PI_HOSTNAME", \
--user "$PI_SSH_USERNAME" \
--ask-pass \
--become \
--become-method sudo使用 Key Mime Pi
執行安裝指令碼後,Key Mime Pi 將可在下列位址存取:
其介面如下所示:

等待輸入的 Key Mime Pi 網頁介面
就像變魔術一樣,當你在瀏覽器中輸入時,按鍵就會出現在與 Pi 連接的電腦上。

Key Mime Pi 可讓你透過瀏覽器將按鍵輸入傳送至遠端電腦。
運作原理
USB 裝置模擬
真正的關鍵在於 Linux 的 USB Human Interface Device (HID) gadget driver(人機介面裝置模擬驅動程式)。它讓使用者模式的應用程式能像 USB 裝置一樣與作業系統互動。
key-mime-pi 設定指令碼會在 /dev/hidg0 建立一個檔案路徑。任何程式都能讀寫此路徑,作業系統則會將資料轉換為鍵盤訊號。
為了模擬鍵盤,Pi 必須依據 USB HID spec(人機介面規格) 與作業系統溝通。這份文件長達 97 頁,充滿對應碼與表格,讀起來頗為吃力,但鍵盤的協定其實非常簡單。
每次按鍵時,鍵盤會傳送一個稱為「report」的 8 位元組訊息。
| 位元組索引 | 用途 |
|---|---|
| 0 | 修飾鍵(Ctrl、Alt、Shift) |
| 1 | 保留給製造商使用 |
| 2 | 按鍵 #1 |
| 3 | 按鍵 #2 |
| 4 | 按鍵 #3 |
| 5 | 按鍵 #4 |
| 6 | 按鍵 #5 |
| 7 | 按鍵 #6 |
傳送「Hi」的按鍵如下所示:
# H (Right shift + h)
echo -ne "\x20\0\xb\0\0\0\0\0" > /dev/hidg0
# i
echo -ne "\0\0\xc\0\0\0\0\0" > /dev/hidg0
# Release all keys
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0除了發送按鍵按下的訊號外,鍵盤也必須指示按鍵釋放。一個全為零的 8 位元組區塊表示沒有任何按鍵處於作用中。
上述範例一次只傳送一個按鍵,但 HID report 可容納六個按鍵。這表示只要按鍵不重複,你就能在單一訊息中一次傳送多達六個按鍵:
echo -ne "\0\0\x1a\x0b\x04\x17\x18\x13" > /dev/hidg0 && \
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0whatup從 JavaScript 轉譯至 HID
當你在瀏覽器視窗中輸入時,JavaScript 會為每個按鍵產生事件。網站 keycode.info 提供了此功能實際運作的絕佳示範。
JavaScript 按鍵事件包含 keycode,但它們與 HID keycode 不同。幸好,兩者之間大多為一對一對應。為了將 JavaScript 轉譯為 HID,我建立了一個如下所示的對照表:
_JS_TO_HID_KEYCODES = {
3: 0x48, # Pause / Break
8: 0x2a, # Backspace / Delete
9: 0x2b, # Tab
...
65: 0x04, # a
66: 0x05, # b
67: 0x06, # c
68: 0x07, # dKey Mime Pi 伺服器會監聽來自瀏覽器的 JavaScript keycode 事件,將其轉譯為 HID 代碼,然後傳送至 Pi 位於 /dev/hidg0 的 HID 介面。
以下是完整的端對端運作流程:
- 使用者在瀏覽器中按下按鍵。
- 頁面上的 JavaScript 將 JavaScript keycode 傳送至 Pi 上的 Key Mime Pi 伺服器。
- Key Mime Pi 伺服器將 JavaScript keycode 轉譯為對應的 HID 代碼。
- Key Mime Pi 伺服器將 HID 代碼傳送至位於
/dev/hidg0的 USB gadget 介面。 - 與 Pi 的 USB 傳輸線連接的電腦會將其視為鍵盤輸入,使字元顯示在螢幕上。
供電問題
在我的測試中,電腦的 USB 連接埠雖能提供足夠電力啟動 Pi,但系統日誌中仍頻繁出現低電壓警告:
$ sudo journalctl -xe | grep "Under-voltage"
Jun 05 03:46:05 keymimepi kernel: Under-voltage detected! (0x00050005)
Jun 05 03:48:29 keymimepi kernel: Under-voltage detected! (0x00050005)
Jun 05 03:54:22 keymimepi kernel: Under-voltage detected! (0x00050005)Pi 正確地偵測到標準 USB 2.0 與 USB 3.0 連接埠提供的電力不足以滿足其需求。
| Raspberry Pi 型號 | 電力需求 |
|---|---|
| Pi Zero W | 5 V / 1.2 A |
| Pi 4 | 5 V / 3.0 A |
標準 USB 連接埠的供電量則顯得不足:
| USB 連接埠類型 | 供電量 |
|---|---|
| USB 2.0 | 5 V / 0.5 A |
| USB 3.0 | 5 V / 0.9 A |
目前我仍在尋找此問題的解決方案。以下是我尚未測試的一些可能解法:
使用 PoE HAT(乙太網路供電擴充板) 透過乙太網路埠供電使用 Zero2Go Power Adaptor 連接 AC 轉 microUSB 變壓器。
更新:為了解決此問題,我與一家工程公司合作打造了一塊客製化電路板,將 Pi 的 USB-C 連接埠一分為二。第一個連接埠接收 USB 電源,因此仍可為 Pi 提供完整的 3 安培電力;第二個連接埠則負責輸出 USB 資料,讓 Pi 仍能模擬 USB 鍵盤。


TinyPilot Power Connector 讓 Pi 能透過 USB-C 連接埠接收 3 安培電力,同時不失去 USB OTG 功能。
重要的是,電源連接器的資料埠排除了 USB 電源線路。這可確保電腦電源與 Pi 電源之間的電壓差不會造成不必要的電力回流。
疑難排解
驗證驅動程式是否正常運作
若 Key Mime Pi 無法將按鍵輸入轉送至目標電腦,第一步是確認 USB gadget 是否正常運作。
請嘗試下列指令:
echo -ne "\0\0\xb\0\0\0\0\0" > /dev/hidg0 && \
echo -ne "\0\0\xc\0\0\0\0\0" > /dev/hidg0 && \
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0若一切正常,你應該會在透過 USB 與 Pi 連接的電腦上看到下列輸出:
hi寫入 HID 介面時停滯
在 Pi Zero W 上測試 Key Mime Pi 時,我曾遇到寫入 /dev/hidg0 時無限停滯的情況。更換另一條 Micro-USB 轉 USB-A 傳輸線後問題即消失。我懷疑第一條傳輸線可能已損壞,或僅支援供電而不支援資料傳輸。若你遇到寫入 /dev/hidg0 時停滯的情況,請嘗試使用支援資料傳輸的 USB 傳輸線(多數 USB 傳輸線皆有支援)。
下一步:嵌入顯示輸出
遠端輸入雖然有趣,但有點不切實際。對系統輸入時,通常也需要看到輸出畫面才有幫助。
我的下一步是擷取目標電腦的 HDMI 輸出,並將其嵌入 Key Mime Pi 的網頁介面。如此一來,我就能將 Pi 插上無螢幕伺服器,並在瀏覽器中擁有虛擬主控台。這基本上就是一個低成本、可自行改造的 KVM over IP(KVM 遠端管理) 裝置。
我已使用 ffplay 與 HDMI 延伸器做出可運作的原型,但仍在研究如何將所有功能整合至單一瀏覽器視窗中,並保持低延遲。

我可以使用 HDMI 延伸器檢視遠端電腦的螢幕輸出,但仍在努力將所有功能整合至瀏覽器中。
想要預先設定好的套件嗎?
我現在已有能在單一瀏覽器視窗中同時擷取目標裝置影像輸出並傳送按鍵輸入的完整解決方案。

詳細的後續文章即將發布,在此期間,你可以預購已預先設定好的 KVM Pi 套件,其中包含打造專屬 KVM Pi 所需的一切:
原始碼
Key Mime Pi 的程式碼完全以寬鬆的 MIT 授權條款開源:
- key-mime-pi:將按鍵輸入轉送至 Pi 虛擬鍵盤的網頁伺服器。
- ansible-role-key-mime-pi:用於設定 Pi 的 USB gadget 功能並將網頁伺服器安裝為 systemd service 的 Ansible role。
致謝
- raspberrypisig/pizero-usb-hid-keyboard 是我找到的第一個能在 Pi 上成功安裝虛擬 USB HID 裝置的範例程式碼。
- Fmstrat/diy-ipmi 為本專案帶來靈感,並證明了讓 Pi 作為 KVM over IP 運作是可行的。
- Rafael Medina(拉斐爾·梅迪納)提供了我所看過對 HID 協定最易讀的解說。
- 感謝讓 USB gadget 功能得以實現的 Linux 與 Raspberry Pi OS 開發者。
隨機一篇部落格