1 #include "../globals.h"
6 #include "../oscam-string.h"
8 #if defined(__CYGWIN__)
10 #define __nullnullterminated
11 #include <specstrings.h>
15 #if !defined(__CYGWIN__)
16 #if !defined(__APPLE__)
17 #include <PCSC/pcsclite.h>
18 #include <PCSC/winscard.h>
19 #include <PCSC/wintypes.h>
20 #include <PCSC/reader.h>
24 #if defined(__APPLE__)
32 #define ERR_INVALID -1
35 #if defined(__CYGWIN__)
49 SCARDCONTEXT hContext
;
51 DWORD dwActiveProtocol
;
54 static int32_t pcsc_init(struct s_reader
*pcsc_reader
)
58 LPSTR mszReaders
= NULL
;
59 char *ptr
, **readers
= NULL
;
60 char *device
= pcsc_reader
->device
;
64 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC establish context for PCSC pcsc_reader %s", device
);
65 SCARDCONTEXT hContext
;
66 memset(&hContext
, 0, sizeof(hContext
));
67 rv
= SCardEstablishContext(SCARD_SCOPE_SYSTEM
, NULL
, NULL
, &hContext
);
68 if(rv
== SCARD_S_SUCCESS
)
70 if(!cs_malloc(&pcsc_reader
->crdr_data
, sizeof(struct pcsc_data
)))
72 struct pcsc_data
*crdr_data
= pcsc_reader
->crdr_data
;
73 crdr_data
->hContext
= hContext
;
75 // here we need to list the pcsc readers and get the name from there,
76 // the pcsc_reader->device should contain the pcsc_reader number
77 // and after the actual device name is copied in crdr_data->pcsc_name .
78 rv
= SCardListReaders(crdr_data
->hContext
, NULL
, NULL
, &dwReaders
);
79 if(rv
!= SCARD_S_SUCCESS
)
81 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC failed listing readers [1] : (%lx)", (unsigned long)rv
);
84 if(!cs_malloc(&mszReaders
, dwReaders
))
86 rv
= SCardListReaders(crdr_data
->hContext
, NULL
, mszReaders
, &dwReaders
);
87 if(rv
!= SCARD_S_SUCCESS
)
89 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC failed listing readers [2]: (%lx)", (unsigned long)rv
);
93 /* Extract readers from the null separated string and get the total
100 ptr
+= cs_strlen(ptr
) + 1;
106 rdr_log(pcsc_reader
, "PCSC : no pcsc_reader found");
107 NULLFREE(mszReaders
);
111 if(!cs_malloc(&readers
, nbReaders
* sizeof(char *)))
113 NULLFREE(mszReaders
);
121 device_line
= strdup((const char *)&pcsc_reader
->device
);
122 device_first
= strsep(&device_line
, ":");
123 device_second
= strsep(&device_line
, ":");
124 reader_nb
= atoi(device_first
);
126 /* fill the readers table */
131 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC pcsc_reader %d: %s", nbReaders
, ptr
);
132 readers
[nbReaders
] = ptr
;
133 if ((reader_nb
== -1) && (device_second
!= NULL
) && strstr(ptr
,device_second
)){
134 reader_nb
= nbReaders
;
136 ptr
+= cs_strlen(ptr
) + 1;
140 if(reader_nb
< 0 || reader_nb
>= nbReaders
)
142 rdr_log(pcsc_reader
, "Wrong pcsc_reader index: %d", reader_nb
);
143 NULLFREE(mszReaders
);
145 NULLFREE(device_line
);
151 snprintf(crdr_data
->pcsc_name
, sizeof(crdr_data
->pcsc_name
), "%s", readers
[reader_nb
]);
154 NULLFREE(mszReaders
);
155 NULLFREE(device_line
);
159 rdr_log(pcsc_reader
, "PCSC failed establish context (%lx)", (unsigned long)rv
);
165 static int32_t pcsc_do_api(struct s_reader
*pcsc_reader
, const uint8_t *buf
, uint8_t *cta_res
, uint16_t *cta_lr
, int32_t l
)
168 DWORD dwSendLength
, dwRecvLength
;
173 rdr_log(pcsc_reader
, "ERROR: Data length to be send to the pcsc_reader is %d", l
);
178 dwRecvLength
= CTA_RES_LEN
;
180 struct pcsc_data
*crdr_data
= pcsc_reader
->crdr_data
;
181 if(crdr_data
->dwActiveProtocol
== SCARD_PROTOCOL_T0
)
183 // explanantion as to why we do the test on buf[4] :
184 // Issuing a command without exchanging data :
185 //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.
186 //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.)
187 //The cbSendLength parameter must be set to four, the size of the T=0 header information (CLA, INS, P1, and P2).
188 //The pbRecvBuffer will receive the SW1 and SW2 status codes from the operation.
189 //The pcbRecvLength should be at least two and will be set to two upon return.
191 { dwSendLength
= l
; }
193 { dwSendLength
= l
- 1; }
194 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength
, cs_hexdump(1, buf
, l
, tmp
, sizeof(tmp
)));
195 rv
= SCardTransmit(crdr_data
->hCard
, SCARD_PCI_T0
, (LPCBYTE
) buf
, dwSendLength
, NULL
, (LPBYTE
) cta_res
, (LPDWORD
) &dwRecvLength
);
196 *cta_lr
= dwRecvLength
;
198 else if(crdr_data
->dwActiveProtocol
== SCARD_PROTOCOL_T1
)
201 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "sending %lu bytes to PCSC : %s", (unsigned long)dwSendLength
, cs_hexdump(1, buf
, l
, tmp
, sizeof(tmp
)));
202 rv
= SCardTransmit(crdr_data
->hCard
, SCARD_PCI_T1
, (LPCBYTE
) buf
, dwSendLength
, NULL
, (LPBYTE
) cta_res
, (LPDWORD
) &dwRecvLength
);
203 *cta_lr
= dwRecvLength
;
207 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC invalid protocol (T=%lu)", (unsigned long)crdr_data
->dwActiveProtocol
);
211 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "received %d bytes from PCSC with rv=%lx : %s", *cta_lr
, (unsigned long)rv
, cs_hexdump(1, cta_res
, *cta_lr
, tmp
, sizeof(tmp
)));
213 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC doapi (%lx ) (T=%d), %d", (unsigned long)rv
, (crdr_data
->dwActiveProtocol
== SCARD_PROTOCOL_T0
? 0 : 1), *cta_lr
);
215 if(rv
== SCARD_S_SUCCESS
)
226 static int32_t pcsc_activate_card(struct s_reader
*pcsc_reader
, uint8_t *atr
, uint16_t *atr_size
)
228 struct pcsc_data
*crdr_data
= pcsc_reader
->crdr_data
;
230 DWORD dwState
, dwAtrLen
, dwReaderLen
;
231 unsigned char pbAtr
[ATR_MAX_SIZE
];
232 char tmp
[sizeof(pbAtr
) * 3 + 1];
234 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC initializing card in (%s)", crdr_data
->pcsc_name
);
235 dwAtrLen
= sizeof(pbAtr
);
238 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC resetting card in (%s) with handle %ld", crdr_data
->pcsc_name
, (long)(crdr_data
->hCard
));
239 rv
= SCardReconnect(crdr_data
->hCard
, SCARD_SHARE_EXCLUSIVE
, SCARD_PROTOCOL_T0
| SCARD_PROTOCOL_T1
, SCARD_RESET_CARD
, &crdr_data
->dwActiveProtocol
);
241 if(rv
!= SCARD_S_SUCCESS
)
243 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv
);
247 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC resetting done on card in (%s)", crdr_data
->pcsc_name
);
248 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC Protocol (T=%d)", (crdr_data
->dwActiveProtocol
== SCARD_PROTOCOL_T0
? 0 : 1));
250 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC getting ATR for card in (%s)", crdr_data
->pcsc_name
);
251 rv
= SCardStatus(crdr_data
->hCard
, NULL
, &dwReaderLen
, &dwState
, &crdr_data
->dwActiveProtocol
, pbAtr
, &dwAtrLen
);
252 if(rv
== SCARD_S_SUCCESS
)
254 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "PCSC Protocol (T=%d)", (crdr_data
->dwActiveProtocol
== SCARD_PROTOCOL_T0
? 0 : 1));
255 memcpy(atr
, pbAtr
, dwAtrLen
);
256 *atr_size
= dwAtrLen
;
258 rdr_log(pcsc_reader
, "ATR: %s", cs_hexdump(1, (uint8_t *)pbAtr
, dwAtrLen
, tmp
, sizeof(tmp
)));
259 memcpy(pcsc_reader
->card_atr
, pbAtr
, dwAtrLen
);
260 pcsc_reader
->card_atr_length
= dwAtrLen
;
265 rdr_log_dbg(pcsc_reader
, D_DEVICE
, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv
);
271 static int32_t pcsc_activate(struct s_reader
*reader
, struct s_ATR
*atr
)
273 unsigned char atrarr
[ATR_MAX_SIZE
];
274 uint16_t atr_size
= 0;
275 if(pcsc_activate_card(reader
, atrarr
, &atr_size
) == OK
)
277 if(ATR_InitFromArray(atr
, atrarr
, atr_size
) != ERROR
) // ATR is OK or softfail malformed
286 static int32_t pcsc_check_card_inserted(struct s_reader
*pcsc_reader
)
288 struct pcsc_data
*crdr_data
= pcsc_reader
->crdr_data
;
289 DWORD dwState
, dwAtrLen
, dwReaderLen
;
290 unsigned char pbAtr
[64];
293 dwAtrLen
= sizeof(pbAtr
);
298 // Do we have a card ?
299 if(!crdr_data
->pcsc_has_card
&& !crdr_data
->hCard
)
301 // try connecting to the card
302 rv
= SCardConnect(crdr_data
->hContext
, crdr_data
->pcsc_name
, SCARD_SHARE_SHARED
, SCARD_PROTOCOL_T0
| SCARD_PROTOCOL_T1
, &crdr_data
->hCard
, &crdr_data
->dwActiveProtocol
);
303 if(rv
== (SCARDHANDLE
)SCARD_E_NO_SMARTCARD
)
305 // no card in pcsc_reader
306 crdr_data
->pcsc_has_card
= 0;
309 SCardDisconnect(crdr_data
->hCard
, SCARD_RESET_CARD
);
310 crdr_data
->hCard
= 0;
312 // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC card in %s removed / absent [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
315 else if(rv
== (SCARDHANDLE
)SCARD_W_UNRESPONSIVE_CARD
)
317 // there is a problem with the card in the pcsc_reader
318 crdr_data
->pcsc_has_card
= 0;
319 crdr_data
->hCard
= 0;
320 rdr_log(pcsc_reader
, "PCSC card in %s is unresponsive. Eject and re-insert please.", crdr_data
->pcsc_name
);
323 else if(rv
== SCARD_S_SUCCESS
)
326 crdr_data
->pcsc_has_card
= 1;
327 rdr_log(pcsc_reader
, "PCSC was opened with handle: %ld", (long)crdr_data
->hCard
);
331 // if we get here we have a bigger problem -> display status and debug
332 // rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC pcsc_reader %s status [dwstate=%lx rv=(%lx)]", crdr_data->pcsc_name, dwState, (unsigned long)rv );
338 // if we get there the card is ready, check its status
339 rv
= SCardStatus(crdr_data
->hCard
, NULL
, &dwReaderLen
, &dwState
, &crdr_data
->dwActiveProtocol
, pbAtr
, &dwAtrLen
);
341 if(rv
== SCARD_S_SUCCESS
&& (dwState
& (SCARD_PRESENT
| SCARD_NEGOTIABLE
| SCARD_POWERED
)))
347 SCardDisconnect(crdr_data
->hCard
, SCARD_RESET_CARD
);
348 crdr_data
->hCard
= 0;
349 crdr_data
->pcsc_has_card
= 0;
355 static int32_t pcsc_get_status(struct s_reader
*reader
, int32_t *in
)
357 struct pcsc_data
*crdr_data
= reader
->crdr_data
;
358 int32_t ret
= pcsc_check_card_inserted(reader
);
359 *in
= crdr_data
->pcsc_has_card
;
363 static int32_t pcsc_close(struct s_reader
*pcsc_reader
)
365 struct pcsc_data
*crdr_data
= pcsc_reader
->crdr_data
;
366 rdr_log_dbg(pcsc_reader
, D_IFD
, "PCSC : Closing device %s", pcsc_reader
->device
);
367 SCardDisconnect(crdr_data
->hCard
, SCARD_LEAVE_CARD
);
368 SCardReleaseContext(crdr_data
->hContext
);
372 const struct s_cardreader cardreader_pcsc
=
376 .skip_extra_atr_parsing
= 1,
377 .skip_t1_command_retries
= 1,
378 .skip_setting_ifsc
= 1,
379 .reader_init
= pcsc_init
,
380 .get_status
= pcsc_get_status
,
381 .activate
= pcsc_activate
,
382 .card_write
= pcsc_do_api
,