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 애플리케이션과 통신하기 위한 두 개의 대량 엔드포인트를 제공합니다.
0x2D01 액세서리 + adb 액세서리 개발 시에 디버깅 용도로 사용됩니다. 사용자가 Android 기기 설정에서 USB 디버깅을 사용 설정한 경우에만 사용할 수 있습니다.
AOAv2 0x2D02 오디오 Android 기기에서 액세서리로 오디오를 스트리밍하는 용도입니다.
0x2D03 오디오 + adb
0x2D04 액세서리 + 오디오
0x2D05 액세서리 + 오디오 + adb

AOAv1에서 사용되는 제품 ID(0x2D000x2D01)는 AOAv2에서 계속 지원됩니다.

오디오 지원

AOAv2는 44100Khz 비트 전송률의 2채널 16비트 PCM 오디오를 지원하는 표준 USB 오디오 클래스 인터페이스를 통해 Android 기기에서 액세서리로 오디오 출력을 지원합니다(이후 오디오 모드가 추가될 수 있습니다).

오디오 지원을 사용 설정하려면 액세서리가 새 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를 사용하면 액세서리가 하나 이상의 USB 인간 인터페이스 기기(HID)를 Android 기기에 등록할 수 있습니다. 이 접근 방식은 USB 마우스 및 키보드와 같은 일반적인 USB HID 기기의 통신 방향을 바꿉니다. 일반적으로 HID 기기는 USB 호스트(개인용 컴퓨터)에 연결된 주변기기이지만 AOA에서는 USB 호스트가 USB 주변기기에 하나 이상의 입력 기기로 작동할 수 있습니다.

HID 지원은 표준 HID 이벤트의 프록시입니다. 구현은 이벤트의 내용이나 유형을 가정하지 않고 단순히 입력 시스템으로 전달하여 AOAv2 액세서리가 HID 기기(마우스, 키보드, 게임 컨트롤러 등)로 작동하도록 합니다. HID 지원을 사용하여 미디어 도크의 재생/일시중지 버튼과 같은 기본 기능이나 마우스 및 풀사이즈 QWERTY 키보드가 있는 도킹 스테이션과 같은 고급 기능을 제공할 수 있습니다.

AOAv2에는 액세서리가 Android 기기에 하나 이상의 HID 입력 장치로 작동할 수 있도록 하는 새로운 USB 제어 요청이 추가되었습니다. HID 지원은 엔드포인트 0의 제어 요청을 통해 전체적으로 처리되므로 새로운 USB 인터페이스는 필요하지 않습니다. 새로운 제어 요청 4가지는 다음과 같습니다.

  • ACCESSORY_REGISTER_HID는 Android 기기에 새 HID 기기를 등록합니다. 액세서리는 다른 세 개 호출의 HID 기기를 식별하는 데 사용되는 ID를 제공합니다. 이 ID는 USB 연결이 끊어지거나 액세서리가 ACCESSORY_UNREGISTER_HID를 전송하여 HID 기기의 등록을 취소할 때까지 유효합니다.
  • ACCESSORY_UNREGISTER_HID는 이전에 ACCESSORY_REGISTER_HID를 통해 등록된 HID 기기의 등록을 취소합니다.
  • ACCESSORY_SET_HID_REPORT_DESC는 Android 기기에 HID 기기의 보고서 설명어를 전송합니다. 이 요청은 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은 USB를 통해 USB 호스트(액세서리)와 직접 통신할 수 있는 Android 애플리케이션을 지원합니다. AOAv2는 이러한 지원을 지속하며 액세서리가 Android 운영체제 자체와 통신할 수 있는 새로운 기능(특히 오디오 및 입력 시스템)을 추가합니다. AOAv2의 디자인을 통해 원래의 기능 모음 외에 새로운 오디오 및 HID 지원까지 활용하는 액세서리를 제작할 수 있습니다. 새 기능을 원래 기능과 함께 사용하면 됩니다.

Android 앱 없이 AOAv2 연결하기

오디오 및 HID 지원을 활용하지만 Android 기기의 애플리케이션과 통신하지 않는 액세서리(예: 오디오 도크)를 설계할 수 있습니다. 이러한 액세서리의 경우 사용자는 새로 연결한 액세서리를 검색하고 통신할 수 있는 Android 애플리케이션과 연결하라는 대화상자 메시지를 수신할 필요가 없습니다.

액세서리가 연결된 후 이러한 대화상자를 표시하지 않으려면 액세서리가 제조업체 및 모델 이름을 Android 기기로 전송하지 않도록 선택할 수 있습니다. Android 기기에 대화상자 문자열이 제공되지 않으면 다음과 같은 상황이 발생합니다.

  • 시스템은 액세서리와 통신할 애플리케이션을 찾으려고 시도하지 않습니다.
  • 기기가 액세서리 모드로 전환된 후에 Android 기기 USB 구성에 액세서리 USB 인터페이스가 없습니다.