aoa2.0を実装してみた

38
AOA2.0を実装してみた(USB) ADK勉強会(東京) BootCamp#2 2012/10/13 Yuuichi Akagawa

Upload: yuuichi-akagawa

Post on 31-May-2015

3.182 views

Category:

Technology


1 download

DESCRIPTION

ADK勉強会(東京) BootCamp#2で発表した、AOA2.0実装のお話。ABC2012東北やABC2013Sで展示したもの。

TRANSCRIPT

Page 1: AOA2.0を実装してみた

AOA2.0を実装してみた(USB編)

ADK勉強会(東京) BootCamp#22012/10/13

Yuuichi Akagawa

Page 2: AOA2.0を実装してみた

自己紹介

Yuuichi Akagawa (あかがわ ゆういち)– C言語と同い年

本業は某SI企業でインフラ担当

ADKで何かを作るのではなくて、ADKをいろんなマイコンに実装するのがマイブーム

Androidアプリはあんまり作れませんJavaが嫌いなの(ゝω・)

Copyright © 2012 Yuuichi Akagawa 1

Page 3: AOA2.0を実装してみた

今日語る内容

ADK 2012ボードについては語りません。

あくまでもADK2(AOA2.0)に関する部分だけ。

しかもUSBだけ。Bluetoothはナシよ。

Copyright © 2012 Yuuichi Akagawa 2

Page 4: AOA2.0を実装してみた

改めて、ADKとは

Android Open Accessory Development Kit

Android Open Accessoryのリファレンス実装

Android側はUSB Accessory APIを利用

アクセサリ側は Android Open Accessory protocol(AOA)を実装

でもまあ、メンドクサイからもろもろADKということで

Copyright © 2012 Yuuichi Akagawa 3

Page 5: AOA2.0を実装してみた

ADK 2011 / AOA1.0昨年5月のGoogle I/Oで発表されたADKはADK2011 / AOA1.0と呼ぶことになった

マイコンボードはArduino Mega 2560ベース

現時点でADKと呼ばれているものは、ほぼ全てこれ

アクセサリ側がUSBホストとして実装され、USB接続により通信と給電機能が提供される

Copyright © 2012 Yuuichi Akagawa 4

Page 6: AOA2.0を実装してみた

ADK 2012 / AOA2.0 (通称ADK2)

今年6月のGoogle I/Oで発表されたADKはADK2012 / AOA2.0。Android4.1以降で対応

マイコンボードはArduino Dueベース(Cortex‐M3)

新機能

– ADK connection over Bluetooth– USB Audio / Bluetooth Audio(A2DP)– HID

Copyright © 2012 Yuuichi Akagawa 5

Page 7: AOA2.0を実装してみた

ADK2012に関する詳しい情報

@magoroku15さんが横浜Android PF部で発表してます。非常に詳しく解析されています。

回路図やソースコードから解析を進めるアプローチ。必見。Copyright © 2012 Yuuichi Akagawa 6

http://www.slideshare.net/magoroku15/adk2012

Page 8: AOA2.0を実装してみた

ぼくのアプローチ

仕様から攻めます– http://developer.android.com/tools/adk/aoa2.html

そして、動かしながらUSBアナライザで観察

Copyright © 2012 Yuuichi Akagawa 7

Page 9: AOA2.0を実装してみた

ぼくのアプローチ

使うマイコンは

– Arduino UNO + USB Host Shield– GR‐SAKURA

Copyright © 2012 Yuuichi Akagawa 8

Page 10: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 9

AOA1.0からの変更点

Page 11: AOA2.0を実装してみた

AOA2.0

AOA1.0とAOA2.0

AOA2.0はAOA1.0の上位互換。USB接続のAccessoryモードという点では同じ。

10Copyright © 2012 Yuuichi Akagawa

Accessory API

AOA1.0

BluetoothUSB

A2DP HIDAudio Play HIDRFCOMM

ADK2012

※ADK over BTはAOAに規定されていない。実際にはAccessoryではない。

Page 12: AOA2.0を実装してみた

コントロール転送一覧

request description

51 (0x33) AOAプロトコルバージョン取得

52(0x34) アクセサリ識別文字列送信

53(0x35) アクセサリモード切り替え

54(0x36) HID デバイスの登録

55(0x37) HIDデバイスの登録解除

56(0x38) HID report descriptorの送信

57(0x39) HID Reportの送信

58(0x40) Audioモードの設定

11Copyright © 2012 Yuuichi Akagawa

AOA2.0では新たに5つ追加

Page 13: AOA2.0を実装してみた

USB Product ID

AOA Protocol Version Product ID Support  function

