次の方法で共有


元のインターフェイス

次のジョイスティック ミニドライバー コールバックは、元のインターフェイスに固有です。 SYS_DYNAMIC_DEVICE_INIT メッセージの処理から戻る前に、4 つのジョイスティック固有のコールバックを VJoyD VJOYD_Register_Device_Driver サービスに登録する必要があります。 EAX は、ポーリング ルーチン、EBX (構成ハンドラー)、ECX (機能コールバック)、および EDX (識別ルーチン) を指している必要があります。 ジョイスティック ミニドライバーの登録シーケンスの例を次に示します。

   
Mov eax、offset32 _PollRoutine@8
Mov ebx、offset32 _CfgRoutine
Mov ecx、offset32 _HWCapsRoutine@8
Mov edx、offset32 _JoyIdRoutine@8
VxDcall VJOYD_Register_Device_Driver

登録に加えて、ミニドライバーは、この時点で他の初期化を実行できます。 ジョイスティック ミニドライバー モデルは、SYS_DYNAMIC_DEVICE_EXIT に応じた特定のアクションを必要としませんが、VxD は最終的な内部クリーンアップのために、そのようなアクションを使用する場合があります。

構成マネージャー コールバック

CONFIGRET CM_HANDLER CfgRoutine( CONFIGFUNC cfFuncName,
    SUBCONFIGFUNC scfSubFuncName, DEVNODE dnToDevNode,
    ULONG dwRefData, ULONG ulFlags );

構成マネージャーのインターフェイス方法に関する一般的な情報は、Windows Driver Development Kit (DDK) の Windows Me セクションにあるプラグ アンド プレイ環境の部分で入手できます。 Windows Driver Kit (WDK) は DDK の後継です。

構成マネージャー コールバックは、VJoyD がコールバックを受信したときにミニドライバーが読み込まれる場合にのみ、ミニドライバーに渡されます。 このため、このコールバックの現在の実装には重大な問題が存在します。 VJoyD は、システムの起動時にデバイス ノードが列挙されている場合、構成マネージャーが実行時にデバイスの再構成などの特別なイベントに対するメッセージを送信する場合、およびシステムが停止している場合に、関連付けられているデバイス ノードのコールバックを受け取ります。 したがって、これらのメッセージを受信する時間内に読み込まれるのは、前回のブートで選択されたデバイスのみとなります。 ユーザーはシステムを起動し、ジョイスティックを構成し、ゲームをプレイし、ジョイスティックの構成を解除し、このコールバックを呼び出さずにシャットダウンする可能性があるため、このコールバックが呼び出されたときに実行される関数の数は潜在的に制限されることになります。

ハードウェア リソースを必要としないデバイスの場合、これが問題になることはありません。 そのようなリソースを使用するデバイスについては複数のオプションがあり、ブート時に構成されている場合にのみ機能する、構成マネージャーからリソースを動的に割り当てる、またはレジストリでのデバイス ノードの割り当てを検索して情報を要求することができます。

上記の情報を踏まえると、ドライバーは、最初にドライバーが読み込まれてから SYS_DYNAMIC_DEVICE_INIT を受け取ったとき、またはポーリング ルーチンを介して初めて読み込まれたときに正しく初期化されることになります。 同様に、SYS_DYNAMIC_DEVICE_EXIT メッセージを受信したときにリソースを解放する必要があります。

もう 1 つの問題は、現在サービスが提供されているジョイスティック デバイスのすべての構成マネージャー コールバックが、読み込まれたすべてのミニドライバーに送信されるということです。 ただし、dnToDevNode パラメーターを使ってデバイス識別子を調べ、このドライバーが処理できるデバイスと照合することができます。

ポーリング コールバック

int stdcall PollRoutine( int type, LPJOYOEMPOLLDATA pojd );

ポーリング ルーチンは、joyGetPos または joyGetPosEx を呼び出すアプリケーションに直接応答する形で呼び出されるか、Windows 95/98/Me が joySetCapture を呼び出したアプリケーションに対して joyGetPos を定期的に呼び出すときに呼び出されます。 アプリケーションがそこからデータを必要としていることを確認できるのは、ミニドライバーが最初にポーリング コールバックの呼び出しを受け取ったときのみです。 他のすべてのコールバックは、アプリケーションがデータを要求したかどうかに関係なく、現在使用可能な 16 個のジョイスティックの一覧に含まれているすべてのデバイスに対して呼び出されます。

戻り値は、JOY_OEMPOLLRC_YOUPOLL、JOY_OEMPOLLRC_FAIL、JOY_OEMPOLLRC_OK のいずれかです。 ボタンのみのポーリングを除き、戻り値はアプリケーションに返される前に JOYERR_NOERROR または JOYERR_UNPLUGGED のいずれかに解釈されます。 ボタンのポーリングは常に成功と見なされます。

