changed protocoll to use 2 byte length
[nfcbtpcsc.git] / ifdhandler.c
blob905ad0f23c37391b598db322249cb5fd816d12b2
1 /*****************************************************************
3 / File : ifdhandler.c
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 */
17 #include <pcsclite.h>
18 #include <ifdhandler.h>
19 #include <debuglog.h>
20 #include "nfc.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.
60 returns:
62 IFD_SUCCESS
63 IFD_COMMUNICATION_ERROR
65 Log1(PCSC_LOG_DEBUG, "IFDHCreateChannel");
66 return getDevice();
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
81 is also powered down.
83 returns:
85 IFD_SUCCESS
86 IFD_COMMUNICATION_ERROR
88 Log1(PCSC_LOG_DEBUG, "IFDHCloseChannel");
90 closeSocket();
92 return IFD_SUCCESS;
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
109 returns:
111 IFD_SUCCESS
112 IFD_ERROR_TAG
114 Log1(PCSC_LOG_DEBUG, "IFDHGetCapabilities");
115 RESPONSECODE rv;
116 switch (Tag)
118 case TAG_IFD_ATR:
119 readUID(Length, Value);
120 rv = IFD_SUCCESS;
121 break;
123 case TAG_IFD_SLOTS_NUMBER:
124 (*Length) = 1;
125 (*Value) = IFDH_MAX_SLOTS;
126 rv = IFD_SUCCESS;
127 break;
129 case TAG_IFD_SIMULTANEOUS_ACCESS:
130 (*Length) = 1;
131 (*Value) = IFDH_MAX_READERS;
132 rv = IFD_SUCCESS;
133 break;
135 default:
136 (*Length) = 0;
137 rv = IFD_ERROR_TAG;
139 return rv;
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
154 returns:
156 IFD_SUCCESS
157 IFD_ERROR_TAG
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.
179 returns:
181 IFD_SUCCESS
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;
191 return IFD_SUCCESS;
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
208 be zero'd)
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.
219 Notes:
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.
227 returns:
229 IFD_SUCCESS
230 IFD_ERROR_POWER_ACTION
231 IFD_COMMUNICATION_ERROR
232 IFD_NOT_SUPPORTED
234 Log1(PCSC_LOG_DEBUG, "IFDHPowerICC");
235 RESPONSECODE rv;
236 switch (Action)
238 case IFD_RESET:
239 case IFD_POWER_UP:
240 readUID(AtrLength, Atr);
241 rv = IFD_SUCCESS;
242 break;
243 default:
244 *AtrLength = 0;
245 Atr = 0;
246 rv = IFD_NOT_SUPPORTED;
247 break;
249 return rv;
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
260 differences.
262 SendPci
263 Protocol - 0, 1, .... 14
264 Length - Not used.
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.
275 RecvPci
276 Protocol - 0, 1, .... 14
277 Length - Not used.
279 Notes:
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.
288 returns:
290 IFD_SUCCESS
291 IFD_COMMUNICATION_ERROR
292 IFD_RESPONSE_TIMEOUT
293 IFD_ICC_NOT_PRESENT
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.
320 Notes:
321 RxLength should be zero on error.
323 Log1(PCSC_LOG_DEBUG, "IFDHControl");
324 *pdwBytesReturned = 0;
325 return IFD_SUCCESS;
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:
333 returns:
334 IFD_ICC_PRESENT
335 IFD_ICC_NOT_PRESENT
336 IFD_COMMUNICATION_ERROR
338 //Log1(PCSC_LOG_DEBUG, "IFDHICCPresence");
339 int ret = 0;
340 ret = readPresence();
341 if (ret == 1)
343 Log1(PCSC_LOG_DEBUG, "present");
344 return IFD_ICC_PRESENT;
346 else
348 Log1(PCSC_LOG_DEBUG, "not present");
349 return IFD_ICC_NOT_PRESENT;