PCSC那事儿(七)

 

5

上面说了,很多情况下,得直面 ResourceManager

既然如此,就耐心分析分析。

 

RESOURCEMANAGER

 

Class RESOURCEMANAGER[6]

属性

HANDLE hContext

 

方法

RESOURCEMANAGER()

~RESOURCEMANAGER()

 

RESPONSECODE EstablishContext (

IN DWORD Scope, // A scope indicator (see below)

IN DWORD Reserved1, // Reserved for future use to allow privileged // administrative programs to act on behalf of

// another user

IN DWORD Reserved2 // Reserved for future use to allow privileged // administrative programs to act on behalf of

// another terminal

)

建立与 ICC ResourceManager 通讯的上下文。

Scope

SCARD_SCOPE_USER (在用户域中完成设备数据库操作)、 SCARD_SCOPE_SYSTEM (在系统域中完成设备数据库操作)。要求应用程序具有相应的操作权限。在 PCSC-LITE

中就不用操心了,只有 SCARD_SCOPE_SYSTEM

 

RESPONSECODE ReleaseContext()

释放已经建立的通讯上下文。

 

RESOURCEDB

 

Class RESOURCEDB[6]

这个专门用来体现 ICC Resource Manager 的主要责任,包括维护系统已知的 ICCSPs,cards readers 的信息。

看这个名字,就明白些了。名字和风水很有关系。这在设计中,专门有提到命名的方法,

名字起得不好,最终会遭到重构。

RESOURCEDB DB 就是数据库。提供了各种方法用于管理这些信息。手段当然和一般的 DB 有些类似,包括 insert delete create 各种 resources 之间的联系,查询数据库。

 

RESOURCEDB 实际从 RESOURCEDBQUERY 派生,并继承了 RESOURCEDBQUERY 的方法。

属性

RESOURCEMANAGER resmgr

方法

RESOURCEDB(IN RESOURCEMANAGER resmgr)

这招是什么?很正常,初始化。

那是表面。

实际体现了组合优于继承的大师级设计思想。

 

~RESOURCEDB()

 

RESPONSECODE IntroduceReader(

IN STR ReaderName // Friendly name to be associated with the // reader

IN STR DeviceName // System-specific name of the reader device. // Should conform to OS-specific naming // conventions.

)

 

组织说,相关的安装程序或读卡器驱动会用到这个函数。

把读卡器介绍给 Resource Manager database 。关联上 ReaderName DeviceName.

看看,被介绍给 Resource Manager database ,从此和 Resource Manager 有了千丝万缕的

联系。

RESPONSECODE ForgetReader(IN STR ReaderName//Friendly name associated with

reader

)

咳。得罪了 ResourceManager ,被从团体中,剔除出去。

 

RESPONSECODE IntroduceReaderGroup(

IN STR GroupName // Group name to be added to the // Resource Manager database

)

ResourceManager 的收金人 Resource Manager database ,建立了一个读卡器组,

还起了名字  GroupName 。准备广收门徒。

 

 

RESPONSECODE ForgetReaderGroup(

IN STR GroupName // Group name to be removed from the Resource // Manager database

)

这个 GroupName ,犯了风水大忌,被 Resource Manager database 删除了。

 

 

RESPONSECODE AddReaderToGroup(

IN STR ReaderName // Name of Reader

IN STR GroupName // Group name to which Reader is to be added

)

前面的 IntroduceReaderGroup 说明了,立了牌子,起了名,准备收读卡器,

充实组员。 Reader  组员名字, GroupName 组名字。

 

 

RESPONSECODE RemoveReaderFromGroup(

IN STR ReaderName // Name of Reader

IN STR GroupName // Group name from which Reader is to be // removed

)

某组员,得罪了 DB ,或出意外了, DB 把它从 Group 中剔除。

 

RESPONSECODE IntroduceCardType(

IN STR CardName // Friendly name for the card being introduced

IN BYTE[] ATRRefVal // ATR reference value to match in determining card type

IN BYTE[] ATRMask // Mask which is logically AND’d with an card ATR // prior to comparison with the ATR reference value

IN BYTE[] ProviderId // Unique identifier for the primary service provider, // encoding is system specific

IN GUID[] Interfaces // List of unique identifiers for the card Interfaces // supported by the card

)

根据 ATR ,相关的 Mask ICCSP ,和卡接口,把 card type 介绍给 DB.

