@ledgerhq/device-transport-kit-react-native-hid 0.0.0-rn-hid-20250221115747 → 0.0.0-rn-hid-sync-onboarding-behavior-20250516092329

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1 -1
  2. package/android/build.gradle +3 -1
  3. package/android/src/main/kotlin/com/ledger/androidtransporthid/TransportHidModule.kt +14 -5
  4. package/android/src/main/kotlin/com/ledger/androidtransporthid/bridge/serialization.kt +2 -0
  5. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/DefaultAndroidUsbTransport.kt +75 -32
  6. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/connection/AndroidUsbApduSender.kt +72 -32
  7. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/controller/UsbPermissionReceiver.kt +1 -1
  8. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/utils/UsbDeviceMapper.kt +27 -36
  9. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/UsbConst.android.kt +1 -1
  10. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceApduSender.kt +2 -1
  11. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnection.kt +11 -11
  12. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionStateMachine.kt +8 -4
  13. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/SendApduResult.kt +4 -0
  14. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/device/LedgerDevice.kt +64 -49
  15. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/device/UsbInfo.kt +4 -3
  16. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/connection/InternalConnectedDevice.kt +1 -1
  17. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/FramerService.kt +1 -1
  18. package/android/src/test/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionStateMachineTest.kt +713 -0
  19. package/android/src/test/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionTest.kt +218 -0
  20. package/lib/cjs/api/bridge/DefaultNativeModuleWrapper.js +1 -1
  21. package/lib/cjs/api/bridge/DefaultNativeModuleWrapper.js.map +3 -3
  22. package/lib/cjs/api/bridge/NativeTransportModule.js +1 -1
  23. package/lib/cjs/api/bridge/NativeTransportModule.js.map +1 -1
  24. package/lib/cjs/api/bridge/mapper.js +1 -1
  25. package/lib/cjs/api/bridge/mapper.js.map +2 -2
  26. package/lib/cjs/api/bridge/types.js +1 -1
  27. package/lib/cjs/api/bridge/types.js.map +1 -1
  28. package/lib/cjs/api/transport/NativeModuleWrapper.js +1 -1
  29. package/lib/cjs/api/transport/NativeModuleWrapper.js.map +1 -1
  30. package/lib/cjs/api/transport/RNHidTransport.js +1 -1
  31. package/lib/cjs/api/transport/RNHidTransport.js.map +3 -3
  32. package/lib/cjs/package.json +17 -12
  33. package/lib/esm/api/bridge/DefaultNativeModuleWrapper.js +1 -1
  34. package/lib/esm/api/bridge/DefaultNativeModuleWrapper.js.map +3 -3
  35. package/lib/esm/api/bridge/NativeTransportModule.js +1 -1
  36. package/lib/esm/api/bridge/NativeTransportModule.js.map +1 -1
  37. package/lib/esm/api/bridge/mapper.js +1 -1
  38. package/lib/esm/api/bridge/mapper.js.map +3 -3
  39. package/lib/esm/api/bridge/types.js.map +1 -1
  40. package/lib/esm/api/transport/RNHidTransport.js +1 -1
  41. package/lib/esm/api/transport/RNHidTransport.js.map +3 -3
  42. package/lib/esm/package.json +17 -12
  43. package/lib/types/api/bridge/DefaultNativeModuleWrapper.d.ts +1 -1
  44. package/lib/types/api/bridge/DefaultNativeModuleWrapper.d.ts.map +1 -1
  45. package/lib/types/api/bridge/NativeTransportModule.d.ts.map +1 -1
  46. package/lib/types/api/bridge/mapper.d.ts.map +1 -1
  47. package/lib/types/api/bridge/types.d.ts +2 -2
  48. package/lib/types/api/bridge/types.d.ts.map +1 -1
  49. package/lib/types/api/transport/NativeModuleWrapper.d.ts +1 -1
  50. package/lib/types/api/transport/NativeModuleWrapper.d.ts.map +1 -1
  51. package/lib/types/api/transport/RNHidTransport.d.ts.map +1 -1
  52. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  53. package/package.json +19 -14
  54. package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
  55. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  56. package/android/gradle/wrapper/gradle-wrapper.properties +0 -7
  57. package/android/gradlew +0 -252
  58. package/android/gradlew.bat +0 -94
  59. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/DeviceAction.kt +0 -23
@@ -3,6 +3,7 @@ package com.ledger.devicesdk.shared.androidMainInternal.transport.deviceconnecti
3
3
  import com.ledger.devicesdk.shared.api.apdu.SendApduResult
4
4
  import com.ledger.devicesdk.shared.internal.service.logger.LoggerService
