前編・後編 (US配列) では、Raspberry Pi Zero 2 W を USB OTG ガジェットモードで「キーボード(HID)」として認識させ、ネットワーク経由で受け取ったテキストをターゲットPCへ入力する仕組みを構築しました。
しかし、前編・後編 (US配列) の実装例は主にUS配列ベースのマッピングだったため、日本語キーボード(JIS配列)を使う環境では記号の配置ズレやIMEキーの扱いなど、追加の調整が必要になります。
本記事 続編(JIS配列対応) では、日本語(JIS)配列で使われるキーや記号を極力網羅したサンプルを紹介します。特に「無変換」「変換」「半角/全角」などのIME制御キーや、大文字入力(Shift)時の記号、Fキー・矢印キーなどもまとめています。環境によってはそのまま動作しないキーもあるため、参考にしながら調整いただければ幸いです。
前提
-
Raspberry Pi Zero 2 W で USB ガジェットモードを有効にし、
/dev/hidg0
へ書き込みできる状態 (前編・後編参照)。 - ターゲットPC の OS が **「日本語キーボード(106/109キー)として認識している」**こと。
- Windows: デバイスマネージャやキーボード設定で「日本語キーボード」と認識されているか確認
- Linux/Mac: XKB設定やシステム設定で
jp106
/JIS配列になっていること
- Python でスクリプトを動かせる環境が整っている(例: Raspberry Pi OS)。
なぜJIS配列だと難しい?
- US配列 に比べて、記号キーの配置が複雑かつ、OS依存要素が多いため。
- 日本語IMEsでの「半角/全角キー」「無変換/変換キー」の扱いが統一されていない。
- JIS配列のキーコード と OSが期待する配列 がずれると、入力結果が変わってしまう。
- 特に「円記号(\¥)」や「Shift + 数字キー記号」のマッピングは環境によっては異なります。
サンプル実装例 (改良版)
以下のコードは、JIS配列+IME制御キーも含め、できる限り広く対応するためのサンプルです。
- 大文字 (A–Z) を入力する際は、自動的に Shift + 対応する小文字 を送信します。
-
Shiftが必要な記号 (例:
!
,"
,#
,(
,)
, など) もマッピング済み。 - IMEキー (半角/全角, 無変換, 変換, カタカナ/ひらがな) も追加しています。
- Fキー・矢印キー などは JIS/US共通 なので、同じUsage IDを使用しています。
import time
#
# 修飾キーのビット定義 (modifier)
#
MOD_LCTRL = 0x01
MOD_LSHIFT = 0x02
MOD_LALT = 0x04
MOD_LGUI = 0x08
MOD_RCTRL = 0x10
MOD_RSHIFT = 0x20
MOD_RALT = 0x40
MOD_RGUI = 0x80
#
# JIS配列で「Shift不要」の文字(英小文字・数字・一部記号など)
#
KEYMAP_JIS = {
# --- 英小文字 ---
'a': 0x04, 'b': 0x05, 'c': 0x06, 'd': 0x07,
'e': 0x08, 'f': 0x09, 'g': 0x0A, 'h': 0x0B,
'i': 0x0C, 'j': 0x0D, 'k': 0x0E, 'l': 0x0F,
'm': 0x10, 'n': 0x11, 'o': 0x12, 'p': 0x13,
'q': 0x14, 'r': 0x15, 's': 0x16, 't': 0x17,
'u': 0x18, 'v': 0x19, 'w': 0x1A, 'x': 0x1B,
'y': 0x1C, 'z': 0x1D,
# --- 数字 (Shift不要) ---
'1': 0x1E, '2': 0x1F, '3': 0x20, '4': 0x21,
'5': 0x22, '6': 0x23, '7': 0x24, '8': 0x25,
'9': 0x26, '0': 0x27,
# --- 制御・空白系 ---
'\n': 0x28, # Enter
'\r': 0x28, # Enter(別表現)
'\t': 0x2B, # Tab
' ': 0x2C, # Space
'\b': 0x2A, # Backspace
'\x1b': 0x29, # ESC (ASCII 0x1B)
# --- JIS配列での「そのまま」記号 ---
'-': 0x2D, # '-'
'^': 0x2E, # '^'
'@': 0x2F, # '@'
'[': 0x30, # '['
']': 0x31, # ']' (実際のキーボード刻印では省略されがち)
';': 0x33, # ';'
':': 0x34, # ':'
',': 0x36, # ','
'.': 0x37, # '.'
'/': 0x38, # '/'
# --- 円記号/バックスラッシュ問題 ---
# 環境によって円記号が 0x31 や 0x89 など異なる実装がある。
# ここでは便宜上 '\' を 0x31, '¥' を 0x89 にしてみる。
'\\': 0x31, # バックスラッシュ(US配列で']'位置相当)
'¥': 0x89, # Keyboard International3 などを使う例
}
#
# JIS配列で「Shiftが必要」な記号
# (例: '!' は Shift + '1', '"' は Shift + '2' 等)
#
SHIFTKEYMAP_JIS = {
'!': 0x1E, # Shift + '1'
'"': 0x1F, # Shift + '2'
'#': 0x20, # Shift + '3'
'$': 0x21, # Shift + '4'
'%': 0x22, # Shift + '5'
'&': 0x23, # Shift + '6'
'\'': 0x24, # Shift + '7' => アポストロフィ
'(': 0x25, # Shift + '8'
')': 0x26, # Shift + '9'
'=': 0x2D, # Shift + '-'
'~': 0x2E, # Shift + '^'
'`': 0x2F, # Shift + '@' (バッククォート)
'{': 0x30, # Shift + '['
'+': 0x33, # Shift + ';'
'*': 0x34, # Shift + ':'
'<': 0x36, # Shift + ','
'>': 0x37, # Shift + '.'
'?': 0x38, # Shift + '/'
'|': 0x89, # Shift + '¥' (例: '|')
}
#
# 日本語特有キー (IME切替など)
# 実際に機能するかは OS&IME設定次第
#
SPECIAL_KEYS_JIS = {
"HANKAKU_ZENKAKU": 0x35, # 半角/全角キー(IME ON/OFF)の例
"MUHENKAN": 0x88, # 無変換
"HENKAN": 0x8A, # 変換
"KATAHIRA": 0x90, # カタカナ/ひらがな
}
#
# Fキー、矢印キーなど (JIS/US共通)
#
FUNCTION_KEYS = {
"F1": 0x3A, "F2": 0x3B, "F3": 0x3C, "F4": 0x3D,
"F5": 0x3E, "F6": 0x3F, "F7": 0x40, "F8": 0x41,
"F9": 0x42, "F10": 0x43, "F11": 0x44, "F12": 0x45,
"PRINT_SCREEN": 0x46,
"SCROLL_LOCK": 0x47,
"PAUSE": 0x48,
"INSERT": 0x49, "HOME": 0x4A, "PAGE_UP": 0x4B,
"DELETE": 0x4C, "END": 0x4D, "PAGE_DOWN": 0x4E,
"RIGHT_ARROW": 0x4F, "LEFT_ARROW": 0x50,
"DOWN_ARROW": 0x51, "UP_ARROW": 0x52,
}
def convert_jis_key(ch: str) -> tuple[int,int]:
"""
1文字/特殊キー名を受け取り、(modifier, usage_id) を返す。
usage_id=0 は押下なしとみなす。
"""
# --- 大文字A-Z => Shift + 小文字キー
if 'A' <= ch <= 'Z':
keycode = KEYMAP_JIS.get(ch.lower(), 0)
if keycode != 0:
return (MOD_LSHIFT, keycode)
else:
return (0, 0)
# --- 小文字/数字/記号(Shift不要)
if ch in KEYMAP_JIS:
return (0, KEYMAP_JIS[ch])
# --- Shift必須記号
if ch in SHIFTKEYMAP_JIS:
return (MOD_LSHIFT, SHIFTKEYMAP_JIS[ch])
# --- 日本語特有キー
if ch in SPECIAL_KEYS_JIS:
return (0, SPECIAL_KEYS_JIS[ch])
# --- Fキー・矢印・他特殊キー
if ch in FUNCTION_KEYS:
return (0, FUNCTION_KEYS[ch])
# --- 未定義
return (0, 0)
def make_report(modifier: int, usage_id: int) -> bytes:
"""
8バイトのHIDレポートを組み立てる。
[modifier, 0x00, usage_id, 0x00, 0x00, 0x00, 0x00, 0x00]
"""
return bytes([modifier, 0x00, usage_id, 0x00, 0x00, 0x00, 0x00, 0x00])
def send_jis_keys(sequence):
"""
引数 sequence は:
- 文字列("Hello!\n")なら1文字ずつ処理
- リスト(["F1","LEFT_ARROW","HANKAKU_ZENKAKU"])なら各要素を1キーとみなす
"""
if isinstance(sequence, str):
items = list(sequence)
else:
items = sequence
with open("/dev/hidg0", "wb") as f:
for ch in items:
mod, usage = convert_jis_key(ch)
if usage != 0:
# 押下
f.write(make_report(mod, usage))
time.sleep(0.01)
# 離す
f.write(make_report(0, 0))
time.sleep(0.01)
使用例
# 例1: 通常の文字列送信
send_jis_keys("Hello, World!\n")
# 例2: 半角/全角キーでIME ON/OFFトグルを試す
send_jis_keys(["HANKAKU_ZENKAKU"])
# 例3: 大文字+記号などを混在
send_jis_keys("ABC!@#(JIS)\n")
# 例4: Fキーや矢印キー
send_jis_keys(["F1", "LEFT_ARROW", "RIGHT_ARROW"])
IME周りの動作について
-
半角/全角 (HANKAKU_ZENKAKU)
- WindowsではIMEのON/OFFトグルとして働くことが多いですが、設定やIMEによっては動作が異なる場合もあります。
-
無変換 / 変換 / カタカナ/ひらがな
- OS・IMEによって挙動はまちまち。全く反応しないIMEもあれば、変換モードを切り替えるIMEも。
-
IMEでの日本語入力
-
"あいうえお"
のように 直接全角文字を送る ことはできません。キーボードはあくまでキー押下イベントを送るため、最終的に文字を確定するのはOS側のIMEです。
-
Fキー、矢印キー、Home/End/Insert/Delete
- これらは JIS/US配列に依存しないUsage ID を使います。
- 多くの場合、そのまま正常に動作しますが、一部キー(ScrollLockなど)が期待通りに動かない例もあります。
- 必要に応じて OS側の設定やキーマッピングを確認してください。
よくある質問
-
「¥」が入力できない / 「\」になってしまう
- Windows日本語環境では、ASCII
0x5C
(バックスラッシュ) をフォント上「円記号」で表示する仕様があり混乱しがち。 - キーコードレベルとフォント表示が一致しない例も多いので、レジストリやIMEの設定を調整する場合があります。
- Windows日本語環境では、ASCII
-
大文字や記号が合わない
- ターゲットPC側が US配列 として認識している可能性。必ず JIS配列(106/109キー) になっているか確認してください。
-
IMEキー(無変換/変換/カタカナ/ひらがな等)が効かない
- IMEの設定で無効化されている / 別のキー割り当てになっている可能性があります。
- WindowsやLinuxのIME設定を見直してみてください。
-
Unicode文字や絵文字を入力したい
- キー入力レベルではASCIIやJP106配列の範囲しか送れません。絵文字や特殊文字は、OS側のIMEやソフトウェアで入力対応している必要があります。
まとめ
- JIS配列 で記号や大文字入力、IME制御キーまで幅広くカバーするには、相応のマッピング辞書が必要です。
- 本記事のサンプルコードでは「Shift記号」や「大文字(A–Z)」も考慮した改良版マップを用意しています。
- ただし、OSやIME、キーボード固有の違いによって挙動が変わる場合があるため、自環境に合わせて微調整 してください。
- Raspberry Pi Zero 2 W を USBキーボードとしてエミュレートし、遠隔で入力する用途などにぜひ活用してみてください。
参考リンク
- USB HID Usage Tables (公式ドキュメント)
- Microsoft Docs: Keyboard Scan Code Specification
- Raspberry Pi Zero 2 W で USBキーボードをエミュレート(前編・後編)
- Linuxのキーコード設定 (XKB) など
以上