USB 割り込み転送要求を送信する方法 (Windows ストア アプリ)

USB デバイスは、割り込みエンドポイントをサポートすることによって、定期的にデータを送受信することができます。これを実現するために、ホストは定期的にデバイスをポーリングし、ホストがデバイスをポーリングするたびにデータが送信されます。割り込み転送は、多くの場合、デバイスからの割り込みデータを取得するために使われます。 ここでは、Windows ストア アプリで、デバイスから継続的な割り込みデータを取得する方法について説明します。

割り込みエンドポイントの情報

割り込みエンドポイントの場合、記述子は次のようなプロパティを公開します。これらの値は単なる情報であり、転送バッファーの管理方法に影響を与えないようにする必要があります。

  • データを送信できる頻度

    エンドポイント記述子の Interval の値を取得することによってこの情報を取得します (「UsbInterruptOutEndpointDescriptor.Interval」または「UsbInterruptInEndpointDescriptor.Interval」をご覧ください)。この値は、バス上の各フレームで、デバイスにデータが送信される頻度、またはデバイスからデータが受信される頻度を示します。

      Interval プロパティは、bInterval 値 (USB 仕様で定義されている) とは異なります。

    この値は、デバイスとの間でデータが送信される頻度を示します。たとえば、High-Speed デバイスでは、Interval が 125 マイクロ秒の場合、データは 125 マイクロ秒ごとに送信されます。Interval が 1,000 マイクロ秒の場合、データは 1 ミリ秒ごとに送信されます。

  • 各サービス間隔で送信できるデータ量

    エンドポイント記述子でサポートされる最大パケット サイズを取得することによって、送信できるバイト数を取得します (「UsbInterruptOutEndpointDescriptor.MaxPacketSize」または「UsbInterruptInEndpointDescriptor.MaxPacketSize」をご覧ください)。最大パケット サイズはデバイスの速度によって制約されます。Low-Speed デバイスの場合は最大 8 バイトです。Full-Speed デバイスの場合は最大 64 バイトです。高帯域幅の High-Speed デバイスの場合、アプリでは最大 3,072 バイト/マイクロフレームで、最大パケット サイズを超えるデータを送受信できます。

      SuperSpeed デバイス上の割り込みエンドポイントでは、さらに多くのバイト数を送信できます。この値は、USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR の wBytesPerInterval によって指定されます。この記述子を取得するには、UsbEndpointDescriptor.AsByte プロパティを使って記述子バッファーを取得し、DataReader メソッドを使ってバッファーを解析します。

割り込み OUT 転送

USB デバイスは、ホストからのデータを定期的に受信する割り込み OUT エンドポイントをサポートできます。ホストは、デバイスをポーリングするたびに、データを送信します。Windows ストア アプリは、送信するデータを指定する割り込み OUT 転送要求を開始できます。この要求は、デバイスがホストからのデータの受信を確認すると完了します。Windows ストア アプリでは、UsbInterruptOutPipe にデータを書き込むことができます。

割り込み IN 転送

逆に、USB デバイスでは、デバイスによって生成されたハードウェア割り込みをホストに通知する方法として、割り込み IN エンドポイントをサポートできます。 通常、キーボードやポインティング デバイスなどの USB ヒューマン インターフェイス デバイス (HID) は、割り込み OUT エンドポイントをサポートします。割り込みが発生すると、エンドポイントは割り込みデータを格納しますが、そのデータはすぐにホストに届けられるわけではありません。エンドポイントは、ホスト コントローラーがデバイスをポーリングするまで待機する必要があります。データが生成されてからホストに到達する時間までの遅延を最小限にするために、ホストは定期的にデバイスをポーリングします。Windows ストア アプリでは、UsbInterruptInPipe で受信されたデータを取得できます。この要求は、デバイスからのデータがホストで受信されたときに完了します。

はじめに...

割り込み OUT エンドポイントへの書き込み

アプリが割り込み OUT 転送要求を送信する方法は、バルク OUT 転送の場合と同じです。異なる点は、ターゲットが UsbInterruptOutPipe で表される割り込み OUT パイプであることです。詳しくは、「USB バルク転送要求を送信する方法 (Windows ストア アプリ)」をご覧ください。

手順 1: 割り込みイベント ハンドラーの実装 (割り込み IN)

デバイスからのデータが割り込みパイプで受信されると、DataReceived イベントが発生します。割り込みデータを取得するには、アプリでイベント ハンドラーを実装する必要があります。このハンドラーの eventArgs パラメーターはデータ バッファーを指します。