AOA 1.0 0x2D00 accessory

0x2D01 accessory + adb

AOA 2.0 0x2D02 audio

0x2D03 audio + adb

0x2D04 accessory + audio

0x2D05 accessory + audio + adb

Copyright © 2012 Yuuichi Akagawa 12

機能の追加によりProduct IDが追加された

Page 14: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 13

Protocol Version

2を返すようになった

フィールド 値

bmRequestType 0b11100000 ・デバイス→ホスト・リクエストタイプ:ベンダ・受信:デバイス

bRequest 51 (0x33)

wValue 0

wIndex 0

wLength 2

デバイスリクエスト

レスポンス

‐ 非対応(STALL応答)

0x0001 AOA1.0

0x0002 AOA2.0 (Android 4.1以上)

Page 15: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 14

Protocol Version

古いADK実装だと、JB端末が接続出来ない問題

if (protocol == 1) {Serial.print("device supports protcol 1¥n");

} else {Serial.print("could not read device protocol version¥n");return false;

}

ADK_release_0512

残念!

Microchipのライブラリ等も、古いものは同じような実装になっていたらしい。

if (protocol >= 1) {Serial.print("device supports protocol 1 or higher¥n");

} else {Serial.print("could not read device protocol version¥n");return false;

}

ADK_release_20120606Google I/O前にこっそり修正されていた

Page 16: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 15

Protocol Version

ちなみにYaoadkは、6/23に取り込み済み

GR‐SAKURA版は 初から1以上で判定するよう作っておいた

STM32F4‐Discovery版は…直してない (゚o゚;

//get protocolunsigned short protocol = ‐1;protocol = getProtocol();if(protocol < 1 ){tkusbh_disconnect(TIMEOUT_INFINITE);return false;

}#ifdef DEBUGprintf("ADK supportd.(%d)¥n", protocol);

#endif

Page 17: AOA2.0を実装してみた

ACCESSORY_SEND_STRING

アクセサリ識別文字列は変更なし

AOA2.0ではmanufacturerとmodelを省略すると、接続してもアプリを起動をしない

string ID 値 備考

0 manufacturer name accessory_filterマッチング対象

1 model name accessory_filterマッチング対象

2 description 接続時のダイアログに表示される

3 version accessory_filterマッチング対象

4 URI 対応するアプリがインストールされていない場合、当該のURIをブラウザで開く

5 serial number仕様上はそれぞれ256バイトまで

16Copyright © 2012 Yuuichi Akagawa

Page 18: AOA2.0を実装してみた

アプリ自動起動抑止

前述の通りAOA2.0では、以下の2つを送信しないと、アプリ自動起動を抑止できる

manufacturer namemodel name

ただし、これを行うとAccessoryとしては認識しない。Audioモードで使用することが前提→  USB PID=0x2D02 or 0x2D03が返される

Copyright © 2012 Yuuichi Akagawa 17

Page 19: AOA2.0を実装してみた

HIDサポート

Androidアプリは不要

Audio Dockの制御ボタン等を実装可能

もちろん、キーボードやマウスの実装も可能

複数のHIDデバイスを設定可能

本物のHIDと異なり、レポートデータはコントロール転送で行う

AudioやAccessoryとの併用を想定

HID単体ならAndroid側のUSBホスト機能で十分

18Copyright © 2012 Yuuichi Akagawa

Page 20: AOA2.0を実装してみた

ACCESSORY_REGISTER_HIDHIDデバイスの登録

ID番号を指定することで、複数のHIDデバイスを登録することができる

任意のタイミングで実行可能フィールド 値

bmRequestType 0b01100000 ・ホスト→デバイス・リクエストタイプ:ベンダ

bRequest 54 (0x36)

wValue HIDとして登録するID番号

wIndex HID report descriptorのサイズ

Data なし

19Copyright © 2012 Yuuichi Akagawa

Page 21: AOA2.0を実装してみた

ACCESSORY_UNREGISTER_HIDHIDデバイスの登録を解除

任意のタイミングで実行可能

登録していないIDを指定した場合はSTALLが返る

フィールド 値

bmRequestType 0b01100000 ・ホスト→デバイス・リクエストタイプ:ベンダ

bRequest 55 (0x37)

wValue 登録解除したいHIDのID番号

wIndex 0

Data なし

20Copyright © 2012 Yuuichi Akagawa

Page 22: AOA2.0を実装してみた

ACCESSORY_SET_HID_REPORT_DESCHID Report Descriptorを登録する

任意のタイミングで実行可能

登録していないIDを指定した場合はSTALLが返るフィールド 値

