キーボードおよびマウス クラス ドライバーの構成
Note
このトピックは、キーボードおよびマウス クラス ドライバーを構成している開発者向けです。 マウスまたはキーボードを修正する場合は、次を参照してください。
HID 以外のキーボードとマウスは、複数のレガシ バス経由で接続できますが、同じクラス ドライバーを引き続き使用します。 このセクションでは、クラス ドライバー自体の詳細について説明します。 次のセクションでは、コントローラーの詳細について説明します。
このトピックでは、Microsoft Windows 2000 以降でのキーボードおよびマウス デバイスの一般的な物理的な構成について説明します。
次の図は、1 つのキーボードと 1 つのマウスを使用する 2 つの一般的な構成を示しています。
左側の図は、独立したコントローラーを介してシステム バスに接続されたキーボードとマウスを示しています。 一般的な構成は、i8042 コントローラーを介して操作される PS/2 スタイルのキーボードと、シリアル ポート コントローラーを介して操作されるシリアル スタイルのマウスで構成されます。
次の追加情報は、キーボードとマウスの製造元にとって重要です。
- キーボードは、セキュリティ上の理由からオペレーティング システム スタックによって排他モードで開かれます
- Windows では、複数のキーボードとマウス デバイスの同時接続がサポートされています。
- Windows では、各デバイスへのクライアントによる独立したアクセスはサポートされていません。
クラス ドライバーの機能
このトピックでは、次の Microsoft Windows 2000 以降のシステム クラス ドライバーの機能について説明します。
Kbdclass:デバイス クラスのデバイスのクラス ドライバー GUID_CLASS_KEYBOARD
Mouclass、デバイス クラスのデバイスのクラス ドライバー GUID_CLASS_MOUSE
Kbdclass は Kbdclass サービスを実装し、その実行可能イメージはkbdclass.sys。
Mouclass は Mouclass サービスを実装し、その実行可能イメージはmouclass.sys。
Kbdclass と Mouclass の各機能:
デバイス クラスの汎用操作とハードウェアに依存しない操作。
プラグ アンド プレイ、電源管理、および Windows Management Instrumentation (WMI)。
レガシ デバイスの操作。
複数のデバイスの同時操作。
関数ドライバーがデバイスの入力データ バッファーからクラス ドライバーのデータ バッファーにデータを転送するために使用するクラス サービス コールバック ルーチン の接続。
デバイス オブジェクトの構成
次の図は、プラグ アンド プレイ PS/2 スタイルのキーボードとマウス デバイスのデバイス オブジェクトの構成を示しています。 各クラス ドライバーは、オプションの上位レベル のデバイス フィルター DO を介して関数デバイス オブジェクト (FDO) にアタッチされる上位レベルのクラス フィルター デバイス オブジェクト (フィルター DO) を作成します。 上位レベルのデバイス フィルター ドライバーは、上位レベルのデバイス フィルター DO を作成します。 I8042prt は関数 DO を作成し、ルート バス ドライバーによって作成された物理デバイス オブジェクト (PDO) にアタッチします。
PS/2 キーボード
キーボード ドライバー スタックは、次で構成されます。
- Kbdclass、上位レベルのキーボード クラス フィルター ドライバー
- 1 つ以上のオプションの上位レベルのキーボード フィルター ドライバー
- 関数ドライバー I8042prt
PS/2 マウス
マウス ドライバー スタックは、次で構成されます。
- マウス クラス フィルター ドライバーの上位レベルである Mouclass
- 1 つ以上のオプションの上位レベルのマウス フィルター ドライバー
- 関数ドライバー I8042prt
Kbdclass と Mouclass では、2 つの異なるモードで複数のデバイスをサポートできます。 一対一モードでは、各デバイスには独立したデバイス スタックがあります。 クラス ドライバーは、各デバイス スタックに独立したクラス DO を作成してアタッチします。 各デバイス スタックには、独自の制御状態と入力バッファーがあります。 Microsoft Win32 サブシステムは、一意のファイル オブジェクトを介して各デバイスからの入力にアクセスします。
グランドマスター モードでは、クラス ドライバーは次のようにすべてのデバイスを操作します。
クラス ドライバーは、すべてのデバイスを表す グランドマスター クラス DO と、各デバイスの 下位クラス DO の両方を作成します。
クラス ドライバーは、下位クラス DO を各デバイス スタックにアタッチします。 下位クラス DO の下のデバイス スタックは、一対一モードで作成されたものと同じです。
グランドマスター クラス DO は、すべての下位 DO の操作を制御します。
Win32 サブシステムは、グランドマスター クラス デバイスを表すファイル オブジェクトを介して、すべてのデバイス入力にアクセスします。
すべてのデバイス入力は、グランドマスターのデータ キューにバッファーされます。
グランドマスターは、1 つのグローバル デバイス状態を維持します。
レジストリ エントリ値 ConnectMultiplePorts が 0x00 に設定されている場合、Kbdclass と Mouclass は 1 対 1 モードで動作します (キー HKLM\Services\CurrentControlSet\<class service>\Parameters の下で、 クラス サービス は Kbdclass または Mouclass です)。 それ以外の場合、Kbdclass と Mouclass はグランドマスター モードで動作します。
クラス ドライバーを使用して開いて閉じる
Microsoft Win32 サブシステムは、その排他的な使用のためにすべてのキーボードとマウス デバイスを開きます。 デバイス クラスごとに、Win32 サブシステムは、すべてのデバイスからの入力を、入力が 1 つの入力デバイスから送信されたかのように扱います。 アプリケーションは、1 つの特定のデバイスからの入力の受信を要求できません。
Win32 サブシステムは、プラグ アンド プレイ マネージャーから、GUID_CLASS_KEYBOARDまたはGUID_CLASS_MOUSEデバイス インターフェイスが有効になっているという通知を受け取った後、プラグ アンド プレイ入力デバイスを動的に開きます。 Win32 サブシステムは、開いているインターフェイスが無効になっているという通知を受け取った後、プラグ アンド プレイ デバイスを閉じます。 Win32 サブシステムでは、レガシ デバイスも名前で開きます (例: "\Device\KeyboardLegacyClass0")。 Win32 サブシステムがレガシ デバイスを正常に開くと、デバイスが後で物理的に削除されたかどうかを判断できないことに注意してください。
Kbdclass と Mouclass が作成要求を受け取った後、プラグ アンド プレイとレガシ操作に対して次の操作を行います。
プラグ アンド プレイ操作
デバイスがプラグ アンド プレイ開始状態の場合、クラス ドライバーはドライバー スタックの下にIRP_MJ_CREATE要求を送信します。 それ以外の場合、クラス ドライバーは、ドライバー スタックに要求を送信せずに要求を完了します。 クラス ドライバーは、デバイスへの読み取りアクセス権を持つ信頼されたファイルを設定します。 グランドマスター デバイスがある場合、クラス ドライバーは下位クラス デバイスに関連付けられているすべてのポートに作成要求を送信します。
レガシ操作
クラス ドライバーは、デバイスを有効にするために、内部デバイス制御要求をポート ドライバーに送信します。
サービス コールバックをデバイスに接続する
クラス ドライバーは、デバイスを開く前に、クラス サービスをデバイスに接続する必要があります。 クラス ドライバーは、クラス DO をデバイス スタックにアタッチした後、クラス サービスを接続します。 関数ドライバーは、クラス サービス コールバックを使用して、デバイスからデバイスのクラス データ キューに入力データを転送します。 デバイスの関数ドライバーの ISR ディスパッチ完了ルーチンは、クラス サービス コールバックを呼び出します。 Kbdclass はクラス サービス コールバック KeyboardClassServiceCallback を提供し、Mouclass はクラス サービス コールバック MouseClassServiceCallback を提供します。
ベンダーは、デバイスの上位レベルのフィルター ドライバーをインストールすることで、クラス サービス コールバックの操作を変更できます。 サンプル キーボード フィルター ドライバー Kbfiltr は KbFilter_ServiceCallback コールバックを定義し、サンプル マウス フィルター ドライバー Moufiltr は MouFilter_ServiceCallback コールバックを定義します。 サンプル フィルター サービス コールバックは、デバイスのポート入力バッファーからクラス データ キューに転送される入力データを変更するように構成できます。 たとえば、フィルター サービス コールバックでは、データの削除、変換、挿入を行うことができます。
クラスとフィルター サービスのコールバックは、次のように接続されます。
クラス ドライバーは、デバイス スタック (IOCTL_INTERNAL_KEYBOARD_CONNECT または IOCTL_INTERNAL_MOUSE_CONNECT) の下に内部デバイス接続要求を送信します。 クラス接続データは、クラス デバイス オブジェクトへのポインターとクラス サービス コールバックへのポインターを含むCONNECT_DATA構造体によって指定されます。
フィルター ドライバーは、接続要求を受信した後、クラス接続データのコピーを保存し、要求の接続データをフィルター接続データに置き換えます。 フィルター接続データは、フィルター デバイス オブジェクトへのポインターと、フィルター ドライバー サービス コールバックへのポインターを指定します。 フィルター ドライバーは、フィルター処理された接続要求を関数ドライバーに送信します。
クラスとフィルター サービスのコールバックは、次のように呼び出されます。
関数ドライバーは、フィルター接続データを使用して、フィルター サービス コールバックへの初期コールバックを行います。
入力データをフィルター処理した後、フィルター サービス コールバックは、保存したクラス接続データを使用して、クラス サービス コールバックへのコールバックを行います。
キーボード デバイスのクエリと設定
I8042prt では、キーボード デバイスに関する情報を照会したり、キーボード デバイスでパラメーターを設定したりするための、次の内部デバイス制御要求がサポートされています。
IOCTL_KEYBOARD_QUERY_ATTRIBUTES
IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
IOCTL_KEYBOARD_QUERY_INDICATORS
IOCTL_KEYBOARD_QUERY_TYPEMATIC
すべてのキーボード デバイス制御要求の詳細については、「 ヒューマン インターフェイス デバイス リファレンス」を参照してください。
キーボードのコード マッパーをスキャンする
Microsoft Windows オペレーティング システムでは、入力デバイスによって提供される PS/2 互換スキャン コードが仮想キーに変換され、Windows メッセージの形式でシステム経由で伝達されます。 デバイスが特定のキーに対して正しくないスキャン コードを生成すると、間違った仮想キー メッセージが送信されます。 これは、ファームウェアによって生成されたスキャン コードを分析し、正しくないスキャン コードをシステムが認識するコードに変更するフィルター ドライバーを記述することで修正できます。 ただし、カーネル レベルのフィルター ドライバーにエラーが存在する場合、これは面倒なプロセスであり、重大な問題につながる場合があります。
Windows 2000 および Windows XP には、スキャン コード のマッピングを可能にするメソッドを提供する新しいスキャン コード マッパーが含まれています。 Windows のスキャン コード マッピングは、次のレジストリ キーに格納されます。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout
メモ また、Control キーの下には キーボード レイアウト キー (複数形に注意してください) もありますが、そのキーは変更しないでください。
キーボード レイアウト キーで、[スキャンコード マップ] の値を追加する必要があります。 この値は REG_BINARY 型 (リトル エンディアン形式) であり、次の表で指定されているデータ形式を持ちます。
開始オフセット (バイト単位) | サイズ (バイト単位) | データ |
---|---|---|
0 | 4 | ヘッダー: バージョン情報 |
4 | 4 | ヘッダー: フラグ |
8 | 4 | ヘッダー: マッピングの数 |
12 | 4 | 個々のマッピング |
... | ... | ... |
最後の 4 バイト | 4 | Null 終端記号 (0x00000000) |
1 番目と 2 番目の DWORDS ストア ヘッダー情報は、現在のバージョンのスキャン コード マッパーのすべてのゼロに設定する必要があります。 3 番目の DWORD エントリは、null 終端マッピングを含む、後続のマッピングの合計数を保持します。 したがって、最小カウントは 1 になります (マッピングは指定されません)。 個々のマッピングは ヘッダーの後に続きます。 各マッピングは、長さが 1 つの DWORD であり、2 つの WORD 長フィールドに分割されます。 各 WORD フィールドには、マップするキーのスキャン コードが格納されます。
マップがレジストリに格納されたら、マッピングを有効にするためにシステムを再起動する必要があります。 keypress でスキャン コードのマッピングが必要な場合、スキャン コードが仮想キーに変換される直前に、ステップがユーザー モードで実行されることに注意してください。 この変換をユーザー モードで行うと、ターミナル サービスで実行しているときにマッピングが正しく機能しないなど、特定の制限が発生する可能性があります。
これらのマッピングを削除するには、Scancode Map レジストリ値を削除して再起動します。
例 1
次に例を示します。 左側の Ctrl キーと CAPS LOCK キーを入れ替える場合は、レジストリ エディター (できればRegedt32.exe) を使用して、Scancode Map キーを次の値で変更します。
00000000 00000000 03000000 3A001D00 1D003A00 00000000
次の表に、DWORD フィールドとスワップされたバイトに分割されたこれらのエントリを示します。
値: 解釈
0x00000000: ヘッダー: バージョン。 すべてのゼロに設定します。
0x00000000: ヘッダー: フラグ。 すべてのゼロに設定します。
0x00000003: マップ内の 3 つのエントリ (null エントリを含む)。
0x001D003A: 左 Ctrl キー --> CAPS LOCK (0x1D --> 0x3A)。
0x003A001D: CAPS LOCK --> 左 Ctrl キー (0x3A --> 0x1D)。
0x00000000: Null 終端記号。
例 2
また、キーボードで一般提供されていないキーを追加したり、使用されていないキーを削除したりすることもできます。 次の例は、 Scancode Map に格納されている値を示しています。右 Ctrl キーを削除し、右 Alt キーの機能をミュート キーとして機能するように変更します。
00000000 00000000 03000000 00001DE0 20E038E0 00000000
次の表に、DWORD フィールドとスワップされたバイトに分割されたこれらのエントリを示します。
値: 解釈
0x00000000: ヘッダー: バージョン。 すべてのゼロに設定します。
0x00000000: ヘッダー: フラグ。 すべてのゼロに設定します。
0x00000003: マップ内の 3 つのエントリ (null エントリを含む)。
0xE01D0000: 右 Ctrl キーを削除します (0xE01D --> 0x00)。
0xE038E020: 右 Alt キー --> ミュート キー (0xE038 --> 0xE020)。
0x00000000: Null 終端記号。
必要なデータが生成されたら、いくつかの方法でレジストリに挿入できます。
- レジストリ エディターを使用してシステム レジストリに簡単に組み込むことができる .reg ファイルを生成できます。
- 追加するレジストリ情報を含む [AddReg] セクションを使用して.inf ファイルを作成することもできます。
- Regedt32.exeを使用して、レジストリに情報を手動で追加できます。
スキャン コード マッパーには、いくつかの長所と短所があります。
利点は次のとおりです。
- マッパーは、ファームウェアエラーを修正するための簡単な修正として使用できます。
- レジストリ内のマップを変更することで、頻繁に使用されるキーをキーボードに追加できます。 頻繁に使用されないキー (右 Ctrl キーなど) は、null (削除) にマップすることも、他のキーと交換することもできます。
- キーの場所は簡単に変更できます。 ユーザーは、頻繁に使用されるキーの場所を簡単にカスタマイズしてメリットを得ることができます。
次の欠点が認識されます。
- マップがレジストリに格納されたら、それをアクティブ化するためにシステムの再起動が必要です。
- レジストリに格納されているマッピングはシステム レベルで機能し、すべてのユーザーに適用されます。 これらのマッピングは、現在のユーザーによって異なる方法で動作するように設定することはできません。
- 現在の実装では、マッピングが常にシステムに接続されているすべてのキーボードに適用されるように、マップの機能が制限されています。 現時点では、キーボードごとにマップを作成することはできません。
マウス デバイスのクエリを実行する
I8042prt では、マウス デバイスに関する情報を照会するために、次の内部デバイス制御要求がサポートされています。
すべてのマウス デバイス制御要求の詳細については、「 ヒューマン インターフェイス デバイス リファレンス」を参照してください。
マウス クラス ドライバーに関連付けられているレジストリ設定
マウス クラス ドライバーに関連付けられているレジストリ キーの一覧を次に示します。
[キー: HKLM\SYSTEM\CurrentControlSet\Services\Mouclass\Parameters]
- MaximumPortsServiced – Windows XP 以降では使用されません。 Windows NT4 の場合のみ。
- PointerDeviceBaseName – マウス クラスのデバイス ドライバーによって作成されるデバイス オブジェクトの基本名を指定します
- ConnectMultiplePorts – クラス デバイス オブジェクトごとに 1 つまたは複数のポート デバイス オブジェクトがあるかどうかを判断します。 このエントリは、主にデバイス ドライバーによって使用されます。
- MouseDataQueueSize - マウス ドライバーによってバッファーに格納されるマウス イベントの数を指定します。 また、非ページ メモリ プール内のマウス ドライバーの内部バッファーのサイズを計算する場合にも使用されます。
絶対ポインティング デバイス
GUID_CLASS_MOUSE型のデバイスの場合、デバイスのファンクション ドライバー:
デバイス固有の入力を処理します。
MouseClassServiceCallback に必要なMOUSE_INPUT_DATA構造体を作成します。
ISR ディスパッチ完了ルーチンで MouseClassServiceCallback を呼び出して、MOUSE_INPUT_DATA構造体を Mouclass データ キューに転送します。
絶対ポインティング デバイスの場合、デバイスの関数ドライバーは、次のように、MOUSE_INPUT_DATA構造体の LastX、 LastY、 および Flags メンバーを設定する必要があります。
ドライバーは、デバイスの入力値をデバイスの最大機能で除算するだけでなく、デバイスの入力値を0xFFFFによってスケーリングします。
LastX = ((device input x value) * 0xFFFF ) / (Maximum x capability of the device) LastY = ((device input y value) * 0xFFFF ) / (Maximum y capability of the device)
ドライバーは 、フラグでMOUSE_MOVE_ABSOLUTEフラグを設定します。
入力を Window Manager によって仮想デスクトップ全体にマップする必要がある場合、ドライバーは Flags でMOUSE_VIRTUAL_DESKTOP フラグを設定 します。 MOUSE_VIRTUAL_DESKTOP フラグが設定されていない場合、Window Manager は入力をプライマリ モニターのみにマップします。
次に、絶対ポインティング デバイスに対するこれらの特別な要件を実装する方法を、デバイスの種類別に指定します。
HID デバイス:
HID マウス デバイス用の Windows ファンクション ドライバーである Mouhid は、これらの特別な要件を自動的に実装します。
PS/2 スタイル デバイス:
上位レベルのフィルター ドライバーが必要です。 フィルター ドライバーは、IsrHook コールバックとクラス サービス コールバックを提供します。 I8042prt は IsrHook を呼び出して生のデバイス入力を処理し、フィルター クラス サービス コールバックを呼び出して入力をフィルター処理します。 フィルター クラス サービス コールバックは、 次に MouseClassServiceCallback を呼び出します。 IsrHook コールバックとクラス サービス コールバックの組み合わせによって、デバイス固有の入力が処理され、必要なMOUSE_INPUT_DATA構造が作成され、デバイス入力データがスケーリングされ、MOUSE_MOVE_ABSOLUTE フラグが設定されます。
Serenum によって列挙されるプラグ アンド プレイ COM ポート デバイス:
プラグ アンド プレイ関数ドライバーが必要です。 関数ドライバーは、必要なMOUSE_INPUT_DATA構造体を作成し、デバイス入力データをスケーリングし、 MouseClassServiceCallback を呼び出す前にMOUSE_MOVE_ABSOLUTE フラグを設定します。
プラグ アンド プレイ以外の COM ポート デバイス:
デバイス固有の関数ドライバーが必要です。 関数ドライバーは、必要なMOUSE_INPUT_DATA構造体を作成し、デバイス入力データをスケーリングし、 MouseClassServiceCallback を呼び出す前にMOUSE_MOVE_ABSOLUTE フラグを設定します。
サポートされていないバス上のデバイス:
デバイス固有の関数ドライバーが必要です。 関数ドライバーは、必要なMOUSE_INPUT_DATA構造体を作成し、デバイス入力データをスケーリングし、 MouseClassServiceCallback を呼び出す前にMOUSE_MOVE_ABSOLUTE フラグを設定します。