レポート記述子を送信する FullSpeed USB デバイスがあり、その関連するエンドポイント記述子bInterval
は 8、つまり 8ms を宣言しています。
次のレポートの抜粋は、デバイスのドライバーが HidUsb の場合に USB Descriptor Dumper から取得されます。
Interface Descriptor: // +several attributes
------------------------------
0x04 bDescriptorType
0x03 bInterfaceClass (Human Interface Device Class)
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface
HID Descriptor: // +bLength, bCountryCode
------------------------------
0x21 bDescriptorType
0x0110 bcdHID
0x01 bNumDescriptors
0x22 bDescriptorType (Report descriptor)
0x00D6 bDescriptorLength
Endpoint Descriptor: // + bLength, bEndpointAddress, wMaxPacketSize
------------------------------
0x05 bDescriptorType
0x03 bmAttributes (Transfer: Interrupt / Synch: None / Usage: Data)
0x08 bInterval (8 frames)
ドライバーを WinUSB に切り替えて使用できるようにした後、libusb を使用して IN 割り込み転送を繰り返しクエリし、このスクリプトを使用して 2 つの libusb 呼び出しの間と libusb 呼び出し中に費やされた実際の時間を計ります。
for (int i = 0; i < n; i++) {
start = std::chrono::high_resolution_clock::now();
forTime = (double)((start - end).count()) / 1000000;
<libusb_interrupt_transfer on IN interrupt endpoint>
end = std::chrono::high_resolution_clock::now();
std::cout << "for " << forTime << std::endl;
transferTime = (double)((end - start).count()) / 1000000;
std::cout << "transfer " << transferTime << std::endl;
std::cout << "sum " << transferTime + forTime << std::endl << std::endl;
}
取得した値のサンプルを次に示します。
for 2.60266
transfer 5.41087
sum 8.04307 //~8
for 3.04287
transfer 5.41087
sum 8.01353 //~8
for 6.42174
transfer 9.65907
sum 16.0808 //~16
for 2.27422
transfer 5.13271
sum 7.87691 //~8
for 3.29928
transfer 4.68676
sum 7.98604 //~8
新しい割り込み転送呼び出しを開始するまでに経過した時間が長すぎる場合 (私の特定のケースでは、しきい値は 6 から 6.5 の間のようです) を除いて、合計値は一貫して 8 ミリ秒に非常に近く、その場合は 16 に等しくなります。 18ms に等しい "for" 測定値が見られ、合計は正確に 24ms に等しくなります。URB トラッカー (私の場合は Microsoft Message Analyzer) を使用すると、メッセージ間の時間差Complete URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
も 8 ミリ秒の倍数 (通常は 8 ミリ秒) になります。要するに、それらは「合計」メジャーに一致します。
したがって、「libusb 割り込み転送呼び出し」の 2 つのリターン間の経過時間は 8ms の倍数であることが明らかであり、これは bInterval 値 8 (FullSpeed -> *1ms -> 8ms) に関連していると思います。
しかし、私が話していることを明確にしたことを願っています-それはどこで強制されますか? 調査にもかかわらず、bInterval 値がどのように影響するかについて明確な説明を見つけることができません。
どうやら、これはドライバーによって強制されます。
したがって、それは次のとおりです。
ドライバーは、8ms が経過するまでリクエストの発火を禁止します。私には最も合理的なオプションのように思えますが、私の URB Traceによると
Dispatch message
、リクエストが返される数ミリ秒前にイベントが発生しました。これは、ホストが残したリアルタイムのデータが、私/メッセージ アナライザーから隠されていることを意味します。ドライバーは、最後の応答から 8ms が経過するまで、私とアナライザーからの応答を隠します。
もしそれが本当にドライバーによって処理されたなら、交換されたメッセージのログで私に示されているものにはどこかに嘘があります. リクエストの直後にレスポンスが来るはずですが、そうではありません。そのため、表示された時間の後にリクエストが送信されるか、表示されている時間よりも早く応答が返されます。
bInterval の尊重の強制はどのように機能しますか?
私の最終的な目標は、その bInterval 値を無視して、8 ミリ秒よりも頻繁にデバイスをポーリングすることです (2 ミリ秒ごとにポーリングできると信じる十分な理由があり、8 ミリ秒の期間はその使用には受け入れられません)。現在の制限がどのように機能するかを知り、探していることが可能であれば、次に何を勉強すべきかを理解できます (例: カスタム WinUSB ドライバーの作成)