次のコード例では、イベント ハンドラーの単純な実装を示します。このハンドラーは、受信した割り込みの数を保持します。ハンドラーが呼び出されるたびに、カウントがインクリメントされます。ハンドラーは、eventArgs パラメーターからデータ バッファーを取得し、割り込みの数と、受信したバイトの長さを表示します。


private async void OnInterruptDataReceivedEvent(UsbInterruptInPipe sender, UsbInterruptInEventArgs eventArgs)
{
    numInterruptsReceived++;

    // The data from the interrupt
    IBuffer buffer = eventArgs.InterruptData;

    // Create a DispatchedHandler for the because we are interracting with the UI directly and the
    // thread that this function is running on may not be the UI thread; if a non-UI thread modifies
    // the UI, an exception is thrown

    await Dispatcher.RunAsync(
                       CoreDispatcherPriority.Normal,
                       new DispatchedHandler(() =>
    {
        ShowData(
        "Number of interrupt events received: " + numInterruptsReceived.ToString()
        + "\nReceived " + buffer.Length.ToString() + " bytes");
    }));
}


手順 2: 割り込みパイプ オブジェクトの取得 (割り込み IN)

DataReceived イベントのイベント ハンドラーを登録するには、次のようなプロパティを使って UsbInterruptInPipe への参照を取得します。

  現在選択されていないインターフェイス設定の割り込みエンドポイントを列挙することによって、パイプ オブジェクトを取得しないでください。データを転送するには、パイプが、アクティブな設定のエンドポイントに関連付けられている必要があります。

手順 3: イベント ハンドラーの登録とデータ受信の開始 (割り込み IN)

次に、DataReceived イベントを発生させる UsbInterruptInPipe オブジェクトで、イベント ハンドラーを登録する必要があります。

次のコード例では、イベント ハンドラーを登録する方法を示します。この例で、クラスはイベント ハンドラー、イベント ハンドラーが登録されているパイプ、およびパイプが現在データを受信しているかどうかを追跡します。このすべての情報が、次の手順で示されているように、イベント ハンドラーを登録解除するために使われます。


private void RegisterForInterruptEvent(TypedEventHandler<UsbInterruptInPipe, UsbInterruptInEventArgs> eventHandler)
{
    // Search for the correct pipe that has the specified endpoint number
    interruptPipe = usbDevice.DefaultInterface.InterruptInPipes[0];

    // Save the interrupt handler so we can use it to unregister
    interruptEventHandler = eventHandler;

    interruptPipe.DataReceived += interruptEventHandler;

    registeredInterruptHandler = true;
}



void RegisterForInterruptEvent(TypedEventHandler<UsbInterruptInPipe, UsbInterruptInEventArgs> eventHandler)
    // Search for the correct pipe that has the specified endpoint number
    interruptInPipe = usbDevice.DefaultInterface.InterruptInPipes.GetAt(pipeIndex);
        
    // Save the token so we can unregister from the event later
    interruptEventHandler = interruptInPipe.DataReceived += eventHandler;

    registeredInterrupt = true;    

}

イベント ハンドラーが登録されると、関連付けられた割り込みパイプでデータが受信されるたびに、イベント ハンドラーが呼び出されます。

手順 4: イベント ハンドラーの登録解除とデータ受信の停止 (割り込み IN)

データの受信が完了したら、イベント ハンドラーを登録解除します。

次のコード例では、イベント ハンドラーを登録解除する方法を示します。この例では、アプリが以前にイベント ハンドラーを登録していた場合、メソッドで追跡されているイベント ハンドラーを取得し、割り込みパイプで登録解除します。


private void UnregisterInterruptEventHandler()
{
    if (registeredInterruptHandler)
    {
        interruptPipe.DataReceived -= interruptEventHandler;

        registeredInterruptHandler = false;
    }
}



void UnregisterFromInterruptEvent(void)
{
    if (registeredInterrupt)
    {
        interruptInPipe.DataReceived -= eventHandler;

        registeredInterrupt = false;
    }
}

イベント ハンドラーが登録解除されると、割り込みイベントでイベント ハンドラーが呼び出されなくなるため、アプリは割り込みパイプからのデータの受信を停止します。これは、割り込みパイプでデータの取得を停止するという意味ではありません。

 

 

表示:
© 2014 Microsoft