I’m trying to communicate from native android app with smart card via external usb card reader.
This detects card reader properly and permission is fine.
fun scanUsbDevices(usbManager: UsbManager) {
this.usbManager = usbManager
devices.clear()
for (device in usbManager.deviceList.values) {
var h_d: UsbEndpoint? = null
var d_h: UsbEndpoint? = null
for (i in 0 until device.interfaceCount) {
val usbInterface = device.getInterface(i)
for (j in 0 until usbInterface.endpointCount) {
val ep: UsbEndpoint = usbInterface.getEndpoint(j)
if (ep.type == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.direction == UsbConstants.USB_DIR_OUT) {
// from host to device
h_d = ep
if (d_h != null) {
devices.add(DataUsbDevice(device, h_d, d_h, usbInterface))
return // should not return here, but break
}
} else if (ep.direction == UsbConstants.USB_DIR_IN) {
// from device to host
d_h = ep
if (h_d != null) {
devices.add(DataUsbDevice(device, h_d, d_h, usbInterface))
return // should not return here, but break
}
}
}
}
}
}
}
Function to send APDU command and receive response
fun writeToSelected(command: ByteArray): String {
val connection: UsbDeviceConnection? = usbManager?.openDevice(devices[cur_device_id].device)
if (connection != null) {
val claimed: Boolean = connection.claimInterface(devices[cur_device_id].usb_interface, true)
if (claimed) {
// tried bulk transfer here from host to device, didn't work
val transferred = connection.controlTransfer(
UsbConstants.USB_TYPE_VENDOR, 0x01, 0, 0, command, command.size, 3000
)
// tried adding delay here
if (transferred >= 0) {
// Read response from the smart card reader
val buffer = ByteArray(devices[cur_device_id].device_to_host_ep.maxPacketSize)
val readBytes = connection.bulkTransfer(
devices[cur_device_id].device_to_host_ep, buffer, 0, buffer.size, 3000
)
if (readBytes >= 0) {
return buffer.copyOf(readBytes).toString(Charsets.UTF_8)
} else
"err 2"
} else {
return "ERR 3"
}
}
} else {
return "conn is null"
}
return "OTHER ERROR"
}
// Example APDU command
val apduCommand = byteArrayOf(
0x00, // CLA (Class)
0xA4.toByte(), // INS (Instruction)
0x04, // P1 (Parameter 1)
0x00, // P2 (Parameter 2)
0x10, // LC (Data Length)
0xA0.toByte(), 0x00, 0x00, 0x07, 0x48, 0x46, 0x4A, 0x49, 0x2D, 0x54, 0x61, 0x78, 0x43, 0x6F, 0x72, 0x65, // Command Data
0x00 // Le (Expected Length)
)
Same APDU command works fine on windows with pcsc-sharp c#.
card readers also return different outputs.
I expect it to return 0x9000.
Is this even possible on android phone or am i doing something wrong?
Is it because usb-otg port?
Is UsbManager too low level and requires something to be build on top of it?