研究材料:
Accessory Interface Specification for Apple Devices.pdf
iPod+Authentication+Coprocessor+Spec+2.0C+R1
如果需要更詳細的協議說明,可以下載MFI Accessory Firmware Specification PDF
(文檔來自蘋果授權方,如有侵權,請告知,本文不宜轉載)
Accessory Interface Specification for Apple Devices.pdf
這個文檔說明了蘋果外設的認證過程、支持的認證模式、外設類型和通信協議,也可以通過查看MFI Accessory Firmware Specification文檔瞭解更加詳細的協議內容,比如iAP2的LINK建立過程如下圖:
iPod+Authentication+Coprocessor+Spec+2.0C+R1.pdf
這個文檔是蘋果MFI認證芯片的datasheet,MFI芯片基於I2C通信接口,例如下圖的I2C地址選擇:
Accessory端如何做bluetooth的驗證呢?
我們以一個場景來描述,比如MFI認證的藍牙設備連接上支持iAP2的iOS設備之後,可以直接拉起一個APP程序到前臺,那麼我們該怎麼做呢?
1、藍牙設備的Service Discovery Protocal(SDP)必須要支持;
2、SDP的Maximum Transmission Unit(MTU)必須最少支持672bytes,這個可以看是否支持MTU協商;
3、不支持SDP消息記錄分片;
4、Extended Inquiry Response(EIR)必須要被支持;
5、service UUID 0x00000000DECAFADEDECADEAFDECACAFE必須在SDP和EIR中被申明;
6、EIR設備名必須和Accessory設備的MFI認證時的IdentificationInformation的名字一致
以上是藍牙部分需要滿足的協議條件,然後接下來就是驅動認證芯片,並完成通過藍牙通道做MFI認證,第一張圖已經說明了驗證的流程,如果想完成設備連接上後,直接打開某一個APP的功能,需要設備發送RequestAppLaunch消息到iOS設備上,通過Accessory Interface說明文檔的26.3.1的RequestAppLaunch數據格式,我們知道需要攜帶一個參數AppBundleID,這個參數類型是utf8,e.g. com.kuili.applaunch,這裏蘋果推薦使用反DNS格式
(對於iAP2流程的link control session和seesion的開發過程這裏忽略,官方例子)
支持MFI iAP2的手機端:
Info.plist中增加如下內容:
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.example.apple-samplecode.data</string>
<string>com.kuili.applaunch</string>
</array>
注意Info.plist中的一個字符串正是accessory設備通過RequestAppLaunch發送過來的AppBundleID
程序中需要引用外部附件框架:
ExternalAccessory.framework
開始通信:
創建一個EASession,數據通過NSInputStream和NSOutputStream讀寫流數據。
讀取設備信息:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableString *info = [[NSMutableString alloc] initWithCapacity:1024];
EAAccessoryManager *manager = [EAAccessoryManager sharedAccessoryManager];
NSArray<EAAccessory *> *accessArr = [manager connectedAccessories];
for (EAAccessory *access in accessArr) {
for (NSString *proStr in access.protocolStrings) {
[info appendFormat:@"protocolString = %@\n", proStr];
}
[info appendFormat:@"\n"];
[info appendFormat:@"manufacturer = %@\n", access.manufacturer];
[info appendFormat:@"name = %@\n", access.name];
[info appendFormat:@"modelNumber = %@\n", access.modelNumber];
[info appendFormat:@"serialNumber = %@\n", access.serialNumber];
[info appendFormat:@"firmwareRevision = %@\n", access.firmwareRevision];
[info appendFormat:@"hardwareRevision = %@\n", access.hardwareRevision];
[info appendFormat:@"dockType = %@\n", access.dockType];
}
dispatch_async(dispatch_get_main_queue(), ^{
label.text = info;
});
});
與外設通信:
EAAccessoryManager *manager = [EAAccessoryManager sharedAccessoryManager];
NSArray<EAAccessory *> *accessArr = [manager connectedAccessories];
if (accessArr.first) {
EASession *session = [[EASession alloc] initWithAccessory:accessArr.firstObject forProtocol:@"com.kuili.applaunch"];
if (!session) return;
NSInputStream *inputStream = [session inputStream];
if (!inputStream) {
// LOG inputStream = null
}
inputStream.delegate = self;
[inputStream open];
}
以上iOS代碼片段引用了以下博客鏈接:http://www.jianshu.com/p/8f69c9c4e71e