<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Not able to perform Legacy DFU with Android 10 and iOS</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/60658/not-able-to-perform-legacy-dfu-with-android-10-and-ios</link><description>I am not able to perform DFU using the Legacy bootloader from SDK v11.0.0 or older with my Android 10 device and/or iOS device.</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 03 Nov 2020 13:28:14 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/60658/not-able-to-perform-legacy-dfu-with-android-10-and-ios" /><item><title>RE: Not able to perform Legacy DFU with Android 10 and iOS</title><link>https://devzone.nordicsemi.com/thread/278274?ContentTypeID=1</link><pubDate>Tue, 03 Nov 2020 13:28:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:86c4aeb6-4cd7-44f8-b4dc-ec278ee197d0</guid><dc:creator>Mxoh</dc:creator><description>&lt;p&gt;Hi there! We faced this problem and applied the new Android DFU library to fix it. However, since doing so we observed that there are more instances of GATT error. We have been monitoring DFU failures in our app and you can see a trend after applying the fix at around mid/end Aug, the DFU disconnected problem users decreased but GATT error users increased significantly.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;img alt=" " height="274" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/Screenshot-2020_2D00_11_2D00_03-at-9.21.00-PM.png" width="582" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=" " height="277" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/Screenshot-2020_2D00_11_2D00_03-at-9.25.37-PM.png" width="590" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Not able to perform Legacy DFU with Android 10 and iOS</title><link>https://devzone.nordicsemi.com/thread/249319?ContentTypeID=1</link><pubDate>Mon, 11 May 2020 23:28:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7cb71b15-41cb-401c-aad7-293d34ba4942</guid><dc:creator>Jose Cazarin</dc:creator><description>&lt;p&gt;I&amp;#39;m here to say that we are seeing the same problem with Android 8 and 9 as well.&lt;br /&gt;Do you have any more information on which versions might be affected?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Not able to perform Legacy DFU with Android 10 and iOS</title><link>https://devzone.nordicsemi.com/thread/246603?ContentTypeID=1</link><pubDate>Fri, 24 Apr 2020 17:56:58 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1b9b6002-144b-41c8-8619-552f7180faa0</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;&lt;span&gt;This is a known issue:&amp;nbsp;&lt;a href="https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library/issues/368"&gt;https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library/issues/368&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Recent version of Android and iOS, or recent smartphones (we didn&amp;#39;t pinpoint it yet), use private resolvable addresses and LL privacy. So&amp;nbsp;when&amp;nbsp;a peripheral performs directed advertisement without being bonded to the central, then the central device may not be able to resolve the address as there is no IRK in its internal resolving list and the directed advertisment packet may be ignored and the central does not send a connection request.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In the Legacy Bootloader we have peer data sharing feature where the application shares the bonding information with the bootloader. The peer data consists of the peer address, the identity resolving key, the encryption key of the link and the system attribute for the Service Changed indication.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;typedef struct
{
    ble_gap_addr_t      addr;                                   /**&amp;lt; BLE GAP address of the device that initiated the DFU process. */
    ble_gap_irk_t       irk;                                    /**&amp;lt; IRK of the device that initiated the DFU process if this device uses Private Resolvable Addresses. */
    ble_gap_enc_key_t   enc_key;                                /**&amp;lt; Encryption key structure containing encrypted diversifier and LTK for re-establishing the bond. */
    uint8_t             sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**&amp;lt; System service attributes for restoring of Service Changed Indication setting in DFU mode. */
} dfu_ble_peer_data_t;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If the central device is not bonded with the peripheral, then the peripheral will only populate the address field. The bootloader will then perfrom directed advertisment towards this address. If the central device is bonded, then the all the fields are populated and the bootloader will advertise using a whitelist.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**@brief Function for starting advertising.
 */
