This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DFU bootloader with Qt - problem for iOS

Hello everyone,

I am working on DFU bootloader application for android  and iOS (using Qt C++).

For android everything works fine, but for iOS I have problems.

In order to enter DFU mode I need to send 0x0104 to control point dfu characteristic and after this device is reset in DFU mode.

After this my app doing next steps: connect to device again > discover services (there is only DFU service now) > write descriptor for  CP characteristic (to enable notifications) > THERE IS A PROBLEM - The delegate for CBPeripheral does not implement -[peripheral:didModifyServices:].

I tried to increment MAC address (device uuid) when enter in DFU mode because I read that devices may be cached by the phone and if they change services list while connected that could cause the problem, but the problem is still there.

Has anyone had a similar problem/experience?

Thanks in advance.

  • Hello,

    I tried DFU on iPhone with nrf connect application and it works.

    After analyzing nrf connect log I realized that DFU steps in my application are different from these in nrf connect.

    Steps in my application:

    -write descriptor for DFU control point characteristic => write value 0100

    -write value 0104 to DFU control point characteristic (00001531-1212-efde-1523-785feabcd123

    -peripheral is disconnected after this and my application automatically reconnect device

    -write descriptor for DFU control point characteristic (0100)

    -write value 0104 to DFU control point characteristic

    -write FW size (size of packet that is going to be sent) in DFU packet characteristic (00001532-1212-efde-1523-785feabcd123)

    -here(if everything is ok) I am getting notification (100101)

    -write init request (0200) to DFU control point characteristic

    -write init packet (generated from FW packet) to DFU packet characteristic

    -write "init done" (0201) to DFU control point characteristic

    -here (if everything is ok) I am getting notification (100201)

    -write "packet receipt notification request" to DFU control point => value 080A00 - means notification for received every 10 packets

    -write "receive firmware image request" (value 03) to DFU control point characteristic

    -after this my app handling notification and sending fw image packets...

    ...

    But in NRF Connect application it seems that device is reset into DFU mode before first write 0104 to DFU control point characteristic..

    Here is log from  nrf connect app:

    10:42:16.776 Connecting MyBleDevice-19817

    10:42:16.784 [MethodCall]connectPeripheral

    10:42:17.152 [Callback]Successful connect to peripheral MyBleDevice-19817

    10:42:17.152 Status changed: Connected to MyBleDevice-19817

    10:42:17.743 [Callback]Successful discover service 6152AA01-ECCC-4179-AC21-C4FDFA137D48

    10:42:17.743 [Callback]Successful discover service 429AAA02-D7BD-4F7D-AFBB-03310DA063D9

    10:42:17.744 [Callback]Successful discover service 994CAA03-399A-435E-8327-7D16D9FC4D29

    10:42:17.745 [Callback]Successful discover service 180F

    10:42:17.745 [Callback]Successful discover service 180A

    10:42:17.745 [Callback]Successful discover service 00001530-1212-EFDE-1523-785FEABCD123

    10:42:18.041 [Callback]Successful discover charact. for service 6152AA01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.041 [MethodCall]readCharacteristicValue 6152BB01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.041 [MethodCall]discoverDescriptorsForCharact. 6152BB01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.041 [Callback]Successful discover charact. for service 6152AA01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [MethodCall]readCharacteristicValue 6152BB02-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [MethodCall]discoverDescriptorsForCharact. 6152BB02-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [Callback]Successful discover charact. for service 6152AA01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [MethodCall]readCharacteristicValue 6152BB03-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [MethodCall]discoverDescriptorsForCharact. 6152BB03-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.042 [Callback]Successful discover charact. for service 6152AA01-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.043 [MethodCall]readCharacteristicValue 6152BB04-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.043 [MethodCall]discoverDescriptorsForCharact. 6152BB04-ECCC-4179-AC21-C4FDFA137D48

    10:42:18.340 [Callback]Successful discover charact. for service 429AAA02-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.340 [MethodCall]readCharacteristicValue 429ABB05-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.340 [MethodCall]discoverDescriptorsForCharact. 429ABB05-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.340 [Callback]Successful discover charact. for service 429AAA02-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [MethodCall]readCharacteristicValue 429ABB06-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [MethodCall]discoverDescriptorsForCharact. 429ABB06-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [Callback]Successful discover charact. for service 429AAA02-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [MethodCall]readCharacteristicValue 429ABB07-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [MethodCall]discoverDescriptorsForCharact. 429ABB07-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [Callback]Successful discover charact. for service 429AAA02-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.341 [MethodCall]readCharacteristicValue 429ABB08-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.342 [MethodCall]discoverDescriptorsForCharact. 429ABB08-D7BD-4F7D-AFBB-03310DA063D9

    10:42:18.520 [Callback]Successful discover charact. for service 994CAA03-399A-435E-8327-7D16D9FC4D29

    10:42:18.520 [MethodCall]readCharacteristicValue 994CBB09-399A-435E-8327-7D16D9FC4D29

    10:42:18.520 [MethodCall]discoverDescriptorsForCharact. 994CBB09-399A-435E-8327-7D16D9FC4D29

    10:42:18.520 [Callback]Successful discover charact. for service 994CAA03-399A-435E-8327-7D16D9FC4D29

    10:42:18.521 [MethodCall]readCharacteristicValue 994CBB0A-399A-435E-8327-7D16D9FC4D29

    10:42:18.521 [MethodCall]discoverDescriptorsForCharact. 994CBB0A-399A-435E-8327-7D16D9FC4D29

    10:42:18.610 [Callback]Successful discover charact. for service 180F

    10:42:18.610 [MethodCall]readCharacteristicValue 2A19

    10:42:18.610 [MethodCall]discoverDescriptorsForCharact. 2A19

    10:42:18.670 [Callback]Successful discover charact. for service 180A

    10:42:18.671 [MethodCall]readCharacteristicValue 2A29

    10:42:18.671 [MethodCall]discoverDescriptorsForCharact. 2A29

    10:42:18.671 [Callback]Successful discover charact. for service 180A

    10:42:18.671 [MethodCall]readCharacteristicValue 2A27

    10:42:18.672 [MethodCall]discoverDescriptorsForCharact. 2A27

    10:42:18.672 [Callback]Successful discover charact. for service 180A

    10:42:18.672 [MethodCall]readCharacteristicValue 2A26

    10:42:18.673 [MethodCall]discoverDescriptorsForCharact. 2A26

    10:42:18.910 [Callback]Successful discover charact. for service 00001530-1212-EFDE-1523-785FEABCD123

    10:42:18.910 [MethodCall]readCharacteristicValue 00001532-1212-EFDE-1523-785FEABCD123

    10:42:18.911 [MethodCall]discoverDescriptorsForCharact. 00001532-1212-EFDE-1523-785FEABCD123

    10:42:18.911 [Callback]Successful discover charact. for service 00001530-1212-EFDE-1523-785FEABCD123

    10:42:18.911 [MethodCall]readCharacteristicValue 00001531-1212-EFDE-1523-785FEABCD123

    10:42:18.912 [MethodCall]discoverDescriptorsForCharact. 00001531-1212-EFDE-1523-785FEABCD123

    10:42:18.912 [Callback]Successful discover charact. for service 00001530-1212-EFDE-1523-785FEABCD123

    10:42:18.912 [MethodCall]readCharacteristicValue 00001534-1212-EFDE-1523-785FEABCD123

    10:42:18.913 [MethodCall]discoverDescriptorsForCharact. 00001534-1212-EFDE-1523-785FEABCD123

    10:42:19.037 [Callback]Successful update value for charact. 6152BB01-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.038 [Callback]Successful discover descriptors for charact. 6152BB01-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.039 [Callback]Successful discover descriptors for charact. 6152BB01-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.089 [Callback]Successful update value for charact. 6152BB02-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.180 [Callback]Successful discover descriptors for charact. 6152BB02-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.180 [Callback]Successful discover descriptors for charact. 6152BB02-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.248 [Callback]Successful update value for charact. 6152BB03-ECCC-4179-AC21-C4FDFA137D48

    10:42:19.404 [MethodCall]cancelPeripheralConnection

    10:42:19.578 [Callback]Successful disconnect from peripheral MyBleDevice-19817

    10:42:19.578 Status changed: Disconnected from MyBleDevice-19817

    10:42:23.720 Connecting to MyBleDevice-19817...

    10:42:23.721 centralManager.connect(peripheral, options: nil)

    10:42:23.723 [Callback]State changed to Connecting

    10:42:24.218 [Callback] Central Manager did connect peripheral

    10:42:24.219 Connected to MyBleDevice-19817

    10:42:24.219 Discovering services...

    10:42:24.219 peripheral.discoverServices(nil)

    10:42:24.817 Services discovered

    10:42:24.820 Starting Legacy DFU...

    10:42:24.823 Connected to MyBleDevice-19817

    10:42:24.824 Services discovered

    10:42:24.824 Legacy DFU Service found

    10:42:24.825 Discovering characteristics in DFU Service...

    10:42:24.825 peripheral.discoverCharacteristics(nil, for: 00001530-1212-EFDE-1523-785FEABCD123)

    10:42:25.117 DFU characteristics discovered

    10:42:25.120 Reading DFU Version number...

    10:42:25.120 peripheral.readValue(00001534-1212-EFDE-1523-785FEABCD123)

    10:42:25.196 Read Response received from 00001534-1212-EFDE-1523-785FEABCD123, value (0x): 0100

    10:42:25.199 Version number read: 0.1

    10:42:25.201 Enabling notifications for 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:25.202 peripheral.setNotifyValue(true, for: 00001531-1212-EFDE-1523-785FEABCD123)

    10:42:25.224 [Callback]State changed to Starting

    10:42:25.326 Notifications enabled for 00001531-1212-EFDE-1523-785FEABCD123

    10:42:25.326 DFU Control Point notifications enabled

    10:42:25.326 Application with buttonless update found

    10:42:25.327 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:25.329 peripheral.writeValue(0x0104, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:25.355 [Callback]State changed to Enabling DFU Mode

    10:42:25.393 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:25.394 Jump to bootloader (Op Code = 1, Upload Mode = 4) request sent

    10:42:25.570 [Callback] Central Manager did disconnect peripheral

    10:42:25.571 Disconnected by the remote device

    10:42:25.571 Connecting to MyBleDevice-19817...

    10:42:25.571 centralManager.connect(peripheral, options: nil)

    10:42:26.012 [Callback] Central Manager did connect peripheral

    10:42:26.012 Connected to MyBleDevice-19817

    10:42:26.013 Discovering services...

    10:42:26.013 peripheral.discoverServices([00001530-1212-EFDE-1523-785FEABCD123])

    10:42:26.371 Services discovered

    10:42:26.372 Legacy DFU Service found

    10:42:26.372 Discovering characteristics in DFU Service...

    10:42:26.373 peripheral.discoverCharacteristics(nil, for: 00001530-1212-EFDE-1523-785FEABCD123)

    10:42:26.611 DFU characteristics discovered

    10:42:26.612 Reading DFU Version number...

    10:42:26.612 peripheral.readValue(00001534-1212-EFDE-1523-785FEABCD123)

    10:42:26.685 Read Response received from 00001534-1212-EFDE-1523-785FEABCD123, value (0x): 0800

    10:42:26.685 Version number read: 0.8

    10:42:26.686 Enabling notifications for 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:26.686 peripheral.setNotifyValue(true, for: 00001531-1212-EFDE-1523-785FEABCD123)

    10:42:26.708 [Callback]State changed to Starting

    10:42:26.790 Notifications enabled for 00001531-1212-EFDE-1523-785FEABCD123

    10:42:26.791 DFU Control Point notifications enabled

    10:42:26.791 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:26.791 peripheral.writeValue(0x0104, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:26.796 Writing image sizes (0b, 0b, 61164b) to characteristic 00001532-1212-EFDE-1523-785FEABCD123...

    10:42:26.796 peripheral.writeValue(0x0000000000000000ecee0000, for: 00001532-1212-EFDE-1523-785FEABCD123, type: .withoutResponse)

    10:42:26.884 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:26.884 Start DFU (Op Code = 1, Upload Mode = 4) request sent

    10:42:28.863 Notification received from 00001531-1212-EFDE-1523-785FEABCD123, value (0x): 100101

    10:42:28.863 Response (Op Code = 1, Status = 1) received

    10:42:28.864 Writing Initialize DFU Parameters...

    10:42:28.864 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:28.865 peripheral.writeValue(0x0200, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:28.868 Writing to characteristic 00001532-1212-EFDE-1523-785FEABCD123...

    10:42:28.870 peripheral.writeValue(0xffffffffffffffff010080006f58, for: 00001532-1212-EFDE-1523-785FEABCD123, type: .withoutResponse)

    10:42:28.871 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:28.871 peripheral.writeValue(0x0201, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:29.049 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:29.049 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:29.050 Notification received from 00001531-1212-EFDE-1523-785FEABCD123, value (0x): 100201

    10:42:29.050 Response (Op Code = 2, Status = 1) received

    10:42:29.051 Initialize DFU Parameters completed

    10:42:29.051 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:29.052 peripheral.writeValue(0x080c00, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:29.098 [Callback]State changed to Uploading

    10:42:29.142 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:29.142 Packet Receipt Notif Req (Op Code = 8, Value = 12) request sent

    10:42:29.142 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:29.143 peripheral.writeValue(0x03, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:29.189 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:29.189 Uploading firmware...

    10:42:29.189 Sending firmware to DFU Packet characteristic...

    10:42:53.786 Notification received from 00001531-1212-EFDE-1523-785FEABCD123, value (0x): 100301

    10:42:53.786 Response (Op Code = 3, Status = 1) received

    10:42:53.787 Upload completed in 24.60 seconds

    10:42:53.787 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:53.788 peripheral.writeValue(0x04, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:53.815 [Callback]State changed to Validating

    10:42:53.854 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:53.854 Validate Firmware (Op Code = 4) request sent

    10:42:53.906 Notification received from 00001531-1212-EFDE-1523-785FEABCD123, value (0x): 100401

    10:42:53.906 Response (Op Code = 4, Status = 1) received

    10:42:53.906 Writing to characteristic 00001531-1212-EFDE-1523-785FEABCD123...

    10:42:53.906 peripheral.writeValue(0x05, for: 00001531-1212-EFDE-1523-785FEABCD123, type: .withResponse)

    10:42:53.914 [Callback]State changed to Disconnecting

    10:42:53.966 Data written to 00001531-1212-EFDE-1523-785FEABCD123

    10:42:53.966 Activate and Reset (Op Code = 5) request sent

    10:42:54.148 [System]Error disconnect from peripheral DfuTarg The specified device has disconnected from us.

    10:42:54.148 Status changed: Disconnected from DfuTarg

    Thanks and best regards

  • If you want to implement peripheral did modify services then you need to have the service changed enabled (but no need to indicate when services change as iOS will automatically disable caching for this peripheral when it finds the service there).

    However, our implementation depends on the peripheral disconnecting and starting again in bootloader, with MAC address + 1.

    Only then you can reconnect, discover your services, enable notifications and start the flashing process.

    I would suggest that you follow the same steps as the nR/F Connect app as this is the supported way to flash OTA :)

    Note 1:, if you add service change to your peripheral's FW, iOS will not see that because it has already cached the GATT table, so you'll have to put the phone in airplane mode or disable bluetooth from the settings (not control center) for at least 10 seconds to clear the cache. if that doesn't work you should try again, or try to restart the phone. after the new GATT table is fetched and service change is there, iOS will no longer cache this peripheral.

    Note 2: iOS has no access to the peripheral's MAC address, so you can't rely on MAC address + 1 to identity the node, you should just scan for peripherals broadcasting DFU / Secure DFU services. additionally we have implemented a name set feature that allows you to set the broadcasting name of the peripheral upon restart so you can easily identify it, please use one of our DFU libraries for android or iOS to see how that works. Here is how iOS the iOS Library implements it.

    Note 3: Android allows you to get the peripheral's MAC address, so you won't need to scan like you do on iOS, you simply send the jump to bootloader command, then increment the mac address by one, and connect to that peripheral straight away.

    let us know if you have any more issues so we can help out.

  • Hi Mostafa,

    Thanks for your answer! 

    I have service changed characteristic added in Generic Attribute service (that mean it is enabled, right?).

    I tried with increment MAC address, and for android it works fine but for iPhone not. Maybe I didn't clear cache appropriately...I will try to turn off bluetooth, wait more than 10s and than turn on again.

  • Yes, this is totally correct, this is not following the spec, but iOS has this as a workaround to disable caching, so just having the characteristic present will disable caching for iOS. to be able to actually use it properly and indicate changes, you must be bonded, but that's not a requirement for iOS.

    You should still increment the MAC address as this is the correct way to do it. as I mentioned, iOS does not have access to the MAC address, so you will still have to scan one more time for the peripheral again when it's in bootloader, it'll appear as a totally different peripheral on iOS, so you can't hold a reference to the old ones object.

    You are probably hitting a cache issue as you didn't have the service changed from before (You don't actually need it anymore you're incrementing the MAC address.) I would say remove the service changed characteristic, then rely on scanning again when the device has restarted into bootloader. only then it'll work on both platforms.

  • I'll give you feedback after try this. Thanks once again!

Related