adk2012
TRANSCRIPT
@magoroku15
Rev.1.0
2012/7/13 横浜android PF部
Who am I
最底辺活動家、下が好き
オーディオマニア
iPhoneだと機器認証しないと取りだせないPCMが、ADK2で取りだせそうなのでやる気満々
昔こんなの作った
オレオレ家電
http://www.slideshare.net/magoroku15/ss-10335135
2012/7/16 横浜android PF部 2
今日のお話
ADK2012の解析 ハード編
ADK2012の解析 ソフト編
CLONEの作り方・可能性
2012/7/16 3 横浜android PF部
http://developer.android.com/tools/adk/index.html
2012/7/16 4 横浜android PF部
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部
Developing Accessories
with ADK 2012の内容
adk1
旧バージョン
adk2012
board
ハード設計情報、回路図、BOM
回路図、レイアウトはEagleで記述
App
Androidアプリのソースコード
External
Ide
IDE用のコードなど
Toolchain
クロスコンパイラ
前半はここを中心に
2012/7/16 6 横浜android PF部
2012/7/16 7 横浜android PF部
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部
2012/7/16 9 横浜android PF部
メインボードの主要部品
hardware/adk2012 BOM.rtf
ATSAM3X8EA-AU
ATMEL製 Coretex-M3
LBMA1BGUG2
村田製作所製 Bluetooth HCI Module
PIC10F200T-I/OT
MicroChip製 PIC10
2012/7/16 10 横浜android PF部
メインボード回路図 電源
コネクタ クロック
USB
書き込み コネクタ
SD-CARD
Bluetooth
hardware/adk2012_base.pdf
2012/7/16 11 横浜android PF部
メインボード回路図 Bluetooth
BTモジュールは,TX,RX,
RTS,CTS,RESET,CLKの
6本のみ使用。
2012/7/16 12 横浜android PF部
PIC10の用途
書き込み
Flashのeraseに使っている
2012/7/16 13 横浜android PF部
2012/7/16 14 横浜android PF部
IOボードの主要部品
hardware/adk2012_LED BOM.rtf
SHT21
SENSIRION製 湿度センサ
MAX44005GDT+
MAXIM製 カラーセンサー
AT42QT2120-HHM
ATMEL製 タッチセンサ
BMP180
BOSCH製 圧力センサ
2012/7/16 15 横浜android PF部
LEDボードの回路図 ARDUINO HEADER AUDIO SENSORS
CAP SENSE
LED & DRIVERS
hardware/adk2012_led.pdf
2012/7/16 16 横浜android PF部
AUDIO
TIのデジタル
アンプ
MPUのDAC0から
OP AMP
IV変換
2012/7/16 17 横浜android PF部
SENSORS
すべてI2C接続
ADCは使わない
2012/7/16 18 横浜android PF部
CAP SENSE
21点の入力スイッチ
GPIOは使わないI2C入力
2012/7/16 19 横浜android PF部
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部
スイッチとLEDの配置
2012/7/16 21 横浜android PF部
2012/7/16 22 横浜android PF部
adk2012/board
MakefileBasedBuild
ATMEL ATMEL SAM3X依存部
App ソースコード
Build
flash
setup
hardware ハード編で説明
library ADK2 ソースコード
tools
2012/7/16 23 横浜android PF部
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.
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
adkInit
BT UART
BTモジュールとのインタフェースとしてUARTを使っているのでその初期化
HCI ホスト(MPU)とBTコントローラの間のIF
SDP
サービスを通知するためのプロトコル
RFCOMM シリアル通信のエミュレーションプロトコル
A2DP
2012/7/16 横浜android PF部 26
adkInit Bluetoothの復習
BT UART BTモジュールとのインタフェースとしてUARTを使っているのでその初期化
HCI ホスト(MPU)とBTコントローラの間のIF
SDP サービスを通知するためのプロトコル
RFCOMM シリアル通信のエミュレーションプロトコル
L2CAP 複数接続を管理するプロトコル
A2DP AVプロファイル、音声通話用のHSPより高音質
2012/7/16 横浜android PF部 27
adkInit BlurToothの復習
2012/7/16 横浜android PF部 28
HCI
HCI
LMP
Baseband
RF
L2CAP
SDP RFCOMM A2DP Control
ホスト側
BTモジュール MCU
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モジュールをリセット
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
•ペアリングの処理
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
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される
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
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
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
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
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
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
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
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
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
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に渡す
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に送信
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
コマンド一覧
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
ライセンスの送信??
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の接続も、アプリ層のコマンド処理は同じ関数で
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
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と同じ
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
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部
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部
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で代用)の初期化
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部
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部
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の電源とクロックを設定
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部
御約束の呪文
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機能を呼び出す
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部
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部
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部
これ曲者
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部
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部
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部
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部
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部
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転送の起動、受信データのコールバックを設定
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部
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が増えてます
2012/7/16 横浜android PF部 69
こんなやつ
2012/7/16 横浜android PF部 70
http://www.slideshare.net/magoroku15/poormans-adk-11350123
もうすぐ5000view
これはADK1.0互換
Audioがいらなければこれでもできると思う
仕様案
センサ、LEDは載せない 必要になった時点で載せればよい
ADK2012の本質はBT,Audio,HID
Bluetooth 欲しい
USBオーディオ PCM 16bit 44.1KHz stereoで出せれば立派なトランスポート
iPhoneは機器認証部品が1社独占のライセンス
HOST + isochronous のサポート
できるだけ安く できればブレッドボードで
2012/7/16 横浜android PF部 71
MCU
NXP のLPC1769
Coretex M3 120MHz Flash 512Kb SRAM 64Kb
Programmer 付き
安価に秋月で入手可能 2500円
I2SでオーディオDACを繋ぎたい
2012/7/16 横浜android PF部 72
プログラミング環境
Eclipse ベースの LPCXpresso
ROMサイズで128Kbまで無償
2012/7/16 横浜android PF部 73
フレームワーク
直叩きでも出来るけど、とりあえず
nxpUSBlib http://www.lpcware.com/content/project/nxpusblib
HOSTモードサポート
Isochronousをサポート
○ UAC(USB Audio Class)のUSB 出力のサンプルあり
ADK1.0のサンプル添付
2012/7/16 横浜android PF部 74
BT モジュール
USBドングル or cc256x
普通のUSBドングルはHCI
BOMにあったLBMA1BGUG2はcc256xをモジュールに加工?
まずは、cc256xで考える
cc256xの入手性は
PANASONIC製のモジュールを見つけた
DigikeyはJP向けに出てこない(輸出できない)
Mouser はオーダは直後にキャンセルされた
chip one stopなんとか入手
2012/7/16 横浜android PF部 75
モジュールだけどBGA
2012/7/16 横浜android PF部 76
このパッドの内VCC,GND,RST,TX,RX,RTS,CTSの
7本の細線をつけられるか?自信なし。
→評価ボードを追加で発注した
技適は当然ありませんorz
まだ電源は入れてないのでヨロシクね
BTは後回しにしてUSBで作業開始
nxpUSBlibに付属のADK1.0ソースをベースに
Linux上のlibUSBでコントロール通信
ACCESSORY + AUDIO に切り替えて
Lsusb -v
2012/7/16 横浜android PF部 77
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
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に
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
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
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
USBで繋ぐには
最初のInterfaceはADK1.0と同じ手順で
VID,PID他,classなど,細かな変更が必要
2,3番目のInterfaceはnxpUSBlibのAudioConfig
用のライブラリを使ってConfig
2012/7/16 横浜android PF部 83
現状
Version2のプロトコルでネゴシエーション
Audio Dockモードでコンフィグ
Isochronous 転送 USBバス上は転送を確認
API経由でデータが受け取れない
2012/7/16 横浜android PF部 84
USBのキャプチャ
2012/7/16 横浜android PF部 85
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が接続されて
初期化完了
今後
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
付録
2012/7/16 横浜android PF部 88
USBの転送
4 種類の転送方式
Interrupt転送 Periodic 転送
少量のデータを一定の間隔で転送
転送の間隔は、対象となるデバイス毎に決める
Isochronous転送 一定のレート・周期で転送
Periodic 転送
Control転送 Configuration情報、コマンド情報、Status情報を転送する方式
Bulk転送 大量のデータを転送する方式
2012/7/16 89 横浜android PF部
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部
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部
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部
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部
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部
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部
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部
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部
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部
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部
付録
2012/7/16 横浜android PF部 100
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 };
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
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 };