【发布时间】:2017-12-19 08:53:58
【问题描述】:
所以最近我一直在使用包含一些信息的智能卡,我在这里想要实现的是通过任何 Android 智能手机使用智能卡读卡器从这些智能卡中获取这些数据。 我一直在使用HID OMNIKEY 3021 USB 智能卡读卡器,它可以读取这些卡(我知道这个读卡器可以通过 Windows 应用程序使用这些卡,因为我已经亲自测试过)
现在 Android 提供了USB Host,只要 Android 智能手机支持,它就可以读取任何 USB 主机。
我正在尝试使用 USB Host 提供的这些类来访问此卡内的数据。
我检测任何 USB 主机的代码:
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
IntentFilter attachedFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
registerReceiver(mUsbAttachedReceiver, attachedFilter);
private final BroadcastReceiver mUsbAttachedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Utils.writeStringToTextFile("\n1 .Get an action : " + action, FileName);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
synchronized (this) {
device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
showToast("Plugged In");
mUsbManager.requestPermission(device, mPermissionIntent);
}
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
showToast("Plugged Out");
// call your method that cleans up and closes communication with the device
}
}
}
};
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
//call method to set up device communication
Utils.writeStringToTextFile("2 .Get an action : " + action + "\nDevice is : " + device, FileName);
showToast("Permission Granted for device");
Handler h = new Handler();
h.postDelayed(run, 1000);
}
} else {
showToast("Permission denied for device" + device);
}
}
}
}
};
一切正常,因为我得到了UsbDevice device,它给出了设备的信息,例如:
Device is : UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1899,mProductId=12322,mClass=0,mSubclass=0,mProtocol=0,mManufacturerName=OMNIKEY AG,mProductName=Smart Card Reader USB,mVersion=2.0,mSerialNumber=null,mConfigurations=[
UsbConfiguration[mId=1,mName=CCID,mAttributes=160,mMaxPower=50,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=null,mClass=11,mSubclass=0,mProtocol=0,mEndpoints=[
UsbEndpoint[mAddress=131,mAttributes=3,mMaxPacketSize=8,mInterval=24]
UsbEndpoint[mAddress=132,mAttributes=2,mMaxPacketSize=64,mInterval=0]
UsbEndpoint[mAddress=5,mAttributes=2,mMaxPacketSize=64,mInterval=0]]]]
现在我正在尝试使用此 UsbDevice device 从卡中获取数据和详细信息,但我没有成功,也找不到任何有用的帖子。
我知道我必须使用 UsbInterface、UsbEndpoint、UsbDeviceConnection 从卡中获取我想要的东西,但我无法这样做。
另外,我找不到任何样品或类似的东西。 谁能指出我正确的方向?
很抱歉,很长的帖子也提前感谢:)
编辑: 感谢Mr. Michael Roland,我能够阅读有关 CCID 的信息,因为阅读器设备通过 USB 接口说出 CCID。
所以我使用了以下代码:
UsbDeviceConnection connection = mUsbManager.openDevice(device);
UsbEndpoint epOut = null, epIn = null;
for (int i = 0; i < device.getInterfaceCount(); i++) {
UsbInterface usbInterface = device.getInterface(i);
connection.claimInterface(usbInterface, true);
for (int j = 0; j < usbInterface.getEndpointCount(); j++) {
UsbEndpoint ep = usbInterface.getEndpoint(j);
showToast("Endpoint is : " + ep.toString() + " endpoint's type : " + ep.getType() + " endpoint's direction : " + ep.getDirection());
Log.d(" ", "EP " + i + ": " + ep.getType());
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
epOut = ep;
} else if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
epIn = ep;
}
}
}
int dataTransferred = 0;
byte[] PC_to_RDR_IccPowerOn = hexStringToByteArray("62" + "00000000" + "00" + "00" + "00" + "0000");
if (epOut != null) {
//Firstly send Power in on Bulk OUT endpoint
dataTransferred = connection.bulkTransfer(epOut, PC_to_RDR_IccPowerOn, PC_to_RDR_IccPowerOn.length, TIMEOUT);
}
StringBuilder result = new StringBuilder();
if (epIn != null) {
final byte[] RDR_to_PC_DataBlock = new byte[epIn.getMaxPacketSize()];
result = new StringBuilder();
//Secondly send Power out on Bulk OUT endpoint
dataTransferred = connection.bulkTransfer(epIn, RDR_to_PC_DataBlock, RDR_to_PC_DataBlock.length, TIMEOUT);
for (byte bb : RDR_to_PC_DataBlock) {
result.append(String.format(" %02X ", bb));
}
if (dataTransferred > 0) {
Utils.writeStringToTextFile("\n2nd buffer received was : " + result.toString(), "Card_communication_data.txt");
String s1 = Arrays.toString(RDR_to_PC_DataBlock);
String s2 = new String(RDR_to_PC_DataBlock);
showToast("received - " + s1 + " - " + s2);
} else {
showToast("received length at 2nd buffer transfer was " + dataTransferred);
}
}
}
我收到了80 13 00 00 00 00 00 00 00 00 3B 9A 96 C0 10 31 FE 5D 00 64 05 7B 01 02 31 80 90 00 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 但我仍然不确定如何处理数据字段:ATR 或如何为PC_to_RDR_XfrBlock 命令形成Command APDU..
我认为我应该这样做
发送封装到 PC_to_RDR_XfrBlock 命令中的命令 APDU
现在;谁能帮我解决这个问题?
编辑 2: 我弄清楚了 ATR 的含义以及如何形成命令 APDU。
但现在我应该切换协议
默认协议是 T=0。要设置 T=1 协议,设备必须向卡发送 PTS(也称为 PPS) 由于 T=0 和 T=1 协议对卡片都是强制性的,因此协议切换的基本 PTS 对卡片是强制性的。 卡片。 如 ISO/IEC 7816-3 中所述,PTS 可用于切换到比以下建议的默认波特率更高的波特率 ATR 中的卡(如果有)(TA(1) 字节)。
我不确定这意味着什么以及如何实现!
【问题讨论】:
标签: java android smartcard smartcard-reader