下图是windows系统中,基于PC/SC标准的智能卡子系统构成组件(摘自: MSDN Library: Platform SDK: Smart Card)
我们的PC/SC兼容的sim卡读写程序和apdu命令发送程序,使用win32 API操作智能卡,基本步骤如下:
1. 与智能卡资源管理器建立连接:
SCARDCONTEXT hSC;
LONG lReturn;
// Establish the context.
lReturn = SCardEstablishContext(SCARD_SCOPE_USER,
NULL,
NULL,
&hSC);
2. 列出读卡器:
LPTSTR pmszReaders = NULL;
LPTSTR pReader;
LONG lReturn, lReturn2;
DWORD cch = SCARD_AUTOALLOCATE;
// Retrieve the list the readers.
// hSC was set by a previous call to SCardEstablishContext.
lReturn = SCardListReaders(hSC,
NULL,
(LPTSTR)&pmszReaders,
&cch );
3. 使用列出的读卡器名称与之连接:
SCARDHANDLE hCardHandle;
LONG lReturn;
DWORD dwAP;
// Connect to the reader.
// hContext is a SCARDCONTEXT previously set by
// a call to SCardEstablishContext.
lReturn = SCardConnect( hSc,
L"QWY Reader 0",
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&hCardHandle,
&dwAP );
4. 发送APDU:
// Transmit the request.
// lReturn is of type LONG.
// hCardHandle was set by a previous call to SCardConnect.
// pbSend points to the buffer of bytes to send./*
For T=0, the data parameters are placed into the pbSendBuffer according to the following structure:
struct {
BYTE
bCla, // The instruction class
bIns, // The instruction code
bP1, // Parameter to the instruction
bP2, // Parameter to the instruction
bP3; // Size of I/O Transfer
} CmdBytes;*/
// dwSend is the DWORD value for the number of bytes to send.
// pbRecv points to the buffer for returned bytes.
// dwRecv is the DWORD value for the number of returned bytes.
lReturn = SCardTransmit(hCardHandle,
SCARD_PCI_T0,
pbSend,
dwSend,
NULL,
pbRecv,
&dwRecv );
5. 退出:
// Terminate the connection.
// lReturn is a LONG variable.
// hCardHandle was set by a previous call to SCardConnect.
lReturn = SCardDisconnect(hCardHandle,
SCARD_LEAVE_CARD);
// Free the context.
// lReturn is of type LONG.
// hSC was set by an earlier call to SCardEstablishContext.
lReturn = SCardReleaseContext(hSC);
windows系统中,智能卡子系统在核态也提供了相关的库函数,帮助智能卡读卡器制造商写PC/SC兼容的驱动程序。下图描述了智能卡子系统提供的相关组件(摘自: Window DDK: Smart Card Devices):
智能卡子系统提供的函数帮助实现:
下面是智能卡子系统提供的核态函数的完整列表,从函数名称可以对应到上面列出的功能:
SmartcardInitializeSmartcardCreateLink
SmartcardDeviceControlSmartcardUpdateCardCapabilities
SmartcardT0Reply
SmartcardT0Request
SmartcardT1Reply
SmartcardT1RequestSmartcardRawReply
SmartcardRawRequestSmartcardLogError
SmartcardAcquireRemoveLock
SmartcardReleaseRemoveLock
SmartcardDeleteLink
SmartcardExit
智能卡资源管理器通过IOCTL -> SmartcardDeviceControl 访问驱动程序,智能卡子系统已经实现的IOCTL code(如:IOCTL_SMARTCARD_GET_ATTRIBUTE)由SmartcardDeviceControl 直接调用,智能卡子系统同时定义了一些必须由智能卡驱动厂商实现的IOCTL code,通过回调函数的方式,由驱动厂商注册。如我们的驱动中注册了以下几个回调函数:
smartcardExtension->ReaderFunction[RDF_TRANSMIT] = USCRTransmit;
smartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = USCRSetProtocol;
smartcardExtension->ReaderFunction[RDF_CARD_POWER] = USCRPower;
smartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = USCRCardTracking;
其他几个RDF_CARD_EJECT RDF_IOCTL_VENDOR RDF_READER_SWALLOW是可选实现。
驱动程序处理IOCTL过程如下图:(摘自: Window DDK: Smart Card Devices)
回调函数 USCRTransmit USCR...利用USB子系统提供的函数按照既定的协议(如CCID,由USB组织指定)与智能卡读卡器通讯。
1. CCID(USB Chip/Smart Card Interface Devices)
摘自 Device Class Specification for USB Chip/Smart Card Interface Devices
CCID由USB组织制订,目的是提供USB智能卡读卡器类设备的标准协议,厂商按照此协议制造的智能卡读卡器可以利用标准的智能卡读卡器类设备驱动程序。目前windows,linux等系统均由CCID类设备驱动程序,windows系统可以通过driver update得到(插入CCID兼容的读卡器,选择driver update即可)。
CCID的不足:
CCID要求USB必须是全速(full speed)设备,至少有bulk out和bulk in,以及默认的 control pipe 。
微软驱动目前的缺点:
虽然CCID标准规定interrupt pipe 为可选节点,但是没有interrupt pipe,目前微软的驱动不能正常工作。
2. ISO7816
详见 http://download.laogu.com/download/7816.chm
参考:
MSDN Library
Windows DDK
http://www.gemplus.com.cn/techno/pcsc/