Android USB アクセサリーは、Android Open Accessory(AOA)プロトコルに準拠する必要があります。AOA プロトコルは、アクセサリーによる Android 搭載デバイスとの通信の検出方法と設定方法を定義したものです。アクセサリーは次の手順に従う必要があります。
- デバイスとの接続を待ち、検出します。
- デバイスがアクセサリー モードをサポートしているか判別します。
- 必要に応じて、デバイスをアクセサリー モードで起動させます。
- デバイスが AOA をサポートしていれば、デバイスとの通信を確立します。
以降のセクションでは、これらの手順の実装方法について説明します。
デバイス接続を待機して検出する
アクセサリーは、Android 搭載デバイスとの接続を継続的に確認する必要があります。デバイスが接続されたら、デバイスがアクセサリー モードをサポートしているかどうかを判別します。
アクセサリー モードのサポートを判別する
注: アクセサリーの接続に USB デバッグは必要ありませんが、開発中は ADB が必要になる場合があります。詳しくは、デバッグに関する考慮事項をご覧ください。
Android 搭載デバイスが接続されると、次の 3 つの状態のいずれかになります。
- Android アクセサリー モードをサポートしており、アクセサリー モードになっている。
- Android アクセサリー モードをサポートしているが、アクセサリー モードにはなっていない。
- Android アクセサリー モードをサポートしていない。
アクセサリーは、最初の接続時に、接続されたデバイスの USB デバイス記述子に含まれているバージョン、ベンダー ID、プロダクト ID を確認します。ベンダー ID は Google の ID(0x18D1
)と一致する必要があります。デバイスがすでにアクセサリー モードになっている場合、プロダクト ID は 0x2D00
または 0x2D01
でなければなりません。アクセサリーは独自の通信プロトコルを使用して、一括転送エンドポイント経由でデバイスとの通信を確立できます(デバイスをアクセサリー モードで起動する必要はありません)。
注: 0x2D00
は、アクセサリー モードをサポートする Android 搭載デバイス用に予約された ID です。0x2D01
は、アクセサリー モードと Android Debug Bridge(ADB)プロトコルをサポートするデバイス用に予約された ID です。このプロトコルは、ADB 用の 2 つの一括エンドポイントを持つ第 2 のインターフェースを公開します。パソコンでアクセサリーをシミュレートする場合は、これらのエンドポイントを使用してアクセサリー アプリをデバッグできます。一般的に、アクセサリーがデバイス上で ADB へのパススルーを実装していない限り、このインターフェースは使用しません。
USB デバイス記述子のバージョン、ベンダー ID、プロダクト ID が予想される値と一致しない場合、デバイスが Android アクセサリー モードをサポートしているかどうかをアクセサリーが判別することはできません。アクセサリーは、デバイスのサポートを判別するためにデバイスをアクセサリー モードで起動しようと試みます(詳細は下記を参照)。
重要なポイント: USB アクセサリーは、最初の handshake 時にヘッダーを送信する必要があります。ヘッダーには、メーカー、モデル、バージョンが含まれています。バージョンは省略可能なフィールドですが、バージョンのみで一致する Android アプリをインストールしても、アクセサリーがバージョンを送信しない場合、Android 10 以前を搭載した Android デバイスは、システム プロセスでスローされている例外により再起動します。
アクセサリー モードで起動を試みる
バージョン、ベンダー ID、プロダクト ID がアクセサリー モードの Android 搭載デバイスに対応していない場合、デバイスがアクセサリー モードをサポートしている(ただし、そのモードになっていない)のかサポートしていないのかをアクセサリーが判別することはできません。これは、アクセサリー モードをサポートする(ただし、そのモードになっていない)デバイスが最初に報告するのはデバイス メーカーのベンダー ID とプロダクト ID であり、AOA のベンダー ID とプロダクト ID ではないためです。
アクセサリーは、デバイスがアクセサリー モードをサポートしているかどうかを判別するため、デバイスをアクセサリー モードで起動しようと試みます。
- デバイスが Android アクセサリー プロトコルをサポートしているかどうかを判別するには、コントロール リクエスト 51(GET プロトコル)を送信します。デバイスがこのプロトコルをサポートしていれば、サポートしているプロトコル バージョンを表すゼロ以外の数値を返します。コントロール リクエストはエンドポイント 0 にあり、次の特性を持ちます。
requestType: USB_DIR_IN | USB_TYPE_VENDOR request: 51 value: 0 index: 0 data: protocol version number (16 bits little endian sent from the device to the accessory)
- デバイスからサポートされているプロトコル バージョンが返された場合は、識別文字列の情報を含むコントロール リクエストをデバイスに送信します。この情報により、デバイスはアクセサリーに適したアプリを決定できます(適切なアプリが存在しない場合は、URL をユーザーに提示します)。コントロール リクエストは各文字列 ID ごとにエンドポイント 0 にあり、次の特性を持ちます。
requestType: USB_DIR_OUT | USB_TYPE_VENDOR request: 52 value: 0 index: string ID data zero terminated UTF8 string sent from accessory to device
次の文字列 ID がサポートされます。各文字列の最大サイズは 256 バイトです(
\0
によりゼロで終わる必要があります)。manufacturer name: 0 model name: 1 description: 2 version: 3 URI: 4 serial number: 5
- コントロール リクエストを送信して、アクセサリー モードで起動するようにデバイスに要求します。コントロール リクエストはエンドポイント 0 にあり、次の特性を持ちます。
requestType: USB_DIR_OUT | USB_TYPE_VENDOR request: 53 value: 0 index: 0 data: none
以上のステップを完了した後、アクセサリーは、接続された USB デバイスがアクセサリー モードでバスに再登録され、接続されたデバイスとして再び列挙されるのを待ちます。このアルゴリズムでは、ベンダー ID とプロダクト ID を確認することでアクセサリー モードのサポートを判別しています。デバイスがアクセサリー モードへの切り替えに成功した場合、これらの ID は正しい(デバイス メーカーの ID ではなく、Google のベンダー ID とプロダクト ID に対応している)はずです。ID とバージョンが正しければ、アクセサリーはデバイスとの通信を確立するステップに進みます。
注: 現在、AOA は AOA と MTP の同時接続をサポートしていません。AOA から MTP に切り替えるには、USB デバイスを物理的に取り外すか電源を切断してから、MTP を使用して再接続します。
いずれかのステップが失敗した場合、アクセサリーはデバイスが Android アクセサリー モードをサポートしていないと判断し、別のデバイスが接続されるのを待ちます。
デバイスとの通信を確立する
アクセサリーは、アクセサリー モードの Android 搭載デバイスを検出すると、デバイスのインターフェース記述子とエンドポイント記述子をクエリして、デバイスと通信するための一括エンドポイントを取得します。
インターフェースと一括エンドポイントの数は、次に示すように、Android 搭載デバイスのプロダクト ID によって異なります。
- プロダクト ID が
0x2D00
の場合、インターフェースは 1 つで、入力および出力通信用に 2 つの一括エンドポイントがあります。 - プロダクト ID が
0x2D01
の場合、インターフェースは 2 つで、入力および出力通信用にそれぞれ 2 つの一括エンドポイントがあります。第 1 のインターフェースは標準の通信を処理し、第 2 のインターフェースは ADB 通信を処理します。インターフェースを使用するには、第 1 の一括入力 / 出力エンドポイントを見つけて、SET_CONFIGURATION
(0x09
)デバイス リクエストによりデバイス設定の値を 1 に設定し、エンドポイントを使用して通信を行います。