这个函数在什么时候使用,在 ICCSP 安装的时候使用到。

 

从前面,你能看出 Resource Manager 命令 Resource Manager DB 去招募读卡器。

在谈卷7的时候,大家知道了读卡器经常欺负 card type

所以,还得招募 card type ,要不读卡器去欺负谁?读卡器就是工头,卡卡们就是

广大工人。

 

RESPONSECODE ForgetCardType(

IN STR CardName // Friendly name for the card to be removed

)

有个卡卡离开了。 DB 把它从花名册中删除。

 

RESOURCEQUERY

 

Class RESOURCEQUERY[6]

上面提到了。 RESOUCEQUERY DB parent.

 

老子英雄儿好汉。

这里采用了继承,体现了 has-a 的关系。设计大师如是说。

 

RESOUCEQUERY(IN RESOURCEMANAGER resmgr)

~RESOURCEQUERY()

RESPONSECODE ListReaderGroups(

OUT STR[] Groups // Array of strings containing the Group names

)

列出 DB 中所有读卡器组名。开始阅兵了。

 

RESPONSECODE ListReaders(

IN STR[] Groups // Array of strings containing Group names of // interest

OUT STR[] Readers // Array of strings containing Readers within the // Groups

)

列出 DB Groups 这些组中所有读卡器的名字。

 

RESPONSECODE ListCardTypes(

IN BYTE[] ATR // ATR string to compare against known card types; // maybe NULL

IN GUID[] Interfaces // Array of GUIDs associated with the desired // interfaces

OUT STR[] Cards // Array of strings containing Card Types

)

返回所有的匹配 ATR 或者 interface card types. 如果 ATR Interface 都是 NULL ,则

返回系统中所有的 card types.

ATR 的匹配是通过查找 DB ,把参数 ATR DB 中的 ATR ATRMask 与操作后,和 DB

ATR 比较。如果参数 ATR NULL ,则那么列出所有的卡类型。

 

 

RESPONSECODE GetProviderId(

IN STR CardName // Friendly name for a Card Type

OUT BYTE[] ProviderId // Reference to the Primary SP(s)

)

给定 Card Type name ,查询该种 Card Type 能够提供的 SP id.

 

RESPONSECODE ListInterfaces(

IN STR CardName // Friendly name for a Card Type

OUT GUID[] Interfaces // Array of GUIDs associated with the supported // Interfaces

)

根据给定的 card type 名字,返回该 card type 对应的 interfaces

 

SCARDTRACK

 

Class SCARDTRACK[6]

 

要认识 SCARDTRACK ,先认识 SCARD_READERSTATE.

