因此,我的任务是编写与智能卡一起工作的代码。环境是C#.Net,Xamarin。智能卡读卡器(接触式,而不是NFC)连接到霍尼韦尔手持设备。因此,由于各种原因,我不能只使用一些第三方库,我的任务是它。
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.
因此,现在通信的大门已经打开,我显然需要发送一个请求出站,并从相应的出站和入站端点获得应答。
我可以构建一个APDU命令的BulkTransfer,并获得一个2字节的响应,然后我尝试在入站端口上使用APDU响应执行另一个BulkTransfer,但总是失败,返回-1。
我看过其他讨论设置通信协议,波特率等的帖子,但不确定这是否是问题所在。我对串行/USB通信的这种粒度级别完全是新的。不确定下一步要让设备进行来回通信。
这里是我正在做的连接到设备的简短总结。至于具体设备,它是一个霍尼韦尔CN 80手持式扫描仪设备,附带CAC阅读器(也是霍尼韦尔)。至于我想做的,只是想打电话验证卡是否存在(或者不是)。我并不是想实际向设备发送数据,只是一个命令来查询设备并得到适当的回复。
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?
}
}
}
}
}
}
}
1条答案
按热度按时间zd287kbt1#
(想写评论,但它得到了相当长...)
在不使用制造商提供的驱动程序的情况下,技术上有两种可能性:
1.读卡器使用标准USB CCID协议。然后您需要在软件中实现该协议。该协议在here中进行了描述。有一个开源实现libccid可供参考。
1.阅读器使用一些专有协议。然后你需要从供应商那里得到协议描述并实现它。
要区分两者,请参考读卡器规格和/或检查它的USB描述符。您可能还想看看here和here。
一些附加(随机)注解:
免责声明:我不是XamarinMaven,所以请验证我的想法。
祝您的项目好运!
编辑〉您可能也会发现这些帖子很有趣:1、2
编辑2〉有一个PoC javascript CCID implementation,你可能会发现更容易遵循。
看到官方驱动程序如何使用具有CCID dissector的Wireshark与读取器通信也是非常有启发性的。