So, I have been tasked with writing code to work with smart cards. The environment is C#.Net, Xamarin. The smart card reader (contact, not NFC) is attached to a Honeywell handheld device. So, with the sparse pieces out there, and I can't just use some third-party library for a variety of reasons, I am tasked with it.
Using Android.Hardware.Usb, I can get to the following.
UsbManager - created to context of application.
Scan connected USB devices to the handheld
Properly detecting the specific device.
Getting the configuration object.
Then to the interface
and finally finding the 3 endpoints.. Isochronous, Inbound and Outbound.
Request permission to use the specific device.
and finally Open the device for a UsbConnection handle.
So, now that the door is open to communicate, I need to obviously send a request outbound and get an answer back from the respective out and in endpoints.
I can build the BulkTransfer of an APDU Command and get a response that 2 bytes are available to be received. I then try to do another BulkTransfer on the inbound port with an APDU Response, but it always fails with -1.
I have seen other posts that discuss setting communication protocols, baud rates, etc but not sure if that is the issue or not. I am totally new to this granular level of serial/usb communications. Unsure of next steps to get the back/forth communication to the device.
Here is an abbreviated summation of what I am doing to get connected to the device. As for specific equipment, it is a Honeywell CN80 handheld scanner device with an attached CAC reader (also Honeywell). As for what I am trying to do, just trying to call a verify card exists (or not). I am not trying to actually send data to the device, just a command to inquire against the device and get a proper answer back.
public void attemptingSmartCommunications()
{
_myUsbManager = (UsbManager)_myMainActivity.GetSystemService(Context.UsbService);
foreach (var d in _myUsbManager.DeviceList)
{ // method checks the device for proper VID/PID
var dev = d.Value;
if (isExpectedDevice(dev))
{
for (var dc = 0; dc < dev.ConfigurationCount; dc++)
{
// SHOULD only be 1 configuration from what I have encountered.
_myUsbConfiguration = dev.GetConfiguration(dc);
for (var di = 0; di < _myUsbConfiguration.InterfaceCount; di++)
{
_myUsbInterface = _myUsbConfiguration.GetInterface(di);
// Add on context of each endpoint
for (var ep = 0; ep < _myUsbInterface.EndpointCount; ep++)
{
var intEndpoint = _myUsbInterface.GetEndpoint(ep);
// which one do we need, store into their own respecive properties
// for in/out/isochronous
switch (intEndpoint.Address.ToString())
{
case "XferIsochronous":
// Control pipe for communication
_myIsochronousEndpoint = intEndpoint;
break;
case "130":
// Read IN FROM the USB Device with response
_myInEndpoint = intEndpoint;
break;
case "131":
// Write OUT TO the USB Device with command/request
_myOutEndpoint = intEndpoint;
break;
}
}
// now, I have the endpoints to request send and read back, make sure permission
if( _myUsbManager.HasPermission(_myUsbDevice))
{
myConnection = _myUsbManager.OpenDevice(_myUsbDevice);
var apdu = MyStaticSmartCardAPDUCommand;
// prepares the 4-byte request of CLA, INS, P1, P2 (no data in request)
var byteBuffer = apdu.CommandAsBytes();
var bufferLen = byteBuffer.Length;
var resultBytes = _myUsbDeviceConnection.BulkTransfer(_myOutEndpoint, byteBuffer, bufferLen, 2000);
// I get indication of 2 byte response
if( resultBytes > 0 )
{
// default buffer prepared with 4 bytes. SW1, SW2 + 2 expected bytes
var apduResp = new APDUResponse(resultBytes);
byteBuffer = apduResp.GetResponseBuffer();
var responseStatus = _myUsbDeviceConnection.BulkTransfer(_myInEndpoint, byteBuffer, byteBuffer.Length, 3000);
// HERE is where it always fails.
// Am I on the right track? Completely out of it?
}
}
}
}
}
}
}