structure {

STR Reader; // reader name

VOID UserData; // user defined data

DWORD CurrentState; // current state of reader at time of call

DWORD EventState; // state of reader after state change } SCARD_READERSTATE;

 

Reader 要被监控的读卡器的名字

UserData 任意的应用相关数据

CurrentState 读卡器的当前状态,可以是如下值或如下值的组合

 

SCARD_STATE_UNAWARE 对于 APPLICATION 来说,读卡器状态未知

 

SCARD_STATE_IGNORE  APPLICATION 对这个读卡器不感兴趣,排除出监控行列

 

SCARD_STATE_UNAVAILABLE APPLICATION 认为读卡器处于不可用状态

 

SCARD_STATE_EMPTY APPLICATION 认为读卡器中没有卡

 

SCARD_STATE_PRESENT APPLICATION 认为读卡器中已经插入卡片

 

SCARD_STATE_ATRMATCH APPLICATION 认为匹配目标 ATR 卡片已经插入读卡器,这种状态假设 SCARD_STATE_PRESENT 成立。

SCARD_STATE_EXCLUSIVE   APPLICATION 认为读卡器中的卡操作排它使用,采用了独占机制。这种状态假设 SCARD_STATE_PRESENT 成立。

 

 

SCARD_STATE_INUSE APPLICATION 认为读卡器中卡正被一个或多个应用程序使用。

这种状态假设 SCARD_STATE_PRESENT 成立。

 

 

EventState Resource Manager 获取到的读卡器的当前状态。

状态值可以是如下值或值的组合。

 

SCARD_STATE_IGNORE APPLICATION 已经设置了 IGNORE 状态。

 

SCARD_STATE_CHANGED 读卡器的状态发生了变化。

 

SCARD_STATE_UNKNOWN

Resource Manger 发现给定读卡器的名字没有被注册。设置该位同时也设置。 SCARD_STATE_CHANGED.

 

SCARD_STATE_UNAVAILABLE 读卡器不可用。

 

SCARD_STATE_EMPTY 读卡器中没有卡。

 

SCARD_STATE_PRESENT 读卡器已经插入卡。

 

SCARD_STATE_ATRMATCH 已经找到和目标 ATR 匹配的卡。如果该位被设置,则同时设置  SCARD_STATE_PRESENT.

 

SCARD_STATE_EXCLUSIVE 读卡器中的卡采用了排它机制。

 

 

SCARD_STATE_INUSE 读卡器中的卡正被一个或多个应用程序使用。

如果该位被设置,则同时设置  SCARD_STATE_PRESENT.

 

接着讲 SCARDTRACK

 

SCARDTRACK(IN RESOURCEMANGER resmgr)

这招式,提过了。

~SCARDTRACK()

 

RESPONSECODE LocateCards(

IN STR[] Cards // Array of strings giving the names of the Card // Types of interest

IN OUT SCARD_READERSTATE[] ReaderStates // Array of READERSTATE // structures for readers of interest

)

这是个非阻塞函数。根据第一个参数提供的 card type 名字,在第二个参数

中返回读卡器状态。

 

 

RESPONSECODE GetStatusChange(

IN OUT SCARD_READERSTATE[] ReaderStates // Array of READERSTATE // structures for readers of interest

IN DWORD Timeout // Time-out value in milliseconds

)

 

这是个阻塞函数。调用该方法,发生阻塞,直到 ReaderStates 中表示

的状态发生改变或者超时。

Timeout INFINITE 时候,表示永久等待。

 

多好呀,能够永久等待,直到某个 Reader 的状态发生变化。

Timeout 是0,则该函数立即返回。

 

RESPONSECODE Cancel()

取消阻塞的 GetStatusChange() 函数。

 

SCARDCOMM

 

Class SCARDCOMM[6]

这个类的主要职责 提供和特定的卡或读卡器的通讯接口。

 

管理连接,控制传输,收发命令,和提供卡状态信息。

 

属性

 

private RESOURCEMANAGER resmgr // Reference to a RESOURCEMANAGER // object

private HANDLE hCard // Handle to a Context associated with communication to a specific card and/or Reader. Set to NULL on object creation. This context is established using the Connect()method and destroyed using Disconnect().

 

方法

SCARDCOMM(RESOURCEMANAGER resmgr)

这招不再提了。入门招式。

 

~SCARDCOMM()

 

RESPONSECODE Connect(

IN STR ReaderName // Friendly name for a Reader

IN DWORD Flags // Desired access mode information

IN DWORD PreferredProtocols // Card communications protocols that may be used

OUT DWORD ActiveProtocol // Protocol actually in use

)

Flags 访问模式 表明是否可共享访问读卡器

PreferredProtocols 通讯协议 T0 T1

实际使用的协议在 ActiveProtocol 中返回

 

RESPONSECODE Reconnect(

IN DWORD Flags // desired access mode

IN DWORD PreferredProtocols // card communications protocols

// which may be used

IN DWORD Initialization // Specify card initialization to be performed

OUT DWORD ActiveProtocol // protocol actually in use

)

 

这个方法用来清除错误。

Initialization 参数用来指定重新连接时候的附加动作

SCARD_RESET_CARD 热复位

SCARD_UNPOWER_CARD  冷复位

可以在 Flags 更改连接协议。

 

RESPONSECODE Disconnect(

IN DWORD Disposition // Desired Card disposition action

)

Dispostion 指定附加动作

拔除卡片

复位卡片

断电关闭卡片

弹出卡片

没收卡片

 

RESPONSECODE Status(

OUT STR[] Reader // Friendly name of the connected reader

OUT DWORD State // Current status the connection

OUT DWORD ActiveProtocol // protocol actually in use

OUT BYTE Atr[] // ATR data buffer

)

 

返回当前连接的状态

Reader 返回所连接读卡器的名字

State 返回当前的读卡器状态

如果有卡片插入读卡器

ActiveProtocol 返回通讯的握手协议

Atr 返回卡片的 ATR

 

State

 

SCARD_UNKNOWN

无法通讯。

 

SCARD_ABSENT

读卡器中没有卡片。

 

SCARD_PRESENT

读卡器中已经插入卡片,但未到达可以使用的位置。

 

SCARD_SWALLOWED

读卡器中已经插入卡片,且到达可以使用的位置,但是还没有上电。

 

SCARD_POWERED

卡片已经上电,但是 hanlder 还无法识别卡模式。

 

SCARD_NEGOTIABLE

卡片已经复位,并等待 PTS 协商。

 

SCARD_SPECIFIC

卡片已经复位,特定的通讯协议已经建立。

 

RESPONSECODE BeginTransaction()

事务处理开始

 

RESPONSECODE EndTransaction()

事务处理结束

 

RESPONSECODE Cancel()

解除 BeginTransaction 给其它 APPLICATION 带来的阻塞

 

RESPONSECODE Transmit(

IN SCARD_IO_HEADER SendPci // Send protocol structure

IN BYTE[] SendBuffer // Data buffer for send data

IN OUT SCARD_IO_HEADER RecvPci // Receive protocol structure

IN OUT BYTE[] RecvBuffer // Data buffer for receive data

OUT DWORD RecvLength // Length of received data

)

 

收发函数

但前进之前,先停下,看看

structure {

DWORD Protocol;

DWORD Length;

} SCARD_IO_HEADER;

 

Protocol 通讯协议

Length SCARD_IO_HEADER 结构体长度

 

 

继续前进。

 

RecvBuffer 接收缓冲区

RecvLength 接收到的数据长度

SendBuffer 发送缓冲区

 

 

RESPONSECODE Control(

IN DWORD ControlCode // Vendor-defined control code

IN BYTE[] InBuffer // Input data buffer

IN OUT BYTE[] OutBuffer // Output data buffer

OUT DWORD OutBufferLength // Length of data in output data buffer

)

 

这个嘛?通过 Ioctl 对读卡器进行直接通讯。主要目的是提供与产商

定义功能特征的通讯。

 

RESPONSECODE GetReaderCapabilities (

IN OUT DWORD Tag // Value of tag associated with attribute to retrieve

OUT BYTE[] Buffer // Data returned

)

返回读卡器属性 ( 卷3 ).

 

RESPONSECODE SetReaderCapabilities (

IN DWORD Tag // Value of tag associated with attribute to retrieve

IN BYTE[] Buffer // Data returned

)

设置读卡器属性 ( 卷3 ).

 

5 结束。

 

 

 

声明:

如果目前,您仅仅只想用用 API 函数,或者您想先体验体验,

见网络上的 vc PCSC 接口编程,

或者直接看 PCSC-LITE 提供 API 头文件,

或者直接看 testpcsc.c 文件。

 

 

小结

 

大家有空的话,可以考虑看看卷 2 ,卷 3 ,卷4,卷 8 ,卷 9 ,卷 10

这些卷和应用的关系已经很小了。这里就不再消耗您的宝贵时间 ( 生命 ) 了。

下面开始对 PCSC-LITE 的代码解说。

快! The sands of time are running out for you.

最新的PCSC、CCID以及测试源码。 贴一段源码: LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1, /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext) { (void)pvReserved1; (void)pvReserved2; if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL && dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL) { *phContext = 0; return SCARD_E_INVALID_VALUE; } /* * Unique identifier for this server so that it can uniquely be * identified by clients and distinguished from others */ *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535)); Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%X", *phContext); return SCARD_S_SUCCESS; } LONG SCardReleaseContext(SCARDCONTEXT hContext) { /* * Nothing to do here RPC layer will handle this */ Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%X", hContext); return SCARD_S_SUCCESS; } LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) { LONG rv; READER_CONTEXT * rContext = NULL; uint32_t readerState; (void)hContext; PROFILE_START *phCard = 0; if ((dwShareMode != SCARD_SHARE_DIRECT) && !(dwPreferredProtocols & SCARD_PROTOCOL_T0) && !(dwPreferredProtocols & SCARD_PROTOCOL_T1) && !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) && !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)) return SCARD_E_PROTO_MISMATCH; if (dwShareMode != SCARD_SHARE_EXCLUSIVE && dwShareMode != SCARD_SHARE_SHARED && dwShareMode != SCARD_SHARE_DIRECT) return SCARD_E_INVALID_VALUE; Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d", szReader, dwPreferredProtocols); rv = RFReaderInfo((LPSTR) szReader, &rContext); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader); return rv; } /* * Make sure the reader is working properly */ rv = RFCheckReaderStatus(rContext); if (rv != SCARD_S_SUCCESS) re
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值