bmRequestType 0b01100000 ・ホスト→デバイス・リクエストタイプ:ベンダ

bRequest 56 (0x38)

wValue 登録するHIDのID番号

wIndex ディスクリプタのサイズがエンドポイントのパケットサイズより大きい場合には分割して送信する必要があるため、そのときのインデックス番号を指定する(0スタート)。1パケットで収まる場合は0を指定する。

Data HID Report Descriptor 21Copyright © 2012 Yuuichi Akagawa

Page 23: AOA2.0を実装してみた

ACCESSORY_SEND_HID_EVENTHID Reportデータを送信する

任意のタイミングで実行可能

エラーの場合はSTALLが返る(IDやReport Descriptorが未登録など)

フィールド 値

bmRequestType 0b01100000 ・ホスト→デバイス・リクエストタイプ:ベンダ

bRequest 57 (0x39)

wValue HIDのID番号

wIndex 0

Data HID Reportデータ

22Copyright © 2012 Yuuichi Akagawa

Page 24: AOA2.0を実装してみた

HID実装例

JoyStickをマウスとして動作させてみた

このレベルならArduinoでも楽勝

ソースはこちらで公開中https://github.com/YuuichiAkagawa/Arduino‐AOA2

Copyright © 2012 Yuuichi Akagawa 23

Page 25: AOA2.0を実装してみた

Audioサポート

いわゆるUSB Audio

現時点ではPCM 2ch 16bit 44.1kHzをサポート

Accessoryとは無関係なのでアプリ開発は不要

Android標準のPlayerで音楽再生すると、USB Audio Classに準じたデータがアイソクロナス転

送で送られてくるので、マイコン側でタイミング取って再生すれば良い。

24Copyright © 2012 Yuuichi Akagawa

Page 26: AOA2.0を実装してみた

Audioサポート

ACCESSORY_STARTの前に実行する

AOA2.0のサポート範囲はここまで

フィールド 値

bmRequestType 0b01100000 ・ホスト→デバイス・リクエストタイプ:ベンダ

bRequest 58 (0x40)

wValue 0 : none (デフォルト)1 : PCM 2ch 16bit 44.1kHz

wIndex 0

Data なし

25Copyright © 2012 Yuuichi Akagawa

Page 27: AOA2.0を実装してみた

Audioサポート

Accessoryに切替後、アイソクロナスINトランザクションを発行すると、データが送られてくる

端末側をミュートにしていると、USBに All ‘0’のデータが流れてくる。音量設定には影響されない。(Nexus [email protected]の場合)

26Copyright © 2012 Yuuichi Akagawa

Page 28: AOA2.0を実装してみた

Audioサポート

Interface Descriptor

bLength 9

bDescriptorType INTERFACE

bInterfaceNumber 2

bAlternateSetting 1

bNumEndpoints 1

bInterfaceClass Audio

bInterfaceSubClass Audio streaming

bInterfaceProtocol Undefined

iInterface None

27Copyright © 2012 Yuuichi Akagawa

Audio AS Descriptor

bLength 7

bDescriptorType CS_INTERFACE

bDescriptorSubtype AS_GENERAL

bTerminalLink 0x01

bDelay 1

wFormatTag 0x0001

Audio AS Descriptor

bLength 11

bDescriptorType CS_INTERFACE

bDescriptorSubtype FORMAT_TYPE

bFormatType FORMAT_TYPE_I

bNrChannels 2

bSubframeSize 2

bBitResolution 16

bSamFreqType 1

tSamFreq[1] 44100 Hz

Endpoint Descriptor

bLength 9

bDescriptorType ENDPOINT

bEndpointAddress 4 IN

bmAttributes.TransferType Isochronous

bmAttributes.SynchronizationType Synchronous

wMaxPacketSize.PacketSize 256

bInterval 1

bSyncAddress 0 OUT

Audio EP Descriptor

bLength 7

bDescriptorType CS_ENDPOINT

bDescriptorSubtype EP_GENERAL

bmAttributes.SamplingFrequency 1

bmAttributes.Pitch 0

bmAttributes.MaxPacketsOnly 0

bLockDelayUnits Milliseconds

wLockDelay 1

Nexus 7 (4.1.1)のディスクリプタ(Audio Interfaceのみ抜粋)

Page 29: AOA2.0を実装してみた

Audioサポート

28Copyright © 2012 Yuuichi Akagawa

1msインターバルでのアイソクロナス転送

2ch x 16bit x 44100÷1000 = 176.4 bytes /packet割り切れないから、176x9 + 180で 1764bytes/10packets

Page 30: AOA2.0を実装してみた

