InfiniTimeOrg / InfiniTime

Firmware for Pinetime smartwatch written in C++ and based on FreeRTOS
GNU General Public License v3.0
2.64k stars 902 forks source link

DFU fails with "Android DFU library" for version > 1.11.1 #1933

Open InfocuspSamyakVora opened 6 months ago

InfocuspSamyakVora commented 6 months ago

Verification

What happened?

Firmware update failed with error message: "Disconnected from GATT server"

What should happen instead?

Firmware should be updated

Reproduction steps

Create a flutter app Install dependency: nordic_dfu: 6.0.1

Add code for DFU with this library. Build the flutter application

Try updating the infinitime image with the new built firmware. The firmware update fails with error message:

Disconnected from GATT server

More details?

Logs for DFU failure:

2023-12-22 13:13:20.835 11446-16181 DfuImpl         com.project.project         I Sending Start DFU command (Op Code = 1, Upload Mode = 4)
2023-12-22 13:13:20.924 11446-16181 DfuImpl         com.project.project         I Sending image size array to DFU Packet (0b, 0b, xxxxxxb)
2023-12-22 13:13:26.100 11446-16181 DfuImpl         com.project.project         I Sending the Initialize DFU Parameters START (Op Code = 2, Value = 0)
2023-12-22 13:13:26.189 11446-16181 DfuImpl         com.project.project         I Sending 14 bytes of init packet
2023-12-22 13:13:26.189 11446-16181 DfuImpl         com.project.project         I Sending init packet (Value = xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx)
2023-12-22 13:13:26.194 11446-16181 DfuImpl         com.project.project         I Sending the Initialize DFU Parameters COMPLETE (Op Code = 2, Value = 1)
2023-12-22 13:13:27.231 11446-16181 DfuImpl         com.project.project         I Sending Receive Firmware Image request (Op Code = 3)
2023-12-22 13:13:27.323 11446-16181 DfuImpl         com.project.project         I Uploading firmware...
2023-12-22 13:13:32.410 11446-11464 BluetoothGatt      com.project.project         D onClientConnectionState() - status=0 clientIf=5 device=xx:xx:xx:xx:xx:xx
2023-12-22 13:13:32.410 11446-11464 DfuBaseService     com.project.project         I Disconnected from GATT server
2023-12-22 13:13:32.411 11446-16181 DfuImpl         com.project.project         E Disconnected while sending data

The android-dfu-library version used in the project is: 2.3.0. The latest working stable version of android-dfu-library for updating the firmware is 1.11.1.

For same chip with this flutter application (with newer android-dfu-library version), DFU works for firmwares other than Infinitime. URL for Android DFU library: https://github.com/NordicSemiconductor/Android-DFU-Library

Version

main

Companion app

No response

JF002 commented 6 months ago

Hi @InfocuspSamyakVora and thank you for reporting this issue.

The DFU protocol implemented in InfiniTime originally comes from the NRF SDK. It was very handy to test the implementation using NRF tools (NRFConnect and some Python scripts) before any FOSS companion supported InfiniTime.

IIRC, at that time, the protocol we implemented was already labelled as "legacy" : no security features, no authentication, no cryptography,...

Recent releases of NRFConnect do not work with InfiniTime anymore. I guess they upgraded the API, or removed support for the legacy protocol.

Maintaining support with whatever decisions NRF take about their DFU protocol is not one of our goals, though, so we simlply removed all mentions of NRFConnect in our documentation, and we encourage users to use one of the many FOSS companion apps that are now available.

Since NRFConnect does not work anymore with InfiniTime, I'm not really surprised that their Android DFU library does not work either. I currently do not plan on supporting them, though.

I guess NRF libs and tools are intended to be used with firmware that integrate NRF BLE stack and bootloader, which are closed source. InfiniTime does not use them. We use Nimble as BLE stack and a custom made bootloader based on MCUBoot. Both Nimble and MCUBoot are open source software.

hardik-infocusp commented 6 months ago

Thanks for the response @JF002.

My hypothesis for latest version of NRFConnect and other apps not working is the "Secure DFU". Android SDK after 1.12 is supporting the "Secure" DFU. I am not sure if that is backward compatible (doing secure and legacy both).

When we use the older android SDK (which supports Legacy DFU), the DFU works fine, but we try to use the latest SDK, it stops working.

Google Play Store doesn't allow using the older SDK anymore and we are forced to use the latest SDK. And that is why we are trying to find the way to get the DFU working with new SDK.

JF002 commented 6 months ago

Well, in that case, if you want to use the NRF SDK on Android, I guess you'll have to implement the new/secure protocol (or whatever the SDK expects) in InfiniTime.

Another option would be to not use the NRF SDK for the OTA and implement the DFU protocol from InfiniTime in your app? Many companion app (Gadgetbridge, Amazfish, Siglo,...) have already done this in multiple languages.

FintasticMan commented 6 months ago

It seems this is an issue that GadgetBridge has also run up against. The solutiom in that case was to call disableMtuRequest() instead of specifying an MTU value. See this comment.