@ledgerhq/device-transport-kit-react-native-hid 0.0.0-rn-hid-20250221112139 → 0.0.0-rnhid-transport-20250411151739

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 (72) hide show
  1. package/README.md +1 -1
  2. package/android/build.gradle +101 -0
  3. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  4. package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  5. package/android/gradle.properties +1 -0
  6. package/android/gradlew +252 -0
  7. package/android/gradlew.bat +94 -0
  8. package/android/src/main/AndroidManifest.xml +3 -0
  9. package/android/src/main/kotlin/com/ledger/androidtransporthid/BridgeEvents.kt +42 -0
  10. package/android/src/main/kotlin/com/ledger/androidtransporthid/TransportHidModule.kt +241 -0
  11. package/android/src/main/kotlin/com/ledger/androidtransporthid/TransportHidPackage.kt +25 -0
  12. package/android/src/main/kotlin/com/ledger/androidtransporthid/bridge/serialization.kt +124 -0
  13. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/AndroidUsbTransport.kt +16 -0
  14. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/DefaultAndroidUsbTransport.kt +298 -0
  15. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/UsbPermissionRequester.kt +18 -0
  16. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/connection/AndroidUsbApduSender.kt +133 -0
  17. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/controller/UsbAttachedReceiverController.kt +59 -0
  18. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/controller/UsbDetachedReceiverController.kt +58 -0
  19. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/controller/UsbPermissionReceiver.kt +92 -0
  20. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/model/LedgerUsbDevice.kt +16 -0
  21. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/model/ProductId.kt +11 -0
  22. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/model/UsbPermissionEvent.kt +14 -0
  23. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/model/UsbState.kt +16 -0
  24. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/model/VendorId.kt +11 -0
  25. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/utils/UsbDeviceMapper.kt +46 -0
  26. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMain/transport/usb/utils/UsbMapper.kt +56 -0
  27. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/UsbConst.android.kt +8 -0
  28. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceApduSender.kt +13 -0
  29. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnection.kt +95 -0
  30. package/android/src/main/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionStateMachine.kt +314 -0
  31. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/Apdu.kt +44 -0
  32. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/ApduBuilder.kt +88 -0
  33. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/ApduParser.kt +37 -0
  34. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/ApduUtils.kt +37 -0
  35. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/apdu/SendApduResult.kt +47 -0
  36. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/connection/ConnectedDevice.kt +25 -0
  37. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/connection/ConnectionResult.kt +45 -0
  38. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/device/BleInformation.kt +8 -0
  39. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/device/LedgerDevice.kt +89 -0
  40. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/device/UsbInfo.kt +7 -0
  41. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/disconnection/DisconnectionResult.kt +10 -0
  42. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/discovery/ConnectivityType.kt +10 -0
  43. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/discovery/DiscoveryDevice.kt +18 -0
  44. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/discovery/DiscoveryResult.kt +28 -0
  45. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/utils/ByteArrayExtension.kt +116 -0
  46. package/android/src/main/kotlin/com/ledger/devicesdk/shared/api/utils/StringExtension.kt +21 -0
  47. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/connection/InternalConnectedDevice.kt +13 -0
  48. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/connection/InternalConnectionResult.kt +41 -0
  49. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/coroutine/SDKScope.kt +25 -0
  50. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/coroutine/SDKScopeHandler.kt +18 -0
  51. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/event/SdkEventDispatcher.kt +19 -0
  52. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/service/logger/DisableLoggerService.kt +12 -0
  53. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/service/logger/LogInfo.kt +52 -0
  54. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/service/logger/LogLevel.kt +13 -0
  55. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/service/logger/LoggerService.kt +10 -0
  56. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/Transport.kt +21 -0
  57. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/TransportEvent.kt +18 -0
  58. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/FramerService.kt +210 -0
  59. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/FramerUtils.kt +35 -0
  60. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/model/ApduConst.kt +9 -0
  61. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/model/ApduFrame.kt +66 -0
  62. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/model/ApduFramerHeader.kt +74 -0
  63. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/framer/model/FramerConst.kt +14 -0
  64. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/utils/ByteExtension.kt +21 -0
  65. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/transport/utils/InternalByteArrayExtension.kt +18 -0
  66. package/android/src/main/kotlin/com/ledger/devicesdk/shared/internal/utils/Controller.kt +12 -0
  67. package/android/src/test/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionStateMachineTest.kt +713 -0
  68. package/android/src/test/kotlin/com/ledger/devicesdk/shared/androidMainInternal/transport/deviceconnection/DeviceConnectionTest.kt +218 -0
  69. package/lib/cjs/package.json +2 -1
  70. package/lib/esm/package.json +2 -1
  71. package/lib/types/tsconfig.prod.tsbuildinfo +1 -1
  72. package/package.json +6 -5
