adk2012

103
@magoroku15 Rev.1.0 2012/7/13 横浜android PF

Upload: magoroku-yamamoto

Post on 31-May-2015

7.516 views

Category:

Education


2 download

TRANSCRIPT

Page 1: Adk2012

@magoroku15

Rev.1.0

2012/7/13 横浜android PF部

Page 2: Adk2012

Who am I

最底辺活動家、下が好き

オーディオマニア

iPhoneだと機器認証しないと取りだせないPCMが、ADK2で取りだせそうなのでやる気満々

昔こんなの作った

オレオレ家電

http://www.slideshare.net/magoroku15/ss-10335135

2012/7/16 横浜android PF部 2

Page 3: Adk2012

今日のお話

ADK2012の解析 ハード編

ADK2012の解析 ソフト編

CLONEの作り方・可能性

2012/7/16 3 横浜android PF部

Page 4: Adk2012

http://developer.android.com/tools/adk/index.html

2012/7/16 4 横浜android PF部

Page 5: Adk2012

Accessory Development Kit 2012

Guideの内容

ADK2.0の使い方

Alarm Clock

Playing Audio

Developing Accessories with ADK 2012 $> mkdir android-accessories

$> cd android-accessories

$> repo init -u https://android.googlesource.com/accessories/manifest

$> repo sync

2012/7/16 5 横浜android PF部

Page 6: Adk2012

Developing Accessories

with ADK 2012の内容

adk1

旧バージョン

adk2012

board

ハード設計情報、回路図、BOM

回路図、レイアウトはEagleで記述

App

Androidアプリのソースコード

External

Ide

IDE用のコードなど

Toolchain

クロスコンパイラ

前半はここを中心に

2012/7/16 6 横浜android PF部

Page 7: Adk2012

2012/7/16 7 横浜android PF部

Page 8: Adk2012

adk2012/board

MakefileBasedBuild

hardware adk2012 BOM.rtf メインボードの部品表

adk2012_base_eng.zip メインボードの回路

adk2012_base_fab.zip メインボードのガーバー

adk2012_LED BOM.rtf IOボードの部品表

adk2012_led_eng.zip IOボードの回路

adk2012_led_fab.zip IOボードのガーバー

adk2_led_layout.pdf IOの外装図

adk2012_flex_eng.zip フレキ回路図

adk2012_flex_fab.zip フレキの指示書

library

tools

2012/7/16 8 横浜android PF部

Page 9: Adk2012

2012/7/16 9 横浜android PF部

Page 10: Adk2012

メインボードの主要部品

hardware/adk2012 BOM.rtf

ATSAM3X8EA-AU

ATMEL製 Coretex-M3

LBMA1BGUG2

村田製作所製 Bluetooth HCI Module

PIC10F200T-I/OT

MicroChip製 PIC10

2012/7/16 10 横浜android PF部

Page 11: Adk2012

メインボード回路図 電源

コネクタ クロック

USB

書き込み コネクタ

SD-CARD

Bluetooth

hardware/adk2012_base.pdf

2012/7/16 11 横浜android PF部

Page 12: Adk2012

メインボード回路図 Bluetooth

BTモジュールは,TX,RX,

RTS,CTS,RESET,CLKの

6本のみ使用。

2012/7/16 12 横浜android PF部

Page 13: Adk2012

PIC10の用途

書き込み

Flashのeraseに使っている

2012/7/16 13 横浜android PF部

Page 14: Adk2012

2012/7/16 14 横浜android PF部

Page 15: Adk2012

IOボードの主要部品

hardware/adk2012_LED BOM.rtf

SHT21

SENSIRION製 湿度センサ

MAX44005GDT+

MAXIM製 カラーセンサー

AT42QT2120-HHM

ATMEL製 タッチセンサ

BMP180

BOSCH製 圧力センサ

2012/7/16 15 横浜android PF部

Page 16: Adk2012

LEDボードの回路図 ARDUINO HEADER AUDIO SENSORS

CAP SENSE

LED & DRIVERS

hardware/adk2012_led.pdf

2012/7/16 16 横浜android PF部

Page 17: Adk2012

AUDIO

TIのデジタル

アンプ

MPUのDAC0から

OP AMP

IV変換

2012/7/16 17 横浜android PF部

Page 18: Adk2012

SENSORS

すべてI2C接続

ADCは使わない

2012/7/16 18 横浜android PF部

Page 19: Adk2012

CAP SENSE

21点の入力スイッチ

GPIOは使わないI2C入力

2012/7/16 19 横浜android PF部

Page 20: Adk2012

LEDS AND DRIVERS

TLC5947

24チャネル定電流シンク出力

1チャネルあたりの最大定電流値= 30mA

12ビット(4096階調)PWMコントロール

流し込み側が4ch、吸いこみ側が24x2チャンネル

24x2x4 = 192chのLEDを4096階調

この内の3chで1個のRGB LEDを点灯

2012/7/16 20 横浜android PF部

Page 21: Adk2012

スイッチとLEDの配置

2012/7/16 21 横浜android PF部

Page 22: Adk2012

2012/7/16 22 横浜android PF部

Page 23: Adk2012

adk2012/board

MakefileBasedBuild

ATMEL ATMEL SAM3X依存部

App ソースコード

Build

flash

setup

hardware ハード編で説明

library ADK2 ソースコード

tools

2012/7/16 23 横浜android PF部

Page 24: Adk2012

ADK Connection over Bluetooth

ADK L;

void setup() {

L.adkInit();

L.btStart();

}

2012/7/16 横浜android PF部 24

http://developer.android.com/tools/adk/adk2.html#adk-conn

The ADK 2012 app and hardware accessory use a Bluetooth

Serial Port Profile (SPP) connection to communicate. This

connection allows two way communication between the ADK

accessory and Android devices.

Page 25: Adk2012

adkInit

