![]() |
libusb 1.0.24
USBデバイスにアクセスするためのクロス・プラットフォームのユーザー・ライブラリ
|
このページでは、イベントとタイミングをポーリングするためのlibusbの機能について説明します。これらの関数は 非同期API のユーザーにのみ必要です。より単純な 同期API のみを使用している場合、これらの関数を呼び出す必要はありません。 詳細…
データ構造体 | |
struct | libusb_pollfd |
Typedef | |
typedef void(* | libusb_pollfd_added_cb) (int fd, short events, void *user_data) |
typedef void(* | libusb_pollfd_removed_cb) (int fd, void *user_data) |
このページでは、イベントとタイミングをポーリングするためのlibusbの機能について説明します。これらの関数は 非同期API のユーザーにのみ必要です。より単純な 同期API のみを使用している場合、これらの関数を呼び出す必要はありません。
ここで説明する機能の正当性については、非同期API文書の イベント処理 節で既に説明しています。要約すると、libusbはイベント処理用の内部スレッドを作成しないため、保留中のイベントを処理できるように、特定の時点でアプリケーションがlibusbを呼び出すことに頼っています。
あなたのメインループは、おそらくすでに他のイベント・ソース(キーボードのキーの押下、マウスの動き、ネットワーク・ソケットなど)のファイル・デスクリプターのセットで poll() または select() またはその変種を呼び出しています。あなたは次に、libusbのファイル・デスクリプターを poll()/select() 呼び出しに追加します。これらのデスクリプターでアクティビティが検出されたら、 libusb_handle_events() を呼び出す必要があります。
複雑なイベントを処理する一つとして、libusbは、指定された時間後にタイムアウトする非同期転送をサポートします。
一部のプラットフォームではtimerfdが使用されるため、タイムアウト処理は単なる別のfdですが、他のプラットフォームでは、タイムアウト時またはタイムアウト後にlibusbを呼び出して処理する必要があります。 したがって、メイン・イベント・ループでlibusbのファイル・デスクリプターを考慮することに加えて、ファイル・デスクリプター・アクティビティがない場合でも、libusbを一定の時点で呼び出す必要がある場合があることも考慮する必要があります。詳細は 時間ベースのイベントに関する注意 を参照してください。
libusbを呼び出す必要がある時期を正確に知るために、libusbは、ポーリング可能なファイル・デスクリプターのセットと、次のタイムアウトがいつ期限切れになるかに関する情報を提供します。
非同期入出力APIを使用している場合は、以下の2つの選択肢のいずれかを選択する必要があります。そうしないと、入出力が完了しません。
アプリケーションがlibusbのみを中心に展開し、他のイベント・ソースを処理する必要がない場合は、以下のようなプログラム構造にすることができます:
このような単純なメイン・ループを使用すると、ファイル・デスクリプターのセットの管理やタイムアウトの処理について心配する必要はありません。 libusb_handle_events() は、これらの詳細を内部で処理します。
より高度なアプリケーションでは、ネットワーク・ソケット、X11イベント、マウスの動きなど、他のイベント・ソースを監視するメイン・ループがすでに存在します。ファイル・デスクリプターのセットを公開することで、libusbはそのようなメイン・ループにきれいに統合されるように設計されています。
他のイベント・ソースのファイル・デスクリプターをポーリングすることに加えて、あなたはlibusbからファイル・デスクリプターのセットを取得し、それらも監視します。libusbのファイル・デスクリプターでアクティビティを検出すると、あなたは非ブロッキング・モードで libusb_handle_events_timeout() を呼び出します。
さらに、libusbは特定の時点でイベントを処理する必要がある場合もあります。 これらの時点ではファイル・デスクリプター・アクティビティは生成されないため、アプリケーションはこれらの瞬間の次の1つが何時発生するかを(libusb_get_next_timeout()を呼び出すことにより)継続的に認識し、これらの瞬間が発生したときに非ブロッキング・モードで libusb_handle_events_timeout() を呼び出す必要があります。 これは、それに応じて poll()/select() タイムアウトを調整する必要があることを意味します。
libusbは、ポーリングするファイル・デスクリプターのセットを提供し、それらすべてをポーリングして、それらを単一のエンティティとして扱うことを期待します。 セット内の各ファイル・デスクリプターの意味は、プラットフォームに依存する内部実装の詳細であり、リリースごとに異なる場合があります。 ファイル・デスクリプターの意味を解釈しようとしないでください。libusbが示すように、すべてを一度にポーリングしてください。
擬似コードで書くと、以下のようなものが必要です:
時間を追跡し、特定の瞬間にlibusbを呼び出す必要があるという上記の複雑さは、いささか頭痛の種です。最大限の互換性を得るには、上記のようにメイン・ループを作成する必要がありますが、アプリケーションでサポートされているプラットフォームを制限すれば、より単純なスキームを使用することもできます。
これらの時間ベースのイベントの複雑化は、以下のプラットフォームでは不要です:
これらの構成では、 libusb_get_next_timeout() は常に0を返すため、メイン・ループは以下のように簡略化できます:
メイン・ループを上記のように単純化すると、一部のプラットフォーム(レガシーなLinuxプラットフォームや、時間ベースのイベント要件がある可能性のあるlibusbでサポートされる将来のプラットフォームを含む)との互換性が失われることに注意してください。結果として生じる問題は、アプリケーションの奇妙なバグとして表示される可能性があります。
あなたは libusb_pollfds_handle_timeouts() 関数を使用してランタイム・チェックを実行し、時間ベースのイベントの複雑さを無視しても安全かどうかを確認できます。アプリケーションがメイン・ループでlibusbの次のタイムアウトを無視するショートカットを使用している場合は、アプリケーションの起動時に libusb_pollfds_handle_timeouts() の戻り値を確認し、プラットフォームでこれらのタイミングの問題が発生した場合はアプリケーションの実行を中止(abort)することをお勧めします。
libusbがイベント・ソースとして使用するファイル・デスクリプターのセットは、アプリケーションの存続期間中に変更される可能性があります。 libusb_get_pollfds()を繰り返し呼び出す必要はなく、 libusb_set_pollfd_notifiers() を使用して、ファイル・デスクリプター・セットが変更されたときの通知関数を設定できます。
残念なことに、複数のスレッドが機能するようになると、状況はさらに複雑になります。2つのスレッドが同じファイル・デスクリプターを監視している場合、イベントが発生したときに1つのスレッドのみがウェイクアップされるという事実は、いくつかの頭痛の種になります。
これらの問題を解決するために、イベント・ロックとイベント待ちロックとlibusb_handle_events_locked()エンティティが追加されています。あなたは、それ以外の場合は、これらのエンティティを気にする必要はありません。
追加の文書も参照下さい: マルチ・スレッド・アプリケーションと非同期入出力
typedef void( * libusb_pollfd_added_cb) (int fd, short events, void *user_data) |
イベントを監視するファイル・デスクリプターのセットに新しいファイル・デスクリプターを追加する必要がある場合に呼び出されるコールバック関数。
fd | 新しいファイル・デスクリプター |
events | 監視したいイベント。 libusb_pollfd に説明があります。 |
user_data | libusb_set_pollfd_notifiers() の呼び出しで指定されたユーザー・データへのポインタ |
typedef void( * libusb_pollfd_removed_cb) (int fd, void *user_data) |
イベントを監視しているファイル・デスクリプターのセットからファイル・デスクリプターを一つ削除する必要がある場合に呼び出されるコールバック関数。 このコールバックから戻った後は、そのファイル・デスクリプターを再度使用しないでください。
fd | 監視を止めたいファイル・デスクリプター |
user_data | libusb_set_pollfd_notifiers() の呼び出しで指定されたユーザー・データへのポインタ |
int libusb_try_lock_events | ( | libusb_context * | ctx | ) |
イベント処理ロックの取得を試みます。このロックは、一度に1つのスレッドのみがlibusbイベント・ソースを監視していることを確認するために使用されます。
このロックを使用する必要があるのは、libusbのファイル・デスクリプターに対して poll() または select() を直接呼び出すアプリケーションを開発している場合のみです。あなたがlibusbのイベント処理ループ関数(例: libusb_handle_events())だけを使う場合は、このロックを気にする必要はありません。
このロックを保持している期間は実際にイベントを処理しているのだと信頼されます。イベントを処理しなくなった場合、あなたはできるだけ早く libusb_unlock_events() を呼び出さなければなりません。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
void libusb_lock_events | ( | libusb_context * | ctx | ) |
イベント処理ロックを取得し、競合する場合は取得が成功するまでブロックします。このロックは、一度に1つのスレッドのみがlibusbイベント・ソースを監視していることを確認するために使用されます。
このロックを使用する必要があるのは、libusbのファイル・デスクリプターに対して poll() または select() を直接呼び出すアプリケーションを開発している場合のみです。あなたがlibusbのイベント処理ループ関数(例: libusb_handle_events())だけを使う場合は、このロックを気にする必要はありません。
このロックを保持している期間は実際にイベントを処理しているのだと信頼されます。イベントを処理しなくなった場合、あなたはできるだけ早く libusb_unlock_events() を呼び出さなければなりません。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL マルチ・スレッド・アプリケーションと非同期入出力 |
void libusb_unlock_events | ( | libusb_context * | ctx | ) |
libusb_try_lock_events() または libusb_lock_events() で以前に取得したロックを解除します。このロックを解除すると、 libusb_wait_for_event() でブロックされていたスレッドがすべてウェイクアップします。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL マルチ・スレッド・アプリケーションと非同期入出力 |
int libusb_event_handling_ok | ( | libusb_context * | ctx | ) |
このスレッドがイベント処理を実行しても問題がないかどうかを判断します。
libusbがすべてのイベント・ハンドラーを一時的に停止する必要がある場合があります。これは、ファイル・デスクリプターをポーリングしてその場合が当てはまるかどうかを確認する前に使用する必要がある関数です。
この関数がスレッドにイベント・ロックを放棄するように指示する場合は、 マルチ・スレッド・アプリケーションと非同期入出力 に記載されている通常のロジックを続行する必要があります。ループ次の反復では、スレッドはイベント・ロックの取得に失敗するため、イベント待ちになります。
この関数は、イベント・ロックが保持されている間に呼び出す必要があります。スレッドが現在のイベント・ハンドラーでない場合は、この関数の結果について心配する必要はありません。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
int libusb_event_handler_active | ( | libusb_context * | ctx | ) |
アクティブなスレッドがイベントを処理しているかどうか(つまり、誰がイベント処理ロックを保持しているかどうか)を判別します。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
void libusb_interrupt_event_handler | ( | libusb_context * | ctx | ) |
イベントを処理しているアクティブなスレッドに割り込み中断させます。これは主に、アプリケーションが libusb_exit() を呼び出したいときに、専用のイベント処理スレッドに割り込み中断させる場合に役立ちます。
バージョン 1.0.21 以降。 LIBUSB_API_VERSION >= 0x01000105
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL マルチ・スレッド・アプリケーションと非同期入出力 |
void libusb_lock_event_waiters | ( | libusb_context * | ctx | ) |
イベント待ちロックを取得します。 このロックは、イベントが完了したときに通知したい状況で取得するように設計されていますが、他のいくつかのスレッドはイベント処理中であるため、 libusb_handle_events() の呼び出しは許可されていません。
あなたは、次に、このロックを取得し、別のスレッドがまだイベントを処理していることを再確認してから、 libusb_wait_for_event() を呼び出します。
あなたがこのロックを使用する必要があるのは、libusbのファイル・デスクリプターで poll() または select() を直接呼び出すアプリケーションを開発している場合していて、2つのスレッドからのイベントを同時に処理している可能性がある場合のみです。libusbのイベント処理ループ関数(例えば libusb_handle_events() など)のみを使っている場合は、このロックを気にする必要はありません。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL マルチ・スレッド・アプリケーションと非同期入出力 |
void libusb_unlock_event_waiters | ( | libusb_context * | ctx | ) |
イベント待ちロックを解除します。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL マルチ・スレッド・アプリケーションと非同期入出力 |
int libusb_wait_for_event | ( | libusb_context * | ctx, |
struct timeval * | tv | ||
) |
別のスレッドがイベントの完了を通知するのを待ちます。イベント待ちロックを保持した状態で呼び出す必要があります。 libusb_lock_event_waiters() を参照してください。
この関数は、以下の条件のいずれかが満たされるまでブロックされます:
条件1は自明です。 条件2は、転送のコールバックが完了した後にスレッドをブロックしているのを解除します。条件3は、以前にイベントを処理していたスレッドがもはや処理をしなくなったことを意味するため重要です。したがってイベントが完了する場合は、別のスレッドが代わりにイベント処理を開始する必要があります。
この関数は、スレッドをスリープ状態にする前にイベント待ちロックを解放し、ウェイクアップ時にロックを再取得します。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
tv | このブロッキング関数の最大タイムアウト。 NULL値は無制限のタイムアウトを示します。 |
int libusb_handle_events_timeout_completed | ( | libusb_context * | ctx, |
struct timeval * | tv, | ||
int * | completed | ||
) |
保留中のイベントを処理します。
libusbは、タイムアウトの期限が切れているかどうかを確認し、ファイル・デスクリプターのセットでアクティビティを確認することにより、 "保留中のイベント" を判別します。
timevalに0(ゼロ)が渡された場合、この関数は保留中のイベントを処理し、すぐに非ブロッキングスタイルで戻ります。
timevalが0以外で渡され、かつ、現在保留中のイベントがない場合、この関数は、指定されたタイムアウトまでイベントが処理されるのを待機しブロックします。イベントが到着したり、シグナルが発生したりすると、この関数はそれだけ早く戻ります。
completed パラメーターがNULLでない場合、イベント処理ロックを取得してから、completedパラメーターの示すポインタで示された整数が0でない場合、この関数はすぐに戻ります。これにより、指定の転送の完了を競合無しで待機できます。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
tv | イベントの待機をブロックする最大時間、または非ブロック・モードの場合はすべてゼロのtimeval構造体 |
completed | チェックする完了整数へのポインタ、またはNULL |
int libusb_handle_events_timeout | ( | libusb_context * | ctx, |
struct timeval * | tv | ||
) |
保留中のイベントを処理する
libusb_handle_events_timeout_completed() と同様ですが、completedパラメーターがない場合、この関数を呼び出すことは、NULLのcompletedパラメーターを指定して libusb_handle_events_timeout_completed() を呼び出すことと同じです。
この関数は、主に下位互換性のために保持されています。すべての新しいコードは、競合状態を回避するために libusb_handle_events_completed() または libusb_handle_events_timeout_completed() を呼び出す必要があります。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
tv | イベントの待機をブロックする最大時間、または非ブロック・モードの場合はすべてゼロのtimeval構造体 |
int libusb_handle_events | ( | libusb_context * | ctx | ) |
保留中のイベントをブロック・モードで処理します。 現在、60秒にハード・コードされたタイムアウトがありますが、将来的には無制限にする予定です。この関数がブロッキングか非ブロッキングかをより細かく制御する場合、またはタイムアウトを制御する場合は、代わりに libusb_handle_events_timeout_completed() を使用してください。
この関数は、主に下位互換性のために保持されています。すべての新しいコードは、競合状態を回避するために libusb_handle_events_completed() または libusb_handle_events_timeout_completed() を呼び出す必要があります。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
int libusb_handle_events_completed | ( | libusb_context * | ctx, |
int * | completed | ||
) |
保留中のイベントをブロックモードで処理します。
libusb_handle_events() のように、completedパラメータを追加して、指定の転送の完了を競合無しで待機できるようにします。
completedパラメーターについては libusb_handle_events_timeout_completed() に詳しい説明があります。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
completed | チェックする完了整数へのポインタ、またはNULL |
int libusb_handle_events_locked | ( | libusb_context * | ctx, |
struct timeval * | tv | ||
) |
他のスレッドがすでに処理しているかどうかを確認せずに、ファイル・デスクリプターをポーリングして保留中のイベントを処理します。 イベント・ロックを保持した状態で呼び出す必要があります。 libusb_lock_events() を参照してください。
この関数は、イベント・ロックを取得し、(libusb_handle_events() または同様なのを使用するのではなく)libusbのファイル・デスクリプター子で直接 poll()/select() を呼び出す状況で呼び出されるように設計されています。 libusbのデスクリプターでイベントを検出するため、(イベント・ロックを保持したまま)タイムアウト値をゼロにしてこの関数を呼び出します。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
tv | イベント待ちをブロックする最大時間、または非ブロック・モードの場合はゼロ |
int libusb_pollfds_handle_timeouts | ( | libusb_context * | ctx | ) |
libusbのファイル・デスクリプターを監視するときに、アプリケーションが特別なタイミングの考慮事項を適用する必要があるかどうかを決定します。
この関数は、独自のメインループ(より高度な選択肢)でlibusbのファイル・デスクリプターを取得してポーリングするアプリケーションでのみ役立ちます。
通常、libusbのイベント・ハンドラーは、(ファイル・デスクリプター・セットにアクティビティがある場合に加えて)特定の時点で呼び出す必要があります。通常のアプローチは、 libusb_get_next_timeout() を使用して、次のタイムアウトがいつ発生するかを確認し、 poll()/select() を調整することです。それに応じてタイムアウトし、その時点でライブラリを呼び出すことができるようにします。
libusbでサポートされている一部のプラットフォームには、この機能がありません。タイミングに関連するイベントは、ファイル・デスクリプター・セットのアクティビティによって表され、そして libusb_get_next_timeout() は常に0を返します。この関数を使用すると、そのようなプラットフォームで実行しているかどうかを検出できます。
v1.0.5以降
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
int libusb_get_next_timeout | ( | libusb_context * | ctx, |
struct timeval * | tv | ||
) |
libusbが処理する必要がある次の内部タイムアウトを決定します。この関数は、libusbのファイル・デスクリプターで poll() や select() などを自分で呼び出す場合にのみ使用する必要があります。 libusb_handle_events() またはその変種を直接呼び出す場合は、この関数を使用する必要はありません。
select() または poll() が結果を返すまで待機する時間を決定するには、あなたはメイン・ループでこの関数を呼び出す必要があります。 libusbはこのタイムアウトで呼び出される必要があるため、あなたは select() または poll() 呼び出しの上限として使用する必要があります。
タイムアウトの期限が切れたら、 libusb_handle_events_timeout() (おそらく非ブロッキング・モード)を呼び出して、libusbがタイムアウトを処理できるようにします。
この関数は、戻り値1(成功)、かつ、全てゼロのtimevalを返す場合があります。この場合は、libusbのタイムアウトがすでに期限切れになっていることを示しているため、すぐに libusb_handle_events_timeout() などを呼び出す必要があります。 戻り値0は、保留中のタイムアウトがないことを示します。
一部のプラットフォームでは、この関数は常に0(保留中のタイムアウト無し)を返します。 時間ベースのイベントに関する注意 を参照してください。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
tv | タイムアウト・イベントを処理するためにlibusbを呼び出す必要がある、現在の時刻(clock)に対する相対時間の出力場所 |
void libusb_set_pollfd_notifiers | ( | libusb_context * | ctx, |
libusb_pollfd_added_cb | added_cb, | ||
libusb_pollfd_removed_cb | removed_cb, | ||
void * | user_data | ||
) |
ファイル・デスクリプターの追加/削除の通知機能を登録します。これらの関数は、libusbがイベント・ソースとして使用するすべての新規または削除されたファイル・デスクリプターに対して呼び出されます。
通知機能を削除するには、関数ポインタにNULL値を渡します。
注意: これらの通知機能を登録する前でも、ファイル・デスクリプターが追加されている可能性があることに注意してください(たとえば、libusb_init() の時)
さらに、削除通知機能は a class="el" href="group__libusb__lib.html#gadc174de608932caeb2fc15d94fa0844d">libusb_exit() 中に呼び出される可能性があることに注意してください(たとえば、 libusb_init() 時にオープンされてポーリング・セットに追加されたファイル・デスクリプターをクローズするとき)。 これが不要な場合は、 libusb_exit() を呼び出す直前に通知機能を削除してください。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
added_cb | 追加通知用の関数へのポインタ |
removed_cb | 削除通知の関数へのポインタ |
user_data | コールバックに返されるユーザー・データ(コンテキスト情報の受け渡しに役立ちます) |
const struct libusb_pollfd** libusb_get_pollfds | ( | libusb_context * | ctx | ) |
libusbイベント・ソースとしてメイン・ループによってポーリングされる必要があるファイル・デスクリプターのリストを取得します。
返されるリストはNULLで終了するため、完了したら libusb_free_pollfds() で解放する必要があります。実際のリストの内容には触れないでください。
ファイル・デスクリプターはUnix固有の概念であるため、この関数はWindowsでは使用できず、常にNULLを返します。
ctx | 操作するコンテキスト、またはデフォルトのコンテキストの場合はNULL |
void libusb_free_pollfds | ( | const struct libusb_pollfd ** | pollfds | ) |
libusb_pollfd 構造体のリストを解放します。これは libusb_get_pollfds() で割り当てられたすべてのpollfdリストに対して呼び出す必要があります。
バージョン 1.0.20 以降。 LIBUSB_API_VERSION >= 0x01000104
NULLのpollfdリストを使用してこの関数を呼び出すことは合法です。この場合、関数は単に何もしません。
pollfds | 解放したい libusb_pollfd 構造体のリスト |