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

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

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 設定に表示されません。