5
5
  import com.ledger.devicesdk.shared.internal.service.logger.buildSimpleErrorLogInfo
6
+ import kotlinx.coroutines.CoroutineDispatcher
6
7
  import kotlinx.coroutines.CoroutineScope
7
8
  import kotlinx.coroutines.launch
8
9
  import kotlin.coroutines.resume
@@ -14,17 +15,18 @@ internal class DeviceConnection<Dependencies>(
14
15
  private var deviceApduSender: DeviceApduSender<Dependencies>,
15
16
  isFatalSendApduFailure: (SendApduResult.Failure) -> Boolean,
16
17
  reconnectionTimeoutDuration: Duration,
18
+ coroutineDispatcher: CoroutineDispatcher,
17
19
  private val onTerminated: (DeviceConnection<Dependencies>) -> Unit,
18
- private val coroutineScope: CoroutineScope,
19
20
  private val loggerService: LoggerService,
20
21
  ) {
21
22
  private val stateMachine: DeviceConnectionStateMachine
23
+ private val coroutineScope = CoroutineScope(coroutineDispatcher)
22
24
 
23
25
  init {
24
26
  stateMachine = DeviceConnectionStateMachine(
25
- sendApduFn = {
27
+ sendApduFn = { apdu, abortTimeoutDuration ->
26
28
  coroutineScope.launch {
27
- val res = deviceApduSender.send(it)
29
+ val res = deviceApduSender.send(apdu, abortTimeoutDuration)
28
30
  handleApduResult(res)
29
31
  }
30
32
  },
@@ -33,7 +35,7 @@ internal class DeviceConnection<Dependencies>(
33
35
  },
34
36
  isFatalSendApduFailure = isFatalSendApduFailure,
35
37
  reconnectionTimeoutDuration = reconnectionTimeoutDuration,
36
- coroutineScope = coroutineScope,
38
+ coroutineDispatcher = coroutineDispatcher,
37
39
  onError = {
38
40
  loggerService.log(
39
41
  buildSimpleErrorLogInfo(
@@ -51,15 +53,12 @@ internal class DeviceConnection<Dependencies>(
51
53
  stateMachine.handleApduResult(result)
52
54
  }
53
55
 
54
- public fun setApduSender(apduSender: DeviceApduSender<Dependencies>) {
55
- deviceApduSender = apduSender
56
- }
57
-
58
56
  public fun getApduSender(): DeviceApduSender<Dependencies> {
59
57
  return deviceApduSender
60
58
  }
61
59
 
62
- public fun handleDeviceConnected() {
60
+ public fun handleDeviceConnected(apduSender: DeviceApduSender<Dependencies>) {
61
+ deviceApduSender = apduSender
63
62
  stateMachine.handleDeviceConnected()
64
63
  }
65
64
 
@@ -67,12 +66,13 @@ internal class DeviceConnection<Dependencies>(
67
66
  stateMachine.handleDeviceDisconnected()
68
67
  }
69
68
 
70
- public suspend fun requestSendApdu(apdu: ByteArray): SendApduResult =
69
+ public suspend fun requestSendApdu(apdu: ByteArray, triggersDisconnection: Boolean, abortTimeoutDuration: Duration): SendApduResult =
71
70
  suspendCoroutine { cont ->
72
71
  stateMachine.requestSendApdu(
73
72
  DeviceConnectionStateMachine.SendApduRequestContent(
74
73
  apdu = apdu,
75
- triggersDisconnection = apduTriggersDisconnection(apdu),
74
+ triggersDisconnection = apduTriggersDisconnection(apdu) || triggersDisconnection,
75
+ abortTimeoutDuration = abortTimeoutDuration,
76
76
  resultCallback = cont::resume
77
77
  )
78
78
  )
@@ -5,28 +5,31 @@ import com.ledger.devicesdk.shared.api.apdu.SendApduResult
5
5
  import com.ledger.devicesdk.shared.internal.service.logger.LoggerService
6
6
  import com.ledger.devicesdk.shared.internal.service.logger.buildSimpleDebugLogInfo
7
7
  import com.ledger.devicesdk.shared.internal.service.logger.buildSimpleInfoLogInfo
8
+ import kotlinx.coroutines.CoroutineDispatcher
8
9
  import kotlinx.coroutines.CoroutineScope
9
10
  import kotlinx.coroutines.Job
10
11
  import kotlinx.coroutines.launch
11
12
  import kotlin.time.Duration
12
13
 
13
14
  internal class DeviceConnectionStateMachine(
14
- private val sendApduFn: (apdu: ByteArray) -> Unit,
15
+ private val sendApduFn: (apdu: ByteArray, abortTimeoutDuration: Duration) -> Unit,
15
16
  private val onTerminated: () -> Unit,
16
17
  private val isFatalSendApduFailure: (SendApduResult.Failure) -> Boolean,
17
18
  private val reconnectionTimeoutDuration: Duration,
18
- private val coroutineScope: CoroutineScope,
19
19
  private val onError: (Throwable) -> Unit,
20
20
  private val loggerService: LoggerService,
21
+ coroutineDispatcher: CoroutineDispatcher,
21
22
  ) {
22
-
23
+ private val coroutineScope = CoroutineScope(coroutineDispatcher)
23
24
  private var state: State = State.Connected
24
25
 
26
+ fun getState() = state
27
+
25
28
  private fun pushState(newState: State) {
26
29
  when (newState) {
27
30
  is State.Connected -> {}
28
31
  is State.SendingApdu -> {
29
- sendApduFn(newState.requestContent.apdu)
32
+ sendApduFn(newState.requestContent.apdu, newState.requestContent.abortTimeoutDuration)
30
33
  }
31
34
 
32
35
  is State.WaitingForReconnection -> {
@@ -277,6 +280,7 @@ internal class DeviceConnectionStateMachine(
277
280
  data class SendApduRequestContent(
278
281
  val apdu: ByteArray,
279
282
  val triggersDisconnection: Boolean,
283
+ val abortTimeoutDuration: Duration,
280
284
  val resultCallback: (SendApduResult) -> Unit
281
285
  )
282
286
 
@@ -44,4 +44,8 @@ public sealed class SendApduFailureReason {
44
44
  public data object DeviceDisconnected : SendApduFailureReason()
45
45
 
46
46
  public data object Unknown : SendApduFailureReason()
47
+
48
+ public data object AbortTimeout : SendApduFailureReason()
49
+
50
+ public data object EmptyResponse : SendApduFailureReason()
47
51
  }
@@ -1,62 +1,76 @@
1
1
  package com.ledger.devicesdk.shared.api.device
2
2
 
3
3
  public sealed class LedgerDevice(
4
- public val name: String,
5
- public val usbInfo: UsbInfo,
6
- public val bleInformation: BleInformation? = null,
4
+ public val name: String,
5
+ public val usbInfo: UsbInfo,
6
+ public val bleInformation: BleInformation? = null,
7
7
  ) {
8
- public data object Flex : LedgerDevice(
9
- name = "Ledger Flex",
10
- usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x70"),
11
- bleInformation =
12
- BleInformation(
13
- serviceUuid = "13d63400-2c97-3004-0000-4c6564676572",
14
- notifyCharacteristicUuid = "13d63400-2c97-3004-0001-4c6564676572",
15
- writeWithResponseCharacteristicUuid = "13d63400-2c97-3004-0002-4c6564676572",
16
- writeWithoutResponseCharacteristicUuid = "13d63400-2c97-3004-0003-4c6564676572",
17
- ),
18
- )
8
+ public data object Flex :
9
+ LedgerDevice(
10
+ name = "Ledger Flex",
11
+ usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x70", "0x0007"),
12
+ bleInformation =
13
+ BleInformation(
14
+ serviceUuid = "13d63400-2c97-3004-0000-4c6564676572",
15
+ notifyCharacteristicUuid =
16
+ "13d63400-2c97-3004-0001-4c6564676572",
17
+ writeWithResponseCharacteristicUuid =
18
+ "13d63400-2c97-3004-0002-4c6564676572",
19
+ writeWithoutResponseCharacteristicUuid =
20
+ "13d63400-2c97-3004-0003-4c6564676572",
21
+ ),
22
+ )
19
23
 
20
- public data object Stax : LedgerDevice(
21
- name = "Ledger Stax",
22
- usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x60"),
23
- bleInformation =
24
- BleInformation(
25
- serviceUuid = "13d63400-2c97-6004-0000-4c6564676572",
26
- notifyCharacteristicUuid = "13d63400-2c97-6004-0001-4c6564676572",
27
- writeWithResponseCharacteristicUuid = "13d63400-2c97-6004-0002-4c6564676572",
28
- writeWithoutResponseCharacteristicUuid = "13d63400-2c97-6004-0003-4c6564676572",
29
- ),
30
- )
24
+ public data object Stax :
25
+ LedgerDevice(
26
+ name = "Ledger Stax",
27
+ usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x60", "0x0006"),
28
+ bleInformation =
29
+ BleInformation(
30
+ serviceUuid = "13d63400-2c97-6004-0000-4c6564676572",
31
+ notifyCharacteristicUuid =
32
+ "13d63400-2c97-6004-0001-4c6564676572",
33
+ writeWithResponseCharacteristicUuid =
34
+ "13d63400-2c97-6004-0002-4c6564676572",
35
+ writeWithoutResponseCharacteristicUuid =
36
+ "13d63400-2c97-6004-0003-4c6564676572",
37
+ ),
38
+ )
31
39
 
32
- public data object NanoX : LedgerDevice(
33
- name = "Nano X",
34
- usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x40"),
35
- bleInformation =
36
- BleInformation(
37
- serviceUuid = "13d63400-2c97-0004-0000-4c6564676572",
38
- notifyCharacteristicUuid = "13d63400-2c97-0004-0001-4c6564676572",
39
- writeWithResponseCharacteristicUuid = "13d63400-2c97-0004-0002-4c6564676572",
40
- writeWithoutResponseCharacteristicUuid = "13d63400-2c97-0004-0003-4c6564676572",
41
- ),
42
- )
40
+ public data object NanoX :
41
+ LedgerDevice(
42
+ name = "Nano X",
43
+ usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x40", "0x0004"),
44
+ bleInformation =
45
+ BleInformation(
46
+ serviceUuid = "13d63400-2c97-0004-0000-4c6564676572",
47
+ notifyCharacteristicUuid =
48
+ "13d63400-2c97-0004-0001-4c6564676572",
49
+ writeWithResponseCharacteristicUuid =
50
+ "13d63400-2c97-0004-0002-4c6564676572",
51
+ writeWithoutResponseCharacteristicUuid =
52
+ "13d63400-2c97-0004-0003-4c6564676572",
53
+ ),
54
+ )
43
55
 
44
- public data object NanoSPlus : LedgerDevice(
45
- name = "Nano S Plus",
46
- usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x50"),
47
- bleInformation = null,
48
- )
56
+ public data object NanoSPlus :
57
+ LedgerDevice(
58
+ name = "Nano S Plus",
59
+ usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x50", "0x0005"),
60
+ bleInformation = null,
61
+ )
49
62
 
50
- public data object NanoS : LedgerDevice(
51
- name = "Nano S",
52
- usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x10"),
53
- bleInformation = null,
54
- )
63
+ public data object NanoS :
64
+ LedgerDevice(
65
+ name = "Nano S",
66
+ usbInfo = UsbInfo(LEDGER_USB_VENDOR_ID, "0x10", "0x0001"),
67
+ bleInformation = null,
68
+ )
55
69
 
56
70
  public companion object {
57
71
  public const val LEDGER_USB_VENDOR_ID: String = "0x2c97"
58
72
 
59
- //Cannot use reflexion here to get all subclasses as it depends of the JVM
73
+ // Cannot use reflexion here to get all subclasses as it depends of the JVM
60
74
  private val subclasses = buildList {
61
75
  add(Flex)
62
76
  add(Stax)
@@ -69,6 +83,7 @@ public sealed class LedgerDevice(
69
83
  return subclasses
70
84
  }
71
85
 
72
- public fun getAllDevicesWithBluetooth(): List<LedgerDevice> = getAllDevices().filter { it.bleInformation != null }
86
+ public fun getAllDevicesWithBluetooth(): List<LedgerDevice> =
87
+ getAllDevices().filter { it.bleInformation != null }
73
88
  }
74
- }
89
+ }
@@ -1,6 +1,7 @@
1
1
  package com.ledger.devicesdk.shared.api.device
2
2
 
3
3
  public data class UsbInfo(
4
- val vendorId: String,
5
- val productIdMask: String,
6
- )
4
+ val vendorId: String,
5
+ val productIdMask: String,
6
+ val bootloaderProductId: String,
7
+ )
@@ -9,5 +9,5 @@ internal data class InternalConnectedDevice(
9
9
  val name: String,
10
10
  val ledgerDevice: LedgerDevice,
11
11
  val connectivity: ConnectivityType,
12
- val sendApduFn: suspend (ByteArray) -> SendApduResult,
12
+ val sendApduFn: suspend (apdu: ByteArray, triggersDisconnection: Boolean, abortTimeoutDuration: kotlin.time.Duration) -> SendApduResult,
13
13
  )
@@ -186,7 +186,7 @@ internal class FramerService(
186
186
  apduSize = null
187
187
  rawApdu = parser.extractRemainingBytesValue()
188
188
  }
189
- nbrDataRead += mtu
189
+ nbrDataRead += rawApdu.size
190
190
  add(
191
191
  ApduFrame(
192
192
  header = header,