Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package com.pilloxa.dfu;

import android.app.NotificationManager;
Expand Down Expand Up @@ -45,22 +44,39 @@ 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);
} else {
starter.setZip(filePath);
}

Log.d(LOG_TAG, "Starting DFU for device: " + address + " with file: " + filePath);
final DfuServiceController controller = starter.start(this.reactContext, DfuService.class);
}

Expand Down Expand Up @@ -199,4 +215,4 @@ public void onError(final String deviceAddress, final int error, final int error
}
}
};
}
}
17 changes: 16 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -8,6 +21,7 @@ declare module "react-native-nordic-dfu" {
packetReceiptNotificationParameter,
retries,
maxMtu,
forceDfu,
}: {
deviceAddress: string;
deviceName?: string;
Expand All @@ -16,6 +30,7 @@ declare module "react-native-nordic-dfu" {
packetReceiptNotificationParameter?: number;
retries?: number;
maxMtu?: number;
forceDfu?: boolean;
}): Promise<string>;
}

Expand All @@ -36,4 +51,4 @@ declare module "react-native-nordic-dfu" {

static removeAllListeners(name: "DFUProgress" | "DFUStateChanged"): void;
}
}
}
13 changes: 10 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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");
Expand All @@ -72,6 +78,7 @@ function startDFU({
{
retries,
maxMtu,
forceDfu, // NEW: Pass forceDfu to native module
}
);
} else {
Expand All @@ -97,4 +104,4 @@ function startDFU({
*/
const DFUEmitter = new NativeEventEmitter(RNNordicDfu);

export { NordicDFU, DFUEmitter };
export { NordicDFU, DFUEmitter };