120 void ADK::adkInit(void){

121

131

132 //bt init

133 static const BtFuncs myBtFuncs =

{this, btVerboseScanCbkF, btConnReqF, btConnStartF,

btConnEndF, btPinRequestF,btLinkKeyRequest, btLinkKeyCreated, btAclDataRxF, btSspShowF};

134 btInit(&myBtFuncs); //BT UART & HCI driver

135 btSdpRegisterL2capService(); //SDP daemon

136 btRfcommRegisterL2capService(); //RFCOMM framework

137 eliza(); //easter egg

138 btA2dpRegister(); //A2DP profile

139

2012/7/16 横浜android PF部 25

Page 26: Adk2012

adkInit

BT UART

BTモジュールとのインタフェースとしてUARTを使っているのでその初期化

HCI ホスト(MPU)とBTコントローラの間のIF

SDP

サービスを通知するためのプロトコル

RFCOMM シリアル通信のエミュレーションプロトコル

A2DP

2012/7/16 横浜android PF部 26

Page 27: Adk2012

adkInit Bluetoothの復習

BT UART BTモジュールとのインタフェースとしてUARTを使っているのでその初期化

HCI ホスト(MPU)とBTコントローラの間のIF

SDP サービスを通知するためのプロトコル

RFCOMM シリアル通信のエミュレーションプロトコル

L2CAP 複数接続を管理するプロトコル

A2DP AVプロファイル、音声通話用のHSPより高音質

2012/7/16 横浜android PF部 27

Page 28: Adk2012

adkInit BlurToothの復習

2012/7/16 横浜android PF部 28

HCI

HCI

LMP

Baseband

RF

L2CAP

SDP RFCOMM A2DP Control

ホスト側

BTモジュール MCU

Page 29: Adk2012

btInit #1

559 char btInit(const BtFuncs* btf){

564 const uint8_t* script = cc256x_init_script;

572 initBtUart(1);

578 packetState = hciCmdPacketStart(0x3f, 0x336);

579 packetState = hciCmdPacketAddU32(packetState,

BT_BAUDRATE);

580 hciCmdPacketFinish(packetState);

581 btTxCmdPacket();

582 btRxPacket(); //it responds at old speed

592 //init script

593 while(*script++){

594

595 dbgPrintf("¥r%d", num++);

596 cmd = (HCI_Cmd*)script;

597 btTxCmdPacketEx(cmd);

598 script += 3 + cmd->totalParamLen;

599 btRxEventPacket(0);

605 }

606

607 //get buffer size

608 packetState =

hciCmdPacketStart(HCI_OGF_Informational,

HCI_CMD_Read_Buffer_Size);

609 hciCmdPacketFinish(packetState);

610 btTxCmdPacket();

611 do{

612

btRxEventPacket(HCI_EVT_Command_Complete_Event);

613 }while(evt->params[1] !=

(HCI_OPCODE(HCI_OGF_Informational,

HCI_CMD_Read_Buffer_Size) & 0xFF) ||

614 evt->params[2] !=

(HCI_OPCODE(HCI_OGF_Informational,

HCI_CMD_Read_Buffer_Size) >> 8));

615

2012/7/16 横浜android PF部 29

BTモジュールのファームを書きこむ

•UARTを初期化

•GPIO経由でBTモジュールをリセット

Page 30: Adk2012

btInit #2

616 uint16_t aclLen, aclNum, scoNum;

617 uint8_t scoLen;

618

619 aclLen = (((uint16_t)evt->params[5]) << 8) | evt->params[4];

620 scoLen = evt->params[6];

621 aclNum = (((uint16_t)evt->params[8]) << 8) | evt->params[7];

622 scoNum = (((uint16_t)evt->params[10]) << 8) | evt->params[9];

623

628 gAclPacketsCanSend = aclNum;

629

630 //set connectibility/discoverability

631 pageState = 0;

632 btDiscoverableConnectable();

633

634 //enable simple passcodes

635 if(SUPORT_SSP){

636 packetState = hciCmdPacketStart(HCI_OGF_Controller_and_Baseband, HCI_CMD_Write_Simple_Pairing_Mode);

637 packetState = hciCmdPacketAddU8(packetState, 1); //enable it

638 hciCmdPacketFinish(packetState);

639 btTxCmdPacket();

640 do{

641 btRxEventPacket(HCI_EVT_Command_Complete_Event);

642 }while(evt->params[1] != (HCI_OPCODE(HCI_OGF_Controller_and_Baseband, HCI_CMD_Write_Simple_Pairing_Mode) & 0xFF) ||

643 evt->params[2] != (HCI_OPCODE(HCI_OGF_Controller_and_Baseband, HCI_CMD_Write_Simple_Pairing_Mode) >> 8));

644 }

645

651 }

652

2012/7/16 横浜android PF部 30

•ペアリングの処理

Page 31: Adk2012

btStart() #1

void btStart(){

L.btEnable(adkBtConnectionRequest, adkBtLinkKeyRequest,

adkBtLinkKeyCreated,adkBtPinRequest, NULL);

L.btRfcommReserveDlci(RFCOMM_DLCI_NEED_EVEN);

for(i = 0, f = -1; i < sizeof(sdpDescrADK); i++){

if(sdpDescrADK[i] == MAGIX){

if(f == -1) f = i;

else break;

}

}

sdpDescrADK[f] = dlci >> 1;

L.btRfcommRegisterPort(dlci, btAdkPortOpen, btAdkPortClose, btAdkPortRx);

L.btSdpServiceDescriptorAdd(sdpDescrADK, sizeof(sdpDescrADK));

}

2012/7/16 横浜android PF部 31

Page 32: Adk2012

btStart() #2

void btStart(){

L.btEnable(adkBtConnectionRequest, adkBtLinkKeyRequest,

adkBtLinkKeyCreated,adkBtPinRequest, NULL);

L.btRfcommReserveDlci(RFCOMM_DLCI_NEED_EVEN);

for(i = 0, f = -1; i < sizeof(sdpDescrADK); i++){

if(sdpDescrADK[i] == MAGIX){

if(f == -1) f = i;

else break;

}

}

sdpDescrADK[f] = dlci >> 1;

L.btRfcommRegisterPort(dlci, btAdkPortOpen, btAdkPortClose, btAdkPortRx);

L.btSdpServiceDescriptorAdd(sdpDescrADK, sizeof(sdpDescrADK));

}

2012/7/16 横浜android PF部 32

•ADK固有のハンドシェークパラメタを設定

• static BtFuncs cbks;に登録してハンドシェークの過程でCallbackされる

Page 33: Adk2012

adkBtLinkKeyReques

1605 static char adkBtLinkKeyRequest(const uint8_t* mac,

uint8_t* buf){ //link key create

1606

1607 uint8_t i, j;

1608

1609 Serial.print("Key request from ");

1610 Serial.print(mac[5], HEX);

1611 Serial.print(":");

1612 Serial.print(mac[4], HEX);

1613 Serial.print(":");

1614 Serial.print(mac[3], HEX);

1615 Serial.print(":");

1616 Serial.print(mac[2], HEX);

1617 Serial.print(":");

1618 Serial.print(mac[1], HEX);

1619 Serial.print(":");

1620 Serial.print(mac[0], HEX);

1621 Serial.print(" -> ");

1622

1623 for(i = 0; i < numPairedDevices; i++){

1624

1625 for(j = 0; j < Bluetooth_MAC_SIZE &&

savedMac[i][j] == mac[j]; j++);

1626 if(j == Bluetooth_MAC_SIZE){ //match

1627

1628 Serial.print("{");

1629 for(j = 0; j < Bluetooth_LINK_KEY_SIZE; j++){

1630

1631 Serial.print(" ");

1632 Serial.print(savedKey[i][j], HEX);

1633 buf[j] = savedKey[i][j];

1634 }

1635 Serial.println(" }");

1636 return 1;

1637 }

1638 }

1639 Serial.println("FAIL");

1640 return 0;

1641 }

2012/7/16 横浜android PF部 33

Page 34: Adk2012

adkBtConnectionRequest

1588 static char

adkBtConnectionRequest(const uint8_t*

mac, uint32_t devClass, uint8_t linkType){

//return 1 to accept

1589

1590 Serial.print("Accepting connection

from ");

1591 Serial.print(mac[5], HEX);

1592 Serial.print(":");

1593 Serial.print(mac[4], HEX);

1594 Serial.print(":");

1595 Serial.print(mac[3], HEX);

1596 Serial.print(":");

1597 Serial.print(mac[2], HEX);

1598 Serial.print(":");

1599 Serial.print(mac[1], HEX);

1600 Serial.print(":");

1601 Serial.println(mac[0], HEX);

1602 return 1;

1603 }

1604

2012/7/16 横浜android PF部 34

Page 35: Adk2012

adkBtLinkKeyCreated

1643 static void adkBtLinkKeyCreated(const uint8_t* mac, const

uint8_t* buf){ //link key was just created, save it if you

want it later

1644

1645 uint8_t j;

1646

1647 Serial.print("Key created for ");

1648 Serial.print(mac[5], HEX);

1649 Serial.print(":");

1650 Serial.print(mac[4], HEX);

1651 Serial.print(":");

1652 Serial.print(mac[3], HEX);

1653 Serial.print(":");

1654 Serial.print(mac[2], HEX);

1655 Serial.print(":");

1656 Serial.print(mac[1], HEX);

1657 Serial.print(":");

1658 Serial.print(mac[0], HEX);

1659 Serial.print(" <- ");

1660

1661 Serial.print("{");

1662 for(j = 0; j < Bluetooth_LINK_KEY_SIZE; j++){

1663

1664 Serial.print(" ");

1665 Serial.print(buf[j], HEX);

1666 }

1667 Serial.print(" }");

1668

1669 if(numPairedDevices < maxPairedDevices){

1670

1671 for(j = 0; j < Bluetooth_LINK_KEY_SIZE; j++)

savedKey[numPairedDevices][j] = buf[j];

1672 for(j = 0; j < Bluetooth_MAC_SIZE; j++)

savedMac[numPairedDevices][j] = mac[j];

1673 numPairedDevices++;

1674 Serial.print("saved to slot ");

1675 Serial.print(numPairedDevices);

1676 Serial.print("/");

1677 Serial.println(maxPairedDevices);

1678 }

1679 else{

1680 Serial.println("out of slots...discaring¥n");

1681 }

1682 }

2012/7/16 横浜android PF部 35

Page 36: Adk2012

adkBtPinRequest

1684 static char adkBtPinRequest(const uint8_t* mac, uint8_t* buf){ //fill buff with PIN code, return num bytes used (16 max) return 0 to decline

1685

1686 uint8_t v, i = 0;

1687

1688 Serial.print("PIN request from ");

1689 Serial.print(mac[5], HEX);

1690 Serial.print(":");

1691 Serial.print(mac[4], HEX);

1692 Serial.print(":");

1693 Serial.print(mac[3], HEX);

1694 Serial.print(":");

1695 Serial.print(mac[2], HEX);

1696 Serial.print(":");

1697 Serial.print(mac[1], HEX);

1698 Serial.print(":");

1699 Serial.print(mac[0], HEX);

1700

1701 if(btPIN){

1702 Serial.print(" -> using pin '");

1703 Serial.print((char*)btPIN);

1704 Serial.println("'");

1705 for(i = 0; btPIN[i]; i++) buf[i] = btPIN[i];

1706 return i;

1707 }

1708 else Serial.println(" no PIN set. rejecting");

1709 return 0;

1710 }

2012/7/16 横浜android PF部 36

Page 37: Adk2012

btStart() #2

void btStart(){

L.btEnable(adkBtConnectionRequest, adkBtLinkKeyRequest,

adkBtLinkKeyCreated,adkBtPinRequest, NULL);

L.btRfcommReserveDlci(RFCOMM_DLCI_NEED_EVEN);

for(i = 0, f = -1; i < sizeof(sdpDescrADK); i++){

if(sdpDescrADK[i] == MAGIX){

if(f == -1) f = i;

else break;

}

}

sdpDescrADK[f] = dlci >> 1;

L.btRfcommRegisterPort(dlci, btAdkPortOpen, btAdkPortClose, btAdkPortRx);

L.btSdpServiceDescriptorAdd(sdpDescrADK, sizeof(sdpDescrADK));

}

2012/7/16 横浜android PF部 37

"Key request from” +MAC +KEY

“Accepting connection from“ +MAC

"Key created for “ +MAC +SLOT

"PIN request from “ +MAC +PIN

Page 38: Adk2012

btStart() #3

void btStart(){

L.btEnable(adkBtConnectionRequest, adkBtLinkKeyRequest,

adkBtLinkKeyCreated,adkBtPinRequest, NULL);

L.btRfcommReserveDlci(RFCOMM_DLCI_NEED_EVEN);

for(i = 0, f = -1; i < sizeof(sdpDescrADK); i++){

if(sdpDescrADK[i] == MAGIX){

if(f == -1) f = i;

else break;

}

}

sdpDescrADK[f] = dlci >> 1;

L.btRfcommRegisterPort(dlci, btAdkPortOpen, btAdkPortClose, btAdkPortRx);

L.btSdpServiceDescriptorAdd(sdpDescrADK, sizeof(sdpDescrADK));

}

2012/7/16 横浜android PF部 38

Page 39: Adk2012

btRfcommReserveDlci

408 #define RFCOMM_DLCI_PREFERENCE_NONE 0x80 //use this param to the below

409 #define RFCOMM_DLCI_NEED_EVEN 0x81

410 #define RFCOMM_DLCI_NEED_ODD 0x82

411

412 uint8_t btRfcommReserveDlci(uint8_t preference){

413

414 uint8_t start = 0, end = 64, step = 2;

415

416 if(preference == RFCOMM_DLCI_PREFERENCE_NONE) step = 1;

417 else if(preference == RFCOMM_DLCI_NEED_EVEN);

418 else if(preference == RFCOMM_DLCI_NEED_ODD) start++;

419 else{

420

421 start = preference;

422 end = preference + 1;

423 step = 1;

424 }

425

426 while(start < end && (reserved & (1ULL << ((uint64_t)start)))) start += step;

427

428 if(start >= end) return 0; //we failed

429

430 reserved |= (1ULL << ((uint64_t)start));

431

432 return start;

433 }

2012/7/16 横浜android PF部 39

Page 40: Adk2012

btStart() #4

void btStart(){

L.btEnable(adkBtConnectionRequest, adkBtLinkKeyRequest,

adkBtLinkKeyCreated,adkBtPinRequest, NULL);

L.btRfcommReserveDlci(RFCOMM_DLCI_NEED_EVEN);

for(i = 0, f = -1; i < sizeof(sdpDescrADK); i++){

if(sdpDescrADK[i] == MAGIX){

if(f == -1) f = i;

else break;

}

}

sdpDescrADK[f] = dlci >> 1;

L.btRfcommRegisterPort(dlci, btAdkPortOpen, btAdkPortClose, btAdkPortRx);

L.btSdpServiceDescriptorAdd(sdpDescrADK, sizeof(sdpDescrADK));

}

2012/7/16 横浜android PF部 40

Page 41: Adk2012

btRfcommRegisterPort

366 void btRfcommRegisterPort(uint8_t dlci, BtRfcommPortOpenF oF,

BtRfcommPortCloseF cF, BtRfcommPortRxF rF){

367

368 if(dlci >= NUM_DLCIs) return; //no such DLCI;

369

370 gPortHandlers[dlci].oF = oF; // OPENハンドラ

371 gPortHandlers[dlci].cF = cF; // CLOSE ハンドラ

372 gPortHandlers[dlci].rF = rF; // 受信ハンドラ

373 }

2012/7/16 横浜android PF部 41

受信ハンドラを設定

データを受け取るとCallBack

Page 42: Adk2012

btAdkPortRx

1527 static void btAdkPortRx(void* port, uint8_t dlci, const uint8_t*

data, uint16_t sz){

1528

1529 uint8_t reply[MAX_PACKET_SZ];

1530 uint32_t i;

1531 uint8_t seq, cmd;

1532 uint16_t cmdSz;

1533 uint8_t* ptr;

1534

1535 while(sz || bufPos){

1536

1537 uint16_t sendSz = 0;

1538

1539 //copy to buffer as much as we can

1540 while(bufPos < MAX_PACKET_SZ && sz){

1541 cmdBuf[bufPos++] = *data++;

1542 sz--;

1543 }

1544

1545 //see if a packet exists

1546 if(bufPos < 4) return; // too small to be a packet ->

discard

1547 cmd = cmdBuf[0];

1548 seq = cmdBuf[1];

1549 cmdSz = cmdBuf[3];

1550 cmdSz <<= 8;

1551 cmdSz += cmdBuf[2];

1552

1553 if(bufPos - 4 < cmdSz) return; //not entire command

received yet

1554

1555 sendSz = adkProcessCommand(cmd, cmdBuf + 4,

cmdSz, 1, reply + 4, MAX_PACKET_SZ - 4);

1556 if(sendSz){

1557

1558 reply[0] = cmd | CMD_MASK_REPLY;

1559 reply[1] = seq;

1560 reply[2] = sendSz;

1561 reply[3] = sendSz >> 8;

1562 sendSz += 4;

1563

1564 L.btRfcommPortTx(port, dlci, reply, sendSz);

1565 }

1566

1567 //adjust buffer as needed

1568 for(i = 0; i < bufPos - cmdSz - 4; i++){

1569 cmdBuf[i] = cmdBuf[i + cmdSz + 4];

1570 }

1571 bufPos = i;

1572 }

1573 }

2012/7/16 横浜android PF部 42

受け取ったデータをadkProcessCommandに渡す

Page 43: Adk2012

adkProcessCommand

1274 static uint16_t adkProcessCommand(uint8_t cmd, const uint8_t* dataIn, uint16_t sz, char fromBT, uint8_t* reply, uint16_t maxReplySz){ //returns num bytes to reply with (or 0 for no reply)

1288 //process packet

1289 switch(cmd){

1290

1291 case BT_CMD_GET_PROTO_VERSION:

1292 {

1293 reply[sendSz++] = BT_PROTO_VERSION_CURRENT;

1294 }

1295 break;

1296

1297 case BT_CMD_GET_SENSORS:

1298 {

1299 putLE32(reply, &sendSz, hTemp);

1300 putLE32(reply, &sendSz, hHum);

1301 putLE32(reply, &sendSz, bPress);

1302 putLE32(reply, &sendSz, bTemp);

1303 putLE16(reply, &sendSz, prox[0]);

1304 putLE16(reply, &sendSz, prox[1]);

1305 putLE16(reply, &sendSz, prox[3]);

1306 putLE16(reply, &sendSz, prox[4]);

1307 putLE16(reply, &sendSz, prox[5]);

1308 putLE16(reply, &sendSz, prox[2]);

1309 putLE16(reply, &sendSz, prox[6]);

1310 putLE16(reply, &sendSz, accel[0]);

1311 putLE16(reply, &sendSz, accel[1]);

1312 putLE16(reply, &sendSz, accel[2]);

1313 putLE16(reply, &sendSz, mag[0]);

1314 putLE16(reply, &sendSz, mag[1]);

1315 putLE16(reply, &sendSz, mag[2]);

1316 }

1317 break;

1318

1319 case BT_CMD_FILE_LIST:

1320 {

1321

1322 if(sz){ //reset

1323

1324 if(*dirP) L.fatfsCloseDir(*dirP);

1325 if(L.fatfsOpenDir(dirP, (char*)dataIn)) *dirP = 0;

1326 }

1327 if(*dirP){

1328

2012/7/16 横浜android PF部 43

アプリ層のコマンドを処理

センサの値をAndroidに送信

Page 44: Adk2012

adkProcessCommand

1177 #define BT_CMD_GET_PROTO_VERSION 1 // () -> (u8 protocolVersion)

1178 #define BT_CMD_GET_SENSORS 2 // () -> (sensors:

i32,i32,i32,i32,u16,u16,u16,u16,u16,u16,u16,i16,i16,i16,i16,i16,i16)

1179 #define BT_CMD_FILE_LIST 3 // FIRST: (char name[]) -> (fileinfo or single zero byte)

OR NONLATER: () -> (fileinfo or empty or single zero byte)

1180 #define BT_CMD_FILE_DELETE 4 // (char name[0-255)) -> (char success)

1181 #define BT_CMD_FILE_OPEN 5 // (char name[0-255]) -> (char success)

1182 #define BT_CMD_FILE_WRITE 6 // (u8 data[]) -> (char success)

1183 #define BT_CMD_FILE_CLOSE 7 // () -> (char success)

1184 #define BT_CMD_GET_UNIQ_ID 8 // () -> (u8 uniq[16])

1185 #define BT_CMD_BT_NAME 9 // (char name[]) -> () OR () -> (char name[])

1186 #define BT_CMD_BT_PIN 10 // (char PIN[]) -> () OR () -> (char PIN[])

1187 #define BT_CMD_TIME 11 // (timespec) -> (char success)) OR () > (timespec)

1188 #define BT_CMD_SETTINGS 12 // () -> (alarm:u8,u8,u8,brightness:u8,color:u8,u8,u8:volume:u8) or

(alarm:u8,u8,u8,brightness:u8,color:u8,u8,u8:volume:u8) > (char success)

1189 #define BT_CMD_ALARM_FILE 13 // () -> (char file[0-255]) OR (char file[0-255]) > (char success)

1190 #define BT_CMD_GET_LICENSE 14 // () -> (u8 licensechunk[]) OR () if last sent

1191 #define BT_CMD_DISPLAY_MODE 15 // () -> (u8) OR (u8) -> ()

1192 #define BT_CMD_LOCK 16 // () -> (u8) OR (u8) -> ()

2012/7/16 横浜android PF部 44

コマンド一覧

Page 45: Adk2012

adkProcessCommand

1471 case BT_CMD_GET_LICENSE:

1472 {

1473 static const uint32_t maxPacket = MAX_PACKET_SZ - 10; //seems reasonable

1474

1475 if(*licPos >= sizeof(gzippedLicences)){ //send terminator

1476 reply[sendSz++] = 0;

1477 *licPos = 0;

1478 }

1479 else{

1480

1481 uint32_t left = sizeof(gzippedLicences) - *licPos;

1482 if(left > maxPacket) left = maxPacket;

1483 reply[sendSz++] = 1;

1484 while(left--) reply[sendSz++] = gzippedLicences[(*licPos)++];

1485 }

1486 }

1487 break;

2012/7/16 横浜android PF部 45

ライセンスの送信??

Page 46: Adk2012

processUSBAccessory

1772 // USB accessory

1773 static void processUSBAccessory()

1774 {

1781 int res = L.accessoryReceive(receiveBuf, sizeof(receiveBuf));

1782 if (res >= 4) {

1783 uint8_t cmd = receiveBuf[0];

1784 uint8_t seq = receiveBuf[1];

1785 uint16_t size = receiveBuf[2] | receiveBuf[3] << 8;

1786

1792 uint16_t replylen = adkProcessCommand(cmd, receiveBuf + 4, size, 0, reply + 4, MAX_PACKET_SZ - 4);

1793 if (replylen > 0) {

1794 reply[0] = cmd | CMD_MASK_REPLY;

1795 reply[1] = seq;

1796 reply[2] = replylen;

1797 reply[3] = replylen >> 8;

1798 replylen += 4;

1799

1800 dbgPrintf("ADK: USB: sending %d bytes¥n", replylen);

1801 L.accessorySend(reply, replylen);

1802 }

1803 }

1804 }

1805

2012/7/16 横浜android PF部 46

USBの接続も、アプリ層のコマンド処理は同じ関数で

Page 47: Adk2012

ADK Connection over Bluetooth

のまとめ

BTモジュールとの接続は5ピン

TX,RX,CTS,RTS,RST

HCIレベルで操作

ペアリング、PINの処理ほか

BTモジュールはcc256xを前提

cc256xのROMコードを抱き込み

HCIレベルの互換性は不明

アプリ層のコマンドはBTとUSBと共通

2012/7/16 横浜android PF部 47

Page 48: Adk2012

ADK Connection over USB

ADK L; void setup() { L.adkInit();

L.usbSetAccessoryStringVendor(...);

L.usbSetAccessoryStringName(...);

L.usbSetAccessoryStringLongname(...);

L.usbSetAccessoryStringVersion(...);

L.usbSetAccessoryStringUrl(...);

L.usbSetAccessoryStringSerial(...);

L.usbStart();

}

2012/7/16 横浜android PF部 48

http://developer.android.com/tools/adk/adk2.html#adk-conn

ADK1.0と同じ

Page 49: Adk2012

USB Audio Dock Implementation

ADK L;

void setup() {

L.audioInit(); L.usbh_init()

L.usbStart();

}

void loop(void)

{

...

L.adkEventProcess(); //let the adk framework do its thing

...

}

2012/7/16 49 横浜android PF部

http://developer.android.com/tools/adk/adk2.html#audio-dock

Page 50: Adk2012

L.audioInit()を読んでみる

ADK L;

void setup() {

L.audioInit(); // オーディオの初期化

L.usbh_init() // USBの初期化

L.usbStart(); // USBの起動

}

void loop(void)

{

...

L.adkEventProcess(); // アプリケーション定義の

... // コマンド処理

}

2012/7/16 50 横浜android PF部

Page 51: Adk2012

L.audioInit()→audioInit()

libraries/ADK/Audio.c

36 void audioInit(void)

37 {

38 PMC_EnablePeripheral(ID_PWM); // PWMCをPON

39 PWMC_ConfigureClocks(0, 0, BOARD_MCK);

40 PWMC_ConfigureChannel(PWM, 0, PWM_CMR_CPRE_MCK, 0, 0);

41 PWMC_ConfigureEventLineMode(PWM, 0, 1);

43 audioSetSample(AUDIO_NULL, DEFAULT_AUDIO_SAMPLERATE);

45 PWMC_EnableChannel(PWM, 0);

46 PMC_EnablePeripheral(ID_DACC); // DACCをPON

47 DACC_Initialize(DACC, ID_DACC, 1, 4, 0, 0, BOARD_MCK, 8,

DACC_CHANNEL_0, 0, 16 );

48 DACC_EnableChannel(DACC, DACC_CHANNEL_0);

49 }

PMC: Power Management Controller

PWMC: Plus Width Modulation Controller

DACC: Digital Audio Converter Controller

2012/7/16 51 横浜android PF部

Page 52: Adk2012

L.audioInit() →audioSetSample()

#define BOARD_MCK 84000000ULL

73 void audioSetSample(int source, uint32_t samplerate)

74 {

75 sampleRates[source] = samplerate;

77 // if we're not the highest priority audio source, dont set it

78 if (source != highestPriAudio())

79 return;

81 samplerate =

(BOARD_MCK + samplerate - 1) / samplerate;

//err on the side of slower audio

83 PWMC_SetPeriod(PWM, 0, samplerate);

84 PWMC_ConfigureComparisonUnit(PWM, 0, (samplerate + 1) >> 1, 1);

85 }

2012/7/16 52 横浜android PF部

DAC(PWMで代用)の初期化

Page 53: Adk2012

L.audioInit()

#define DEFAULT_AUDIO_SAMPLERATE 44100

static uint32_t sampleRates[AUDIO_MAX_SOURCE];

static uint32_t audioActive; // bitmap of active audio sources

#define AUDIO_NULL 0

#define AUDIO_USB 1

#define AUDIO_BT 2

#define AUDIO_ALARM 3

#define AUDIO_MAX_SOURCE 4

2012/7/16 53 横浜android PF部

Page 54: Adk2012

L.usbh_init()を読んでみる

ADK L;

void setup() {

L.audioInit(); L.usbh_init()

L.usbStart();

}

void loop(void)

{

...

L.adkEventProcess(); //let the adk framework do its thing

...

}

2012/7/16 54 横浜android PF部

Page 55: Adk2012

L.usbh_init()

libraries/ADK/Usbh.c

void usbh_init(void)

{

usbh.state = USBH_DISABLED;

pmc_enable_periph_clk(ID_UOTGHS);

/* Enable UPLL 480 MHz */

/* Wait that UPLL is considered locked by the PMC */

/* USB clock register: USB Clock Input is UTMI PLL */

PMC->PMC_USB = PMC_USB_USBS | PMC_USB_USBDIV(0);

PMC->PMC_SCER = PMC_SCER_UOTGCLK;

NVIC_SetPriority(UOTGHS_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

NVIC_EnableIRQ(UOTGHS_IRQn);

coopSpawn(&usbhTask, NULL, 2048);

Usb_freeze_clock();

}

2012/7/16 55 横浜android PF部

USBの電源とクロックを設定

Page 56: Adk2012

L.usbh_init()

USBH_DEVICE_TRY_ACCESSORY

DEVICE_TO_HOST | TYPE_VENDOR,0x33, version

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 1, "Google, Inc.“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 2, "DemoKit“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 3, "DemoKit ADK2012“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 4, "2.0“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5,http://www.android.com

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5, "0000000012345678“

HOST_TO_DEVICE | TYPE_VENDOR,0x3a, 1

HOST_TO_DEVICE | TYPE_VENDOR,0x35, 0

2012/7/16 56 横浜android PF部

御約束の呪文

Page 57: Adk2012

L.usbh_init()

USBH_DEVICE_TRY_ACCESSORY

DEVICE_TO_HOST | TYPE_VENDOR,0x33, version

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 1, "Google, Inc.“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 2, "DemoKit“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 3, "DemoKit ADK2012“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 4, "2.0“

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5,http://www.android.com

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5, "0000000012345678“

HOST_TO_DEVICE | TYPE_VENDOR,0x3a, 1

HOST_TO_DEVICE | TYPE_VENDOR,0x35, 0

2012/7/16 57 横浜android PF部

1か所追加これがAudio機能を呼び出す

Page 58: Adk2012

L.usbh_init()→usbTask()

/* for the coop threading system */

static void usbhTask(void* ptr)

{

for (;;) {

coopYield();

usbh_work();

accessory_work();

}

}

2012/7/16 58 横浜android PF部

Page 59: Adk2012

usbh_work()

755 void usbh_work(void)

USBH_INIT

USBH_DEVICE_UNATTACHED

USBH_WAIT_FOR_DEVICE

USBH_DEVICE_ATTACHED

USBH_DEVICE_ATTACHED_SOF_WAIT

USBH_DEVICE_ATTACHED_RESET

USBH_DEVICE_ATTACHED_RESET_WAIT

USBH_DEVICE_ATTACHED_POST_RESET_WAIT

USBH_DEVICE_ATTACHED_QUERY

この時点でVendorとProductがみえるので次で

確認

USBH_DEVICE_TRY_ACCESSORY

0x18d12d00: // accessory

0x18d12d01: // accessory + adb

0x18d12d02: // audio

0x18d12d03: // audio + adb

0x18d12d04: // accessory + audio

0x18d12d05: // accessory + audio + adb

TRUE FALSE

2012/7/16 59 横浜android PF部

Page 60: Adk2012

usbh_work() USBH_DEVICE_TRY_ACCESSORY

DEVICE_TO_HOST | TYPE_VENDOR,0x33, versionの取得

versionが1又は2以外ならstateをUSBH_DEVICE_IDLEへ

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 1, “Google, Inc.”を送る

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 2, “DemoKit”送る

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 3, “DemoKit ADK2012”送る

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 4, “2.0”送る

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5, http://www.android.com送る

HOST_TO_DEVICE | TYPE_VENDOR,0x34, 5, “0000000012345678“送る

HOST_TO_DEVICE | TYPE_VENDOR,0x3a, 1 Auidoモードを要求

1:mono, 2:stereo

HOST_TO_DEVICE | TYPE_VENDOR,0x35, 0 AccessoryをON

stateをUSBH_DEVICE_IDLEへ

•以上の処理で、Android側が別のVendor,ProductのUSB ディバイスに変化して、新たなUSBデイバイスの検出処理が開始される

•コード0x3aがADK2.0で追加された

2012/7/16 60 横浜android PF部

これ曲者

Page 61: Adk2012

usbh_work()

755 void usbh_work(void)

USBH_INIT

USBH_DEVICE_UNATTACHED

USBH_WAIT_FOR_DEVICE

USBH_DEVICE_ATTACHED

USBH_DEVICE_ATTACHED_SOF_WAIT

USBH_DEVICE_ATTACHED_RESET

USBH_DEVICE_ATTACHED_RESET_WAIT

USBH_DEVICE_ATTACHED_POST_RESET_WAIT

USBH_DEVICE_ATTACHED_QUERY

この時点でVendorとProductがみえるので次で

確認

USBH_DEVICE_TRY_ACCESSORY

0x18d12d00: // accessory

0x18d12d01: // accessory + adb

0x18d12d02: // audio

0x18d12d03: // audio + adb

0x18d12d04: // accessory + audio

0x18d12d05: // accessory + audio + adb

TRUE FALSE

2012/7/16 61 横浜android PF部

Page 62: Adk2012

usbh_work() USBH_DEVICE_ACCESSORY_INIT

755 void usbh_work(void)

USBH_INIT

USBH_DEVICE_UNATTACHED

USBH_WAIT_FOR_DEVICE

USBH_DEVICE_ATTACHED

USBH_DEVICE_ATTACHED_SOF_WAIT

USBH_DEVICE_ATTACHED_RESET

USBH_DEVICE_ATTACHED_RESET_WAIT

USBH_DEVICE_ATTACHED_POST_RESET_WAIT

USBH_DEVICE_ATTACHED_QUERY

USBH_DEVICE_ACCESSORY_INIT

USBH_DEVICE_ACCESSORY

この時点でVendorとProductがみえる

Accessoryの

初期化

TRUE FALSE

0x18d12d00: // accessory

0x18d12d01: // accessory + adb

0x18d12d02: // audio

0x18d12d03: // audio + adb

0x18d12d04: // accessory + audio

0x18d12d05: // accessory + audio + adb

2012/7/16 62 横浜android PF部

Page 63: Adk2012

usbh_work() USBH_DEVICE_ACCESSORY_INIT

set configuration 1

○ HOST_TO_DEVICE,SETUP_SET_CONFIGURATION,

accessory_init(&usbh.dev)を呼んで

○ USBH_DEVICE_ACCESSORYへ

2012/7/16 63 横浜android PF部

Page 64: Adk2012

L.usbh_init()→accessory_init()

accessory_init()

デイバイスのコンフィギュレーションディスクリプタを読み

If typeが DESCRIPTOR_INTERFACE なら

If num_ep == 2 && class == 0xff &&

sub_class == 0xff &&(inendp <= 0 || outendp <= 0) なら

→accessory interface

if class == 0x1(Audio) &&sub_class == 0x2(Streaming) && num_ep > 0 なら

→interface is audio

If type がDESCRIPTOR_ENDPOINT なら

acc_interfaceのinendp, outendpを設定

audio_interfaceのaudioendpを設定

2012/7/16 64 横浜android PF部

Page 65: Adk2012

usbh_work() USBH_DEVICE_TRY_ACCESSORY

755 void usbh_work(void)

USBH_INIT

USBH_DEVICE_UNATTACHED

USBH_WAIT_FOR_DEVICE

USBH_DEVICE_ATTACHED

USBH_DEVICE_ATTACHED_SOF_WAIT

USBH_DEVICE_ATTACHED_RESET

USBH_DEVICE_ATTACHED_RESET_WAIT

USBH_DEVICE_ATTACHED_POST_RESET_WAIT

USBH_DEVICE_ATTACHED_QUERY

USBH_DEVICE_TRY_ACCESSORY

USBH_DEVICE_ACCESSORY_INIT

USBH_DEVICE_IDLE

0x18d12d00: // accessory

0x18d12d01: // accessory + adb

0x18d12d02: // audio

0x18d12d03: // audio + adb

0x18d12d04: // accessory + audio

0x18d12d05: // accessory + audio + adb

この時点でVendorとProductがみえる

TRUE FALSE

Accessoryに

変更を試みる Accessoryの

初期化

USBH_DEVICE_IDLE

2012/7/16 65 横浜android PF部

Page 66: Adk2012

L.usbh_init()→accessory_init()

設定されるendpoint inendp, outendp, audioendp

呼び出す処理 audioOn(AUDIO_USB, audsamplerate);

pmc_enable_periph_clk(ID_SMC);

SETUP_SET_INTERFACEを送信

struct usb_setup_packet setup = (struct usb_setup_packet){

USB_SETUP_DIR_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE,

SETUP_SET_INTERFACE,

audio_alternate_setting,

audiointerface,

0

};

usbh_send_setup(&setup, NULL, false);

usbh_queue_iso_transfer(audiopipe, audrecvbuf, sizeof(audrecvbuf), &audio_iso_callback, NULL);

2012/7/16 66 横浜android PF部

ISO転送の起動、受信データのコールバックを設定

Page 67: Adk2012

16ビットStereoで受け取ったデータを12ビットmonoに変更

Iso転送の完了割り込みで呼ばれる

Underrun,overrunの調整

process_audio(audbuf + curraudbuf * AUDBUFSIZE +

audbufpos, buf, pos); /* take 16 bit stereo signed samples and downconvert in place to mono 12

bit unsigned */

size_t process_audio(uint16_t *outbuf, uint16_t *inbuf, size_t len)

audio_iso_callback()

2012/7/16 67 横浜android PF部

Page 68: Adk2012

ADK2/usbh.c

switch ((usbh.dev.vid << 16) | usbh.dev.pid) {

case 0x18d12d00: // accessory

case 0x18d12d01: // accessory + adb

case 0x18d12d02: // audio

case 0x18d12d03: // audio + adb

case 0x18d12d04: // accessory + audio

case 0x18d12d05: // accessory + audio + adb

2012/7/16 68 横浜android PF部

IDが増えてます

Page 69: Adk2012

2012/7/16 横浜android PF部 69

Page 70: Adk2012

こんなやつ

2012/7/16 横浜android PF部 70

http://www.slideshare.net/magoroku15/poormans-adk-11350123

もうすぐ5000view

これはADK1.0互換

Audioがいらなければこれでもできると思う

Page 71: Adk2012

仕様案

センサ、LEDは載せない 必要になった時点で載せればよい

ADK2012の本質はBT,Audio,HID

Bluetooth 欲しい

USBオーディオ PCM 16bit 44.1KHz stereoで出せれば立派なトランスポート

iPhoneは機器認証部品が1社独占のライセンス

HOST + isochronous のサポート

できるだけ安く できればブレッドボードで

2012/7/16 横浜android PF部 71

Page 72: Adk2012

MCU

NXP のLPC1769

Coretex M3 120MHz Flash 512Kb SRAM 64Kb

Programmer 付き

安価に秋月で入手可能 2500円

I2SでオーディオDACを繋ぎたい

2012/7/16 横浜android PF部 72

Page 73: Adk2012

プログラミング環境

Eclipse ベースの LPCXpresso

ROMサイズで128Kbまで無償

2012/7/16 横浜android PF部 73

Page 74: Adk2012

フレームワーク

直叩きでも出来るけど、とりあえず

nxpUSBlib http://www.lpcware.com/content/project/nxpusblib

HOSTモードサポート

Isochronousをサポート

○ UAC(USB Audio Class)のUSB 出力のサンプルあり

ADK1.0のサンプル添付

2012/7/16 横浜android PF部 74

Page 75: Adk2012

BT モジュール

USBドングル or cc256x

普通のUSBドングルはHCI

BOMにあったLBMA1BGUG2はcc256xをモジュールに加工?

まずは、cc256xで考える

cc256xの入手性は

PANASONIC製のモジュールを見つけた

DigikeyはJP向けに出てこない(輸出できない)

Mouser はオーダは直後にキャンセルされた

chip one stopなんとか入手

2012/7/16 横浜android PF部 75

Page 76: Adk2012

モジュールだけどBGA

2012/7/16 横浜android PF部 76

このパッドの内VCC,GND,RST,TX,RX,RTS,CTSの

7本の細線をつけられるか?自信なし。

→評価ボードを追加で発注した

技適は当然ありませんorz

まだ電源は入れてないのでヨロシクね

Page 77: Adk2012

BTは後回しにしてUSBで作業開始

nxpUSBlibに付属のADK1.0ソースをベースに

Linux上のlibUSBでコントロール通信

ACCESSORY + AUDIO に切り替えて

Lsusb -v

2012/7/16 横浜android PF部 77

Page 78: Adk2012

Device Descriptor

Bus 003 Device 016: ID 18d1:2d04

Device Descriptor:

bLength 18

bDescriptorType 1

bcdUSB 2.00

bDeviceClass 0 (Defined at Interface level)

bDeviceSubClass 0

bDeviceProtocol 0

bMaxPacketSize0 64

idVendor 0x18d1

idProduct 0x2d04

bcdDevice 2.16

iManufacturer 2 samsung

iProduct 3 Galaxy Nexus

iSerial 4 014994750801300D

bNumConfigurations 1

case 0x18d12d00: // accessory

case 0x18d12d01: // accessory + adb

case 0x18d12d02: // audio

case 0x18d12d03: // audio + adb

case 0x18d12d04: // accessory + audio

case 0x18d12d05: // accessory + audio + adb

Page 79: Adk2012

Configuration Descriptor

Configuration Descriptor:

bLength 9

bDescriptorType 2

wTotalLength 133

bNumInterfaces 3

bConfigurationValue 1

iConfiguration 0

bmAttributes 0x80 (Bus Powered)

MaxPower 500mA

これが曲者、AudioモードでSTREOを指定するとAUDIOが見えず、この値が32?で、Interfaceも1に

Page 80: Adk2012

Interface#1 – 従来のADK部分

Endpoint Descriptor:

bLength 7

bDescriptorType 5

bEndpointAddress 0x81 EP 1 IN

bmAttributes 2

Transfer Type Bulk

Synch Type None

Usage Type Data

wMaxPacketSize 0x0200 1x 512 bytes

bInterval 0

Endpoint Descriptor:

bLength 7

bDescriptorType 5

bEndpointAddress 0x02 EP 2 OUT

bmAttributes 2

Transfer Type Bulk

Synch Type None

Usage Type Data

wMaxPacketSize 0x0200 1x 512 bytes

bInterval 0

Interface Descriptor:

bLength 9

bDescriptorType 4

bInterfaceNumber 0

bAlternateSetting 0

bNumEndpoints 2

bInterfaceClass 255 Vendor Specific Class

bInterfaceSubClass 255 Vendor Specific Subclass

bInterfaceProtocol 0

iInterface 6 Android Accessory Interface

Page 81: Adk2012

Interface#2 – AudioControl

Interface Descriptor:

bLength 9

bDescriptorType 4

bInterfaceNumber 1

bAlternateSetting 0

bNumEndpoints 0

bInterfaceClass 1 Audio

bInterfaceSubClass 1 Control Device

bInterfaceProtocol 0

iInterface 0

AudioControl Interface Descriptor:

bLength 10

bDescriptorType 36

bDescriptorSubtype 1 (HEADER)

bcdADC 1.00

wTotalLength 40

bInCollection 2

baInterfaceNr( 0) 0

baInterfaceNr( 1) 1

AudioControl Interface Descriptor:

bLength 12

bDescriptorType 36

bDescriptorSubtype 2 (INPUT_TERMINAL)

bTerminalID 1

wTerminalType 0x0201 Microphone

bAssocTerminal 0

bNrChannels 2

wChannelConfig 0x0003

Left Front (L)

Right Front (R)

iChannelNames 0

iTerminal 0

AudioControl Interface Descriptor:

bLength 9

bDescriptorType 36

bDescriptorSubtype 3 (OUTPUT_TERMINAL)

bTerminalID 3

wTerminalType 0x0101 USB Streaming

bAssocTerminal 2

bSourceID 2

iTerminal 0

AudioControl Interface Descriptor:

bLength 9

bDescriptorType 36

bDescriptorSubtype 6 (FEATURE_UNIT)

bUnitID 2

bSourceID 1

bControlSize 2

bmaControls( 0) 0x00

bmaControls( 0) 0x00

iFeature 0

Page 82: Adk2012

Interface#3 – AudioStream

Interface Descriptor:

bLength 9

bDescriptorType 4

bInterfaceNumber 2

bAlternateSetting 1

bNumEndpoints 1

bInterfaceClass 1 Audio

bInterfaceSubClass 2 Streaming

bInterfaceProtocol 0

iInterface 0

AudioStreaming Interface Descriptor:

bLength 7

bDescriptorType 36

bDescriptorSubtype 1 (AS_GENERAL)

bTerminalLink 1

bDelay 1 frames

wFormatTag 1 PCM

AudioStreaming Interface Descriptor:

bLength 11

bDescriptorType 36

bDescriptorSubtype 2 (FORMAT_TYPE)

bFormatType 1 (FORMAT_TYPE_I)

bNrChannels 2

bSubframeSize 2

bBitResolution 16

bSamFreqType 1 Discrete

tSamFreq[ 0] 44100

Endpoint Descriptor:

bLength 9

bDescriptorType 5

bEndpointAddress 0x82 EP 2 IN

bmAttributes 13

Transfer Type Isochronous

Synch Type Synchronous

Usage Type Data

wMaxPacketSize 0x0100 1x 256 bytes

bInterval 4

bRefresh 0

bSynchAddress 0

AudioControl Endpoint Descriptor:

bLength 7

bDescriptorType 37

bDescriptorSubtype 1 (EP_GENERAL)

bmAttributes 0x01

Sampling Frequency

bLockDelayUnits 1 Milliseconds

wLockDelay 1 Milliseconds

Page 83: Adk2012

USBで繋ぐには

最初のInterfaceはADK1.0と同じ手順で

VID,PID他,classなど,細かな変更が必要

2,3番目のInterfaceはnxpUSBlibのAudioConfig

用のライブラリを使ってConfig

2012/7/16 横浜android PF部 83

Page 84: Adk2012

現状

Version2のプロトコルでネゴシエーション

Audio Dockモードでコンフィグ

Isochronous 転送 USBバス上は転送を確認

API経由でデータが受け取れない

2012/7/16 横浜android PF部 84

Page 85: Adk2012

USBのキャプチャ

2012/7/16 横浜android PF部 85

Page 86: Adk2012

Debug console

AOA Demo Running

Device Unattached.

Device Attached.

Getting Device Data.

Android Device Detected - Non-Accessory mode.

Device Unattached.

Device Attached.

Getting Device Data.

Audio mode disable

Android Device Detected - Accessory mode.

Getting Config Data.

HOST_GETCONFIG_Successful

156 268467540

endpoint >> 128

endpoint >> 0

Input Audio Interface is initialized

2012/7/16 横浜android PF部 86

最初はMPTが見える

呪文を唱える

別のdeviceが接続されて

初期化完了

Page 87: Adk2012

今後

Audio Dockを作る Isochronousを何とか受け取れるようにする

I2SでオーディオDACに繋ぐ

BTで繋ぐ USB,CCの両面で

CCの場合はファームを流し込む形では技適取れないよなぁ、

Bomコスト3000円でCCにファーム流しこみ済で技適取得モジュール作ったら買う人いる?

@10,000円で海外含めて10,000台出るなら……….. 無理ね。

HIDを試す Audioと同様に呪文を唱えるとHIDとしてアクセサリを接続できるみたい

キーボードとか、タブレットとか軽く作れるんじゃないかな

2012/7/16 横浜android PF部 87

Page 88: Adk2012

付録

2012/7/16 横浜android PF部 88

Page 89: Adk2012

USBの転送

4 種類の転送方式

Interrupt転送 Periodic 転送

少量のデータを一定の間隔で転送

転送の間隔は、対象となるデバイス毎に決める

Isochronous転送 一定のレート・周期で転送

Periodic 転送

Control転送 Configuration情報、コマンド情報、Status情報を転送する方式

Bulk転送 大量のデータを転送する方式

2012/7/16 89 横浜android PF部

Page 90: Adk2012

EDとTD

ED EndpointDescriptor

転送の対象となるEndpointを管理

デバイスのアドレス、Endpoint の番号、デバイスのSpeed、MaxPacketSize などを含む

TD TransferDescriptor

Endpoint に転送するデータパケットについての情報を管理

PID、データトグル情報、メモリのアドレス、転送完了時のステータス情報を含む

HCD Host Controller Driver

ED、TD 群を転送タイプ毎にList という形に纏めて、

List の先頭アドレスをHC に渡します。

List の先頭アドレスの受けわたし方

○ HC の内部レジスタを介する方法、

○ メモリ HostControllerCommunicationArea(HCCA)を介する方法

HC Host Controller

転送処理を完了したTD をDoneQueueにリスト化

DoneQueueの先頭アドレスをHCDに通知

2012/7/16 90 横浜android PF部

Page 91: Adk2012

Non-Periodic 転送用List

Bulk転送、Control転送用のListの形式

Bulk転送用HeadPointer HcBulkHeadED

Control転送用HeadPointer HcControlHeadED

Head Pointer E

D

TD

TD

TD

E

D

TD

E

D

TD

TD

2012/7/16 91 横浜android PF部

Page 92: Adk2012

Periodic 転送用List

32個のHeadPointer

32msで一周

全てのHeadPointerにEDをつないでおくと、1回/1msで参照

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

Head Pointer

2012/7/16 92 横浜android PF部

Page 93: Adk2012

Endpoint参照の周期

32ms毎に参照

4ms毎に参照

1ms毎に参照

0

17

8

1

2

3

4

5

6

7

9

10

11

12

13

14

15

16

24

20

28

18

26

22

30

25

21

29

19

27

23

31

32 16 8 4 2 1

Endpoint Poll Interval (ms)

Interrupt

Head

Pointers

Interrupt

Endpoint

Descriptor

2012/7/16 93 横浜android PF部

Page 94: Adk2012

HcBulkHeadED

HcControlHeadED

InterruptHeadED#0

InterruptHeadED#1

InterruptHeadED#2

InterruptHeadED#3

InterruptHeadED#4

InterruptHeadED#5

InterruptHeadED#6

InterruptHeadED#1

0 InterruptHeadED#3

1

32個全てから参照する事で1ms毎に参

Interrupt転送 Isochronous転送

bulk転送

control転送

2012/7/16 94 横浜android PF部

Page 95: Adk2012

ED:Endpoint Descripter 3 2 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0

1 6 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0

Dword 0 — MPS F K S D EN FA

Dword 1 TD Queue Tail Pointer (TailP) —

Dword 2 TD Queue Head Pointer (HeadP) 0 C H

Dword 3 Next Endpoint Descriptor (NextED) —

• FA USBディバイスのアドレス

• EN endpoint番号

• D 転送方向

• S 速度(0:full 1:low)

• K Skip

• F TDタイプ(0:GTD 1:ITD)

• MPS パケットサイズ

• TailP 終端EDのアドレス

• H 停止。HCがセット

• C ToggleCarry

• HeapP 先頭EDのアドレス

• NextED 次のED 2012/7/16 95 横浜android PF部

Page 96: Adk2012

TD:Transfer Descriptor

GTDとITDの2種類

GTD General Transfer Descriptor

ITD Isochronous Transfer Descriptor

0~8192byteのバッファをもつ

EDにリンクされる

HCが処理して処理後にDoneQueueに繋がる

2012/7/16 96 横浜android PF部

Page 97: Adk2012

GTD General Transfer Descriptor

3 2 2 2 2 2 2 2 2 1 1 0 0

1 8 7 6 5 4 3 1 0 9 8 3 0

Dword 0 CC EC T DI DP R —

Dword 1 Current Buffer Pointer (CBP)

Dword 2 Next TD (NextTD) 0

Dword 3 Buffer End (BE)

• R DataUnderrunを無視

• DP 方向とPIDを指定

• DI 割り込みタイミング

• T DataToggle

• EC エラーカウント

• CC 完了コード

• CBP バッファ領域

• NextTD 次のTD

• BE バッファの末尾アドレス

2012/7/16 97 横浜android PF部

Page 98: Adk2012

ITD Isochronous Transfer Descriptor 3 2 2 2 2 2 2 2 1 1 1 1 0 0 0

1 8 7 6 4 3 1 0 6 5 2 1 5 4 0

Dword 0 CC – FC DI — SF

Dword 1 Buffer Page 0 (BP0) —

Dword 2 NextTD 0

Dword 3 Buffer End (BE)

Dword 4 Offset1/PSW1 Offset0/PSW0

Dword 5 Offset3/PSW3 Offset2/PSW2

Dword 6 Offset5/PSW5 Offset4/PSW4

Dword 7 Offset7/PSW7 Offset6/PSW6

• SF 転送開始フレーム

• DI 割り込みを待たせる時間

• FC 転送フレームすう0-7

• CC 完了コード

• BP0 バッファの先頭アドレス

• NextTD 次のITD

• BE バッファの終端

• OffsetN

• 下位12ビットがオフセット

• 12ビット目で上位20ビットを決める

0 BufferPage0の上位20ビット

1 BufferEndの上位20ビット

• OSWN

• サイズとCC

• CCがNotAccessedでOfffsetNとして扱う

2012/7/16 98 横浜android PF部

Page 99: Adk2012

HCCA Host Controller Communication Area

Offset

Size

(bytes)

Name

R/W

Description

0 128 HccaInterrruptTable R 32 個のInterrupt ED へのポインタ

0x80 2 HccaFrameNumber W 現在のフレーム番号。このフィールドは、各フレームのED 処理開始

前にHC が更新

0x82 2 HccaPad1 W HC がHccaFrameNumber をアップデートした際に、0 がセットされ

ます。 0x84 4 HccaDoneHead W フレームの終了時、WriteBackDoneHead

割り込みが有効になっていた場合、HC

はこのフィールドにHcDoneHead 値を書き込みむ。

HC が書き込むと、Software がこのフィールドをクリアして、HcInterruptStatus のWD ビットをクリアしない限り、HC はこのフィ

ールドに書き込みません。 0x88 116 reserved R/W Reserved for use by HC

Figure 4-5: Host Controller Communications Area Format

2012/7/16 99 横浜android PF部

Page 100: Adk2012

付録

2012/7/16 横浜android PF部 100

Page 101: Adk2012

android-omap-tuna-3.0-jb-pre1/drivers/usb/gadget

2012/7/16 横浜android PF部 101

806 static struct android_usb_function

*supported_functions[] = {

807 &adb_function,

808 &acm_function,

809 &mtp_function,

810 &ptp_function,

811 &rndis_function,

812 &mass_storage_function,

813 &accessory_function,

814 &audio_source_function,

815 NULL

816 };

Page 102: Adk2012

android-omap-tuna-3.0-jb-pre1/drivers/usb/gadget

2012/7/16 横浜android PF部 102

125 static struct usb_interface_descriptor acc_interface_desc = {

126 .bLength = USB_DT_INTERFACE_SIZE,

127 .bDescriptorType = USB_DT_INTERFACE,

128 .bInterfaceNumber = 0,

129 .bNumEndpoints = 2,

130 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,

131 .bInterfaceSubClass = USB_SUBCLASS_VENDOR_SPEC,

132 .bInterfaceProtocol = 0,

133 };

134

135 static struct usb_endpoint_descriptor acc_highspeed_in_desc = {

136 .bLength = USB_DT_ENDPOINT_SIZE,

137 .bDescriptorType = USB_DT_ENDPOINT,

138 .bEndpointAddress = USB_DIR_IN,

139 .bmAttributes = USB_ENDPOINT_XFER_BULK,

140 .wMaxPacketSize

Page 103: Adk2012

android-omap-tuna-3.0-jb-pre1/drivers/usb/gadget

2012/7/16 横浜android PF部 103

213 static struct snd_pcm_hardware audio_hw_info = {

214 .info = SNDRV_PCM_INFO_MMAP |

215 SNDRV_PCM_INFO_MMAP_VALID |

216 SNDRV_PCM_INFO_BATCH |

217 SNDRV_PCM_INFO_INTERLEAVED |

218 SNDRV_PCM_INFO_BLOCK_TRANSFER,

219

220 .formats = SNDRV_PCM_FMTBIT_S16_LE,

221 .channels_min = 2,

222 .channels_max = 2,

223 .rate_min = SAMPLE_RATE,

224 .rate_max = SAMPLE_RATE,

225

226 .buffer_bytes_max =1024 * 1024,

227 .period_bytes_min =64,

228 .period_bytes_max =512 * 1024,

229 .periods_min =2,

230 .periods_max =1024,

231 };