static void advertising_start(void)
{
    if (!m_is_advertising)
    {
        uint32_t err_code;

        // Initialize advertising parameters (used when starting advertising).
        memset(&amp;amp;m_adv_params, 0, sizeof(m_adv_params));

        if (m_ble_peer_data_valid)
        {
            ble_gap_irk_t empty_irk = {{0}};

            if (memcmp(m_ble_peer_data.irk.irk, empty_irk.irk, sizeof(empty_irk.irk)) == 0)
            {
                advertising_init(BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE);
                m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
                m_adv_params.p_peer_addr = &amp;amp;m_ble_peer_data.addr;
                m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
                m_adv_params.interval    = 0;
                m_adv_params.timeout     = 0;
            }
            else
            {
                ble_gap_irk_t  * p_irk[1];
                ble_gap_addr_t * p_addr[1];

                p_irk[0]  = &amp;amp;m_ble_peer_data.irk;
                p_addr[0] = &amp;amp;m_ble_peer_data.addr;

                ble_gap_whitelist_t whitelist;
                whitelist.addr_count = 1;
                whitelist.pp_addrs   = p_addr;
                whitelist.irk_count  = 1;
                whitelist.pp_irks    = p_irk;

                advertising_init(BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED);
                m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
                m_adv_params.fp          = BLE_GAP_ADV_FP_FILTER_CONNREQ;
                m_adv_params.p_whitelist = &amp;amp;whitelist;
                m_adv_params.interval    = APP_ADV_INTERVAL;
                m_adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
            }
        }
        else
        {
            advertising_init(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
            m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND;
            m_adv_params.p_peer_addr = NULL;
            m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
            m_adv_params.interval    = APP_ADV_INTERVAL;
            m_adv_params.timeout     = APP_ADV_TIMEOUT_IN_SECONDS;
        }

        err_code = sd_ble_gap_adv_start(&amp;amp;m_adv_params);
        APP_ERROR_CHECK(err_code);

        nrf_gpio_pin_clear(ADVERTISING_LED_PIN_NO);

        m_is_advertising = true;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If the central&amp;nbsp;bonds with the application before resetting into the bootloader, then the bootloader will advertise using the a whitelist and the central will not have any issue with reconnecting to the bootloader after sending the DFU start command to the DFU service in the application, which triggers a reset into the bootloader.&amp;nbsp; It is also possible to altered the code so that it performs undirected advertisment, i.e.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;if (memcmp(m_ble_peer_data.irk.irk, empty_irk.irk, sizeof(empty_irk.irk)) == 0)
{
    advertising_init(BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE);
    m_adv_params.type        = BLE_GAP_ADV_TYPE_ADV_IND; // BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
    m_adv_params.p_peer_addr = &amp;amp;m_ble_peer_data.addr;
    m_adv_params.fp          = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval    = 300;
    m_adv_params.timeout     = 180;
}&lt;/pre&gt;.&lt;/p&gt;
&lt;p&gt;So the solution would be to either bond with the application before performing the DFU so that the bootloader uses advertising with the whitelist and not directed advertisement. Or modify the source code to perform undirected advertisment instead as shown above.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you are interested in the relevant parts of the specification then see below&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bj&amp;oslash;rn&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;It is important to understand that when the Legacy DFU solution was designed, then the addresses used in the directed advertisment packet needed to be public or random, they could not be resolvable as is allowed in the newer specifications.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;BLUETOOTH SPECIFICATION Version 4.1 [Vol 6] page 40 of 174&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;2.3.1.2 ADV_DIRECT_IND&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Payload field consists of AdvA and InitA fields. The AdvA field shall contain the advertiser&amp;rsquo;s public or random device address as indicated by TxAdd. The InitA field is the address of the device to which this PDU is addressed. The InitA field shall contain the initiator&amp;rsquo;s public or random device address as indicated by RxAdd.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When the newer Bluetooth Specifications allowed directed advertisment packets to use resolvable addresses then they also added the Central Address Resolution characteristic to the GAP service.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 3, Part C page 1397&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;12.4 CENTRAL ADDRESS RESOLUTION&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;The Peripheral should check if the peer device supports address resolution by reading the Central Address Resolution characteristic before using directed&lt;/em&gt;&lt;br /&gt;&lt;em&gt;advertisement where the initiator address is set to a Resolvable Private Address (RPA).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Legacy DFU solution will simply&amp;nbsp;pass the&amp;nbsp;Resolvable Private&amp;nbsp;Address (RPA) used in the connection request to the bootloader that uses this as the initiator address in the directed advertisment packet, without checking this CAR characteristic.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, even if the bootloader is modified to check the CAR characteristic, the central could still ignore the directed advertisment packet as the central might not be able to resolve the Initiator address in the directed advertisment packet&amp;nbsp;there is no entry in the&amp;nbsp;Central&amp;#39;s Bluetooth Controller Resolving List as the peripheral and central has not been bonded and exchanged IRKs.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 6, Part B page 3065&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;6.2.2 Connectable directed event type&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Link Layer shall use resolvable private addresses for the advertiser&amp;rsquo;s device address (AdvA field). If an IRK is available in the Link Layer Resolving&lt;br /&gt;List for the peer device, then the target&amp;rsquo;s device address (TargetA field) shall use a resolvable private address. If an IRK is not available in the Link Layer&lt;br /&gt;Resolving List or the IRK is set to zero for the peer device, then the target&amp;rsquo;s device address (TargetA field) shall use the Identity Address when entering the&lt;br /&gt;Advertising State and using connectable directed events.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;When an advertiser receives a connection request that contains a resolvable private address for the initiator&amp;rsquo;s address (InitA field) and address resolution is&lt;/em&gt;&lt;br /&gt;&lt;em&gt;enabled, the Link Layer shall resolve the private address (see Section 1.3.2.3).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So it seems that Android 10 enables Address Resolution and is not able to resolve the Initiator address as there is no IRK. The nRF should use the identity address instead of the Resolvable Private Address.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>