最近Windows不信が募ってきて、RTX 3050が載っているマウスDAIVをゲーム用に持っているのに、ついついPS5を買ってしまいました。
やるのは主に原神なわけなんですが、「マルチプレイ募集掲示板からUIDを転記して参加する」のがつらすぎる!
ほなキーボードエミュレーションしますか
用意するもの
- どこのご家庭にも余っているRaspberry Pi Zero W (2があるならなお良い)
- 比較的まともそうなmicroSDカード
- まともなUSB A-microUSBケーブル (一昔まえのスマートフォンをパソコンにつなぐのに使うのに十分なグレードのもの)
- SDカードを読み書きできるパソコン
- Wi-Fi環境のある家庭
- やる気
- HDMI液晶ディスプレイと有線キーボードはあったほうがいいかもしれないけど別にいらない
SDカードにRasberry Pi OSを焼く
普通にRaspberry Pi Imagerを使いましょう。
Pi ZeroにデスクトップつきのDebianなんか焼いたら◯んでしまうので、Otherを開く。
Lite
を選ぶ。
あとは焼くSDカードを選ぶ。
ここで「設定を編集する」
こんな感じで適当に設定する。
Wi-Fiのところは注意が必要で、今どきの5GHzアクセスポイントにつなぐことができません。ルーターから5G
みたいなのとそうじゃないのがあるときは、そうじゃない方にしましょう。
SSH鍵も設定しておくと楽。何を言っているかわからない人は「パスワード認証」にチェックを入れておけばOK。
保存して、先程のダイアログを「はい」で書き込みに進む。
Piを起動する
書き込みの終わったSDカードはPiに挿して電源を入れましょう。電源供給をする場合は右の端子に挿してくださいね。
初回起動の設定は割と時間かかるので、お茶でも飲んで待ちましょう。
SSHログインする
最近はWindowsでもssh
コマンドが使えるはずなので、Win + Rして wt
と入れてEnter押してください。Macの人はターミナル。Linuxの人はこの記事読む必要ある?
ホスト名を nanapi.local
、ユーザーを nekono
で設定したので、コマンドラインに
ssh nekono@nanapi.local
と入れてEnterを押しましょう。初回だと「この接続先信頼していい?」みたいなことを訊かれるのでyes
と答える。SSH鍵を設定した人はすぐログイン完了。パスワードの人はパスワードを入れる (打ったパスワードは一切画面に表示されないので、打てたと思ったらEnterを押せば良い)。
入れたのを確認したら
sudo shutdown now
HIDガジェットの設定をする
vimで色々できるならそうすればいいですが、難しいと思うので、一旦パソコンにSDカードを挿し直してください。
config.txt
というファイルが見えると思いますので、 先頭に1行書き足しちゃいましょう。
dtoverlay=dwc2,dr_mode=peripheral
それから cmdline.txt
というのがありますので、 rootwait
の後ろに書き足す。
... rootwait modules-load=dwc2,libcomposite ...
SDカードを挿して起動、SSH接続。以下は参考記事からほぼそのまま拝借。
sudo tee /usr/local/bin/setup_hid_keyboard.sh
下記をコピペで貼り付けたら Ctrl + D
#!/bin/bash
# モジュールロード
# 起動時に、/boot/firmware/cmdline.txt で libcomposite がロードされるはずなので、必ずしも必要ではないが念のため
modprobe libcomposite
# configfs が自動マウントされていない場合に備え、ディレクトリの存在チェック
# if [ ! -e /sys/kernel/config/usb_gadget ]; then
# mount -t configfs none /sys/kernel/config
# fi
# 実際にマウントされているかどうかをチェック
if ! mountpoint -q /sys/kernel/config; then
mount -t configfs none /sys/kernel/config
fi
cd /sys/kernel/config/usb_gadget/
mkdir -p mykeyboard
cd mykeyboard
# ベンダーID / プロダクトID 設定 (例)
echo 0x1d6b > idVendor
echo 0x0104 > idProduct
# USBバージョン設定 (例: USB2.0 = 0x0200)
echo 0x0200 > bcdUSB
echo 0x0100 > bcdDevice # デバイスバージョン
# 文字列記述子の設定 (英語:0x409)
mkdir -p strings/0x409
# 文字列 (シリアル/メーカー/製品名)
echo "1234567890" > strings/0x409/serialnumber
echo "MyPiVendor" > strings/0x409/manufacturer
echo "MyPiKeyboard" > strings/0x409/product
# Config ディレクトリの作成
mkdir -p configs/c.1
mkdir -p configs/c.1/strings/0x409
echo "Config 1: Keyboard" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
# HID 機能の追加 (ブートプロトコル対応キーボード)
mkdir -p functions/hid.usb0
echo 1 > functions/hid.usb0/protocol # 1=キーボード
echo 1 > functions/hid.usb0/subclass # 1=ブートインターフェース
echo 8 > functions/hid.usb0/report_length
# レポートディスクリプタ
# keyboard_report.desc は /home/pi に用意しておく
# なお、本記事では例として /home/pi に用意していますが、ご自身の環境に合わせて変更してください。
echo -ne "\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x03\xc0" > functions/hid.usb0/report_desc
# 上で作ったHID機能をConfigに紐づけ
ln -s functions/hid.usb0 configs/c.1/
# UDC(USB Device Controller)のバインド
UDCNAME=$(ls /sys/class/udc | head -n 1)
echo $UDCNAME > UDC
# 特定の UDC 名がわかっているのであれば、明示的に指定するほうがより安全
# ここだけオリジナルに追記
chown nekono:nekono /dev/hidg0
これは、「私はUSBキーボードですよ」とケーブルを通じて主張する部分です。最後の部分は、 /dev/hidg0
というこのあと使うファイルの所有権を変える部分なので、ユーザー名は設定したものを使ってください。
権限設定は本当はudevっていうのを使うべきなんだけど、たかがRas Piにそこまでこだわるのもだるいのでこれでいいかと。
sudo chmod +x /usr/local/bin/setup_hid_keyboard.sh
実行権限を付与しておきます。
次に自動起動設定
sudo tee /etc/systemd/system/hidgadget.service
以下を貼り付けてCtrl + D
[Unit]
Description=Setup HID Gadget for USB OTG
# After=systemd-modules-load.service network.target sysinit.target local-fs.target
# 環境によっては configfs の自動マウント設定を確認する必要がある
After=systemd-modules-load.service network.target sys-kernel-config.mount
ConditionPathExists=/sys/kernel/config
[Service]
# 今回は一度設定を行うだけなので Type=oneshot とし、RemainAfterExit=yes にしている
Type=oneshot
ExecStart=/usr/local/bin/setup_hid_keyboard.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
そして有効化と再起動。
sudo systemctl enable hidgadget.service
sudo reboot
ここまでやると、再起動後にPS5側で「キーボードが接続されました」とか出るようになるはず。
タイピングスクリプトをこしらえる
/dev/hidg0
っていうファイルにキーボードの状態が変わった旨のメッセージを書き込むだけなんですが、まあそれを自動化しないと意味がないわけですね。
こういう面倒なのはChatGPTに丸投げしましょうかね。
cat > type.py
貼り付け内容は以下の通り。
#!/usr/bin/env python3
import sys
import time
NULL_CHAR = chr(0)
ENTER_KEY = 40 # HID usage ID for Enter key
SHIFT_KEY = 0x02 # HID usage ID for Shift key
DELAY_TIME = 0.05 # Constant delay time (seconds)
def get_key_code(char):
"""Return the HID usage ID for a given character and whether Shift is required."""
# Handle digits 0-9
if '0' <= char <= '9':
return (ord(char) - ord('1') + 30 if char != '0' else 39, False)
# Handle lowercase letters a-z
elif 'a' <= char <= 'z':
return (ord(char) - ord('a') + 4, False)
# Handle uppercase letters A-Z (Shift is required)
elif 'A' <= char <= 'Z':
return (ord(char) - ord('A') + 4, True)
return None # Ignore unsupported characters
def write_report(report):
with open('/dev/hidg0', 'rb+') as fd:
fd.write(report.encode())
def send_key(char):
key_code_data = get_key_code(char)
if key_code_data:
key_code, shift_required = key_code_data
# If Shift is required, press it along with the key
if shift_required:
write_report(chr(SHIFT_KEY) + NULL_CHAR + chr(key_code) + NULL_CHAR*4)
time.sleep(DELAY_TIME)
write_report(NULL_CHAR*8) # Release all keys
else:
write_report(NULL_CHAR*2 + chr(key_code) + NULL_CHAR*5)
time.sleep(DELAY_TIME)
write_report(NULL_CHAR*8) # Release all keys
time.sleep(DELAY_TIME)
def press_alt_backquote():
# Press and hold Alt (modifier 0x04)
write_report(chr(0x04) + NULL_CHAR + NULL_CHAR*6)
time.sleep(DELAY_TIME)
# Press backquote (usage ID 0x35)
write_report(chr(0x04) + NULL_CHAR + chr(0x35) + NULL_CHAR*5)
time.sleep(DELAY_TIME)
# Release backquote, keep holding Alt
write_report(chr(0x04) + NULL_CHAR + NULL_CHAR*6)
time.sleep(DELAY_TIME)
# Release Alt
write_report(NULL_CHAR*8)
time.sleep(DELAY_TIME)
def press_enter():
# Press Enter
write_report(NULL_CHAR*2 + chr(ENTER_KEY) + NULL_CHAR*5)
time.sleep(DELAY_TIME)
# Release Enter
write_report(NULL_CHAR*8)
time.sleep(DELAY_TIME)
def main():
if len(sys.argv) != 2:
print("Usage: python3 send_keys.py <string_of_text>")
sys.exit(1)
input_string = sys.argv[1]
# Perform the Alt + backquote sequence
press_alt_backquote()
# Send the input string as keystrokes
for char in input_string:
send_key(char)
# Press and release Enter
press_enter()
if __name__ == "__main__":
main()
chmod +x type.py
使い方ですが、まず原神のユーザー検索モードを UID
にします。
ここでSSH接続したPi上で下のように入力
./type.py 869999999
「日本語入力を解除して」「UIDを入れて」「Enterキーを押す」ところまでやってくれます。
私のキーボードはUS配列なので日本語解除は Alt + Backquote
ですが、日本語配列設定の場合はAltキーを押す必要はないかと思います (全角半角キーはBackquoteキーと同じキーです) 。