diff --git a/android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java b/android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java index 39a0347..5212d93 100644 --- a/android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java +++ b/android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java @@ -1,4 +1,3 @@ - package com.pilloxa.dfu; import android.app.NotificationManager; @@ -45,15 +44,31 @@ public void startDFU(String address, String name, String filePath, int packetRec int mtu = options.getInt("maxMtu"); starter.setMtu(mtu); } + + // NEW: Add forceDfu option for Legacy DFU bootloaders (like Adafruit) + if (options.hasKey("forceDfu")) { + boolean forceDfu = options.getBoolean("forceDfu"); + if (forceDfu) { + starter.setForceDfu(true); + Log.d(LOG_TAG, "Force DFU mode enabled (Legacy DFU)"); + } + } + if (name != null) { starter.setDeviceName(name); } - // mimic behavior of iOSDFULibrary when packetReceiptNotificationParameter is set to `0` - see: https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library/blob/master/iOSDFULibrary/Classes/Implementation/DFUServiceInitiator.swift#L115 + + // mimic behavior of iOSDFULibrary when packetReceiptNotificationParameter is set to `0` - see: https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library/blob/master/iOSDFULibrary/Classes/Implementation/DFUServiceInitiator.swift#L115 if (packetReceiptNotificationParameter > 0) { + starter.setPacketsReceiptNotificationsEnabled(true); starter.setPacketsReceiptNotificationsValue(packetReceiptNotificationParameter); + Log.d(LOG_TAG, "PRN enabled with value: " + packetReceiptNotificationParameter); } else { + starter.setPacketsReceiptNotificationsEnabled(true); starter.setPacketsReceiptNotificationsValue(1); + Log.d(LOG_TAG, "PRN set to default value: 1"); } + starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true); if (filePath.endsWith(".bin") || filePath.endsWith(".hex")) { starter.setBinOrHex(DfuBaseService.TYPE_APPLICATION, filePath).setInitFile(null, null); @@ -61,6 +76,7 @@ public void startDFU(String address, String name, String filePath, int packetRec starter.setZip(filePath); } + Log.d(LOG_TAG, "Starting DFU for device: " + address + " with file: " + filePath); final DfuServiceController controller = starter.start(this.reactContext, DfuService.class); } @@ -199,4 +215,4 @@ public void onError(final String deviceAddress, final int error, final int error } } }; -} +} \ No newline at end of file diff --git a/index.d.ts b/index.d.ts index a7f4b3d..9fe542d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,18 @@ declare module "react-native-nordic-dfu" { export class NordicDFU { + /** + * Start the DFU process + * @param config - DFU configuration object + * @param config.deviceAddress - Device MAC address (Android) or UUID (iOS) + * @param config.deviceName - Optional device name for notification + * @param config.filePath - Path to firmware .zip file + * @param config.alternativeAdvertisingNameEnabled - iOS only: Send unique name before bootloader mode (default: true) + * @param config.packetReceiptNotificationParameter - PRN value: Lower (1-6) = slower/reliable, Higher (10-15) = faster. Use 1 for Legacy DFU. (default: 12) + * @param config.retries - Android only: Number of connection retries (default: 3) + * @param config.maxMtu - Android only: Maximum MTU size (default: 23) + * @param config.forceDfu - Android only: Force DFU mode for Legacy DFU bootloaders like Adafruit (default: false) + * @returns Promise that resolves with device address on success + */ static startDFU({ deviceAddress, deviceName, @@ -8,6 +21,7 @@ declare module "react-native-nordic-dfu" { packetReceiptNotificationParameter, retries, maxMtu, + forceDfu, }: { deviceAddress: string; deviceName?: string; @@ -16,6 +30,7 @@ declare module "react-native-nordic-dfu" { packetReceiptNotificationParameter?: number; retries?: number; maxMtu?: number; + forceDfu?: boolean; }): Promise; } @@ -36,4 +51,4 @@ declare module "react-native-nordic-dfu" { static removeAllListeners(name: "DFUProgress" | "DFUStateChanged"): void; } -} +} \ No newline at end of file diff --git a/index.js b/index.js index 3ad12b9..1efe7c1 100644 --- a/index.js +++ b/index.js @@ -25,7 +25,10 @@ function rejectPromise(message) { * @param {string} [obj.deviceName = null] The name of the device in the update notification * @param {string} obj.filePath The file system path to the zip-file used for updating * @param {Boolean} obj.alternativeAdvertisingNameEnabled Send unique name to device before it is switched into bootloader mode (iOS only) - * @param {number} obj.packetReceiptNotificationParameter set number of packets of firmware data to be received by the DFU target before sending a new Packet Receipt Notification + * @param {number} obj.packetReceiptNotificationParameter Set number of packets of firmware data to be received by the DFU target before sending a new Packet Receipt Notification. Lower values (1-6) = slower but more reliable. Higher values (10-15) = faster. Use 1 for problematic Legacy DFU bootloaders. + * @param {number} obj.retries Number of connection retries (Android only, default: 3) + * @param {number} obj.maxMtu Maximum MTU size (Android only, default: 23) + * @param {Boolean} obj.forceDfu Force DFU mode - required for Legacy DFU bootloaders like Adafruit (Android only, default: false) * @returns {Promise} A promise that resolves or rejects with the `deviceAddress` in the return value * * @example @@ -34,7 +37,9 @@ function rejectPromise(message) { * NordicDFU.startDFU({ * deviceAddress: "C3:53:C0:39:2F:99", * deviceName: "Pilloxa Pillbox", - * filePath: "/data/user/0/com.nordicdfuexample/files/RNFetchBlobTmp4of.zip" + * filePath: "/data/user/0/com.nordicdfuexample/files/RNFetchBlobTmp4of.zip", + * packetReceiptNotificationParameter: 1, // Use 1 for Adafruit boards + * forceDfu: true // Enable for Legacy DFU bootloaders * }) * .then(res => console.log("Transfer done:", res)) * .catch(console.log); @@ -47,6 +52,7 @@ function startDFU({ packetReceiptNotificationParameter = 12, retries = 3, // Android only maxMtu = 23, // Android only + forceDfu = false, // Android only - NEW: for Legacy DFU bootloaders }) { if (deviceAddress == undefined) { return rejectPromise("No deviceAddress defined"); @@ -72,6 +78,7 @@ function startDFU({ { retries, maxMtu, + forceDfu, // NEW: Pass forceDfu to native module } ); } else { @@ -97,4 +104,4 @@ function startDFU({ */ const DFUEmitter = new NativeEventEmitter(RNNordicDfu); -export { NordicDFU, DFUEmitter }; +export { NordicDFU, DFUEmitter }; \ No newline at end of file