ポーリングされたデバイスが応答しない場合、またはミニドライバーが処理できないポーリングを VJoyD が要求した場合は、JOY_OEMPOLLRC_FAIL が返されます。 前者の場合は、アプリケーションがすべてを停止し、ユーザーがデバイスへの接続をチェックするように要求する可能性が高いため、実際に失敗していない限り、デバイスが失敗しないようにする必要があります。 たとえば、最初のポーリングが失敗した場合、joySetCapture の呼び出しは失敗します。 デバイスの軽微な障害については、ユーザーの介入が必要になるまで、または回復不能なデバイス エラーが検出されるまでは、エラー レポートが生成されないようにする必要があります。 たとえば、パケット ベースのプロトコルを使用して通信するデバイスであれば、1 つのパケットが有効でない場合でも、ポーリングの失敗と判断する前に再試行を試みるべきです。

最終的にエラーを返すのは、実際のデバイス障害を認識した時点でなければなりません。そうでないと、アプリケーションはユーザーの介入が必要かどうかを判断できません。 エラー回復の実行中に古いデータや誤ったデータが返される場合は、返されるデータの意味、許可されるポーリングの数、または最初のエラーから許容される時間を制限して、ドライバーが遅延しないようにする必要があります。 ミニドライバーが制御していないデバイスでポーリングを実行するように要求された場合、またはサービスを提供できないポーリングの種類またはサブタイプを実行するように要求された場合は、常に失敗が正しい応答となります。

標準のアナログ ポーリングで正しい結果が得られる場合は、JOY_OEMPOLLRC_YOUPOLL を使用できます。

JOYINFOEX 構造体に要求されたデータが格納されている場合は、通常のケースで JOY_OEMPOLLRC_OK を返す必要があります。

ポーリングを使用してデバイスで初期化を実行する場合は、注意する必要があります。 アプリケーションは、リターン コードをチェックすることで、デバイスの可用性をチェックする初期ポーリングを実行できます。 その後は、エラー チェックなしで後続のポーリングを行うことができます。 joySetCapture が行うのは、基本的にはこのような動作です。 理想的には、すべての初期化と最初のポーリングを実行すべきです。 デバイスのセットアップに必要な時間が 1 秒程度であれば、デバイスが存在し、動作していることを確認し、最初のポーリングで不活性データを返せば十分です。

API ドライバーとシステム ドライバーは、アプリケーションによって行われた要求に対して検証を実行し、完了時に必要なデータをアプリケーション構造にコピーします。 この機能は、ミニドライバーでレプリケートすべきではありません。 ただし、あるプロセスがデバイスをポーリングしている最中でも、別のプロセスによるポーリングが妨げられることはありません。 このようなイベントの結果は、異なるサンプルから 2 つの軸が報告される状況ほど悪くありません。 ミニドライバーは必要に応じて、独自のプロセス同期を実行できます。

戻り値は、"type" パラメーターとそれがサポートするデバイスによって異なります。 ボタンとボタン番号は常に返す必要があります。 POV ポーリングが必要であることをミニドライバーに対して指定する方法はないため、軸が要求された場合は、この値を返す必要があります。 デバイスでサポートされていない場合は、POV_UNDEFINED を設定します。 1 軸のポーリングの場合、値は JOYPOLLDATA 構造体 (DirectX 5.0 以降では VJPOLLDATA 構造体) の dwX メンバーに返されます。 要求軸数が奇数の複数軸要求の場合、JOYOEMPOLLDATA 構造体の do_other メンバーは、最後の軸を所定の位置に返すか、次の軸に対して返すかを指定します。 たとえば、3 軸のポーリングでは、返される軸が X、Y、Z のいずれであるか、または X、Y、R のいずれであるかを指定します。

次の一覧は、考え得るその他の戻り値を型別に分類したものです (余分なデータを入力できますが、軸数が奇数のすべてのポーリングでは、返される内容を決定するために do_other メンバーをデコードする必要があることに注意してください)。

  • JOY_OEMPOLL_GETBUTTONS: 余分なものはありません。

  • JOY_OEMPOLL_POLL1: do_other メンバーで指定された軸が dwX メンバーで返されます。

  • JOY_OEMPOLL_POLL2: X 軸と Y 軸は dwX メンバーと dwY メンバーで返されます。

  • JOY_OEMPOLL_POLL3: X 軸と Y 軸は dwX メンバーと dwY メンバーで返されます。

    do_other メンバーが 0 以外の場合は、dwR メンバーで R 軸が返されます。 それ以外の場合は、dwZ メンバーで Z 軸が返されます。

  • JOY_OEMPOLL_POLL4: X 軸、Y 軸、Z 軸、R 軸はそれぞれ dwXdwYdwZ、および dwR メンバーで返されます。

  • JOY_OEMPOLL_POLL5: X 軸、Y 軸、Z 軸、R 軸はそれぞれ dwXdwYdwZ、および dwR メンバーで返されます。

    do_other メンバーが 0 以外の場合は、dwR メンバーで V 軸が返されます。 それ以外の場合は、dwZ メンバーで U 軸が返されます。

  • JOY_OEMPOLL_POLL6: X 軸、Y 軸、Z 軸、R 軸、U 軸、V 軸はそれぞれ dwXdwYdwZdwRdwUdwV の各メンバーで返されます。