@@ -0,0 +1,241 @@
1
+ package com.ledger.androidtransporthid
2
+
3
+ import android.app.PendingIntent
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import android.hardware.usb.UsbManager
7
+ import android.util.Base64
8
+ import com.facebook.react.bridge.LifecycleEventListener
9
+ import com.facebook.react.bridge.Promise
10
+ import com.facebook.react.bridge.ReactApplicationContext
11
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
12
+ import com.facebook.react.bridge.ReactMethod
13
+ import com.ledger.androidtransporthid.bridge.toWritableMap
14
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.AndroidUsbTransport
15
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.DefaultAndroidUsbTransport
16
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.controller.ACTION_USB_PERMISSION
17
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.controller.UsbAttachedReceiverController
18
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.controller.UsbDetachedReceiverController
19
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.controller.UsbPermissionReceiver
20
+ import com.ledger.devicesdk.shared.api.discovery.DiscoveryDevice
21
+ import com.ledger.devicesdk.shared.internal.connection.InternalConnectedDevice
22
+ import com.ledger.devicesdk.shared.internal.connection.InternalConnectionResult
23
+ import com.ledger.devicesdk.shared.internal.event.SdkEventDispatcher
24
+ import com.ledger.devicesdk.shared.internal.service.logger.LoggerService
25
+ import com.ledger.devicesdk.shared.internal.transport.TransportEvent
26
+ import kotlinx.coroutines.CoroutineScope
27
+ import kotlinx.coroutines.Dispatchers
28
+ import kotlinx.coroutines.Job
29
+ import kotlinx.coroutines.flow.launchIn
30
+ import kotlinx.coroutines.flow.onEach
31
+ import kotlinx.coroutines.launch
32
+ import timber.log.Timber
33
+ import kotlin.random.Random
34
+ import kotlin.time.Duration.Companion.milliseconds
35
+
36
+ class TransportHidModule(
37
+ private val reactContext: ReactApplicationContext,
38
+ private val coroutineScope: CoroutineScope
39
+ ) :
40
+ ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
41
+ override fun getName(): String = "RCTTransportHIDModule"
42
+
43
+ private var usbPermissionReceiver: UsbPermissionReceiver? = null
44
+ private var usbAttachedReceiverController: UsbAttachedReceiverController? = null
45
+ private var usbDetachedReceiverController: UsbDetachedReceiverController? = null
46
+ private var sdkEventDispatcher: SdkEventDispatcher = SdkEventDispatcher()
47
+ private var eventDispatcherListeningJob: Job
48
+ private val loggerService: LoggerService =
49
+ LoggerService { info ->
50
+ Timber.tag("RNHIDModule " + info.tag).d(info.message)
51
+ sendEvent(reactContext, BridgeEvents.TransportLog(info))
52
+ }
53
+
54
+ private val transport: AndroidUsbTransport? by lazy {
55
+ val currentActivity = reactContext.currentActivity
56
+ val currentApplication = currentActivity?.application
57
+
58
+ var transport: AndroidUsbTransport? = null
59
+ if (currentApplication != null) {
60
+ val usbManager = reactContext.getSystemService(Context.USB_SERVICE) as UsbManager
61
+ transport = DefaultAndroidUsbTransport(
62
+ application = currentApplication,
63
+ usbManager = usbManager,
64
+ permissionRequester = { context, manager, device ->
65
+ manager.requestPermission(
66
+ device,
67
+ PendingIntent.getBroadcast(
68
+ context,
69
+ Random.nextInt(),
70
+ Intent(ACTION_USB_PERMISSION).apply {
71
+ setPackage(context.packageName)
72
+ },
73
+ PendingIntent.FLAG_IMMUTABLE,
74
+ ),
75
+ )
76
+ },
77
+ eventDispatcher = sdkEventDispatcher,
78
+ coroutineDispatcher = Dispatchers.IO,
79
+ loggerService = loggerService,
80
+ scanDelay = 500.milliseconds,
81
+ )
82
+ usbPermissionReceiver = UsbPermissionReceiver(
83
+ context = reactContext,
84
+ androidUsbTransport = transport,
85
+ usbManager = usbManager,
86
+ loggerService = loggerService
87
+ )
88
+ usbDetachedReceiverController = UsbDetachedReceiverController(
89
+ context = reactContext,
90
+ androidUsbTransport = transport,
91
+ )
92
+ usbAttachedReceiverController = UsbAttachedReceiverController(
93
+ context = reactContext,
94
+ androidUsbTransport = transport,
95
+ )
96
+ usbPermissionReceiver!!.start()
97
+ usbAttachedReceiverController!!.start()
98
+ usbDetachedReceiverController!!.start()
99
+ }
100
+ transport
101
+ }
102
+
103
+ private val discoveryDevices: MutableList<DiscoveryDevice> = mutableListOf()
104
+ private val connectedDevices: MutableList<InternalConnectedDevice> = mutableListOf()
105
+
106
+ init {
107
+ reactContext.addLifecycleEventListener(this)
108
+ Timber.plant(Timber.DebugTree())
109
+ eventDispatcherListeningJob = sdkEventDispatcher.listen().onEach {
110
+ when (it) {
111
+ is TransportEvent.DeviceConnectionLost -> {
112
+ Timber.tag("RNHIDModule")
113
+ Timber.i("TransportEvent.DeviceConnectionLost ${it.id}")
114
+ connectedDevices.removeIf { device -> device.id == it.id }
115
+ sendEvent(reactContext, BridgeEvents.DeviceDisconnected(it))
116
+ }
117
+
118
+ else -> {}
119
+ }
120
+ }.launchIn(scope = coroutineScope)
121
+ }
122
+
123
+ override fun onHostResume() {}
124
+
125
+ override fun onHostPause() {}
126
+
127
+ override fun onHostDestroy() {
128
+ usbPermissionReceiver?.stop()
129
+ usbAttachedReceiverController?.stop()
130
+ usbDetachedReceiverController?.stop()
131
+ eventDispatcherListeningJob.cancel()
132
+ transport?.stopScan()
133
+ }
134
+
135
+ private var discoveryCount = 0
136
+
137
+ @ReactMethod
138
+ fun startScan(promise: Promise) {
139
+ discoveryCount += 1
140
+ if (discoveryCount > 1) {
141
+ promise.resolve(null)
142
+ return
143
+ }
144
+ try {
145
+ transport!!.startScan().onEach {
146
+ discoveryDevices.clear()
147
+ discoveryDevices += it
148
+ sendEvent(reactContext, BridgeEvents.DiscoveredDevices(it))
149
+ }.launchIn(scope = coroutineScope)
150
+ promise.resolve(null)
151
+ } catch (e: Exception) {
152
+ promise.reject(e);
153
+ }
154
+ }
155
+
156
+ @ReactMethod
157
+ fun stopScan(promise: Promise) {
158
+ discoveryCount -= 1
159
+ if (discoveryCount > 0) {
160
+ promise.resolve(null)
161
+ return
162
+ }
163
+ try {
164
+ transport!!.stopScan()
165
+ promise.resolve(null)
166
+ } catch (e: Exception) {
167
+ promise.reject(e);
168
+ }
169
+ }
170
+
171
+ @ReactMethod()
172
+ fun connectDevice(uid: String, promise: Promise) {
173
+ val device = discoveryDevices.firstOrNull { it.uid == uid }
174
+ if (device == null) {
175
+ promise.reject(Exception("[TransportHidModule][connectDevice] Device not found"))
176
+ return
177
+ }
178
+
179
+ coroutineScope.launch {
180
+ try {
181
+ val connectionResult = transport!!.connect(device)
182
+ when (connectionResult) {
183
+ is InternalConnectionResult.Connected -> {
184
+ connectedDevices.add(connectionResult.device)
185
+ }
186
+
187
+ else -> {}
188
+ }
189
+ promise.resolve(connectionResult.toWritableMap())
190
+ } catch (e: Exception) {
191
+ promise.reject(e)
192
+ }
193
+ }
194
+ }
195
+
196
+ @ReactMethod
197
+ fun disconnectDevice(sessionId: String, promise: Promise) {
198
+ coroutineScope.launch {
199
+ try {
200
+ transport!!.disconnect(sessionId)
201
+ promise.resolve(null);
202
+ } catch (e: Exception) {
203
+ promise.reject(e)
204
+ }
205
+ }
206
+ }
207
+
208
+ @ReactMethod
209
+ fun sendApdu(sessionId: String, apduBase64: String, promise: Promise) {
210
+ try {
211
+ val device = connectedDevices.firstOrNull() { it.id == sessionId }
212
+ if (device == null) {
213
+ promise.reject(Exception("[TransportHidModule][sendApdu] Device not found"))
214
+ return
215
+ }
216
+ coroutineScope.launch {
217
+ try {
218
+ val apdu: ByteArray = Base64.decode(apduBase64, Base64.DEFAULT)
219
+ val res = device.sendApduFn(apdu)
220
+ promise.resolve(res.toWritableMap())
221
+ } catch (e: Exception) {
222
+ Timber.i("$e, ${e.cause}")
223
+ promise.reject(e)
224
+ }
225
+ }
226
+ } catch (e: Exception) {
227
+ Timber.i("$e, ${e.cause}")
228
+ promise.reject(e)
229
+ }
230
+ }
231
+
232
+ @ReactMethod
233
+ fun addListener(eventName: String) {
234
+ // Nothing to do in our case, but React Native will issue a warning if this isn't implemented
235
+ }
236
+
237
+ @ReactMethod
238
+ fun removeListeners(count: Int) {
239
+ // Nothing to do in our case, but React Native will issue a warning if this isn't implemented
240
+ }
241
+ }
@@ -0,0 +1,25 @@
1
+ package com.ledger.androidtransporthid
2
+
3
+ import android.view.View
4
+ import com.facebook.react.ReactPackage
5
+ import com.facebook.react.bridge.NativeModule
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.uimanager.ReactShadowNode
8
+ import com.facebook.react.uimanager.ViewManager
9
+ import kotlinx.coroutines.CoroutineScope
10
+ import kotlinx.coroutines.Dispatchers
11
+
12
+ class TransportHidPackage() : ReactPackage {
13
+ override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
14
+ return mutableListOf(
15
+ TransportHidModule(
16
+ reactContext = reactContext,
17
+ coroutineScope = CoroutineScope(Dispatchers.Default)
18
+ )
19
+ )
20
+ }
21
+
22
+ override fun createViewManagers(p0: ReactApplicationContext): MutableList<ViewManager<View, ReactShadowNode<*>>> {
23
+ return mutableListOf()
24
+ }
25
+ }
@@ -0,0 +1,124 @@
1
+ package com.ledger.androidtransporthid.bridge
2
+
3
+ import android.util.Base64
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.bridge.WritableArray
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.ledger.devicesdk.shared.api.apdu.SendApduFailureReason
8
+ import com.ledger.devicesdk.shared.api.apdu.SendApduResult
9
+ import com.ledger.devicesdk.shared.api.device.LedgerDevice
10
+ import com.ledger.devicesdk.shared.api.discovery.ConnectivityType
11
+ import com.ledger.devicesdk.shared.api.discovery.DiscoveryDevice
12
+ import com.ledger.devicesdk.shared.internal.connection.InternalConnectionResult
13
+ import com.ledger.devicesdk.shared.internal.service.logger.LogInfo
14
+ import com.ledger.devicesdk.shared.internal.service.logger.LogLevel
15
+ import com.ledger.devicesdk.shared.internal.transport.TransportEvent
16
+ import kotlinx.datetime.Clock
17
+
18
+ fun LedgerDevice.toWritableMap(): WritableMap =
19
+ Arguments.createMap().apply {
20
+ putString("name", name)
21
+ putString("usbProductIdMask", usbInfo.productIdMask)
22
+ }
23
+
24
+ fun DiscoveryDevice.toWritableMap(): WritableMap =
25
+ Arguments.createMap().apply {
26
+ putString("uid", uid)
27
+ putString("name", name)
28
+ putMap("ledgerDevice", ledgerDevice.toWritableMap())
29
+ }
30
+
31
+
32
+ internal fun LogLevel.toSerializedString(): String =
33
+ when (this) {
34
+ LogLevel.DEBUG -> "debug"
35
+ LogLevel.INFO -> "info"
36
+ LogLevel.WARNING -> "warning"
37
+ LogLevel.ERROR -> "error"
38
+ }
39
+
40
+
41
+ internal fun LogInfo.toWritableMap(): WritableMap =
42
+ Arguments.createMap().apply {
43
+ putString("level", level.toSerializedString())
44
+ putString("tag", "[TransportHidModule][${tag}]")
45
+ putString("message", message)
46
+ putMap("jsonPayLoad", Arguments.makeNativeMap(jsonPayLoad))
47
+ putString("timestamp", Clock.System.now().toEpochMilliseconds().toString())
48
+ }
49
+
50
+ internal fun InternalConnectionResult.toWritableMap(): WritableMap =
51
+ when (this) {
52
+ is InternalConnectionResult.Connected -> {
53
+ Arguments.createMap().apply {
54
+ putBoolean("success", true)
55
+ putString("sessionId", sessionId)
56
+ putMap("ledgerDevice", device.ledgerDevice.toWritableMap())
57
+ putString("deviceName", device.name)
58
+ }
59
+ }
60
+ is InternalConnectionResult.ConnectionError -> {
61
+ Arguments.createMap().apply {
62
+ putString("error", when (error) {
63
+ /**
64
+ * Most of these errors are for the BLE lib so it does not really make sense
65
+ * to have them here but for the sake of being explicit and not using an "else"
66
+ * where a new error type could be added, we list everything.
67
+ */
68
+ InternalConnectionResult.Failure.BleNotSupported -> "BleNotSupported"
69
+ InternalConnectionResult.Failure.ConnectionTimeout -> "ConnectionTimeout"
70
+ InternalConnectionResult.Failure.DeviceConnectivityBluetoothDisabled -> "DeviceConnectivityBluetoothDisabled"
71
+ InternalConnectionResult.Failure.DeviceConnectivityLocationDisabled -> "DeviceConnectivityLocationDisabled"
72
+ InternalConnectionResult.Failure.DeviceNotFound -> "DeviceNotFound"
73
+ InternalConnectionResult.Failure.InitializingFailed -> "InitializingFailed"
74
+ InternalConnectionResult.Failure.InternalState -> "InternalState"
75
+ InternalConnectionResult.Failure.NoDeviceAddress -> "NoDeviceAddress"
76
+ InternalConnectionResult.Failure.PairingFailed -> "PairingFailed"
77
+ InternalConnectionResult.Failure.PermissionNotGranted -> "PermissionNotGranted"
78
+ InternalConnectionResult.Failure.ServiceNotFound -> "ServiceNotFound"
79
+ is InternalConnectionResult.Failure.Unknown -> "UnknownError: ${error.msg}"
80
+ })
81
+ putBoolean("success", false)
82
+ }
83
+ }
84
+ }
85
+
86
+ internal fun SendApduResult.toWritableMap(): WritableMap {
87
+ when(this) {
88
+ is SendApduResult.Success -> {
89
+ return Arguments.createMap().apply {
90
+ putBoolean("success", true)
91
+ putString("apdu", Base64.encodeToString(apdu, Base64.DEFAULT))
92
+ }
93
+ }
94
+ is SendApduResult.Failure -> {
95
+ return Arguments.createMap().apply {
96
+ putBoolean("success", false)
97
+ putString("error", when (reason) {
98
+ SendApduFailureReason.ApduNotWellFormatted -> "ApduNotWellFormatted"
99
+ SendApduFailureReason.DeviceBusy -> "DeviceBusy"
100
+ SendApduFailureReason.DeviceLocked -> "DeviceLocked"
101
+ SendApduFailureReason.DeviceNotFound -> "DeviceNotFound"
102
+ SendApduFailureReason.NoResponse -> "NoResponse"
103
+ SendApduFailureReason.NoUsbEndpointFound -> "NoUsbEndpointFound"
104
+ SendApduFailureReason.DeviceDisconnected -> "DeviceDisconnected"
105
+ SendApduFailureReason.Unknown -> "Unknown"
106
+ })
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ internal fun TransportEvent.DeviceConnectionLost.toWritableMap(): WritableMap =
113
+ Arguments.createMap().apply {
114
+ putString("id", id)
115
+ }
116
+
117
+ /* lists */
118
+
119
+ fun List<DiscoveryDevice>.toWritableArray(): WritableArray =
120
+ Arguments.createArray().apply {
121
+ forEach {
122
+ pushMap(it.toWritableMap())
123
+ }
124
+ }
@@ -0,0 +1,16 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2023 Ledger SAS
3
+ * SPDX-License-Identifier: LicenseRef-LEDGER
4
+ */
5
+
6
+ package com.ledger.devicesdk.shared.androidMain.transport.usb
7
+
8
+ import com.ledger.devicesdk.shared.internal.transport.Transport
9
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.model.UsbPermissionEvent
10
+ import com.ledger.devicesdk.shared.androidMain.transport.usb.model.UsbState
11
+
12
+ internal interface AndroidUsbTransport: Transport {
13
+ fun updateUsbState(state: UsbState)
14
+
15
+ fun updateUsbEvent(event: UsbPermissionEvent)
16
+ }