@@ -24,9 +24,12 @@ import android.hardware.usb.UsbDeviceConnection
2424import android.hardware.usb.UsbEndpoint
2525import android.hardware.usb.UsbInterface
2626import android.hardware.usb.UsbManager
27+ import android.hardware.usb.UsbRequest
2728import android.os.Handler
2829import android.os.Looper
2930import android.os.ParcelUuid
31+ import androidx.core.content.ContextCompat
32+ import androidx.core.content.edit
3033import com.synonym.bitkitcore.NativeDeviceInfo
3134import com.synonym.bitkitcore.TrezorCallMessageResult
3235import com.synonym.bitkitcore.TrezorTransportCallback
@@ -42,6 +45,7 @@ import to.bitkit.ext.bluetoothManager
4245import to.bitkit.ext.usbManager
4346import to.bitkit.utils.Logger
4447import java.io.File
48+ import java.nio.ByteBuffer
4549import java.util.UUID
4650import java.util.concurrent.ConcurrentHashMap
4751import java.util.concurrent.CountDownLatch
@@ -141,7 +145,7 @@ class TrezorTransport @Inject constructor(
141145 migrated++
142146 }
143147 if (migrated > 0 ) {
144- espPrefs.edit(). clear().commit()
148+ espPrefs.edit(commit = true ) { clear() }
145149 Logger .info(" Migrated '$migrated ' THP credentials from SharedPreferences to files" , context = TAG )
146150 }
147151 } catch (e: Exception ) {
@@ -182,36 +186,37 @@ class TrezorTransport @Inject constructor(
182186
183187 // ==================== TrezorTransportCallback Implementation ====================
184188
185- @Suppress(" TooGenericExceptionCaught" )
186189 override fun enumerateDevices (): List <NativeDeviceInfo > {
187190 val devices = mutableListOf<NativeDeviceInfo >()
188191
189192 // Enumerate USB devices
190- try {
191- val usbDevices = usbManager.deviceList.values
193+ runCatching {
194+ usbManager.deviceList.values
192195 .filter { isTrezorDevice(it) }
193196 .map { device ->
194197 NativeDeviceInfo (
195198 path = device.deviceName,
196199 transportType = " usb" ,
197- name = try { device.productName } catch (_ : SecurityException ) { null } ,
200+ name = runCatching { device.productName }.getOrNull() ,
198201 vendorId = device.vendorId.toUShort(),
199202 productId = device.productId.toUShort(),
200203 )
201204 }
202- devices.addAll(usbDevices)
203- Logger .debug(" USB enumerate found '${usbDevices.size} ' Trezor device(s)" , context = TAG )
204- } catch (e: Exception ) {
205- Logger .error(" USB enumerate failed" , e, context = TAG )
205+ }.onSuccess {
206+ devices.addAll(it)
207+ Logger .debug(" USB enumerate found '${it.size} ' Trezor device(s)" , context = TAG )
208+ }.onFailure {
209+ Logger .error(" USB enumerate failed" , it, context = TAG )
206210 }
207211
208212 // Enumerate Bluetooth devices
209- try {
210- val bleDevices = enumerateBleDevices()
211- devices.addAll(bleDevices)
212- Logger .debug(" BLE enumerate found '${bleDevices.size} ' Trezor device(s)" , context = TAG )
213- } catch (e: Exception ) {
214- Logger .error(" BLE enumerate failed" , e, context = TAG )
213+ runCatching {
214+ enumerateBleDevices()
215+ }.onSuccess {
216+ devices.addAll(it)
217+ Logger .debug(" BLE enumerate found '${it.size} ' Trezor device(s)" , context = TAG )
218+ }.onFailure {
219+ Logger .error(" BLE enumerate failed" , it, context = TAG )
215220 }
216221
217222 Logger .info(" Total enumerate found '${devices.size} ' Trezor device(s)" , context = TAG )
@@ -265,7 +270,7 @@ class TrezorTransport @Inject constructor(
265270 override fun callMessage (
266271 path : String ,
267272 messageType : UShort ,
268- data : ByteArray
273+ data : ByteArray ,
269274 ): TrezorCallMessageResult ? {
270275 // For BLE/THP devices, the Rust side now handles THP protocol directly.
271276 // This callback returns null to let Rust use its built-in THP implementation.
@@ -448,16 +453,15 @@ class TrezorTransport @Inject constructor(
448453 }
449454 }
450455
451- @Suppress(" TooGenericExceptionCaught" )
452456 fun clearDeviceCredential (deviceId : String ) {
453- try {
457+ runCatching {
454458 val file = credentialFile(deviceId)
455459 TrezorDebugLog .log(" CLEAR" , " clearDeviceCredential for: $deviceId , exists=${file.exists()} " )
456460 file.delete()
457461 Logger .info(" Cleared device credential for: '$deviceId '" , context = TAG )
458- } catch (e : Exception ) {
459- TrezorDebugLog .log(" CLEAR" , " EXCEPTION: ${e .message} " )
460- Logger .error(" Failed to clear device credential" , e , context = TAG )
462+ }.onFailure {
463+ TrezorDebugLog .log(" CLEAR" , " EXCEPTION: ${it .message} " )
464+ Logger .error(" Failed to clear device credential" , it , context = TAG )
461465 }
462466 }
463467
@@ -496,10 +500,11 @@ class TrezorTransport @Inject constructor(
496500 PendingIntent .FLAG_UPDATE_CURRENT or PendingIntent .FLAG_MUTABLE ,
497501 )
498502
499- context.registerReceiver(
503+ ContextCompat .registerReceiver(
504+ context,
500505 receiver,
501506 IntentFilter (ACTION_USB_PERMISSION ),
502- Context .RECEIVER_NOT_EXPORTED ,
507+ ContextCompat .RECEIVER_NOT_EXPORTED ,
503508 )
504509
505510 try {
@@ -529,13 +534,11 @@ class TrezorTransport @Inject constructor(
529534
530535 for (i in 0 until usbInterface.endpointCount) {
531536 val endpoint = usbInterface.getEndpoint(i)
532- when {
533- endpoint.type == UsbConstants .USB_ENDPOINT_XFER_INT &&
534- endpoint.direction == UsbConstants .USB_DIR_IN -> {
537+ when (endpoint.direction) {
538+ UsbConstants .USB_DIR_IN if endpoint.type == UsbConstants .USB_ENDPOINT_XFER_INT -> {
535539 readEndpoint = endpoint
536540 }
537- endpoint.type == UsbConstants .USB_ENDPOINT_XFER_INT &&
538- endpoint.direction == UsbConstants .USB_DIR_OUT -> {
541+ UsbConstants .USB_DIR_OUT if endpoint.type == UsbConstants .USB_ENDPOINT_XFER_INT -> {
539542 writeEndpoint = endpoint
540543 }
541544 }
@@ -623,25 +626,39 @@ class TrezorTransport @Inject constructor(
623626 error = " Device not open: $path " ,
624627 )
625628
626- val buffer = ByteArray (USB_CHUNK_SIZE )
627- val bytesRead = openDevice.connection.bulkTransfer(
628- openDevice.readEndpoint,
629- buffer,
630- buffer.size,
631- READ_TIMEOUT_MS ,
632- )
629+ val buffer = ByteBuffer .allocate(USB_CHUNK_SIZE )
630+ val request = UsbRequest ()
631+ try {
632+ if (! request.initialize(openDevice.connection, openDevice.readEndpoint)) {
633+ return TrezorTransportReadResult (
634+ success = false ,
635+ data = byteArrayOf(),
636+ error = " Failed to initialize USB read request" ,
637+ )
638+ }
639+ if (! request.queue(buffer)) {
640+ return TrezorTransportReadResult (
641+ success = false ,
642+ data = byteArrayOf(),
643+ error = " Failed to queue USB read request" ,
644+ )
645+ }
646+ openDevice.connection.requestWait(READ_TIMEOUT_MS .toLong())
647+ ? : return TrezorTransportReadResult (
648+ success = false ,
649+ data = byteArrayOf(),
650+ error = " USB read timed out" ,
651+ )
633652
634- if (bytesRead < 0 ) {
635- return TrezorTransportReadResult (
636- success = false ,
637- data = byteArrayOf(),
638- error = " Read failed: $bytesRead " ,
639- )
653+ buffer.flip()
654+ val bytesRead = buffer.remaining()
655+ val data = ByteArray (bytesRead)
656+ buffer.get(data)
657+ Logger .debug(" USB read '$bytesRead ' bytes from '$path '" , context = TAG )
658+ TrezorTransportReadResult (success = true , data = data, error = " " )
659+ } finally {
660+ request.close()
640661 }
641-
642- val data = buffer.copyOf(bytesRead)
643- Logger .debug(" USB read '$bytesRead ' bytes from '$path '" , context = TAG )
644- TrezorTransportReadResult (success = true , data = data, error = " " )
645662 } catch (e: Exception ) {
646663 Logger .error(" USB read failed" , e, context = TAG )
647664 TrezorTransportReadResult (success = false , data = byteArrayOf(), error = e.message ? : " Unknown error" )
@@ -654,19 +671,29 @@ class TrezorTransport @Inject constructor(
654671 val openDevice = usbConnections[path]
655672 ? : return TrezorTransportWriteResult (success = false , error = " Device not open: $path " )
656673
657- val bytesWritten = openDevice.connection.bulkTransfer(
658- openDevice.writeEndpoint,
659- data,
660- data.size,
661- WRITE_TIMEOUT_MS ,
662- )
674+ val buffer = ByteBuffer .wrap(data)
675+ val request = UsbRequest ()
676+ try {
677+ if (! request.initialize(openDevice.connection, openDevice.writeEndpoint)) {
678+ return TrezorTransportWriteResult (
679+ success = false ,
680+ error = " Failed to initialize USB write request" ,
681+ )
682+ }
683+ if (! request.queue(buffer)) {
684+ return TrezorTransportWriteResult (
685+ success = false ,
686+ error = " Failed to queue USB write request" ,
687+ )
688+ }
689+ openDevice.connection.requestWait(WRITE_TIMEOUT_MS .toLong())
690+ ? : return TrezorTransportWriteResult (success = false , error = " USB write timed out" )
663691
664- if (bytesWritten < 0 ) {
665- return TrezorTransportWriteResult (success = false , error = " Write failed: $bytesWritten " )
692+ Logger .debug(" USB wrote '${data.size} ' bytes to '$path '" , context = TAG )
693+ TrezorTransportWriteResult (success = true , error = " " )
694+ } finally {
695+ request.close()
666696 }
667-
668- Logger .debug(" USB wrote '$bytesWritten ' bytes to '$path '" , context = TAG )
669- TrezorTransportWriteResult (success = true , error = " " )
670697 } catch (e: Exception ) {
671698 Logger .error(" USB write failed" , e, context = TAG )
672699 TrezorTransportWriteResult (success = false , error = e.message ? : " Unknown error" )
@@ -715,6 +742,7 @@ class TrezorTransport @Inject constructor(
715742 }
716743 }
717744
745+ @SuppressLint(" MissingPermission" )
718746 private val bleScanCallback = object : ScanCallback () {
719747 override fun onScanResult (callbackType : Int , result : ScanResult ) {
720748 val device = result.device
@@ -1074,9 +1102,10 @@ class TrezorTransport @Inject constructor(
10741102 Logger .info(" BLE services discovered: '$path '" , context = TAG )
10751103 }
10761104
1105+ @Suppress(" OVERRIDE_DEPRECATION" )
10771106 override fun onCharacteristicChanged (
10781107 gatt : BluetoothGatt ,
1079- characteristic : BluetoothGattCharacteristic
1108+ characteristic : BluetoothGattCharacteristic ,
10801109 ) {
10811110 val path = " ble:${gatt.device.address} "
10821111 val connection = bleConnections[path] ? : return
@@ -1099,7 +1128,7 @@ class TrezorTransport @Inject constructor(
10991128 override fun onCharacteristicWrite (
11001129 gatt : BluetoothGatt ,
11011130 characteristic : BluetoothGattCharacteristic ,
1102- status : Int
1131+ status : Int ,
11031132 ) {
11041133 val path = " ble:${gatt.device.address} "
11051134 val connection = bleConnections[path] ? : return
@@ -1113,7 +1142,7 @@ class TrezorTransport @Inject constructor(
11131142 override fun onDescriptorWrite (
11141143 gatt : BluetoothGatt ,
11151144 descriptor : BluetoothGattDescriptor ,
1116- status : Int
1145+ status : Int ,
11171146 ) {
11181147 val path = " ble:${gatt.device.address} "
11191148 val connection = bleConnections[path] ? : return
0 commit comments