source: branches/smartreader/reader-pcsc.c@ 1012

Last change on this file since 1012 was 1012, checked in by rorothetroll, 13 years ago

resync with trunk

File size: 8.5 KB
Line 
1#ifdef HAVE_PCSC
2
3#include "reader-pcsc.h"
4int pcsc_reader_init(struct s_reader *pcsc_reader, char *device)
5{
6 ULONG rv;
7 DWORD dwReaders;
8 LPSTR mszReaders = NULL;
9 char *ptr, **readers = NULL;
10 int nbReaders;
11 int reader_nb;
12
13 cs_debug("PCSC establish context for PCSC reader %s", device);
14 rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pcsc_reader->hContext);
15 if ( rv == SCARD_S_SUCCESS ) {
16 // here we need to list the pcsc readers and get the name from there,
17 // the pcsc_reader->device should contain the reader number
18 // and after the actual device name is copied in pcsc_reader->pcsc_name .
19 rv = SCardListReaders(pcsc_reader->hContext, NULL, NULL, &dwReaders);
20 if( rv != SCARD_S_SUCCESS ) {
21 cs_debug("PCSC failed listing readers [1] : (%lx)", rv);
22 return 0;
23 }
24 mszReaders = malloc(sizeof(char)*dwReaders);
25 if (mszReaders == NULL) {
26 cs_debug("PCSC failed malloc");
27 return 0;
28 }
29 rv = SCardListReaders(pcsc_reader->hContext, NULL, mszReaders, &dwReaders);
30 if( rv != SCARD_S_SUCCESS ) {
31 cs_debug("PCSC failed listing readers [2]: (%lx)", rv);
32 return 0;
33 }
34 /* Extract readers from the null separated string and get the total
35 * number of readers */
36 nbReaders = 0;
37 ptr = mszReaders;
38 while (*ptr != '\0') {
39 ptr += strlen(ptr)+1;
40 nbReaders++;
41 }
42
43 if (nbReaders == 0) {
44 cs_debug("PCSC : no reader found");
45 return 0;
46 }
47
48 readers = calloc(nbReaders, sizeof(char *));
49 if (readers == NULL) {
50 cs_debug("PCSC failed malloc");
51 return 0;
52 }
53
54 /* fill the readers table */
55 nbReaders = 0;
56 ptr = mszReaders;
57 while (*ptr != '\0') {
58 cs_debug("PCSC reader %d: %s", nbReaders, ptr);
59 readers[nbReaders] = ptr;
60 ptr += strlen(ptr)+1;
61 nbReaders++;
62 }
63
64 reader_nb=atoi((const char *)&pcsc_reader->device);
65 if (reader_nb < 0 || reader_nb >= nbReaders) {
66 cs_debug("Wrong reader index: %d\n", reader_nb);
67 return 0;
68 }
69
70 snprintf(pcsc_reader->pcsc_name,sizeof(pcsc_reader->pcsc_name),"%s",readers[reader_nb]);
71 pcsc_reader->pcsc_has_card=0;
72 pcsc_reader->hCard=0;
73 }
74 else {
75 cs_debug("PCSC failed establish context (%lx)", rv);
76 }
77
78 return 0;
79}
80
81int pcsc_reader_do_api(struct s_reader *pcsc_reader, uchar *buf, uchar *cta_res, ushort *cta_lr, int l, int dbg)
82{
83 ULONG rv;
84 SCARD_IO_REQUEST pioRecvPci;
85 DWORD dwSendLength, dwRecvLength;
86
87
88 dwRecvLength = CTA_RES_LEN;
89
90 if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0) {
91 // explanantion as to why we do the test on buf[4] :
92 // Issuing a command without exchanging data :
93 //To issue a command to the card that does not involve the exchange of data (either sent or received), the send and receive buffers must be formatted as follows.
94 //The pbSendBuffer buffer must contain the CLA, INS, P1, and P2 values for the T=0 operation. The P3 value is not sent. (This is to differentiate the header from the case where 256 bytes are expected to be returned.)
95 //The cbSendLength parameter must be set to four, the size of the T=0 header information (CLA, INS, P1, and P2).
96 //The pbRecvBuffer will receive the SW1 and SW2 status codes from the operation.
97 //The pcbRecvLength should be at least two and will be set to two upon return.
98 if(buf[4])
99 dwSendLength = l;
100 else
101 dwSendLength = l-1;
102 cs_debug("sending %d bytes to PCSC", dwSendLength);
103 rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T0, buf, dwSendLength, &pioRecvPci, cta_res, &dwRecvLength);
104 }
105 else if(pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T1) {
106 dwSendLength = l;
107 cs_debug("sending %d bytes to PCSC", dwSendLength);
108 rv = SCardTransmit(pcsc_reader->hCard, SCARD_PCI_T1, buf, dwSendLength, &pioRecvPci, cta_res, &dwRecvLength);
109 }
110 else {
111 cs_debug("PCSC invalid protocol (T=%d)", pcsc_reader->dwActiveProtocol);
112 return ERR_INVALID;
113 }
114
115 *cta_lr=dwRecvLength;
116 cs_debug("received %d bytes from PCSC with rv=%lx", *cta_lr, rv);
117
118 cs_debug("PCSC doapi (%lx ) (T=%d), %d", rv, ( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1), dwRecvLength );
119 if ( rv == SCARD_S_SUCCESS ){
120 return OK;
121 }
122 else {
123 return ERR_INVALID;
124 }
125
126}
127
128int pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, ushort *atr_size)
129{
130 ULONG rv;
131 DWORD dwState, dwAtrLen, dwReaderLen;
132 BYTE pbAtr[64];
133
134 cs_debug("PCSC initializing card in (%s)", pcsc_reader->pcsc_name);
135 dwAtrLen = sizeof(pbAtr);
136 dwReaderLen=0;
137
138 cs_debug("PCSC resetting card in (%s)", pcsc_reader->pcsc_name);
139 rv = SCardReconnect(pcsc_reader->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &pcsc_reader->dwActiveProtocol);
140 cs_debug("PCSC resetting done on card in (%s)", pcsc_reader->pcsc_name);
141 cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
142
143 if ( rv != SCARD_S_SUCCESS ) {
144 cs_debug("Error PCSC failed to reset card (%lx)", rv);
145 return(0);
146 }
147
148
149 cs_debug("PCSC getting ATR for card in (%s)", pcsc_reader->pcsc_name);
150 rv = SCardStatus(pcsc_reader->hCard,NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
151 if ( rv == SCARD_S_SUCCESS ) {
152 cs_debug("PCSC Protocol (T=%d)",( pcsc_reader->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 : 1));
153 memcpy(atr, pbAtr, dwAtrLen);
154 *atr_size=dwAtrLen;
155#ifdef CS_RDR_INIT_HIST
156 pcsc_reader->init_history_pos=0;
157 memset(pcsc_reader->init_history, 0, sizeof(pcsc_reader->init_history));
158#endif
159 cs_ri_log("ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen));
160 return(1);
161 }
162 else {
163 cs_debug("Error PCSC failed to get ATR for card (%lx)", rv);
164 }
165
166 return(0);
167}
168
169
170int pcsc_check_card_inserted(struct s_reader *pcsc_reader)
171{
172 DWORD dwState, dwAtrLen, dwReaderLen;
173 BYTE pbAtr[64];
174 ULONG rv;
175
176 dwAtrLen = sizeof(pbAtr);
177 rv=0;
178 dwState=0;
179 dwReaderLen=0;
180
181 // Do we have a card ?
182 if (!pcsc_reader->pcsc_has_card && !pcsc_reader->hCard) {
183 // try connecting to the card
184 rv = SCardConnect(pcsc_reader->hContext, pcsc_reader->pcsc_name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &pcsc_reader->hCard, &pcsc_reader->dwActiveProtocol);
185 if (rv==SCARD_E_NO_SMARTCARD) {
186 // no card in reader
187 pcsc_reader->pcsc_has_card=0;
188 if(pcsc_reader->hCard) {
189 SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
190 pcsc_reader->hCard=0;
191 }
192 cs_debug("PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
193 return 0;
194 }
195 else if( rv == SCARD_W_UNRESPONSIVE_CARD ) {
196 // there is a problem with the card in the reader
197 pcsc_reader->pcsc_has_card=0;
198 pcsc_reader->hCard=0;
199 cs_log("PCSC card in %s is unresponsive. Eject and re-insert please.", pcsc_reader->pcsc_name);
200 return 0;
201 }
202 else if( rv == SCARD_S_SUCCESS ) {
203 // we have a card
204 pcsc_reader->pcsc_has_card=1;
205 }
206 else {
207 // if we get here we have a bigger problem -> display status and debug
208 cs_debug("PCSC reader %s status [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
209 return 0;
210 }
211
212 }
213
214 // if we get there the card is ready, check its status
215 rv = SCardStatus(pcsc_reader->hCard, NULL, &dwReaderLen, &dwState, &pcsc_reader->dwActiveProtocol, pbAtr, &dwAtrLen);
216
217 if (rv == SCARD_S_SUCCESS && (dwState & (SCARD_PRESENT | SCARD_NEGOTIABLE | SCARD_POWERED ) )) {
218 cs_debug("PCSC card IS inserted in %s card state [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState,rv);
219 return CARD_INSERTED;
220 }
221 else {
222 SCardDisconnect(pcsc_reader->hCard,SCARD_RESET_CARD);
223 pcsc_reader->hCard=0;
224 pcsc_reader->pcsc_has_card=0;
225 cs_debug("PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", pcsc_reader->pcsc_name, dwState, rv );
226 }
227
228 return 0;
229}
230#endif
231
Note: See TracBrowser for help on using the repository browser.