DirectX 3.0 では、非ポーリング型の JOY_OEMPASSDRIVERDATA が追加されており、do_other メンバーには、アプリケーションが渡す DWORD が格納されます。 この DWORD は、ミニドライバーで定義された任意の関数で使用できますが、特にデバイス固有のコマンドと構成情報を送信するミニドライバーを完全に識別したカスタム セットアップ アプリケーションを実現することを目的としています。

ミニドライバーは、サポートされていないすべての型に対して JOY_OEMPOLLRC_FAIL を返す必要があります。

軸データはダブルワード型で返されますが、標準のジョイスティック コントロール パネル構成を唯一の構成メカニズムとして使用する場合は、軸の値の範囲を約 10 ビットの値に制限する必要があります。 ユーザーは何が起こっているのかを簡単に確認できないため、混乱を避けるのに役立ちます。 既存のアプリケーションとの互換性を確保するために、ミニドライバーによって返される軸は、アナログ ジョイスティックによって返されるものと同じである必要があります (該当する場合)。 たとえば、X は左から右への移動であり、左側が最も小さい値になります。

アクティブ化された POV Hat の場合、方向は角度を 100 で乗算した値で表し、0 が前、9000 が右、18000 が後、27000 が左になります。

デバイスがまだ使用中であることを示唆する肯定的な兆候は、ポーリング ルーチンの呼び出ししかないため、通信ポートなどの共有リソースを使用するミニドライバーは、前回使用された時刻を追跡する必要があります。 使用時間が大幅に長くなった場合、ミニドライバーはデバイスのサンプリングを停止し、ユーザーがデバイスの使用を完了し、別の目的でリソースを使用する場合に備えて、リソースを解放する必要があります。 これは、デバイスの接続が外れていることを示す可能性があるため、通信エラーが発生している場合に重要です。

ハードウェア機能のコールバック

int __stdcall HWCapsRoutine( int joyid, LPJOYOEMHWCAPS pjhwc );

デバイスのハードウェア機能を要求するたびに、HWCapsRoutine が呼び出されます。 特に VJoyD は、VJOYD_Register_Device_Driver から戻る前に HWCapsRoutine を呼び出します。 そのためドライバーは、デバイスが登録される前に、この呼び出しが依存するすべての初期化を完了することが重要です。 これらの値は一般に定数です。 4 つのボタンと 3 つの軸を持ち、そのうちの 3 つ目がスロットルやラダーの値を返すようなデバイスの場合は、次のようにするのが適切です。

pjhwc->dwMaxButtons = 4;    // This should always be the number of buttons 
pjhwc->dwMaxAxes = 4;       // The largest axis number which may be requested 
pjhwc->dwNumAxes = 3;       // The number of axes the device has 

ジョイスティック識別のコールバック

int __stdcall JoyIdRoutine( int joyid, BOOL used );

ユーザーがジョイスティックを 16 個のジョイスティックの 1 つとして構成または構成解除すると、VJoyD は JoyIDRoutine を呼び出します。 ミニドライバーが joyid で要求された ID をサポートできる場合、JoyIdRoutine は 0 以外の値を返します。 ミニドライバーが ID をサポートできない場合、ルーチンは 0 の値を返します。

何らかの変更が行われ、ドライバーを更新するために joyConfigChanged が呼び出されるたびに、VJoyD は JOYSTICKID1 から始まる 16 台のデバイスすべてを循環します。 すべてのデバイスが未使用にリセットされ、システムで使用する必要があるすべてのデバイスを設定するために再びループ処理されます。 コントロール パネルの操作中、このプロセスは多数の呼び出しを伴う可能性があります。これにより、初期化のためのこのコールバックの使用法に問題が発生します。 これは、システムの起動が完了する前に呼び出しが行われた場合、つまり他のサービスが利用できない場合に当てはまります。

複数のデバイスのサービス コールバックを処理するミニドライバーは、ユーザーの混乱を避けるために、ジョイスティック識別子を可能な限り単一の物理デバイスに関連付けるようにする必要があります。 これは 1 つのセッション中に比較的簡単に実装できますが、再起動時には必要にならない可能性があります。

SYS_DYNAMIC_DEVICE_INIT メッセージの処理から戻る前に、4 つのジョイスティック固有のコールバックを VJoyD VJOYD_Register_Device_Driver サービスに登録する必要があります。 EAX は、ポーリング ルーチン、EBX (構成ハンドラー)、ECX (機能コールバック)、および EDX (識別ルーチン) を指している必要があります。 ジョイスティック ミニドライバーの登録シーケンスの例を次に示します。

   
Mov eax、offset32 _PollRoutine@8
Mov ebx、offset32 _CfgRoutine
Mov ecx、offset32 _HWCapsRoutine@8
Mov edx、offset32 _JoyIdRoutine@8
VxDcall VJOYD_Register_Device_Driver

登録に加えて、ミニドライバーは、この時点で他の初期化を実行できます。 ジョイスティック ミニドライバー モデルは、SYS_DYNAMIC_DEVICE_EXIT に応じた特定のアクションを必要としませんが、VxD は最終的な内部クリーンアップのために、そのようなアクションを使用する場合があります。