Android Open Accessory プロトコル 2.0

このドキュメントでは、Android Open Accessory(AOA)プロトコルの初期リリースからの変更点と AOA 1.0 ドキュメントの補足について説明します。AOAv2 には以下の機能が追加されています。

  • オーディオ出力(Android 8.0 ではサポート終了)。
  • Android デバイスへの複数のヒューマン インターフェース デバイス(HID)として機能するアクセサリのサポート。

Android アプリのデベロッパーが利用できる Android SDK API については、変更点はありません。

AOAv2 サポートの検出

接続された Android デバイスがサポート対象のプロトコル バージョンとアクセサリをサポートしているかどうかを判別するには、アクセサリから getProtocol() コマンドを送信して結果を確認する必要があります。AOAv1 の機能のみをサポートする Android デバイスは、プロトコル バージョンとして 1 を返す必要があります。AOAv2 の追加機能をサポートするデバイスは、プロトコル バージョンとして 2 を返す必要があります。AOAv2 は AOAv1 に対して下位互換性があるため、従来のアクセサリ プロトコルに合わせて設計されたアクセサリでも、新しい Android デバイスで引き続き動作します。

次の例は、Accessory Development Kit 2011 のソースコード<adk-src>/adk1/board/AndroidAccessory/AndroidAccessory.cpp)ライブラリでのプロトコル チェックを示します。

bool AndroidAccessory::switchDevice(byte addr)
{
    int protocol = getProtocol(addr);
    if (protocol >= 1) {
        Serial.print("device supports protocol 1 or higher\n");
    } else {
        Serial.print("could not read device protocol version\n");
        return false;
    }

    sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer);
    sendString(addr, ACCESSORY_STRING_MODEL, model);
    sendString(addr, ACCESSORY_STRING_DESCRIPTION, description);
    sendString(addr, ACCESSORY_STRING_VERSION, version);
    sendString(addr, ACCESSORY_STRING_URI, uri);
    sendString(addr, ACCESSORY_STRING_SERIAL, serial);

    usb.ctrlReq(addr, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_VENDOR |
                USB_SETUP_RECIPIENT_DEVICE, ACCESSORY_START, 0, 0, 0, 0, NULL);
    return true;
}

AOAv2 には、アクセサリ モードで使用可能な USB インターフェースの各組み合わせに対応した新しい USB プロダクト ID が含まれています。

バージョン 商品 ID 通信 説明
AOAv1 0x2D00 アクセサリ Android アプリとの通信を目的とした 2 つのバルク エンドポイントを提供します。
0x2D01 アクセサリ + ADB アクセサリ開発時のデバッグ用。ユーザーが Android デバイスの設定で USB デバッグを有効にしている場合にのみ使用できます。
AOAv2 0x2D02 オーディオ Android デバイスからアクセサリへのオーディオ ストリーミング用。
0x2D03 オーディオ + ADB
0x2D04 アクセサリ + オーディオ
0x2D05 アクセサリ + オーディオ + ADB

AOAv1 で使用されるプロダクト ID(0x2D000x2D01)は、AOAv2 でも引き続きサポートされます。

オーディオ サポート

AOAv2 では、Android デバイスからアクセサリへのオーディオ出力で、2 チャンネルの使用が可能な標準 USB オーディオ クラス インターフェース、ビットレートが 44,100 kHz の 16 ビット PCM オーディオ(今後追加される可能性があるオーディオ モード)を介した出力がサポートされています。

オーディオ サポートを有効にするには、アクセサリから新しい USB コントロール リクエストを送信する必要があります。

**SET_AUDIO_MODE**
requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
request:        58
value:          0 for no audio (default),
                1 for 2 channel, 16-bit PCM at 44100 KHz
index:          0
data            none

このコマンドは、ACCESSORY_START コマンドを送信してアクセサリ モードに入る前に送信する必要があります。

HID サポート

アクセサリでは、AOAv2 を介して 1 つ以上の USB ヒューマン インターフェース デバイス(HID)を Android デバイスに登録できます。このアプローチでは、USB マウスやキーボードなどの一般的な USB HID デバイスの通信方向が逆になります。通常、HID デバイスは USB ホスト(パソコンなど)に接続された周辺機器です。しかし、AOA では USB ホストが USB 周辺機器への入力デバイスとして機能できます。

