Xamarin/Android、智能卡、批量传输

carvr3hs  于 2022-12-07  发布在  Android
关注(0)|答案(1)|浏览(162)

因此,我的任务是编写与智能卡一起工作的代码。环境是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?
                  }
               }
            }
         }
      }
   }
}
zd287kbt

zd287kbt1#

(想写评论,但它得到了相当长...)
在不使用制造商提供的驱动程序的情况下,技术上有两种可能性:
1.读卡器使用标准USB CCID协议。然后您需要在软件中实现该协议。该协议在here中进行了描述。有一个开源实现libccid可供参考。
1.阅读器使用一些专有协议。然后你需要从供应商那里得到协议描述并实现它。
要区分两者,请参考读卡器规格和/或检查它的USB描述符。您可能还想看看herehere
一些附加(随机)注解:

  • 使用专有协议的读取器通常模拟USB串行端口。如果是这样的话,那么通过原始USB与读取器通信就没有意义了--请改用此串行端口。
  • 我想阅读器供应商为这个阅读器提供了一些Android驱动程序。我不知道你不使用它们的原因,但你应该使用它们。Java代码应该可以使用bindings library从Xamarin调用。对于原生库,使用P/Invoke(和Xamarin特定的documentation)。
  • 如果某些系统级智能卡API可用(如winscard),则使用它(如可能,使用pcsc-sharp)。
  • 你在代码中所做的就是向USB端点发送一个原始的命令APDU,并期待一个响应APDU作为响应。你肯定需要将命令APDU Package 成一个协议特定的格式(哪一种格式取决于阅读器)。

免责声明:我不是XamarinMaven,所以请验证我的想法。
祝您的项目好运!
编辑〉您可能也会发现这些帖子很有趣:12
编辑2〉有一个PoC javascript CCID implementation,你可能会发现更容易遵循。
看到官方驱动程序如何使用具有CCID dissectorWireshark与读取器通信也是非常有启发性的。

相关问题