首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Xamarin/Android,SmartCard,BulkTransfer

Xamarin/Android,SmartCard,BulkTransfer
EN

Stack Overflow用户
提问于 2022-10-01 23:22:23
回答 1查看 148关注 0票数 0

因此,我的任务是编写代码来处理智能卡。环境为C#.Net,Xamarin。智能卡读取器(联系人,而不是NFC)连接到霍尼韦尔手持设备上。所以,有了稀疏的部分,我不能仅仅因为各种原因而使用第三方库,我要承担这个任务。

代码语言:javascript
复制
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通信完全陌生。不确定接下来的步骤,以获得设备的前后通信。

以下是我为连接到设备所做的工作的简略总结。至于具体的设备,它是一个霍尼韦尔CN80手持扫描仪设备,附带一个CAC阅读器(也是霍尼韦尔)。至于我想要做的事情,只想打电话给验证卡(或不存在)。我并不是真正地向设备发送数据,只是一个命令来询问设备并得到一个正确的答案。

代码语言:javascript
复制
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?
                  }
               }
            }
         }
      }
   }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-04 09:09:36

(想写一篇评论,但写得很长.)

从技术上讲,有两种可能性,不使用制造商的驱动程序:

  1. 读写器采用标准的USB协议。然后您需要在您的软件中实现该协议。该协议被描述为这里。有一个开源实现脂粘,您可以使用它作为参考。
  2. 读取器使用一些专有协议。然后,您需要从供应商那里获得协议描述并实现它。

要区分这两者,请参考读取器规范和/或检查它的USB描述符。您可能还想看看这里这里

一些额外的(随机)注释:

  • 使用专有协议的读取器通常模拟USB串口。如果是这样的话,那么通过原始USB与读取器进行通信是毫无意义的--使用这个串口代替。
  • 我想读取器供应商为这个阅读器提供了一些Android驱动程序。我不知道你不使用它们的原因,但你应该。Java代码应该可以使用绑定库从Xamarin调用。对于本机库,请使用P/调用 (以及特定于Xamarin的文档)。
  • 如果系统级智能卡API可用(例如winscard),那么使用它(如果可能的话使用pcsc-夏普 )。
  • 您在代码中所做的是将一个原始命令APDU发送到USB端点并期望响应-APDU作为响应。您肯定需要将命令APDU包装成特定于协议的格式(取决于读取器)。

免责声明:我不是Xamarin专家,所以请验证我的想法。

祝你的项目好运!

EDIT>你也会发现那些文章很有趣:12

EDIT2>有一个PoC javascript CCID实现,您可能会发现它更容易理解。

看到官方驱动程序如何使用具有WiresharkCCID分解器与读取器进行通信也是非常有启发性的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73922375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档