1 /*****************************************************************
4 / Author : Kristian Beilke nfc@jdkbx.cjb.net
5 / Date : March 05, 2009
6 / Purpose: This provides reader specific low-level calls.
7 / See http://www.linuxnet.com for more information.
8 / License: See file LICENSE and PCSC_LICENSE
10 ******************************************************************/
11 #include <stdio.h> /* Standard input/output definitions */
12 #include <string.h> /* String function definitions */
13 #include <unistd.h> /* UNIX standard function definitions */
14 #include <fcntl.h> /* File control definitions */
15 #include <errno.h> /* Error number definitions */
18 #include <ifdhandler.h>
22 /* Maximum number of readers handled */
23 #define IFDH_MAX_READERS 1
25 /* Maximum number of slots per reader handled */
26 #define IFDH_MAX_SLOTS 1
30 RESPONSECODE
IFDHCreateChannel ( DWORD Lun
, DWORD Channel
) {
32 /* Lun - Logical Unit Number, use this for multiple card slots
33 or multiple readers. 0xXXXXYYYY - XXXX multiple readers,
34 YYYY multiple slots. The resource manager will set these
35 automatically. By default the resource manager loads a new
36 instance of the driver so if your reader does not have more than
37 one smartcard slot then ignore the Lun in all the functions.
38 Future versions of PC/SC might support loading multiple readers
39 through one instance of the driver in which XXXX would be important
40 to implement if you want this.
43 /* Channel - Channel ID. This is denoted by the following:
44 0x000001 - /dev/pcsc/1
45 0x000002 - /dev/pcsc/2
46 0x000003 - /dev/pcsc/3
48 USB readers may choose to ignore this parameter and query
49 the bus for the particular reader.
52 /* This function is required to open a communications channel to the
53 port listed by Channel. For example, the first serial reader on COM1 would
54 link to /dev/pcsc/1 which would be a sym link to /dev/ttyS0 on some machines
55 This is used to help with intermachine independance.
57 Once the channel is opened the reader must be in a state in which it is possible
58 to query IFDHICCPresence() for card status.
63 IFD_COMMUNICATION_ERROR
65 Log1(PCSC_LOG_DEBUG
, "IFDHCreateChannel");
69 /* ifd 3.0 uses this */
70 RESPONSECODE
IFDHCreateChannelByName(DWORD Lun
, LPSTR deviceName
)
72 Log1(PCSC_LOG_DEBUG
, "IFDHCreateChannelByName");
73 return getServiceByName(deviceName
);
76 RESPONSECODE
IFDHCloseChannel ( DWORD Lun
) {
78 /* This function should close the reader communication channel
79 for the particular reader. Prior to closing the communication channel
80 the reader should make sure the card is powered down and the terminal
86 IFD_COMMUNICATION_ERROR
88 Log1(PCSC_LOG_DEBUG
, "IFDHCloseChannel");
95 RESPONSECODE
IFDHGetCapabilities ( DWORD Lun
, DWORD Tag
,
96 PDWORD Length
, PUCHAR Value
) {
98 /* This function should get the slot/card capabilities for a particular
99 slot/card specified by Lun. Again, if you have only 1 card slot and don't mind
100 loading a new driver for each reader then ignore Lun.
102 Tag - the tag for the information requested
103 example: TAG_IFD_ATR - return the Atr and it's size (required).
104 these tags are defined in ifdhandler.h
106 Length - the length of the returned data
107 Value - the value of the data
114 Log1(PCSC_LOG_DEBUG
, "IFDHGetCapabilities");
119 readUID(Length
, Value
);
123 case TAG_IFD_SLOTS_NUMBER
:
125 (*Value
) = IFDH_MAX_SLOTS
;
129 case TAG_IFD_SIMULTANEOUS_ACCESS
:
131 (*Value
) = IFDH_MAX_READERS
;
142 RESPONSECODE
IFDHSetCapabilities ( DWORD Lun
, DWORD Tag
,
143 DWORD Length
, PUCHAR Value
) {
145 /* This function should set the slot/card capabilities for a particular
146 slot/card specified by Lun. Again, if you have only 1 card slot and don't mind
147 loading a new driver for each reader then ignore Lun.
149 Tag - the tag for the information needing set
151 Length - the length of the returned data
152 Value - the value of the data
158 IFD_ERROR_SET_FAILURE
159 IFD_ERROR_VALUE_READ_ONLY
161 Log1(PCSC_LOG_DEBUG
, "IFDHSetCapabilities");
163 return IFD_ERROR_TAG
;
166 RESPONSECODE
IFDHSetProtocolParameters ( DWORD Lun
, DWORD Protocol
,
167 UCHAR Flags
, UCHAR PTS1
,
168 UCHAR PTS2
, UCHAR PTS3
) {
170 /* This function should set the PTS of a particular card/slot using
171 the three PTS parameters sent
173 Protocol - 0 .... 14 T=0 .... T=14
174 Flags - Logical OR of possible values:
175 IFD_NEGOTIATE_PTS1 IFD_NEGOTIATE_PTS2 IFD_NEGOTIATE_PTS3
176 to determine which PTS values to negotiate.
177 PTS1,PTS2,PTS3 - PTS Values.
182 IFD_ERROR_PTS_FAILURE
183 IFD_COMMUNICATION_ERROR
184 IFD_PROTOCOL_NOT_SUPPORTED
186 Log1(PCSC_LOG_DEBUG
, "IFDHSetProtocolParameters");
187 if (Protocol
!= SCARD_PROTOCOL_T0
&& Protocol
!= SCARD_PROTOCOL_T1
)
189 return IFD_PROTOCOL_NOT_SUPPORTED
;
195 RESPONSECODE
IFDHPowerICC ( DWORD Lun
, DWORD Action
,
196 PUCHAR Atr
, PDWORD AtrLength
) {
198 /* This function controls the power and reset signals of the smartcard reader
199 at the particular reader/slot specified by Lun.
201 Action - Action to be taken on the card.
203 IFD_POWER_UP - Power and reset the card if not done so
204 (store the ATR and return it and it's length).
206 IFD_POWER_DOWN - Power down the card if not done already
207 (Atr/AtrLength should
210 IFD_RESET - Perform a quick reset on the card. If the card is not powered
211 power up the card. (Store and return the Atr/Length)
213 Atr - Answer to Reset of the card. The driver is responsible for caching
214 this value in case IFDHGetCapabilities is called requesting the ATR and it's
215 length. This should not exceed MAX_ATR_SIZE.
217 AtrLength - Length of the Atr. This should not exceed MAX_ATR_SIZE.
221 Memory cards without an ATR should return IFD_SUCCESS on reset
222 but the Atr should be zero'd and the length should be zero
224 Reset errors should return zero for the AtrLength and return
225 IFD_ERROR_POWER_ACTION.
230 IFD_ERROR_POWER_ACTION
231 IFD_COMMUNICATION_ERROR
234 Log1(PCSC_LOG_DEBUG
, "IFDHPowerICC");
240 readUID(AtrLength
, Atr
);
246 rv
= IFD_NOT_SUPPORTED
;
252 RESPONSECODE
IFDHTransmitToICC ( DWORD Lun
, SCARD_IO_HEADER SendPci
,
253 PUCHAR TxBuffer
, DWORD TxLength
,
254 PUCHAR RxBuffer
, PDWORD RxLength
,
255 PSCARD_IO_HEADER RecvPci
) {
257 /* This function performs an APDU exchange with the card/slot specified by
258 Lun. The driver is responsible for performing any protocol specific exchanges
259 such as T=0/1 ... differences. Calling this function will abstract all protocol
263 Protocol - 0, 1, .... 14
266 TxBuffer - Transmit APDU example (0x00 0xA4 0x00 0x00 0x02 0x3F 0x00)
267 TxLength - Length of this buffer.
268 RxBuffer - Receive APDU example (0x61 0x14)
269 RxLength - Length of the received APDU. This function will be passed
270 the size of the buffer of RxBuffer and this function is responsible for
271 setting this to the length of the received APDU. This should be ZERO
272 on all errors. The resource manager will take responsibility of zeroing
273 out any temporary APDU buffers for security reasons.
276 Protocol - 0, 1, .... 14
280 The driver is responsible for knowing what type of card it has. If the current
281 slot/card contains a memory card then this command should ignore the Protocol
282 and use the MCT style commands for support for these style cards and transmit
283 them appropriately. If your reader does not support memory cards or you don't
284 want to then ignore this.
286 RxLength should be set to zero on error.
291 IFD_COMMUNICATION_ERROR
294 IFD_PROTOCOL_NOT_SUPPORTED
296 Log1(PCSC_LOG_DEBUG
, "IFDHTransmitToICC");
298 RecvPci
->Protocol
= 1;
300 return sendData(TxBuffer
, TxLength
, RxBuffer
, RxLength
, 0);
303 RESPONSECODE
IFDHControl(DWORD Lun
, DWORD dwControlCode
, PUCHAR TxBuffer
,
304 DWORD TxLength
, PUCHAR RxBuffer
,
305 DWORD RxLength
, PDWORD pdwBytesReturned
) {
307 /* This function performs a data exchange with the reader (not the card)
308 specified by Lun. Here XXXX will only be used.
309 It is responsible for abstracting functionality such as PIN pads,
310 biometrics, LCD panels, etc. You should follow the MCT, CTBCS
311 specifications for a list of accepted commands to implement.
313 TxBuffer - Transmit data
314 TxLength - Length of this buffer.
315 RxBuffer - Receive data
316 RxLength - Length of the received data. This function will be passed
317 the length of the buffer RxBuffer and it must set this to the length
318 of the received data.
321 RxLength should be zero on error.
323 Log1(PCSC_LOG_DEBUG
, "IFDHControl");
324 *pdwBytesReturned
= 0;
328 RESPONSECODE
IFDHICCPresence( DWORD Lun
) {
330 /* This function returns the status of the card inserted in the
331 reader/slot specified by Lun. It will return either:
336 IFD_COMMUNICATION_ERROR
338 //Log1(PCSC_LOG_DEBUG, "IFDHICCPresence");
340 ret
= readPresence();
343 Log1(PCSC_LOG_DEBUG
, "present");
344 return IFD_ICC_PRESENT
;
348 Log1(PCSC_LOG_DEBUG
, "not present");
349 return IFD_ICC_NOT_PRESENT
;