蘋果MFI bluetooth認證開發過程:iDevice和accessory

研究材料:

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章