現: 2024-05-22 (水) 13:31:14 yuji Deleted an attach file: keyboad.png at 2024-06-10 (月) 11:00:23, Deleted an attach file: keyboard.png at 2024-06-10 (月) 11:00:29 at 2024-06-10 (月) 11:04:17 |
|||
---|---|---|---|
Line 1: | Line 1: | ||
+ | * Windows PCのキーボード [#n1beb645] | ||
+ | Windows PCでのキーボードはIBM PCの頃から大きく変わっていない。いまだにPS/2コネクタを持つMotherboardや機種も存在していて,オリジナルなIBM PCのキーボードもちゃんと接続して利用できる。~ | ||
+ | 現在はUSBやBluetoothで接続するキーボードが,一般的に使用されている。~ | ||
+ | ハードウェアは,IBM PC/AT・PS/2のキーボードやUSB/Bluetooth接続のキーボードなどの2つのタイプがある。~ | ||
+ | ハードウェアからキーの情報をデバイスドライバーが受信して押されたキーをWindowsスキャンコードに変換して,フィルタードライバー''kbdclass.sys''に送り処理する構造になっている。~ | ||
+ | ハードウェアの違いをこのような構造で対応している。~ | ||
+ | |||
+ | その後,Windowsスキャンコードから仮想キーコードに変換する時にレイアウトDLLを使ってキー配列を入れ替え処理や言語やキー固有の処理が行われるようになっている。~ | ||
+ | |||
+ | #ref(keyboard.png,,80%) | ||
+ | |||
+ | ** ハードウェア [#q175b1e8] | ||
+ | 物理的なキーボードは,ATキーボード・PS/2キーボードとUSB/Bluetoothキーボードの2つの種類がある。~ | ||
+ | PS/2キーボードは,Note PCなどの内蔵キーボードとしても多く利用されている。~ | ||
+ | |||
+ | *** IBM PC/AT・PS/2キーボード [#f7a7363f] | ||
+ | IBM PC/ATではキーボードを接続するインターフェースにはシリアル通信が使われていた。~ | ||
+ | IBM PS/2シリーズで採用されたPS/2キーボードは,PC/ATで使われたコネクターを小型化したものを使っているが,信号などは同じ。~ | ||
+ | &ref(PS2connector.png,,20%);&ref(PS2connector2.png,,10%);(緑色のコネクタがPS/2コネクタ)~ | ||
+ | |AT Keyboard|PS/2 Keyboard|信号名 |説明 |h | ||
+ | |2 |1 |+DATA |データ信号(正極性)| | ||
+ | | |2 |n.c. |未接続 | | ||
+ | |4 |3 |GND |GND | | ||
+ | |5 |4 |VCC |電源 +5V | | ||
+ | |1 |5 |+CLK |クロック(正極性) | | ||
+ | | |6 |n.c. |未接続 | | ||
+ | | |ケース |Case sealed|接地 | | ||
+ | |||
+ | ATキーボードやPS/2キーボードは,キーボードのセンシング・PCとの通信のためにCPUを搭載していて,シリアル通信でPC側へキー情報を通知している。キー情報は,スキャンコードというコードにエンコードされて送信される。~ | ||
+ | PC側からキーボードにコマンドを送信して,設定を変更出来るようになっている。~ | ||
+ | キーが押されたり離された状態を,メーク/ブレークのスキャンコードとして送信する。~ | ||
+ | |||
+ | 現在のWindows PCでも,キーボードのスキャンコードはそのまま利用している。一般的にはSet2が使用されている。~ | ||
+ | 仕様上はPC側からコマンドを送ってScan Code Setを変更することも可能だが,これはキーボードの機能次第。~ | ||
+ | Set2に対応していれば,Windows PCでの利用は特に問題はない。~ | ||
+ | |||
+ | *** USB/Bluetoothキーボード [#yd87deac] | ||
+ | USBキーボードは,USBデバイスクラスのHID(Human Interface Device)として実装されていて,キーボードのキーの状態はレポート形式で送信される。~ | ||
+ | キーボード状態のレポートは,その時点で押されているキーをすべて列挙するだけのもので,Ctrl/Shift/Altなどの修飾キーの処理は全てその後のソフトウェアで処理されている。~ | ||
+ | |||
+ | Bluetoothキーボードは,ソフトウェア的にはUSB HIDクラスを使用していて,コントローラーや通信プロトコルは違っていても,USBキーボードと同じHIDレポートを送信するようになっている。~ | ||
+ | |||
+ | ** スキャンコード [#f52bc0f3] | ||
+ | キーボードからPCのデバイスドライバーに送られるスキャンコードには,キーを押したときに発生するメークコードと,キーを離したときに発生するブレークコードがある。~ | ||
+ | |||
+ | 使用するセットの種類によりブレークコードの表現が違っていて,Set1は上位ビットを1にしていて,Set2/Set3はメークコードの前に0xF0(16進数)が付けられる。~ | ||
+ | |||
+ | スキャンコードは3種類のコードがあって,それをScan Code Set1/Set2/Set3と後に呼ばれるようになった。~ | ||
+ | - Set1~ | ||
+ | 初代IBM PC,IBM PC XTのキーボード(86キーボードやXTキーボードなどと呼ばれる)で使われていた。~ | ||
+ | - Set2~ | ||
+ | IBM PC/ATのキーボード(101キーボードやEnchanded Keyboard,AT Keyboardなどとも呼ばれる)で使用されたスキャンコード。~ | ||
+ | - Set3~ | ||
+ | IBM PS/2(PS2キーボードとも呼ばれる)で使用されたスキャンコード。~ | ||
+ | |||
+ | 左右に同じキーがある場合,片方に0xE0を付けてどちらのキーが押されたのかを区別している。このためアプリケーションで利用するショートカットなどでは,左右にあるAltキーやCtrlキーを区別出来る物がある。~ | ||
+ | |||
+ | スキャンコードSet1は,最上位ビットを立ててメークとブレークを区別していたため,コードの範囲は0x01~0x7Fまでだった。~ | ||
+ | Windowsスキャンコードでは,メーク・ブレークは別に扱っているので,8bitすべて(0xFFまで)をコード範囲として利用出来るようになっている。~ | ||
+ | このため,101キーボード以後に追加された様々なキーも固有のスキャンコードを持つことが可能になった。~ | ||
+ | |||
+ | USB/Bluetoothキーボードはスキャンコードを使ってはいないが,キーボードからPCへHIDレポートとして送った後,ソフトウェアでWindowsスキャンコードに変換することで,以後の処理は同様に''kbdclass.sys''で扱うようになっている。~ | ||
+ | |||
+ | 最終的にWindowsスキャンコードは仮想キーコードに変換されて,キーを押した(WM_KEYDOWNイベント),キーを離した(WM_KEYUPイベント)というイベントとしてアプリケーションで利用される。~ | ||
+ | それぞれが別々のイベントになるので,Windowsスキャンコードではメークコードのみが使われている。~ | ||
+ | |||
+ | ** キーボード・レイアウト [#w458270c] | ||
+ | Windowsの国際化のため,キーボードのレイアウトには多くのバリエーションがある。~ | ||
+ | |||
+ | ATキーボードやPS/2キーボードのスキャンコードは,86キー・101キーのキートップをベースにしたキーに番号を割り当てたものになっている。~ | ||
+ | 元々はキートップ文字と直接対応していたが,国際化の過程でキーそのものを区別するコードになり,OS側でキーボードのレイアウト(キートップの並び,どのキーを押したらどんな文字や機能になるのかということ)を使用して,そのスキャンコードを個々のキーの仮想キーコードに変換している。~ | ||
+ | |||
+ | キーボードからは2バイトのIDを返す仕組みがあるが,IBM PC/ATのハードウェアがPC互換機として普及していく過程で,このID割り当てを誰も管理しなかったため,キーボードの区別をこのIDで行うことは困難になってしまった。~ | ||
+ | そこで,キーレイアウトに関してはOS側で対応することにしている。~ | ||
+ | |||
+ | USB/Bluetoothキーボードもデバイスに関する情報を返す機能を持っているので,メーカー名やキーボード名などからキーのレイアウトを判別することは可能だと思われるが,この機能も使用されていない。~ | ||
+ | ATキーボードやPS/2キーボードと同様に,OS側でキーレイアウトに対応している。~ | ||
+ | |||
+ | 日本語キーボードとしては106キーボードと呼ばれるタイプ([[OADG>http://oadg.or.jp/]]で定義したことからOADGキーボードと呼ばれることもある)が普及して,これはIBM PC/ATで使用された101キーに変換/無変換/カタカナ・ひらがななどの5個のキーを追加したもの(全角/半角キーは,101のチルダキーを利用している)だが,記号などの配列が違っている。~ | ||
+ | 現在の日本語キーボードは,左右にWindowsキーやメニューキーも搭載されるので,106/109キーボードとか言っている。~ | ||
+ | |||
+ | Windowsを使用している時に突然(Windowsやデバイスドライバーのバグや,ファイルの破損などで)日本語キーボードが英語配列になってしまった,などを経験することがあるかもしれないが,これはソフトウェア処理によってキーボードのレイアウトに対応していることから,何らの原因でこのようなことが起きる。~ | ||
+ | |||
+ | Windowsスキャンコードを仮想キーコードに変換する時にレイアウトDLLである''kbdxxx.dll''ライブラリも使用される。~ | ||
+ | このDLLには,Windowsスキャンコードを仮想キーコードに変換するための変換テーブルが含まれていて,各国対応などのさまざまなキーボードのバリエーションに対応出来るようにしている。~ | ||
+ | 日本語106/109キーボードで使われるのは''kbdjpn.dll''や''kbd106.dll''(Windows10)。 日本語AXキーボード用の''kbdax2.dll''もその一つ。~ | ||
+ | 通常''C:\Windows\System32''に多くの''kbdxxx.dll''が用意されている。~ | ||
+ | |||
+ | Windows10以前のWindowsではレジストリ''HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000411''に, | ||
+ | |名前|US英語キーボード|日本語キーボード|h | ||
+ | |Layout File|kbd101.dll|kbdjpn.dll| | ||
+ | 上記のどちらかが設定されている。~ | ||
+ | |||
+ | Windows10でもこのレジストリに設定されてはいるが,ここが使われるのはRDPを使ってリモートアクセスしている時などに使われるように変更されているようだ。~ | ||
+ | もしRDPなどで英語キーボードになってしまう症状が発生する場合はこのレジストリを,~ | ||
+ | kbdjpn.dll -> kbd106.dll | ||
+ | に変更すると問題が改善する。~ | ||
+ | どうも''Windows10のkbdjpn.dll''は,英語キーボードで日本語入力する場合に使用するレイアウトDLLに変更されているみたい。~ | ||
+ | |||
+ | 通常のWindows10で使用するキーボードのレイアウトのレジストリは,それ以前のWindowsから以下のレジストリへ変更されている。~ | ||
+ | ''HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters''~ | ||
+ | |名前|US英語キーボード|日本語106/109キーボード|h | ||
+ | |LayerDriver JPN|kbd101.dll|kbd106.dll| | ||
+ | |LayerDriver KOR|kbd101a.dll|削除する| | ||
+ | |OverrideKeyboardIdentifier|PCAT_101KEY|PCAT_106KEY| | ||
+ | |OverrideKeyboardSubtype|0|2| | ||
+ | |OverrideKeyboardType|7以外|7| | ||
+ | |||
+ | また,この仮想キーコードに変換するときに使われる''kbdxxx.dll''ライブラリを独自で作成することで,どのようなレイアウトでも定義可能になる。~ | ||
+ | 独自レイアウトライブラリを作成する事ができるMicrosoft純正のツール[[Microsoft Keyboard Layout Creator>https://www.microsoft.com/en-us/download/details.aspx?id=102134]]もある。~ | ||
+ | |||
+ | *** キー入力できなくなるトラブル [#u3627be1] | ||
+ | レイアウトDLLを使って最終的にキー入力が行われるが,これが何らかの理由でファイルが破損していたりすると,キーの一部が入力できなくなるといったトラブルが発生する事がある。~ | ||
+ | |||
+ | このようなトラブルが発生した場合,レイアウトDLLファイルはWindowsのシステムファイルなので,[[いくつかの方法でファイルを修復する>/PC/Windows/修復ツールを使ってWindowsのシステムファイルを修復する]]ことが出来る。~ | ||
+ | |||
+ | &ref(kbdxxxdll.zip,,Windows10(22H2)のレイアウトDLL); | ||
+ | |||
+ | *** 複数のキーボードを同時に接続した場合のレイアウト [#r8499712] | ||
+ | 複数のキーボードを同時に接続した場合,それぞれのキーボードが異なるレイアウト(例えばNote PCは日本語キーボードで,そのPCにUSB接続したキーボードはUS配列など)の時には,通常はどちらか一方の配列になってしまう。~ | ||
+ | |||
+ | レジストリを変更することで,各キーボードで別々のレイアウトを使用するように設定できる。 | ||
+ | |||
+ | 以下は例としてNote PCが日本語でUSBで接続したキーボードが英語USレイアウトの場合のレジストリ設定。~ | ||
+ | - USBで英語USキーボードを接続する。~ | ||
+ | - デバイスマネージャーを開いて,英語USキーボードの''VIDとPID''を確認する。~ | ||
+ | デバイスマネージャーのHIDキーボードで,接続しているUSBキーボードのVIDとPIDが確認できる。~ | ||
+ | - レジストリエディタを起動する。~ | ||
+ | - ''HKEY_LOCALMACHINE\SYSTEM\CurrentControlSet\Enum\HID''を開く。~ | ||
+ | - 接続しているキーボードのVID:PIDを検索する。~ | ||
+ | Vid_XXXX&Pid_YYYYのようなキーが作成されている。~ | ||
+ | 見つかったら,それを開く。この時,キーはUSBのコネクタ前にエントリーされるので現在指しているUSBコネクタのキーを開くようにする。~ | ||
+ | - ''Device Parameters''キーを開いて新規にサブキーを作成する。~ | ||
+ | 新規サブキーをDWORD値で作成する。~ | ||
+ | 作成したキー名を''KeyboardTypeOverride''に変更する。~ | ||
+ | 変更したら値を''4''に設定する。~ | ||
+ | 同様にして,''KeyboardSubtypeOverride''キーをDWORD値で作成し値を''2''にする。~ | ||
+ | |KeyboardTypeOverride|4| | ||
+ | |KeyboardSubtypeOverride|2| | ||
+ | |||
+ | この後,PCをリブートする。~ | ||
+ | これで,Note PCのキーボードは日本語レイアウトで,USB接続した英語USキーボードは英語レイアウトで使用できる。~ | ||
+ | |||
+ | *** 日本語AXキーボード [#a60d2a2e] | ||
+ | 日本語AXキーボードは英語配列の101キーをベースに日本語化したもので,アルファベットや記号類の配置が英語キーボードと同じで,そこに日本語用にキーが追加されている。~ | ||
+ | 以前は,日本語WindowsとAXキーボード(105キーボードとも呼ばれた)の組み合わせが流行った事もあった。~ | ||
+ | |||
+ | これはASCiiのAXマシン以前はPC互換機のPCのみだったため,多くのユーザーは101準拠のキーボードをそのまま使っていて,その配列になれていたからと思われる。~ | ||
+ | IMEオン/オフ用の漢字キーがスペースバーと同じ列にあり,現在の''全角/半角''キーよりも押しやすい。~ | ||
+ | AXキーボードは現在では入手困難だが,kbdax2.dllはWindows 10にも含まれているので今でも使えると思われる。~ | ||
+ | |||
+ | ** キーの入れ替え処理 [#td60d369] | ||
+ | キーボードのレイアウトは上記のレイアウトDLLにより,Windowsスキャンコードから仮想キーコードに変換される時にレイアウト処理が行われる。~ | ||
+ | |||
+ | しかし一部のキーの機能をちょっと変更したいことがある。Windowsではこのようなキーボードのキー入力を入れ替えることが出来るように,以下の2つの方法が用意されている。~ | ||
+ | - デバイスドライバーが使うレジストリでキーを入れ替える~ | ||
+ | フィルタードライバー''kbdclass.sys''でのキー入れ替え処理は,''レジストリ''でキー定義を変更できるようになっている。~ | ||
+ | レジストリを定義した後Windowsを再起動することでキーボード・フィルタードライバーがレジストリの定義をロードする。~ | ||
+ | このため,リアルタイムでのキー入れ替えは出来ないのと,アプリケーション毎にキーを入れ替えることは出来ない。~ | ||
+ | - Windows APIのHookを使用して入れ替える。~ | ||
+ | 仮想キーコードをアプリケーションに渡す時にHook APIを使って入れ替えが出来るようになっている。~ | ||
+ | Hook APIを使う場合はプログラムでキーイベントを書き換えることが出来るので,リアルタイムのキー入れ替えやアプリケーション毎にキーを入れ替えることが可能になる。~ | ||
+ | |||
+ | *** キーボード・フィルタードライバーで入れ替える方法 [#l0b90f12] | ||
+ | キーボード・フィルタードライバー''kbdclass.sys''でキーの入れ替え処理を行う場合は,キーのレイアウト処理の前に行うので,Windowsスキャンコードでキーの入れ替えが出来る。~ | ||
+ | |||
+ | 以下のレジストリに, | ||
+ | HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout\Scancode Map | ||
+ | 入れ替えたいキーのWindowsスキャンコードを設定することで,任意のキーを再割り当てすることが出来る。~ | ||
+ | |||
+ | 例1:CtrlとCapsLockを入れ替える~ | ||
+ | 以下の内容で''ctrl_capslock.reg''ファイルを作成して,レジストリに登録する。~ | ||
+ | Windows Registry Editor Version 5.00 | ||
+ | |||
+ | [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] | ||
+ | "Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1D,00,3A,00,3A,00,1D,00,00,00,00,00 | ||
+ | 値の意味(レジストリへの定義はリトルエンディアン)は,次のようになっている。~ | ||
+ | |定義値|数値|意味|h | ||
+ | |00,00,00,00|0x00000000 |バージョン番号 すべて0| | ||
+ | |00,00,00,00|0x00000000 |フラグ すべて0| | ||
+ | |03,00,00,00|0x00000003 |マッピングを設定する個数&br;マッピング2つとNULL終端を合わせて3| | ||
+ | |1D,00,3A,00|0x001D 0x003A|マッピング1&br;左CtrlをCapsLockに変換| | ||
+ | |3A,00,1D,00|0x003A 0x001D|マッピング2&br;CapsLockを左Ctrlに変換| | ||
+ | |00,00,00,00|0x00000000 |NULL終端| | ||
+ | |||
+ | 例2:DeleteとInsertを入れ替える~ | ||
+ | 以下の内容で''delete_insert.reg''ファイルを作成して,レジストリに登録する。~ | ||
+ | Windows Registry Editor Version 5.00 | ||
+ | |||
+ | [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] | ||
+ | "Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,53,e0,52,e0,52,e0,53,e0,00,00,00,00 | ||
+ | 値の意味(レジストリへの定義はリトルエンディアン)は,次のようになっている。~ | ||
+ | |定義値|数値|意味|h | ||
+ | |00,00,00,00|0x00000000 |バージョン番号 すべて0| | ||
+ | |00,00,00,00|0x00000000 |フラグ すべて0| | ||
+ | |03,00,00,00|0x00000003 |マッピングを設定する個数&br;マッピング2つとNULL終端を合わせて3| | ||
+ | |1D,00,3A,00|0xe053 0xe052|マッピング1&br;DeleteをInsertに変換| | ||
+ | |3A,00,1D,00|0xe052 0xe053|マッピング2&br;InsertをDeleteに変換| | ||
+ | |00,00,00,00|0x00000000 |NULL終端| | ||
+ | |||
+ | レジストリを安全に変更できる[[Change Key>http://satoshi3.sakura.ne.jp/f_soft/dw_win.htm]]というフリーのキー配置変更ツールもある。~ | ||
+ | |||
+ | *** Hook APIを使用して入れ替える方法 [#x14d045f] | ||
+ | Win32APIではイベントを発生させる前段階に割り込むことができる,キーボードフックと呼ばれるAPIがある。これ利用することでキーの差し替えなどが可能になるが,仮想キーコードとのマッピングがされた後なので処理がちょっと複雑になってしまう。~ | ||
+ | Hook APIのキーの入れ替えが面倒なのは,レイアウトによってキーの挙動が変わってしまう理由もある。~ | ||
+ | |||
+ | [[PowerToys>https://learn.microsoft.com/ja-jp/windows/powertoys/]]のKeyboard Managerは,このHook APIを使ってキーの入れ替えを行えるツール。~ | ||
+ | |||
+ | * キーボードのスキャンコード [#j1f21b1c] | ||
+ | - [[キーボードのスキャンコード>./OADG109キーボードのスキャンコード]] | ||
+ | |||
+ | * キーボードで大文字しか入力できなくなった [#q0ad35cc] | ||
+ | ある時,会社のWindowsマシンでUSBで接続しているキーボードからの入力が,大文字しか打てなくなってしまった。キーボードを別のものに交換したりしても改善しない。~ | ||
+ | |||
+ | ログインも出来ない状態なので困ってしまった。仮想キーボードから入力しようとしても同じで小文字が打てない。~ | ||
+ | |||
+ | レイアウトDLLなどのシステムファイルが壊れているのかと思い,dismとsfcコマンドなどを使ってシステム修復(いくつかのシステムファイルが壊れていたのだが・・・)しても改善しない。~ | ||
+ | |||
+ | デバイスマネージャーでキーボードのところを確認すると, | ||
+ | VID:PID=04F2:0400 | ||
+ | VID:PID=1A81:1004 | ||
+ | なぜか,HIDキーボードデバイスが2つあった。~ | ||
+ | PCはデスクトップPCで接続しているUSBキーボードは1個だけなので,HIDキーボードはUSBまたはBluetoothキーボードで使用されるデバイスドライバーなので,2つのHIDキーボードのデバイスドライバーがロードされているのはおかしい((VMWare Workstationなどの仮想化ソフトウェアを使っている場合は,ロードされる場合がある。))。~ | ||
+ | |||
+ | 試しに,VID:PID=1A81:1004の方のデバイスドライバーを強制的にアンインストールすると正常にキー入力が出来るようになった。なのでこのデバイスが原因となっているようだ。~ | ||
+ | しかしこのままでは,ハードウェア変更のスキャンや再起動するとまた2つのデバイスドライバーがロードされてしまう。~ | ||
+ | |||
+ | VID:PID=1A81:1004のデバイスは,無線でマウスとキーボードが接続できるUSBドングルで,キーボードは使っておらずマウスのみ使用していた。~ | ||
+ | どうもキーボードを接続していないとUSBドングルからHIDキーボード・デバイスドライバーに左Shiftキーが押しっぱなしの情報が送られているようだ。USBドングルの動作不具合だね ;( ~ | ||
+ | |||
+ | 2つのキーボードのデバイスドライバーからのキー情報は,フィルタードライバー''kbdclass.sys''へ両方とも送られてその後Windows Kernelに送られるので,勝手にShiftキーが押されて大文字しか入力できなくなっていたというのが原因だった。~ | ||
+ | |||
+ | この問題のUSBドングルを抜いて,大文字しか入力できない問題は解決した :D |