Audio実装例

Android端末で音楽ファイルを再生すると、シールド上のスピーカーから音が出る

シールド上のボタンで再生/停止、次曲、前曲の操作が可能(HID)

Copyright © 2012 Yuuichi Akagawa 29

Page 31: AOA2.0を実装してみた

Audio実装例

回路は超簡単

Copyright © 2012 Yuuichi Akagawa 30

Page 32: AOA2.0を実装してみた

Audio実装例

GR‐SAKURAに実装

標準のUSBホストライブラリではアイソクロナス転送がサポートされていないので自前で実装。(とりあえず受信のみ)

音声再生処理はmituhiromatuura氏のMP3再生ラ

イブラリに含まれるコードを使用させて頂きました。http://homepage3.nifty.com/fpga/gr/

PCMなので受信したデータをそのまま上記ライブラリに渡せば音が出る。

Copyright © 2012 Yuuichi Akagawa 31

Page 33: AOA2.0を実装してみた

Audio実装例

HIDは「Basic Audio Device」

Copyright © 2012 Yuuichi Akagawa 32

/* Basic Audio Device HID Report Descriptor */const byte _hidReportDescriptor[] = {0x05, 0x0c,    //USAGE_PAGE (Consumer Devices)0x09, 0x01,    //USAGE (Consumer Remote Control)0xa1, 0x01,    //COLLECTION (Application)0x85, 0x01,    //Report ID (0x01)0x15, 0x00,    //LOGICAL_MINIMUM (0)0x25, 0x01,    //LOGICAL_MAXIMUM (1)0x75, 0x01,    //REPORT_SIZE (1)0x95, 0x01,    //REPORT_COUNT(1)0x09, 0xe9,    //USAGE (Volume Up)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xea,    //USAGE (Volume Down)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xcd,    //USAGE (Play/Pause)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xb5,    //USAGE (Scan Next Track)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xb6,    //USAGE (Scan Previous Track)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xb7,    //USAGE (Stop)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xb3,    //USAGE (Fast Foward)0x81, 0x02,    //INPUT (Data, Var, Abs)0x09, 0xb4,    //USAGE (Rewind)0x81, 0x02,    //INPUT (Data, Var, Abs)0xc0           //END_COLLECTION

};

Input D7 D6 D5 D4 D3 D2 D1 D0

Byte0 Report ID (0x01)

Byte1 Rewind FastRewind

STOP ScanPrev

ScanNext

Play VolueDown

VolumeUp

Page 34: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 33

おまけ~ Bluetooth ~

Page 35: AOA2.0を実装してみた

ADK connection over Bluetooth

Bluetooth経由でAccessoryが利用できる

USBとはイニシエーションの向きが逆

USBはアクセサリからAndroid端末に接続

BluetoothはAndroid端末からアクセサリに接続

全然AOAじゃない。

ADK用のUUIDが割り振られている

1dd35050‐a437‐11e1‐b3dd‐0800200c9a66

SPPのコードを改変すれば作れるのでは?34Copyright © 2012 Yuuichi Akagawa

Page 36: AOA2.0を実装してみた

USB接続とBluetooth接続の違い

Android側のコード例

35Copyright © 2012 Yuuichi Akagawa

mAdapter = BluetoothAdapter.getDefaultAdapter();BluetoothDevice device = mAdapter.getRemoteDevice(address);mSocket = device.createInsecureRfcommSocketToServiceRecord(ADK_UUID);mSocket.connect();

mInStream = mSocket.getInputStream();mOutStream = mSocket.getOutputStream();

mUSBManager = (UsbManager) getSystemService(Context.USB_SERVICE);UsbAccessory acc = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

ParcelFileDescriptor mFD = mUSBManager.openAccessory(acc);if (mFD != null) {FileDescripter fd = mFD.getFileDescriptor();mInStream = new FileInputStream(fd);mOutStream = new FileOutputStream(fd);}

USB

Bluetooth

どちらも接続確立後は、mInStream, mOutStreamを介してアクセスする。

Intent周りは省略

Intentなんて無い

Page 37: AOA2.0を実装してみた

Bluetooth経由のAudioとかHIDとか

Android側の観点では、元々サポートされているBluetoothのプロファイルを使う。

Audio : A2DPHID     : HID

ADK2012ボード側でこれらを実装して見せただけなので、AOAとはなんら関係無い。当たり前だけど、iOSデバイスだって繋がる。

ぼくは全然興味ありません。

36Copyright © 2012 Yuuichi Akagawa

Page 38: AOA2.0を実装してみた

Copyright © 2012 Yuuichi Akagawa 37

おしまい