HID をサポートすることで、標準的な HID イベントのプロキシとなります。つまり、実装時にイベントの内容や種類について考慮しておく必要がなく、入力システムにイベントをパススルーするだけでよくなります。その結果、AOAv2 アクセサリは、マウス、キーボード、ゲーム コントローラなど、どのような HID デバイスとしても機能することができます。HID サポートを活用することで、メディアドックの再生 / 一時停止ボタンなどの基本機能、マウスや QWERTY キーボードを備えたドッキング ステーションなどの高度な機能が提供できるようになります。

AOAv2 では、新しい USB コントロール リクエストが追加され、Android デバイスへの 1 つ以上の HID 入力デバイスとしてアクセサリを機能させることができます。HID サポートはすべて、エンドポイント 0 のコントロール リクエストを通じて処理されるため、新しい USB インターフェースは不要です。新しいコントロール リクエストには、次の 4 つがあります。

  • ACCESSORY_REGISTER_HID: Android デバイスに新しい HID デバイスを登録します。アクセサリは、以下の 3 つの呼び出しで HID デバイスを識別するための ID を提供します。この ID は、USB が切断されるまで、またはアクセサリが ACCESSORY_UNREGISTER_HID を送信して HID デバイスの登録を解除するまで有効です。
  • ACCESSORY_REGISTER_HID: ACCESSORY_REGISTER_HID で過去に登録された HID デバイスの登録を解除します。
  • ACCESSORY_SET_HID_REPORT_DESC: HID デバイスのレポート記述子を Android デバイスに送信します。このリクエストは、HID デバイスの機能の説明に使用され、HID イベントを Android デバイスにレポートする前に送信する必要があります。レポート記述子がエンドポイント 0 の最大パケットサイズより大きい場合、複数の ACCESSORY_SET_HID_REPORT_DESC コマンドが送信されることで記述子全体が転送されます。
  • ACCESSORY_SEND_HID_EVENT: アクセサリから Android デバイスに入力イベントを送信します。

新しいコントロール リクエストのコード定義は次のとおりです。

/* Control request for registering a HID device.
 * Upon registering, a unique ID is sent by the accessory in the
 * value parameter. This ID will be used for future commands for
 * the device
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_REGISTER_HID_DEVICE
 *  value:          Accessory assigned ID for the HID device
 *  index:          total length of the HID report descriptor
 *  data            none
 */
#define ACCESSORY_REGISTER_HID         54

/* Control request for unregistering a HID device.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_REGISTER_HID
 *  value:          Accessory assigned ID for the HID device
 *  index:          0
 *  data            none
 */
#define ACCESSORY_UNREGISTER_HID         55

/* Control request for sending the HID report descriptor.
 * If the HID descriptor is longer than the endpoint zero max packet size,
 * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
 * commands. The data for the descriptor must be sent sequentially
 * if multiple packets are needed.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_SET_HID_REPORT_DESC
 *  value:          Accessory assigned ID for the HID device
 *  index:          offset of data in descriptor
 *                      (needed when HID descriptor is too big for one packet)
 *  data            the HID report descriptor
 */
#define ACCESSORY_SET_HID_REPORT_DESC         56

/* Control request for sending HID events.
 *
 *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
 *  request:        ACCESSORY_SEND_HID_EVENT
 *  value:          Accessory assigned ID for the HID device
 *  index:          0
 *  data            the HID report for the event
 */
#define ACCESSORY_SEND_HID_EVENT         57

AOAv1 との互換性

最初のプロトコル(AOAv1)では、Android アプリが USB ホスト(アクセサリ)と USB 経由で直接通信するためのサポートが提供されています。AOAv2 でもこのサポートを継続し、さらにアクセサリが Android オペレーティング システムそのもの(特にオーディオ システムと入力システム)と通信するための新機能が追加されました。このような AOAv2 の設計により、従来の機能に加えて、新たにオーディオ サポートと HID サポートを使用するアクセサリが作成できます。新機能は、従来の機能と合わせて使用できます。

Android アプリを使用せずに AOAv2 で接続する

Android デバイス上のアプリと通信することなく、オーディオ サポートや HID サポートを使用するアクセサリ(オーディオ ドックなど)を設計できます。これらのアクセサリでは、ユーザーにダイアログを表示する必要がなく、新しく接続されたアクセサリを検出してアクセサリとの通信が可能な Android アプリと連携させる必要はありません。

アクセサリの接続後にこのようなダイアログを表示しないために、アクセサリからの Android デバイスへのメーカー名とモデル名の送信を止めることができます。それらの文字列が Android デバイスに送信されない場合、次のような動作になります。

  • システムでは、アクセサリと通信するアプリが検出されません。
  • Android デバイスがアクセサリ モードになった後も、アクセサリの USB インターフェースがデバイスの USB 設定に表示されません。