New upstream version 1.5.0

This commit is contained in:
Ludovic Rousseau 2022-01-27 13:05:07 +01:00
parent 3d895c8b7c
commit d964627ccc
31 changed files with 5314 additions and 2984 deletions

948
ChangeLog
View File

@ -1,4 +1,948 @@
commit 74642f87f9e1a937e807acd3a7d2ef600b8d151c (HEAD -> master, zotac/master, origin/master, origin/HEAD) commit f79106c365ed0747109e7e465adb54bf176b1036 (HEAD -> master, tag: 1.5.0, zotac/master, origin/master, origin/HEAD, github/master)
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Thu Jan 27 11:24:13 2022 +0100
Release 1.5.0
Signed-off-by: Ludovic Rousseau <ludovic.rousseau@free.fr>
README.md | 26 ++++++++++++++++++++++++++
configure.ac | 2 +-
2 files changed, 27 insertions(+), 1 deletion(-)
commit 401f9fba36be17592188713f29559c1bf616bde4
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Thu Jan 27 12:50:23 2022 +0100
ReadUSB: Fix compiler warning
ccid_usb.c: In function ReadUSB:
ccid_usb.c:967:61: warning: comparison of integer expressions of different signedness: int and unsigned int [-Wsign-compare]
967 | if (concurrent[slot].length > *length)
src/ccid_usb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit 9c59fc5557c5ac515f87f877fb5a337166b33343
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Thu Jan 27 11:10:22 2022 +0100
Add Thales Shield M4 Reader
readers/Thales_Shield_M4_Reader.txt | 56 +++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 5 +++-
2 files changed, 60 insertions(+), 1 deletion(-)
commit a725a113ee050a5b0e336dca44bbff035786ee16
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Fri Jan 21 11:12:05 2022 +0100
Multi_ReadProc() exits on the *last* slot exit
The function to read data from multi-slots readers should exit only when
the last slot is terminated.
Before the change, the function was terminated with the _first_ slot. So
it was not possible to send PowerDown commands to the other slots of the
same reader.
src/ccid_usb.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
commit 5583333cdb6f30684c8eb569761516ed49c61ec3
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 15:17:46 2022 +0100
Prevent a potential buffer overflow for concurrent multi-slots
Check the buffer is large enough to copy all the received bytes.
The problem should never happen in practice but...
src/ccid_usb.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
commit 1addd756eeb182764fc55a95a9fe1a8af35da805
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Nov 6 14:12:19 2021 +0100
Check the bSeq value when receiving a CCID frame
For multi-slots readers we now use a different USB read routine.
We can now get USB packets that were waiting in the reader but not yet
sent. For example this happens when pcscd is stopped and restarted.
On restart the driver will receive packets that were not yet read during
the previous execution of pcscd.
We must ignore packets with a bSeq that does not correspond to the bSeq
of the command sent by the reader.
src/ccid_serial.c | 5 ++++-
src/ccid_serial.h | 2 +-
src/ccid_usb.c | 8 ++++----
src/ccid_usb.h | 2 +-
src/commands.c | 32 +++++++++++++++++++++-----------
5 files changed, 31 insertions(+), 18 deletions(-)
commit 77376bcefff4831894033f6e06ee95764afa02bd
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 31 14:49:43 2021 +0100
Multi_ReadProc: wait for 100 ms in case of libusb error
We wait a bit to avoid a fast error loop.
If libusb_bulk_transfer() failed because the device has been removed
then the device will stay removed and we may fill the logs with error
messages untill the removal is detected and reported by pcscd hotplug
mechanism.
The only case in which we do NOT wait is LIBUSB_ERROR_TIMEOUT because
this case is expected and we should wait again immediatly.
src/ccid_usb.c | 4 ++++
1 file changed, 4 insertions(+)
commit 298903c8f85cb0e79aeddd6cc7ff50d2829397db
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Oct 27 18:33:40 2021 +0200
Enable TAG_IFD_SLOT_THREAD_SAFE when supported
We only support the case of readers that can support access to all slots
at the same time. That is the case of the sysmoOCTSIM for example.
But if the reader can only support a subset of the slot at the same time
we continue as before. That is the case of the COVADIS Auriga that
declares 3 slots but can only have 2 slots active at the same time.
src/ifdhandler.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
commit 47fd21e31bec8e068910dfb03f6123cc9d3faacf
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Jan 23 10:32:04 2022 +0100
Add suport of simultaneous slot access
This is used for multi slots readers like the sysmoOCTSIM reader with 8
slots.
src/ccid_usb.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 199 insertions(+), 14 deletions(-)
commit 1fa58ab0363455523739c04146c96c84f33a029f
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Oct 27 15:52:42 2021 +0200
Store CCID field bMaxCCIDBusySlots
We will need this value to know the number of slots that can be used
simultanesously.
src/ccid.h | 5 +++++
src/ccid_serial.c | 1 +
src/ccid_usb.c | 1 +
3 files changed, 7 insertions(+)
commit d1cf6bdc73bfe056487432fcd949a7ab8b1e57a7
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Jan 22 17:32:47 2022 +0100
Multi_PollingProc: do not set .terminated here
The field .terminated is set to TRUE in Multi_PollingTerminate() to terminate
the thread.
This line was present since the initial patch
38faa97872a526e069a856df710167fe4c50486a in 2013.
src/ccid_usb.c | 1 -
1 file changed, 1 deletion(-)
commit 0ee9dd19a6258a05553c66ec536325cae04c3341
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Jan 22 14:33:16 2022 +0100
Multi_PollingProc: allocate the libusb transfer once
No need to allocate/free the libusb transfer structure for each
transfer.
We do it once at the beginning of the function.
src/ccid_usb.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
commit a2daf37ee1eaa84fc10a78114372e4eb588ac7ab
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Fri Jan 21 10:58:48 2022 +0100
Multi_PollingProc: log the status name instead of its value
Use libusb_error_name(status) to log a human readable text instead of a
numeric value.
We now have:
00000085 ccid_usb.c:1703:Multi_PollingProc() Multi_PollingProc (1/7): LIBUSB_TRANSFER_CANCELLED
instead of:
00000148 ccid_usb.c:1703:Multi_PollingProc() Multi_PollingProc (1/7): 3
src/ccid_usb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
commit 5259925ceb74eca69b3aad7658df30d6fa938ed6
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Thu Jan 20 18:49:07 2022 +0100
IFDHSetProtocolParameters: always compute readTimeout
If the reader declares CCID_CLASS_AUTO_PPS_PROP the driver does not send
the PC_to_RDR_SetParameters CCID command.
But we must compute the readTimeout to use according to the card ATR.
The default read timeout of 3 seconds may not be a good value in every
cases.
The problem was detected using the SpringCard Puck One reader that does
NOT send time extension requests.
src/ifdhandler.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
commit 560de95fa73f426286aeab9c7191dfacc472bbed
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Jan 16 21:40:02 2022 +0100
Remore unused field "transfer"
The "struct usbDevice_MultiSlot_Extension" had a field
"struct libusb_transfer *transfer;" that was not used.
src/ccid_usb.c | 2 --
1 file changed, 2 deletions(-)
commit 0e0141e05a3a1f05e116700e62a89d2c6c9e25b2
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 16:40:18 2022 +0100
Do not log the libusb error value, just its name
There is no real value to duplicate the libusb error name by the error
value.
"-4 LIBUSB_ERROR_NO_DEVICE" is not more informative than just
"LIBUSB_ERROR_NO_DEVICE".
src/ccid_usb.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
commit 43050f337edb9d38a35dec04ee5448c74b19c272
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 16:24:43 2022 +0100
Do not log LIBUSB_ERROR_NO_DEVICE when a multi slot is removed
When a multi slot reader with simultaneous acces used is removed we get
the error log:
00000000 [140737321879104] ccid_usb.c:1734:Multi_PollingProc() Multi_PollingProc (1/18): error -4 LIBUSB_ERROR_NO_DEVICE
Since this error is expected we do not log it.
src/ccid_usb.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
commit 75f80160d71b0bbcb31b4b81a71e963ed0b35c09
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 13:43:17 2022 +0100
iInterruptRead: log libusb error text version
Log the libusb error name instead of just the decimal code.
In the logs we now have:
00000034 [139678897940032] ccid_usb.c:1526:InterruptRead() InterruptRead (1/7): LIBUSB_TRANSFER_CANCELLED
instead of :
00000034 [139678897940032] ccid_usb.c:1526:InterruptRead() InterruptRead (1/7): 3
src/ccid_usb.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
commit 100a4e910be1012f26fa771496bff5f9346f08f6
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 13:35:42 2022 +0100
Avoid potential data race for card events management
Declare polling_transfer field as _Atomic since it is accessed from
different threads.
The thread running InterruptRead() or Multi_PollingProc() has a
read/write access.
The thread running InterruptStop() or Multi_PollingTerminate() also
access the field to cancel the transfer.
src/ccid_usb.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
commit a6edf774c0a9d2d63c0fd2c939888dcedb3d2904
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 10:02:25 2022 +0100
Avoid potential data race for multi-slots readers
Declare "terminated" field as _Atomic since it is accessed from
different threads: one thread reads the value and the value is set from
another thread to indicate to the first thread to exit.
I have NOT found an occurence of the bug in a real execution. But the
code should be safer now.
src/ccid_usb.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
commit 51d90a5e0f1d1d9abc420207b5543ea50707d6c1
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 19 15:09:25 2022 +0100
Rewrite DEBUG_*() macros
Wrap the code in a "do { [...] } while(0)" so it is possible to use a
construct like:
if (condition)
DEBUG_CRITICAL("Error");
else
normal execution
Before the change, the DEBUG_CRITICAL() was expanded to:
if (condition)
if (LogLevel & DEBUG_LEVEL_CRITICAL)
Log1(PCSC_LOG_CRITICAL, fmt)
else
normal execution
So the "else" was associated to the second "if" instead of the first
one.
And this is an open door for bugs.
To avoid any problem the code should have been:
if (condition)
{
DEBUG_CRITICAL("Error");
}
else
normal execution
DEBUG_*() maros are now safer to use.
src/debug.h | 61 +++++++++++++++++++++++++++----------------------------------
1 file changed, 27 insertions(+), 34 deletions(-)
commit a6ed3fa1bdb554f3a0e01e9d9fb261d88ab298b2
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Jan 15 13:36:55 2022 +0100
IFDHSetProtocolParameters: harmonize log message
Use "Timeout:" for T=0 as for T=1 (line 1068) and when no computation
is done (line 816).
src/ifdhandler.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit 2ffdb61caee2921b5f6d5b2309ea9993e1ca557c
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:29:37 2022 +0100
Add Circle CIR615 CL
readers/Circle_CIR615_CL.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit cf35f360ae11b1cfc4ed79de4d8a35beed7df144
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:28:24 2022 +0100
Add Circle CIR615 CL & 1S
readers/Circle_CIR615_CL_1S.txt | 54 +++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit c1f69339a3a5e9b214c809309f8a5c73e0cecf4d
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:24:48 2022 +0100
Add Circle CIR515 ICC
readers/Circle_CIR515_ICC.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit f9768e1d61955ac630b66d6b57a3f88d33d3c16a
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:23:29 2022 +0100
Add Circle CIR415 CL
readers/Circle_CIR415_CL.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit e90ea431d2fd731408efe384b2ba6c20b42d6a87
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:21:59 2022 +0100
Add Circle CIR315 with idProduct: 0x7004
readers/Circle_CIR315_0x7004.txt | 105 +++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 106 insertions(+)
commit 8ecaacb0aae32d9d21d09f88c076a90f4759357f
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:20:49 2022 +0100
Add Circle CIR315 DI
readers/Circle_CIR315_DI.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit 868abf1248b45469496b2c73e8ac380a607f9241
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:19:19 2022 +0100
Add Circle CIR315 with idProduct: 0x0324
readers/Circle_CIR315_0x0324.txt | 105 +++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 106 insertions(+)
commit 472d0964c94a1113100a753a9cdd0103f75be5e5
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 16:14:24 2022 +0100
Add Circle CIR215 CL with iProduct 0x2100
readers/Circle_CIR215_CL_0x2100.txt | 54 +++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit 0ca1dcd5bb80f46538f20f5226491356c8536d5a
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 15:53:13 2022 +0100
Add Circle CIR125-DOT ICC
readers/Circle_CIR125-DOT_ICC.txt | 54 +++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit bec5918390dc052f49fc032868172602f91f81ba
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 15:51:16 2022 +0100
Add Circle CCR7125 ICC
readers/Circle_CCR7125_ICC.txt | 54 ++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 1 +
2 files changed, 55 insertions(+)
commit 8fcb0d2066c405f5b348458aea4857dc27239215
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Jan 5 15:49:40 2022 +0100
Add Circle CIR125 ICC
readers/Circle_CIR125_ICC.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 3 ++-
2 files changed, 56 insertions(+), 1 deletion(-)
commit fdfa06b98637444f5ef1a4c50c5a520cc9b63f0f
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Nov 17 13:17:08 2021 +0100
ylwrap: update copyright date
ylwrap | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit abb793b270704b0a33f8027253015fc82abbf72e
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Nov 6 14:32:30 2021 +0100
IFDHPowerICC: do not log an error for IFD_NO_SUCH_DEVICE
When a reader is removed pcscd will try to cleanly close the driver and
will try to power down the card (if needed).
WriteUSB() will correctly return STATUS_NO_SUCH_DEVICE. CmdPowerOff()
will also return STATUS_NO_SUCH_DEVICE.
But IFDHPowerICC() did not correctly handled this returned value.
src/ifdhandler.c | 3 +++
1 file changed, 3 insertions(+)
commit 6ebc18e90fea92caf8d79765b08cd6f137100fbe
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Nov 6 13:57:17 2021 +0100
Revert "multi-slots: Start the sequence number at 0 for a new slot"
This reverts commit e3baafb89cee3eae9302e454ca25332401b9569c.
src/ccid_serial.c | 1 -
src/ccid_usb.c | 1 -
2 files changed, 2 deletions(-)
commit d1ee8371e47802dd41a86d9303074214fb7814df
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 24 18:44:46 2021 +0200
Revert "Each slot has its own sequence number"
The Gemalto GemCore SIM Pro Smart Card Reader, that has 2 slots, does
not like to have the same bSeq used for 2 consecutive commands on 2
different slots. The reader does not answer to the second command. I
guess it considers the 2nd command as duplicate ghost or something like
that.
For example we get:
00000007 [140486031439616] ifdhandler.c:1209:IFDHPowerICC() action: PowerDown, usb:08
e6/3480:libudev:0:/dev/bus/usb/001/012 (lun: 0)
00000008 [140486031439616] -> 000000 63 00 00 00 00 00 04 00 00 00
00000257 [140486031439616] ccid_usb.c:948:ReadUSB() Waiting data for slot 0
00000320 [140486107440896] ccid_usb.c:1949:Multi_ReadProc() Read 10 bytes for slot 0
00000024 [140486107440896] ccid_usb.c:1957:Multi_ReadProc() Signaled reader 0 slot 0
00000005 [140486107440896] ccid_usb.c:1917:Multi_ReadProc() Waiting read for reader 0
00000076 [140486031439616] ccid_usb.c:962:ReadUSB() Got 10 bytes for slot 0
00000025 [140486031439616] <- 000000 81 00 00 00 00 00 04 01 00 00
00000008 [140486031439616] eventhandler.c:482:EHStatusHandlerThread() powerState: POW
ER_STATE_UNPOWERED
00000009 [140486031439616] ifdhandler.c:1915:IFDHICCPresence() usb:08e6/3480:libudev:
0:/dev/bus/usb/001/012 (lun: 0)
00000006 [140486031439616] ifdhandler.c:2041:IFDHICCPresence() Card present
00000007 [140486031439616] ifdhandler.c:317:IFDHPolling() usb:08e6/3480:libudev:0:/de
v/bus/usb/001/012 (lun: 0) 600000 ms
00000008 [140486031439616] ccid_usb.c:1801:Multi_InterruptRead() Multi_InterruptRead
(0), timeout: 600000 ms
00167330 [140486023046912] ifdhandler.c:1915:IFDHICCPresence() usb:08e6/3480:libudev:
0:/dev/bus/usb/001/012 (lun: 1)
00000026 [140486023046912] ifdhandler.c:2041:IFDHICCPresence() Card present
00000006 [140486023046912] ifdhandler.c:1209:IFDHPowerICC() action: PowerDown, usb:08
e6/3480:libudev:0:/dev/bus/usb/001/012 (lun: 1)
00000009 [140486023046912] -> 000001 63 00 00 00 00 01 04 00 00 00
00000260 [140486023046912] ccid_usb.c:948:ReadUSB() Waiting data for slot 1
[...]
02329717 [140486023046912] ccid_usb.c:956:ReadUSB() read failed (1/12): 110 Connection timed out
00000028 [140486023046912] ifdhandler.c:1225:IFDHPowerICC() PowerDown failed
The first PC_to_RDR_IccPowerOff command uses bSeq=4 and is for slot=0.
This command works fine.
The second PC_to_RDR_IccPowerOff command is for the slot 1 but uses the
same bSeq=4. The driver never gets an answer for this command.
I revert the change and now the bSeq value used by each command is uniq
for the reader.
This reverts commit 5f63ca79cfa3291a943dd14a54fdefa56da3bf28.
src/ccid.h | 3 ++-
src/ccid_serial.c | 3 ++-
src/ccid_usb.c | 5 +++--
src/commands.c | 18 +++++++++---------
4 files changed, 16 insertions(+), 13 deletions(-)
commit f30bd1fcb1c929b110165eec9cfc29f6b709ef5a
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Tue Nov 2 16:16:26 2021 +0100
Rename Felica in FeliCa in filenames
readers/{SONY_Felica_RC-S300_P.txt => SONY_FeliCa_RC-S300_P.txt} | 0
readers/{SONY_Felica_RC-S300_S.txt => SONY_FeliCa_RC-S300_S.txt} | 0
readers/{SONY_Felica_RC-S660_U.txt => SONY_FeliCa_RC-S660_U.txt} | 0
3 files changed, 0 insertions(+), 0 deletions(-)
commit ab95559647e4382eae699b7823f997aedeb18c70
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Mon Nov 1 13:27:00 2021 +0100
Fix bClassEnveloppe: field name for 3 Bit4id readers
The correct name is "bClassEnvelope".
This problem has been fixed in CCID parse.c in
41119961d8138204b3168e0838272885829815be (May 2013).
readers/Bit4id_Digital_DNA_Key.txt | 2 +-
readers/Bit4id_tokenME_FIPS_v3.txt | 2 +-
readers/bit4id_TokenME-EVO.txt | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
commit adde6fb74833b3ed47b0579863ca526e81483362
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 31 14:02:31 2021 +0100
DisconnectUSB(): disconnect all the slots of a multi-slot reader
When a reader is removed all the slots will become unavailable.
So to avoid errors logs like:
00299802 [139984241678080] ifdhandler.c:1911:IFDHICCPresence() usb:1c34/7124:libudev:0:/dev/bus/usb/001/016 (lun: 10003)
00000037 [139984241678080] -> 000004 65 00 00 00 00 03 06 00 00 00
00000051 [139984241678080] ccid_usb.c:871:WriteUSB() write failed (1/16): -4 LIBUSB_ERROR_NO_DEVICE
we mark all the slots of the same USB device as also disconnected.
This improves the patch in b0cb37f1aee46d04c31c19273f23967f4ae8601c.
src/ccid_usb.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
commit 5d0b4e411b79b68e2166e168230f135ea73f2cb5
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 31 13:56:18 2021 +0100
Multi_InterruptRead: return IFD_NO_SUCH_DEVICE when exiting
The value 0 (IFD_SUCCESS) is not a good answer when the driver is
stopping or removed.
The conversion from 0 to IFD_NO_SUCH_DEVICE is no more done in
IFDHPolling() as the comments wrongly indicates since
commit f83c1ea6806c62d39ba7ba305c92f01658796e47 (Aug 2010) but the code
for multislots was not modified at the same time.
We use IFD_NO_SUCH_DEVICE instead so that pcscd will wait a bit before
asking again.
src/ccid_usb.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
commit e3baafb89cee3eae9302e454ca25332401b9569c
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Oct 30 11:07:20 2021 +0200
multi-slots: Start the sequence number at 0 for a new slot
Each slot has its own sequence number (CCID bSeq field). When a new slot
is created we start the sequence number at 0 instead of using the value
from the previous slot that is copied.
It is not important but it generates cleaner logs.
src/ccid_serial.c | 1 +
src/ccid_usb.c | 1 +
2 files changed, 2 insertions(+)
commit 5f63ca79cfa3291a943dd14a54fdefa56da3bf28
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 24 18:44:46 2021 +0200
Each slot has its own sequence number
src/ccid.h | 3 +--
src/ccid_serial.c | 3 +--
src/ccid_usb.c | 5 ++---
src/commands.c | 18 +++++++++---------
4 files changed, 13 insertions(+), 16 deletions(-)
commit a12a7eb202259b6241ec307fecf8b7d1e365bf7b
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 24 14:24:31 2021 +0200
Fix incorrect comment
src/ccid_usb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit a4eb16ebf922a45cfdd1a916602206378118042a
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 24 14:17:34 2021 +0200
Fix typo in comment
src/ccid_usb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit b801b8ac7be541939d951e2744e42ef0ac07f061
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Oct 27 11:32:43 2021 +0200
Add ACS ACR1281U
readers/ACS_ACR1281U.txt | 54 +++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 3 ++-
2 files changed, 56 insertions(+), 1 deletion(-)
commit 734cea683bdf39dc48816682ba4debcaa0941f47
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Mon Oct 25 09:18:18 2021 +0200
supported_readers: Use FeliCa instead of Felica on SONY request
readers/supported_readers.txt | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
commit ca395d69a2975def7ef8cbf0e03117f5aa474a4f
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Tue Oct 19 23:23:36 2021 +0200
t1_transceive: improve code style
Declare "retries" as an "int" instead of a "unsigned int" so the test
"if (retries <= 0)" is true for negative values of retries.
src/openct/proto-t1.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
commit 831c435d490a1d51d456e04642e18434928c10d8
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Tue Oct 19 22:44:33 2021 +0200
t1_negotiate_ifsd: improve code style
Declare "retries" as an "int" instead of a "unsigned int" so the test
"if (retries <= 0)" is true for negative values of retries.
Move the test on retries _before_ sending the T=1 block. In the previous
code the block was sent but the result was ignored on the third try.
Update the check from "if (retries <= 0)" to "if (retries < 0)" so that
we really perform 3 tries instead of just 2.
Thanks to Stas Sergeev for the bug report
Fix https://github.com/LudovicRousseau/CCID/issues/91
src/openct/proto-t1.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
commit c7d04806efb9a1a0c1b57a444b2e84d93eeb7558
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Oct 13 21:36:08 2021 +0200
Add Nitrokey Nitrokey 3
readers/Nitrokey_Nitrokey_3.txt | 50 +++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 3 ++-
2 files changed, 52 insertions(+), 1 deletion(-)
commit b0cb37f1aee46d04c31c19273f23967f4ae8601c
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Oct 10 17:20:04 2021 +0200
Avoid logging errors when a reader is removed
Add support of TAG_IFD_DEVICE_REMOVED
This tag has been introduced in pcsc-lite version 1.9.5.
When the driver receives the tag TAG_IFD_DEVICE_REMOVED it marks the
USB device as disconnected and will not try to talk to it any more.
So when a USB CCID reader is remove we do not have these errors in the
logs any more:
00000000 [140295925790464] ccid_usb.c:871:WriteUSB() write failed (1/22): -4 LIBUSB_ERROR_NO_DEVICE
00000506 [140295934183168] ccid_usb.c:871:WriteUSB() write failed (1/22): -4 LIBUSB_ERROR_NO_DEVICE
The first error is because IFDHICCPresence() sends the CCID command
PC_to_RDR_GetSlotStatus to know if a card is present.
The second error is because IFDHCloseChannel() sends the CCID command
PC_to_RDR_IccPowerOff to power off the card.
But since the USB device has been removed these 2 CCID commands will
fail and log the error.
Thanks to Jakub Jelen for the bug report
" Reader disconnects are noisy in journal/logs #110 "
https://github.com/LudovicRousseau/PCSC/issues/110
See also https://bugzilla.redhat.com/show_bug.cgi?id=2011128
src/ccid_serial.c | 15 +++++++++++++++
src/ccid_serial.h | 2 ++
src/ccid_usb.c | 28 ++++++++++++++++++++++++++++
src/ccid_usb.h | 1 +
src/defs.h | 2 ++
src/ifdhandler.c | 29 ++++++++++++++++++++++++++++-
6 files changed, 76 insertions(+), 1 deletion(-)
commit daadc5806c01b1d3b92cd7f7a90387a095578553
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sat Oct 9 18:40:06 2021 +0200
utils: Use a more special value to indicate a free slot
The value -1 is not so special as it is also used by pcscd to mark an
invalid slot.
libccid was happy with Lun = -1 for a reader. This should NOT be the
case.
Now the special value is -42.
src/utils.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
commit 84bd2cc64c259f818da568b812f63e2475cfc09c
Merge: cb242a7 92a5302
Author: Ludovic Rousseau <ludovic.rousseau+github@gmail.com>
Date: Wed Sep 29 11:38:09 2021 +0200
Merge pull request #90 from emaxx-google/omnikey-5427-ck
Allow vendor control commands for Omnikey 5427 CK
commit 92a5302eb17146574b0d941739264598144f7fcf
Author: Maksim Ivanov <emaxx@google.com>
Date: Wed Sep 29 07:52:52 2021 +0200
Allow vendor control commands for Omnikey 5427 CK
By default, the PC/SC protocol doesn't allow sending commands (APDUs) to
a reader that doesn't have a card inserted. There's a legitimate use
case (which exactly, isn't relevant here) for supporting this for the
Omnikey 5427 CK reader.
This reader provides a capability for sending APDUs, but only via a
vendor control command. By default, vendor control commands are
forbidden, and can be enabled for all readers via setting the
"ifdDriverOptions" parameter in the Info.plist config to have the bit
"1" (DRIVER_OPTION_CCID_EXCHANGE_AUTHORIZED). However, enabling this
parametere in the config might impose a security risk when using some
readers and applications (see
https://ludovicrousseau.blogspot.com/2011/10/featureccidesccommand.html).
Hence the solution in this commit is to special-case the Omnikey 5427
CK reader and allow any application to send control commands. It was
confirmed with the reader's vendor that this doesn't impose a security
risk here.
src/ccid.h | 1 +
src/ifdhandler.c | 4 ++++
2 files changed, 5 insertions(+)
commit cb242a71fd07dea1a8e4f9efc48684842e7a9387
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Sep 19 10:27:44 2021 +0200
Hack to hide the ELYCTIS CNT reader reader
The ELYCTIS reader is a composite reader with 3 iterfaces:
one 0x1FFA:0x0002:ELYCTIS CL reader
and two 0x04E6:0x5810:ELYCTIS CNT reader
But the "ELYCTIS CNT reader" is in fact a "Identive CLOUD 2700 R Smart
Card Reader" renamed. They both share the same VID/PID.
Since "ELYCTIS" is before "Identive" in the alphabetical order the
VID/PID 0x04E6:0x5810 was now associated with ELYCTIS and not Identive.
The hack is to rename ELYCTIS into ~ELYCTIS for the 2 contact interfaces
so that Identive comes first in the alpahetical order.
readers/ELYCTIS_CL_reader.txt | 4 ++--
readers/supported_readers.txt | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
commit baa0c6e17287ee759bb1d06ca8c505033c62706c
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Sep 19 10:27:20 2021 +0200
Add ELYCTIS CL reader
readers/ELYCTIS_CL_reader.txt | 165 ++++++++++++++++++++++++++++++++++++++++++
readers/supported_readers.txt | 7 +-
2 files changed, 170 insertions(+), 2 deletions(-)
commit 26ad96076523472e9d0d383d014e7b1ad241fd5b
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Wed Sep 8 11:28:48 2021 +0200
Fix SafeNet eToken 5110 SC issue (firmware 0.13)
The SafeNet eToken 5110 SC with firmware 0.13 has the same problem as
the token with firmware 0.12.
We use the same oslution to fix the problem.
Thanks again to Vladimir K for the bug report.
src/ccid.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
commit b48e1e697010431b7f03d4ecfe917ceee95e2c64
Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Tue Sep 7 14:06:46 2021 +0200
Fix SafeNet eToken 5110 SC issue
Some SafeNet eToken 5100 (but not all) have issues when IFSD is negotiated.
For some APDU the communication stops and the token returns 0 bytes.
It is the case with the SafeNet eToken 5110 SC with
ATR: 3B D5 18 00 81 31 3A 7D 80 73 C8 21 10 30
and PC/SC name "SafeNet eToken 5100 [eToken 5110 SC]"
Another SafeNet eToken 5100 with
ATR: 3B D5 18 00 81 31 FE 7D 80 73 C8 21 10 F4
and PC/SC name "SafeNet eToken 5100 [Main Interface]"
does NOT have problems with the the IFSD negotiation.
The 2 devices have (luckily) a different USB CCID descriptor:
--- eToken5100_bug 2021-09-07 11:58:30.245354659 +0200
+++ eToken5100_ok 2021-09-07 11:58:36.621432673 +0200
@@ -2,7 +2,7 @@
iManufacturer: SafeNet
idProduct: 0x0620
iProduct: Token JC
- bcdDevice: 0.12 (firmware release?)
+ bcdDevice: 1.00 (firmware release?)
bLength: 9
bDescriptorType: 4
bInterfaceNumber: 0
@@ -13,7 +13,7 @@
bInterfaceSubClass: 0
bInterfaceProtocol: 0
bulk transfer, optional interrupt-IN (CCID)
- iInterface: eToken 5110 SC
+ iInterface: Main Interface
CCID Class Descriptor
bLength: 0x36
bDescriptorType: 0x21
@@ -26,24 +26,23 @@
dwProtocols: 0x0000 0x0003
T=0
T=1
- dwDefaultClock: 4.800 MHz
- dwMaximumClock: 4.800 MHz
+ dwDefaultClock: 4.000 MHz
+ dwMaximumClock: 4.000 MHz
bNumClockSupported: 0 (will use whatever is returned)
IFD does not support GET CLOCK FREQUENCIES request: LIBUSB_ERROR_PIPE
- dwDataRate: 12903 bps
- dwMaxDataRate: 12903 bps
+ dwDataRate: 10752 bps
+ dwMaxDataRate: 10752 bps
bNumDataRatesSupported: 0 (will use whatever is returned)
IFD does not support GET_DATA_RATES request: LIBUSB_ERROR_PIPE
- dwMaxIFSD: 128
+ dwMaxIFSD: 252
dwSynchProtocols: 0x00000000
dwMechanical: 0x00000000
No special characteristics
- dwFeatures: 0x0001027C
+ dwFeatures: 0x0001023C
....04 Automatic activation of ICC on inserting
....08 Automatic ICC voltage selection
....10 Automatic ICC clock frequency change according to parameters
....20 Automatic baud rate change according to frequency and Fi, Di params
- ....40 Automatic parameters negotiation made by the CCID
..02.. NAD value other than 00 accepted (T=1)
01.... TPDU level exchange
dwMaxCCIDMessageLength: 271 bytes
This fixes Debian bug #993647
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=993647
src/ccid.c | 7 +++++++
src/ccid.h | 1 +
2 files changed, 8 insertions(+)
commit 74642f87f9e1a937e807acd3a7d2ef600b8d151c (tag: 1.4.36)
Author: Ludovic Rousseau <ludovic.rousseau@free.fr> Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Mon Aug 30 11:14:49 2021 +0200 Date: Mon Aug 30 11:14:49 2021 +0200
@ -94,7 +1038,7 @@ Date: Tue Jul 27 17:05:51 2021 +0200
readers/supported_readers.txt | 3 +- readers/supported_readers.txt | 3 +-
2 files changed, 60 insertions(+), 1 deletion(-) 2 files changed, 60 insertions(+), 1 deletion(-)
commit c0c84311c47fcae11ab34ec7b1f70f9518e37931 (tag: 1.4.35, github/master) commit c0c84311c47fcae11ab34ec7b1f70f9518e37931 (tag: 1.4.35)
Author: Ludovic Rousseau <ludovic.rousseau@free.fr> Author: Ludovic Rousseau <ludovic.rousseau@free.fr>
Date: Sun Jul 25 16:00:35 2021 +0200 Date: Sun Jul 25 16:00:35 2021 +0200

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -156,13 +156,10 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS) DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \
COPYING ChangeLog INSTALL NEWS ar-lib compile config.guess \ COPYING ChangeLog INSTALL NEWS README.md ar-lib compile \
config.sub depcomp install-sh ltmain.sh missing ylwrap config.guess config.sub install-sh ltmain.sh missing ylwrap
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION) distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir) top_distdir = $(distdir)
@ -221,6 +218,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -232,6 +231,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -283,6 +283,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -533,7 +534,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -117,6 +117,32 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
History: History:
======== ========
1.5.0 - 27 January 2022, Ludovic Rousseau
- Add support of
- ACS ACR1281U
- Circle CCR7125 ICC
- Circle CIR125 ICC
- Circle CIR125-DOT ICC
- Circle CIR215 CL with iProduct 0x2100
- Circle CIR315 DI
- Circle CIR315 with idProduct: 0x0324
- Circle CIR315 with idProduct: 0x7004
- Circle CIR415 CL
- Circle CIR515 ICC
- Circle CIR615 CL
- Circle CIR615 CL & 1S
- ELYCTIS CL reader
- Nitrokey Nitrokey 3
- Thales Shield M4 Reader
- Add support of simultaneous slot access on multi slots readers
- Use FeliCa instead of Felica on SONY request
- Fix SafeNet eToken 5110 SC issue
- Allow vendor control commands for Omnikey 5427 CK
- always compute readTimeout to use a value greater than default 3 seconds
- Check the bSeq value when receiving a CCID frame
- Avoid logging errors when a reader is removed
- Some other minor improvements
1.4.36 - 30 August 2021, Ludovic Rousseau 1.4.36 - 30 August 2021, Ludovic Rousseau
- Add support of - Add support of
- Lenovo Lenovo Smartcard Wired Keyboard II - Lenovo Lenovo Smartcard Wired Keyboard II

337
aclocal.m4 vendored
View File

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.3 -*- Autoconf -*- # generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -14,8 +14,8 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
[m4_warning([this file was generated for autoconf 2.69. [m4_warning([this file was generated for autoconf 2.71.
You have another version of autoconf. It may work, but is not guaranteed to. You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely. If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])]) To do so, use the procedure documented by the package, typically 'autoreconf'.])])
@ -36,20 +36,24 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# flags that are needed. (The user can also force certain compiler # flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.) # flags/libs to be tested by setting these environment variables.)
# #
# Also sets PTHREAD_CC to any special C compiler that is needed for # Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
# multi-threaded programs (defaults to the value of CC otherwise). (This # needed for multi-threaded programs (defaults to the value of CC
# is necessary on AIX to use the special cc_r compiler alias.) # respectively CXX otherwise). (This is necessary on e.g. AIX to use the
# special cc_r/CC_r compiler alias.)
# #
# NOTE: You are assumed to not only compile your program with these flags, # NOTE: You are assumed to not only compile your program with these flags,
# but also to link with them as well. For example, you might link with # but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# #
# If you are only building threaded programs, you may wish to use these # If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC: # variables in your default LIBS, CFLAGS, and CC:
# #
# LIBS="$PTHREAD_LIBS $LIBS" # LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC" # CC="$PTHREAD_CC"
# CXX="$PTHREAD_CXX"
# #
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to # has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
@ -77,6 +81,7 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# #
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> # Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG> # Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the # under the terms of the GNU General Public License as published by the
@ -104,7 +109,7 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# modified version of the Autoconf Macro, you may extend this special # modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well. # exception to the GPL to apply to your modified version as well.
#serial 24 #serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [ AC_DEFUN([AX_PTHREAD], [
@ -126,6 +131,7 @@ if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS" ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS" LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
@ -145,10 +151,12 @@ fi
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the # (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX). # libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are # Create a list of thread flags to try. Items with a "," contain both
# C compiler flags, and other items are library names, except for "none" # C compiler flags (before ",") and linker flags (after ","). Other items
# which indicates that we try without any flags at all, and "pthread-config" # starting with a "-" are C compiler flags, and remaining items are
# which is a program returning the flags for the Pth emulation library. # library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
@ -216,14 +224,47 @@ case $host_os in
# that too in a future libc.) So we'll check first for the # that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread). # standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;; ;;
esac esac
# Are we compiling with Clang?
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
AS_IF([test "x$GCC" = "xyes"], AS_IF([test "x$GCC" = "xyes"],
[ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
AS_IF([test "x$ax_pthread_clang" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread"])
# The presence of a feature test macro requesting re-entrant function # The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is # definitions is, on some systems, a strong hint that pthreads support is
@ -246,101 +287,6 @@ AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0], [ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
# Are we compiling with Clang?
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
ax_pthread_clang_warning=no
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
PTHREAD_CFLAGS="-pthread"
PTHREAD_LIBS=
ax_pthread_ok=yes
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
if test "x$ax_pthread_ok" = "xno"; then if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do for ax_pthread_try_flag in $ax_pthread_flags; do
@ -350,10 +296,10 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
AC_MSG_CHECKING([whether pthreads work without any flags]) AC_MSG_CHECKING([whether pthreads work without any flags])
;; ;;
-mt,pthread) *,*)
AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_CFLAGS="-mt" PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
PTHREAD_LIBS="-lpthread" AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
;; ;;
-*) -*)
@ -393,7 +339,13 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
# if $ax_pthread_check_cond # if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined" # error "$ax_pthread_check_macro must be defined"
# endif # endif
static void routine(void *a) { a = 0; } static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }], static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr; [pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0); pthread_create(&th, 0, start_routine, 0);
@ -415,6 +367,80 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
done done
fi fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks: # Various other checks:
if test "x$ax_pthread_ok" = "xyes"; then if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS" ax_pthread_save_CFLAGS="$CFLAGS"
@ -460,7 +486,8 @@ if test "x$ax_pthread_ok" = "xyes"; then
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])], [[int i = PTHREAD_PRIO_INHERIT;
return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no]) [ax_cv_PTHREAD_PRIO_INHERIT=no])
]) ])
@ -482,18 +509,28 @@ if test "x$ax_pthread_ok" = "xyes"; then
[#handle absolute path differently from PATH based program lookup [#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"], AS_CASE(["x$CC"],
[x/*], [x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
],
[
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
]
)
])
;; ;;
esac esac
fi fi
fi fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC]) AC_SUBST([PTHREAD_CC])
AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "x$ax_pthread_ok" = "xyes"; then if test "x$ax_pthread_ok" = "xyes"; then
@ -782,7 +819,7 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl AS_VAR_IF([$1], [""], [$5], [$4])dnl
])dnl PKG_CHECK_VAR ])dnl PKG_CHECK_VAR
# Copyright (C) 2002-2020 Free Software Foundation, Inc. # Copyright (C) 2002-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -797,7 +834,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.3], [], m4_if([$1], [1.16.5], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -813,12 +850,12 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.3])dnl [AM_AUTOMAKE_VERSION([1.16.5])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# Copyright (C) 2011-2020 Free Software Foundation, Inc. # Copyright (C) 2011-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -880,7 +917,7 @@ AC_SUBST([AR])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*- # AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -932,7 +969,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*- # AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2020 Free Software Foundation, Inc. # Copyright (C) 1997-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -963,7 +1000,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]]) Usually this means the macro was only invoked conditionally.]])
fi])]) fi])])
# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Copyright (C) 1999-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1154,7 +1191,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*- # Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Copyright (C) 1999-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1222,7 +1259,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*- # Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1250,6 +1287,10 @@ m4_defn([AC_PROG_CC])
# release and drop the old call support. # release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE], AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl [AC_PREREQ([2.65])dnl
m4_ifdef([_$0_ALREADY_INIT],
[m4_fatal([$0 expanded multiple times
]m4_defn([_$0_ALREADY_INIT]))],
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about. dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@ -1286,7 +1327,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
[_AM_SET_OPTIONS([$1])dnl [_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if( m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
[ok:ok],, [ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@ -1338,6 +1379,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[m4_define([AC_PROG_OBJCXX], [m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
]) ])
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
AC_SUBST([CTAGS])
if test -z "$ETAGS"; then
ETAGS=etags
fi
AC_SUBST([ETAGS])
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AC_SUBST([CSCOPE])
AC_REQUIRE([AM_SILENT_RULES])dnl AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
@ -1419,7 +1474,7 @@ for _am_header in $config_headers :; do
done done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1440,7 +1495,7 @@ if test x"${install_sh+set}" != xset; then
fi fi
AC_SUBST([install_sh])]) AC_SUBST([install_sh])])
# Copyright (C) 2003-2020 Free Software Foundation, Inc. # Copyright (C) 2003-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1459,7 +1514,7 @@ fi
rmdir .tst 2>/dev/null rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])]) AC_SUBST([am__leading_dot])])
# Copyright (C) 1998-2020 Free Software Foundation, Inc. # Copyright (C) 1998-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1480,7 +1535,7 @@ fi])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering # From Jim Meyering
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1515,7 +1570,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*- # Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1558,7 +1613,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2020 Free Software Foundation, Inc. # Copyright (C) 1997-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1592,7 +1647,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*- # Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1621,7 +1676,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION], AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Copyright (C) 1999-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1668,7 +1723,7 @@ AC_LANG_POP([C])])
# For backward compatibility. # For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1687,7 +1742,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*- # Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1768,7 +1823,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file rm -f conftest.file
]) ])
# Copyright (C) 2009-2020 Free Software Foundation, Inc. # Copyright (C) 2009-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1828,7 +1883,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
]) ])
# Copyright (C) 2001-2020 Free Software Foundation, Inc. # Copyright (C) 2001-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1856,7 +1911,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])]) AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2020 Free Software Foundation, Inc. # Copyright (C) 2006-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1875,7 +1930,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*- # Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2020 Free Software Foundation, Inc. # Copyright (C) 2004-2021 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,

2
ar-lib
View File

@ -4,7 +4,7 @@
me=ar-lib me=ar-lib
scriptversion=2019-07-04.01; # UTC scriptversion=2019-07-04.01; # UTC
# Copyright (C) 2010-2020 Free Software Foundation, Inc. # Copyright (C) 2010-2021 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>. # Written by Peter Rosin <peda@lysator.liu.se>.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Copyright (C) 1999-2021 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>. # Written by Tom Tromey <tromey@cygnus.com>.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify

View File

@ -27,9 +27,6 @@
/* Define to 1 if you have the `memcpy' function. */ /* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY #undef HAVE_MEMCPY
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have POSIX threads libraries and header files. */ /* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD #undef HAVE_PTHREAD
@ -118,7 +115,9 @@
your system. */ your system. */
#undef PTHREAD_CREATE_JOINABLE #undef PTHREAD_CREATE_JOINABLE
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS #undef STDC_HEADERS
/* composite device are seen as multi-slots */ /* composite device are seen as multi-slots */

6260
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
# Require autoconf 2.61 # Require autoconf 2.61
AC_PREREQ([2.69]) AC_PREREQ([2.69])
AC_INIT([ccid],[1.4.36]) AC_INIT([ccid],[1.5.0])
AC_CONFIG_SRCDIR(src/ifdhandler.c) AC_CONFIG_SRCDIR(src/ifdhandler.c)
AC_CONFIG_AUX_DIR([.]) AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip subdir-objects foreign) AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip subdir-objects foreign)

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -178,8 +178,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -485,7 +487,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -152,8 +152,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = RSA_SecurID Kobil_mIDentity_switch DIST_SUBDIRS = RSA_SecurID Kobil_mIDentity_switch
am__DIST_COMMON = $(srcdir)/Makefile.in am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -462,7 +464,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -176,8 +176,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
@ -194,6 +192,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -205,6 +205,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -254,6 +255,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -482,7 +484,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2020 Free Software Foundation, Inc. # Copyright (C) 1999-2021 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -178,8 +178,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -498,7 +500,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -136,6 +136,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -147,6 +149,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -196,6 +199,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -308,7 +312,6 @@ ctags CTAGS:
cscope cscopelist: cscope cscopelist:
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -1,6 +1,6 @@
# #
# List of readers supported by the CCID driver # List of readers supported by the CCID driver
# Generated: 2021-08-30 # Generated: 2022-01-27
# #
# DO NOT EDIT BY HAND # DO NOT EDIT BY HAND
@ -131,6 +131,7 @@
# ACS # ACS
0x072F:0x1204:ACS ACR101 ICC Reader 0x072F:0x1204:ACS ACR101 ICC Reader
0x072F:0x221A:ACS ACR1251 Dual Reader 0x072F:0x221A:ACS ACR1251 Dual Reader
0x072F:0x2224:ACS ACR1281U
0x072F:0x223B:ACS ACR1252 Dual Reader 0x072F:0x223B:ACS ACR1252 Dual Reader
0x072F:0x223E:ACS ACR1252 Reader 0x072F:0x223E:ACS ACR1252 Reader
0x072F:0x223F:ACS ACR1255U-J1 0x072F:0x223F:ACS ACR1255U-J1
@ -314,16 +315,27 @@
# Circle # Circle
0x31AA:0x0224:Circle Idaxis SecurePIV 0x31AA:0x0224:Circle Idaxis SecurePIV
0x31AA:0x0324:Circle CIR315
0x31AA:0x1000:Circle CIR115 ICC 0x31AA:0x1000:Circle CIR115 ICC
0x31AA:0x1100:Circle CIR125 ICC
0x31AA:0x2000:Circle CIR215 PICC 0x31AA:0x2000:Circle CIR215 PICC
0x31AA:0x2001:Circle CIR215 CL 0x31AA:0x2001:Circle CIR215 CL
0x31AA:0x2100:Circle CIR215 CL
0x31AA:0x3000:Circle CIR315 Dual & 1S 0x31AA:0x3000:Circle CIR315 Dual & 1S
0x31AA:0x3001:Circle CIR315 0x31AA:0x3001:Circle CIR315
0x31AA:0x3002:Circle CIR315 CL 0x31AA:0x3002:Circle CIR315 CL
0x31AA:0x3003:Circle CIR315 DI
0x31AA:0x3100:Circle CIR315 0x31AA:0x3100:Circle CIR315
0x31AA:0x4000:Circle CIR415 CL & 1S 0x31AA:0x4000:Circle CIR415 CL & 1S
0x31AA:0x4001:Circle CIR415 CL
0x31AA:0x5000:Circle CIR515 ICC
0x31AA:0x6000:Circle CIR615 CL & 1S
0x31AA:0x6001:Circle CIR615 CL
0x31AA:0x7001:Circle CCR7115 ICC 0x31AA:0x7001:Circle CCR7115 ICC
0x31AA:0x7003:Circle CCR7315 0x31AA:0x7003:Circle CCR7315
0x31AA:0x7004:Circle CIR315
0x31AA:0x7005:Circle CCR7125 ICC
0x31AA:0x7006:Circle CIR125-DOT ICC
# COVADIS # COVADIS
0x0982:0x0008:COVADIS VEGA-ALPHA 0x0982:0x0008:COVADIS VEGA-ALPHA
@ -354,6 +366,9 @@
0x09D8:0x0427:Elatec TWN4 SmartCard NFC 0x09D8:0x0427:Elatec TWN4 SmartCard NFC
0x09D8:0x0428:Elatec TWN4/B1.06/CPF3.05/S1SC1.32/P (Beta 3) 0x09D8:0x0428:Elatec TWN4/B1.06/CPF3.05/S1SC1.32/P (Beta 3)
# ELYCTIS
0x1FFA:0x0002:ELYCTIS CL reader
# ESMART # ESMART
0x2CE4:0x7479:ESMART Token GOST 0x2CE4:0x7479:ESMART Token GOST
@ -638,6 +653,7 @@
0x20A0:0x4109:Nitrokey Nitrokey Storage 0x20A0:0x4109:Nitrokey Nitrokey Storage
0x20A0:0x4211:Nitrokey Nitrokey Start 0x20A0:0x4211:Nitrokey Nitrokey Start
0x20A0:0x4230:Nitrokey Nitrokey HSM 0x20A0:0x4230:Nitrokey Nitrokey HSM
0x20A0:0x42B2:Nitrokey Nitrokey 3
# NTT Communications Corp. # NTT Communications Corp.
0x04E6:0x511A:NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader 0x04E6:0x511A:NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader
@ -750,9 +766,9 @@
0x1209:0xBEEE:SoloKeys Solo 2 0x1209:0xBEEE:SoloKeys Solo 2
# SONY # SONY
0x054C:0x0D8F:SONY Felica RC-S660/U 0x054C:0x0D8F:SONY FeliCa RC-S660/U
0x054C:0x0DC8:SONY Felica RC-S300/S 0x054C:0x0DC8:SONY FeliCa RC-S300/S
0x054C:0x0DC9:SONY Felica RC-S300/P 0x054C:0x0DC9:SONY FeliCa RC-S300/P
# SPECINFOSYSTEMS # SPECINFOSYSTEMS
0x316E:0x0001:SPECINFOSYSTEMS DIAMOND token 0x316E:0x0001:SPECINFOSYSTEMS DIAMOND token
@ -806,6 +822,9 @@
# Teridian Semiconductors # Teridian Semiconductors
0x1862:0x0000:Teridian Semiconductors TSC12xxFV.09 0x1862:0x0000:Teridian Semiconductors TSC12xxFV.09
# Thales
0x08E6:0x34C7:Thales Shield M4 Reader
# THURSBY SOFTWARE # THURSBY SOFTWARE
0x1976:0x0001:THURSBY SOFTWARE TSS-PK1 0x1976:0x0001:THURSBY SOFTWARE TSS-PK1
@ -878,6 +897,8 @@
0x1050:0x0406:Yubico YubiKey FIDO+CCID 0x1050:0x0406:Yubico YubiKey FIDO+CCID
0x1050:0x0407:Yubico YubiKey OTP+FIDO+CCID 0x1050:0x0407:Yubico YubiKey OTP+FIDO+CCID
# ~ELYCTIS
########################## ##########################
# section: unsupported # section: unsupported
########################## ##########################

View File

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am. # Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -306,8 +306,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
$(top_srcdir)/ylwrap tokenparser.c $(top_srcdir)/ylwrap tokenparser.c
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -325,6 +323,8 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@ CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -336,6 +336,7 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
@ -385,6 +386,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_CXX = @PTHREAD_CXX@
PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_LIBS = @PTHREAD_LIBS@
RANLIB = @RANLIB@ RANLIB = @RANLIB@
SED = @SED@ SED = @SED@
@ -1052,7 +1054,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

View File

@ -576,6 +576,14 @@ int ccid_open_hack_post(unsigned int reader_index)
* have one */ * have one */
ccid_descriptor->bPINSupport = 0; ccid_descriptor->bPINSupport = 0;
break; break;
case SAFENET_ETOKEN_5100:
/* the old SafeNet eToken 5110 SC (firmware 0.12 & 0.13)
* does not like IFSD negotiation. So disable it. */
if ((0x0012 == ccid_descriptor->IFD_bcdDevice)
|| (0x0013 == ccid_descriptor->IFD_bcdDevice))
ccid_descriptor->dwFeatures |= CCID_CLASS_AUTO_IFSD;
break;
} }
/* Gemalto readers may report additional information */ /* Gemalto readers may report additional information */

View File

@ -70,6 +70,11 @@ typedef struct
*/ */
char bMaxSlotIndex; char bMaxSlotIndex;
/*
* Maximum number of slots which can be simultaneously busy
*/
char bMaxCCIDBusySlots;
/* /*
* Slot in use * Slot in use
*/ */
@ -232,6 +237,7 @@ typedef struct
#define HID_OMNIKEY_5422 0x076B5422 #define HID_OMNIKEY_5422 0x076B5422
#define HID_OMNIKEY_3X21 0x076B3031 /* OMNIKEY 3121 or 3021 or 1021 */ #define HID_OMNIKEY_3X21 0x076B3031 /* OMNIKEY 3121 or 3021 or 1021 */
#define HID_OMNIKEY_3821 0x076B3821 /* OMNIKEY 3821 */ #define HID_OMNIKEY_3821 0x076B3821 /* OMNIKEY 3821 */
#define HID_OMNIKEY_5427CK 0x076B5427 /* OMNIKEY 5427 CK */
#define HID_OMNIKEY_6121 0x076B6632 /* OMNIKEY 6121 */ #define HID_OMNIKEY_6121 0x076B6632 /* OMNIKEY 6121 */
#define CHERRY_XX44 0x046A00A7 /* Cherry Smart Terminal xx44 */ #define CHERRY_XX44 0x046A00A7 /* Cherry Smart Terminal xx44 */
#define FUJITSU_D323 0x0BF81024 /* Fujitsu Smartcard Reader D323 */ #define FUJITSU_D323 0x0BF81024 /* Fujitsu Smartcard Reader D323 */
@ -239,6 +245,7 @@ typedef struct
#define IDENTIV_uTrust3701F 0x04E65791 #define IDENTIV_uTrust3701F 0x04E65791
#define IDENTIV_uTrust4701F 0x04E65724 #define IDENTIV_uTrust4701F 0x04E65724
#define BIT4ID_MINILECTOR 0x25DD3111 #define BIT4ID_MINILECTOR 0x25DD3111
#define SAFENET_ETOKEN_5100 0x05290620
#define VENDOR_GEMALTO 0x08E6 #define VENDOR_GEMALTO 0x08E6
#define GET_VENDOR(readerID) ((readerID >> 16) & 0xFFFF) #define GET_VENDOR(readerID) ((readerID >> 16) & 0xFFFF)

View File

@ -220,7 +220,7 @@ status_t WriteSerial(unsigned int reader_index, unsigned int length,
* *
*****************************************************************************/ *****************************************************************************/
status_t ReadSerial(unsigned int reader_index, status_t ReadSerial(unsigned int reader_index,
unsigned int *length, unsigned char *buffer) unsigned int *length, unsigned char *buffer, int bSeq)
{ {
unsigned char c; unsigned char c;
int rv; int rv;
@ -228,6 +228,9 @@ status_t ReadSerial(unsigned int reader_index,
int to_read; int to_read;
int i; int i;
/* ignore bSeq */
(void)bSeq;
/* we get the echo first */ /* we get the echo first */
echo = serialDevice[reader_index].echo; echo = serialDevice[reader_index].echo;
@ -620,6 +623,7 @@ static status_t set_ccid_descriptor(unsigned int reader_index,
serialDevice[reader_index].ccid.bPINSupport = 0x0; serialDevice[reader_index].ccid.bPINSupport = 0x0;
serialDevice[reader_index].ccid.dwMaxDataRate = 344086; serialDevice[reader_index].ccid.dwMaxDataRate = 344086;
serialDevice[reader_index].ccid.bMaxSlotIndex = 0; serialDevice[reader_index].ccid.bMaxSlotIndex = 0;
serialDevice[reader_index].ccid.bMaxCCIDBusySlots = 1;
serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates; serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
serialDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT; serialDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT; serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
@ -934,6 +938,21 @@ status_t CloseSerial(unsigned int reader_index)
} /* CloseSerial */ } /* CloseSerial */
/*****************************************************************************
*
* DisconnectSerial
*
****************************************************************************/
status_t DisconnectSerial(unsigned int reader_index)
{
(void)reader_index;
DEBUG_COMM("Disconnect reader");
return STATUS_UNSUCCESSFUL;
} /* DisconnectSerial */
/***************************************************************************** /*****************************************************************************
* *
* get_ccid_descriptor * get_ccid_descriptor

View File

@ -28,8 +28,10 @@ status_t WriteSerial(unsigned int reader_index, unsigned int length,
unsigned char *Buffer); unsigned char *Buffer);
status_t ReadSerial(unsigned int reader_index, unsigned int *length, status_t ReadSerial(unsigned int reader_index, unsigned int *length,
unsigned char *Buffer); unsigned char *Buffer, int bSeq);
status_t CloseSerial(unsigned int reader_index); status_t CloseSerial(unsigned int reader_index);
status_t DisconnectSerial(unsigned int reader_index);
#endif #endif

View File

@ -28,6 +28,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h> #include <pthread.h>
#include <sys/time.h> #include <sys/time.h>
#include <stdatomic.h>
#include <unistd.h>
#include <ifdhandler.h> #include <ifdhandler.h>
#include <config.h> #include <config.h>
@ -61,18 +63,30 @@ libusb_context *ctx = NULL;
#define CCID_INTERRUPT_SIZE 8 #define CCID_INTERRUPT_SIZE 8
struct multiSlot_ConcurrentAccess
{
unsigned char buffer[10 + MAX_BUFFER_SIZE_EXTENDED];
int length;
pthread_mutex_t mutex;
pthread_cond_t condition;
};
struct usbDevice_MultiSlot_Extension struct usbDevice_MultiSlot_Extension
{ {
int reader_index; int reader_index;
/* The multi-threaded polling part */ /* The multi-threaded polling part */
int terminated; _Atomic int terminated;
int status; int status;
unsigned char buffer[CCID_INTERRUPT_SIZE]; unsigned char buffer[CCID_INTERRUPT_SIZE];
pthread_t thread_proc; pthread_t thread_proc;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t condition; pthread_cond_t condition;
struct libusb_transfer *transfer;
pthread_t thread_concurrent;
struct multiSlot_ConcurrentAccess *concurrent;
libusb_device_handle *dev_handle;
}; };
typedef struct typedef struct
@ -99,11 +113,12 @@ typedef struct
_ccid_descriptor ccid; _ccid_descriptor ccid;
/* libusb transfer for the polling (or NULL) */ /* libusb transfer for the polling (or NULL) */
struct libusb_transfer *polling_transfer; _Atomic (struct libusb_transfer *) polling_transfer;
/* pointer to the multislot extension (if any) */ /* pointer to the multislot extension (if any) */
struct usbDevice_MultiSlot_Extension *multislot_extension; struct usbDevice_MultiSlot_Extension *multislot_extension;
char disconnected;
} _usbDevice; } _usbDevice;
/* The _usbDevice structure must be defined before including ccid_usb.h */ /* The _usbDevice structure must be defined before including ccid_usb.h */
@ -399,7 +414,7 @@ again_libusb:
if ((device_bus || device_addr) if ((device_bus || device_addr)
&& ((bus_number != device_bus) && ((bus_number != device_bus)
|| (device_address != device_addr))) { || (device_address != device_addr))) {
/* not USB the device we are looking for */ /* not the USB device we are looking for */
continue; continue;
} }
#endif #endif
@ -543,7 +558,7 @@ again_libusb:
} }
else else
{ {
/* if an interface number is given by HAL we /* if an interface number is given by udev we
* continue with this device. */ * continue with this device. */
if (-1 == interface_number) if (-1 == interface_number)
{ {
@ -701,7 +716,8 @@ again:
usbDevice[reader_index].interface = interface; usbDevice[reader_index].interface = interface;
usbDevice[reader_index].real_nb_opened_slots = 1; usbDevice[reader_index].real_nb_opened_slots = 1;
usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots; usbDevice[reader_index].nb_opened_slots = &usbDevice[reader_index].real_nb_opened_slots;
usbDevice[reader_index].polling_transfer = NULL; atomic_init(&usbDevice[reader_index].polling_transfer, NULL);
usbDevice[reader_index].disconnected = FALSE;
/* CCID common informations */ /* CCID common informations */
usbDevice[reader_index].ccid.real_bSeq = 0; usbDevice[reader_index].ccid.real_bSeq = 0;
@ -717,6 +733,7 @@ again:
usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10); usbDevice[reader_index].ccid.dwDefaultClock = dw2i(device_descriptor, 10);
usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23); usbDevice[reader_index].ccid.dwMaxDataRate = dw2i(device_descriptor, 23);
usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4]; usbDevice[reader_index].ccid.bMaxSlotIndex = device_descriptor[4];
usbDevice[reader_index].ccid.bMaxCCIDBusySlots = device_descriptor[53];
usbDevice[reader_index].ccid.bCurrentSlotIndex = 0; usbDevice[reader_index].ccid.bCurrentSlotIndex = 0;
usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT; usbDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
if (device_descriptor[27]) if (device_descriptor[27])
@ -840,6 +857,12 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
(void)snprintf(debug_header, sizeof(debug_header), "-> %06X ", (void)snprintf(debug_header, sizeof(debug_header), "-> %06X ",
(int)reader_index); (int)reader_index);
if (usbDevice[reader_index].disconnected)
{
DEBUG_COMM("Reader disconnected");
return STATUS_NO_SUCH_DEVICE;
}
#ifdef ENABLE_ZLP #ifdef ENABLE_ZLP
if (usbDevice[reader_index].ccid.zlp) if (usbDevice[reader_index].ccid.zlp)
{ /* Zero Length Packet */ { /* Zero Length Packet */
@ -860,9 +883,9 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
if (rv < 0) if (rv < 0)
{ {
DEBUG_CRITICAL5("write failed (%d/%d): %d %s", DEBUG_CRITICAL4("write failed (%d/%d): %s",
usbDevice[reader_index].bus_number, usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address, rv, libusb_error_name(rv)); usbDevice[reader_index].device_address, libusb_error_name(rv));
if (LIBUSB_ERROR_NO_DEVICE == rv) if (LIBUSB_ERROR_NO_DEVICE == rv)
return STATUS_NO_SUCH_DEVICE; return STATUS_NO_SUCH_DEVICE;
@ -880,42 +903,113 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
* *
****************************************************************************/ ****************************************************************************/
status_t ReadUSB(unsigned int reader_index, unsigned int * length, status_t ReadUSB(unsigned int reader_index, unsigned int * length,
unsigned char *buffer) unsigned char *buffer, int bSeq)
{ {
int rv; int rv;
int actual_length; int actual_length;
char debug_header[] = "<- 121234 "; char debug_header[] = "<- 121234 ";
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
int duplicate_frame = 0; int duplicate_frame = 0;
if (usbDevice[reader_index].disconnected)
{
DEBUG_COMM("Reader disconnected");
return STATUS_NO_SUCH_DEVICE;
}
read_again: read_again:
(void)snprintf(debug_header, sizeof(debug_header), "<- %06X ", (void)snprintf(debug_header, sizeof(debug_header), "<- %06X ",
(int)reader_index); (int)reader_index);
rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle, if (usbDevice[reader_index].multislot_extension)
usbDevice[reader_index].bulk_in, buffer, *length,
&actual_length, usbDevice[reader_index].ccid.readTimeout);
if (rv < 0)
{ {
*length = 0; /* multi slot read */
DEBUG_CRITICAL5("read failed (%d/%d): %d %s", int slot = usbDevice[reader_index].ccid.bCurrentSlotIndex;
usbDevice[reader_index].bus_number, struct multiSlot_ConcurrentAccess *concurrent = usbDevice[reader_index].multislot_extension->concurrent;
usbDevice[reader_index].device_address, rv, libusb_error_name(rv));
if (LIBUSB_ERROR_NO_DEVICE == rv) rv = 0;
return STATUS_NO_SUCH_DEVICE; pthread_mutex_lock(&concurrent[slot].mutex);
return STATUS_UNSUCCESSFUL; /* a frame is available? */
if (0 == concurrent[slot].length)
{
struct timespec timeout;
time_t timeout_sec = usbDevice[reader_index].ccid.readTimeout / 1000;
long timeout_msec = usbDevice[reader_index].ccid.readTimeout - timeout_sec * 1000;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_sec;
timeout.tv_nsec += timeout_msec * 1000 * 1000;
if (timeout.tv_nsec > 1000 * 1000 * 1000)
{
timeout.tv_sec++;
timeout.tv_nsec -= 1000 * 1000 * 1000;
}
/* wait for a new frame */
DEBUG_COMM2("Waiting data for slot %d", slot);
rv = pthread_cond_timedwait(&concurrent[slot].condition,
&concurrent[slot].mutex, &timeout);
}
if (rv)
{
*length = 0;
DEBUG_CRITICAL5("read failed (%d/%d): %d %s",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address, rv, strerror(rv));
}
else
{
DEBUG_COMM3("Got %d bytes for slot %d", concurrent[slot].length,
slot);
if (concurrent[slot].length > 0)
{
if (concurrent[slot].length > (int)*length)
DEBUG_CRITICAL3("Received %d bytes but expected only %d",
concurrent[slot].length, *length);
else
*length = concurrent[slot].length;
memcpy(buffer, concurrent[slot].buffer, *length);
concurrent[slot].length = 0;
}
else
rv = EINTR;
}
pthread_mutex_unlock(&concurrent[slot].mutex);
if (rv)
return STATUS_UNSUCCESSFUL;
} }
else
{
rv = libusb_bulk_transfer(usbDevice[reader_index].dev_handle,
usbDevice[reader_index].bulk_in, buffer, *length,
&actual_length, usbDevice[reader_index].ccid.readTimeout);
*length = actual_length; if (rv < 0)
{
*length = 0;
DEBUG_CRITICAL4("read failed (%d/%d): %s",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address,
libusb_error_name(rv));
if (LIBUSB_ERROR_NO_DEVICE == rv)
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
*length = actual_length;
}
DEBUG_XXD(debug_header, buffer, *length); DEBUG_XXD(debug_header, buffer, *length);
#define BSEQ_OFFSET 6 #define BSEQ_OFFSET 6
if ((*length >= BSEQ_OFFSET +1) if ((*length >= BSEQ_OFFSET +1)
&& (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1)) && (bSeq != -1)
&& (buffer[BSEQ_OFFSET] != bSeq))
{ {
duplicate_frame++; duplicate_frame++;
if (duplicate_frame > 10) if (duplicate_frame > 10)
@ -923,7 +1017,7 @@ read_again:
DEBUG_CRITICAL("Too many duplicate frame detected"); DEBUG_CRITICAL("Too many duplicate frame detected");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
DEBUG_INFO1("Duplicate frame detected"); DEBUG_INFO1("Invalid frame detected");
goto read_again; goto read_again;
} }
@ -960,6 +1054,8 @@ status_t CloseUSB(unsigned int reader_index)
/* If this is a multislot reader, close using the multislot stuff */ /* If this is a multislot reader, close using the multislot stuff */
if (msExt) if (msExt)
{ {
struct multiSlot_ConcurrentAccess *concurrent;
/* terminate the interrupt waiter thread */ /* terminate the interrupt waiter thread */
Multi_PollingTerminate(msExt); Multi_PollingTerminate(msExt);
@ -970,6 +1066,19 @@ status_t CloseUSB(unsigned int reader_index)
pthread_cond_destroy(&msExt->condition); pthread_cond_destroy(&msExt->condition);
pthread_mutex_destroy(&msExt->mutex); pthread_mutex_destroy(&msExt->mutex);
/* wait for the thread to actually terminate */
pthread_join(msExt->thread_concurrent, NULL);
concurrent = msExt->concurrent;
for (int slot=0; slot<=usbDevice[reader_index].ccid.bMaxSlotIndex;
slot++)
{
/* Create mutex and condition object for the concurrent read */
pthread_cond_destroy(&concurrent[slot].condition);
pthread_mutex_destroy(&concurrent[slot].mutex);
}
free(concurrent);
/* Deallocate the extension itself */ /* Deallocate the extension itself */
free(msExt); free(msExt);
@ -1004,6 +1113,29 @@ status_t CloseUSB(unsigned int reader_index)
} /* CloseUSB */ } /* CloseUSB */
/*****************************************************************************
*
* DisconnectUSB
*
****************************************************************************/
status_t DisconnectUSB(unsigned int reader_index)
{
DEBUG_COMM("Disconnect reader");
libusb_device_handle * dev_handle = usbDevice[reader_index].dev_handle;
for (int i=0; i<CCID_DRIVER_MAX_READERS; i++)
{
if (usbDevice[i].dev_handle == dev_handle)
{
DEBUG_COMM2("Disconnect reader: %d", i);
usbDevice[i].disconnected = TRUE;
}
}
return STATUS_SUCCESS;
} /* DisconnectUSB */
/***************************************************************************** /*****************************************************************************
* *
* get_ccid_descriptor * get_ccid_descriptor
@ -1295,9 +1427,10 @@ int ControlUSB(int reader_index, int requesttype, int request, int value,
if (ret < 0) if (ret < 0)
{ {
DEBUG_CRITICAL5("control failed (%d/%d): %d %s", DEBUG_CRITICAL4("control failed (%d/%d): %s",
usbDevice[reader_index].bus_number, usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address, ret, libusb_error_name(ret)); usbDevice[reader_index].device_address,
libusb_error_name(ret));
return ret; return ret;
} }
@ -1357,7 +1490,7 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
return IFD_COMMUNICATION_ERROR; return IFD_COMMUNICATION_ERROR;
} }
usbDevice[reader_index].polling_transfer = transfer; atomic_store(&usbDevice[reader_index].polling_transfer, transfer);
while (!completed) while (!completed)
{ {
@ -1380,7 +1513,7 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
actual_length = transfer->actual_length; actual_length = transfer->actual_length;
ret = transfer->status; ret = transfer->status;
usbDevice[reader_index].polling_transfer = NULL; atomic_store(&usbDevice[reader_index].polling_transfer, NULL);
libusb_free_transfer(transfer); libusb_free_transfer(transfer);
DEBUG_PERIODIC3("after (%d) (%d)", reader_index, ret); DEBUG_PERIODIC3("after (%d) (%d)", reader_index, ret);
@ -1396,9 +1529,10 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
default: default:
/* if libusb_interrupt_transfer() times out we get EILSEQ or EAGAIN */ /* if libusb_interrupt_transfer() times out we get EILSEQ or EAGAIN */
DEBUG_COMM4("InterruptRead (%d/%d): %d", DEBUG_COMM4("InterruptRead (%d/%d): %s",
usbDevice[reader_index].bus_number, usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address, ret); usbDevice[reader_index].device_address,
libusb_error_name(ret));
return_value = IFD_COMMUNICATION_ERROR; return_value = IFD_COMMUNICATION_ERROR;
} }
@ -1422,8 +1556,7 @@ void InterruptStop(int reader_index)
return; return;
} }
transfer = usbDevice[reader_index].polling_transfer; transfer = atomic_load(&usbDevice[reader_index].polling_transfer);
usbDevice[reader_index].polling_transfer = NULL;
if (transfer) if (transfer)
{ {
int ret; int ret;
@ -1453,6 +1586,13 @@ static void *Multi_PollingProc(void *p_ext)
usbDevice[msExt->reader_index].bus_number, usbDevice[msExt->reader_index].bus_number,
usbDevice[msExt->reader_index].device_address); usbDevice[msExt->reader_index].device_address);
transfer = libusb_alloc_transfer(0);
if (NULL == transfer)
{
DEBUG_COMM("libusb_alloc_transfer error");
goto end;
}
rv = 0; rv = 0;
while (!msExt->terminated) while (!msExt->terminated)
{ {
@ -1460,15 +1600,6 @@ static void *Multi_PollingProc(void *p_ext)
usbDevice[msExt->reader_index].bus_number, usbDevice[msExt->reader_index].bus_number,
usbDevice[msExt->reader_index].device_address); usbDevice[msExt->reader_index].device_address);
transfer = libusb_alloc_transfer(0);
if (NULL == transfer)
{
rv = LIBUSB_ERROR_NO_MEM;
DEBUG_COMM3("libusb_alloc_transfer err %d %s", rv,
libusb_error_name(rv));
break;
}
libusb_fill_bulk_transfer(transfer, libusb_fill_bulk_transfer(transfer,
usbDevice[msExt->reader_index].dev_handle, usbDevice[msExt->reader_index].dev_handle,
usbDevice[msExt->reader_index].interrupt, usbDevice[msExt->reader_index].interrupt,
@ -1480,13 +1611,13 @@ static void *Multi_PollingProc(void *p_ext)
rv = libusb_submit_transfer(transfer); rv = libusb_submit_transfer(transfer);
if (rv) if (rv)
{ {
libusb_free_transfer(transfer); DEBUG_COMM2("libusb_submit_transfer err %s",
DEBUG_COMM3("libusb_submit_transfer err %d %s", rv,
libusb_error_name(rv)); libusb_error_name(rv));
break; break;
} }
usbDevice[msExt->reader_index].polling_transfer = transfer; atomic_store(&usbDevice[msExt->reader_index].polling_transfer,
transfer);
completed = 0; completed = 0;
while (!completed && !msExt->terminated) while (!completed && !msExt->terminated)
@ -1494,7 +1625,7 @@ static void *Multi_PollingProc(void *p_ext)
rv = libusb_handle_events_completed(ctx, &completed); rv = libusb_handle_events_completed(ctx, &completed);
if (rv < 0) if (rv < 0)
{ {
DEBUG_COMM3("libusb_handle_events err %d %s", rv, DEBUG_COMM2("libusb_handle_events err %s",
libusb_error_name(rv)); libusb_error_name(rv));
if (rv == LIBUSB_ERROR_INTERRUPTED) if (rv == LIBUSB_ERROR_INTERRUPTED)
@ -1512,19 +1643,16 @@ static void *Multi_PollingProc(void *p_ext)
} }
} }
usbDevice[msExt->reader_index].polling_transfer = NULL; atomic_store(&usbDevice[msExt->reader_index].polling_transfer,
NULL);
if (rv < 0) if (0 == rv)
libusb_free_transfer(transfer);
else
{ {
int b, slot; int b, slot;
actual_length = transfer->actual_length; actual_length = transfer->actual_length;
status = transfer->status; status = transfer->status;
libusb_free_transfer(transfer);
switch (status) switch (status)
{ {
case LIBUSB_TRANSFER_COMPLETED: case LIBUSB_TRANSFER_COMPLETED:
@ -1566,10 +1694,10 @@ static void *Multi_PollingProc(void *p_ext)
default: default:
/* if libusb_interrupt_transfer() times out /* if libusb_interrupt_transfer() times out
* we get EILSEQ or EAGAIN */ * we get EILSEQ or EAGAIN */
DEBUG_COMM4("Multi_PollingProc (%d/%d): %d", DEBUG_COMM4("Multi_PollingProc (%d/%d): %s",
usbDevice[msExt->reader_index].bus_number, usbDevice[msExt->reader_index].bus_number,
usbDevice[msExt->reader_index].device_address, usbDevice[msExt->reader_index].device_address,
status); libusb_error_name(status));
} }
/* Tell other slots that there's a new interrupt buffer */ /* Tell other slots that there's a new interrupt buffer */
@ -1591,14 +1719,20 @@ static void *Multi_PollingProc(void *p_ext)
} }
} }
msExt->terminated = TRUE; libusb_free_transfer(transfer);
if (rv < 0) if (rv < 0)
{ {
DEBUG_CRITICAL5("Multi_PollingProc (%d/%d): error %d %s", if (rv != LIBUSB_ERROR_NO_DEVICE)
usbDevice[msExt->reader_index].bus_number, DEBUG_CRITICAL4("Multi_PollingProc (%d/%d): error %s",
usbDevice[msExt->reader_index].device_address, usbDevice[msExt->reader_index].bus_number,
rv, libusb_error_name(rv)); usbDevice[msExt->reader_index].device_address,
libusb_error_name(rv));
else
DEBUG_COMM4("Multi_PollingProc (%d/%d): error %s",
usbDevice[msExt->reader_index].bus_number,
usbDevice[msExt->reader_index].device_address,
libusb_error_name(rv));
} }
/* Wake up the slot threads so they will exit as well */ /* Wake up the slot threads so they will exit as well */
@ -1616,6 +1750,7 @@ static void *Multi_PollingProc(void *p_ext)
/* Unlock */ /* Unlock */
pthread_mutex_unlock(&msExt->mutex); pthread_mutex_unlock(&msExt->mutex);
end:
/* Now exit */ /* Now exit */
DEBUG_COMM3("Multi_PollingProc (%d/%d): Thread terminated", DEBUG_COMM3("Multi_PollingProc (%d/%d): Thread terminated",
usbDevice[msExt->reader_index].bus_number, usbDevice[msExt->reader_index].bus_number,
@ -1639,7 +1774,7 @@ static void Multi_PollingTerminate(struct usbDevice_MultiSlot_Extension *msExt)
{ {
msExt->terminated = TRUE; msExt->terminated = TRUE;
transfer = usbDevice[msExt->reader_index].polling_transfer; transfer = atomic_load(&usbDevice[msExt->reader_index].polling_transfer);
if (transfer) if (transfer)
{ {
@ -1668,9 +1803,9 @@ static int Multi_InterruptRead(int reader_index, int timeout /* in ms */)
msExt = usbDevice[reader_index].multislot_extension; msExt = usbDevice[reader_index].multislot_extension;
/* When stopped, return 0 so IFDHPolling will return IFD_NO_SUCH_DEVICE */ /* When stopped, returns IFD_NO_SUCH_DEVICE */
if ((msExt == NULL) || msExt->terminated) if ((msExt == NULL) || msExt->terminated)
return 0; return IFD_NO_SUCH_DEVICE;
DEBUG_PERIODIC3("Multi_InterruptRead (%d), timeout: %d ms", DEBUG_PERIODIC3("Multi_InterruptRead (%d), timeout: %d ms",
reader_index, timeout); reader_index, timeout);
@ -1708,9 +1843,9 @@ again:
/* Don't forget to unlock the mutex */ /* Don't forget to unlock the mutex */
pthread_mutex_unlock(&msExt->mutex); pthread_mutex_unlock(&msExt->mutex);
/* When stopped, return 0 so IFDHPolling will return IFD_NO_SUCH_DEVICE */ /* When stopped, returns IFD_NO_SUCH_DEVICE */
if (msExt->terminated) if (msExt->terminated)
return 0; return IFD_NO_SUCH_DEVICE;
/* Not stopped */ /* Not stopped */
if (status == LIBUSB_TRANSFER_COMPLETED) if (status == LIBUSB_TRANSFER_COMPLETED)
@ -1762,6 +1897,87 @@ static void Multi_InterruptStop(int reader_index)
} /* Multi_InterruptStop */ } /* Multi_InterruptStop */
/*****************************************************************************
*
* Multi_ReadProc
*
****************************************************************************/
static void *Multi_ReadProc(void *p_ext)
{
struct usbDevice_MultiSlot_Extension *msExt;
struct multiSlot_ConcurrentAccess *concurrent;
int reader_index;
int rv;
unsigned char buffer[10 + MAX_BUFFER_SIZE_EXTENDED];
int length;
msExt = p_ext;
concurrent = msExt->concurrent;
reader_index = msExt->reader_index;
DEBUG_COMM3("Multi_ReadProc (%d/%d): thread starting",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address);
while (! msExt->terminated)
{
int slot;
DEBUG_COMM2("Waiting read for reader %d", reader_index);
rv = libusb_bulk_transfer(msExt->dev_handle,
usbDevice[reader_index].bulk_in, buffer, sizeof buffer,
&length, 5 * 1000);
if (rv < 0)
{
/* timeout are expected since we read continuously */
if (LIBUSB_ERROR_TIMEOUT == rv)
continue;
if (LIBUSB_ERROR_NO_DEVICE == rv)
{
DEBUG_INFO4("read failed (%d/%d): %s",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address,
libusb_error_name(rv));
}
else
{
DEBUG_CRITICAL4("read failed (%d/%d): %s",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address,
libusb_error_name(rv));
}
/* wait a bit to avoid a fast error loop */
(void)usleep(100*1000);
continue;
}
#define BSLOT_OFFSET 5
slot = buffer[BSLOT_OFFSET];
DEBUG_COMM3("Read %d bytes for slot %d", length, slot);
/* copy and signal */
pthread_mutex_lock(&concurrent[slot].mutex);
memcpy(concurrent[slot].buffer, buffer, length);
concurrent[slot].length = length;
pthread_cond_signal(&concurrent[slot].condition);
DEBUG_COMM3("Signaled reader %d slot %d", reader_index, slot);
pthread_mutex_unlock(&concurrent[slot].mutex);
}
DEBUG_COMM3("Multi_ReadProc (%d/%d): Thread terminated",
usbDevice[reader_index].bus_number,
usbDevice[reader_index].device_address);
pthread_exit(NULL);
return NULL;
}
/***************************************************************************** /*****************************************************************************
* *
* Multi_CreateFirstSlot * Multi_CreateFirstSlot
@ -1770,6 +1986,7 @@ static void Multi_InterruptStop(int reader_index)
static struct usbDevice_MultiSlot_Extension *Multi_CreateFirstSlot(int reader_index) static struct usbDevice_MultiSlot_Extension *Multi_CreateFirstSlot(int reader_index)
{ {
struct usbDevice_MultiSlot_Extension *msExt; struct usbDevice_MultiSlot_Extension *msExt;
struct multiSlot_ConcurrentAccess *concurrent;
/* Allocate a new extension buffer */ /* Allocate a new extension buffer */
msExt = malloc(sizeof(struct usbDevice_MultiSlot_Extension)); msExt = malloc(sizeof(struct usbDevice_MultiSlot_Extension));
@ -1779,17 +1996,38 @@ static struct usbDevice_MultiSlot_Extension *Multi_CreateFirstSlot(int reader_in
/* Remember the index */ /* Remember the index */
msExt->reader_index = reader_index; msExt->reader_index = reader_index;
msExt->terminated = FALSE; /* dev_handle of the physical reader */
msExt->dev_handle = usbDevice[reader_index].dev_handle;
atomic_init(&msExt->terminated, FALSE);
msExt->status = 0; msExt->status = 0;
msExt->transfer = NULL;
/* Create mutex and condition object for the interrupt polling */ /* Create mutex and condition object for the interrupt polling */
pthread_mutex_init(&msExt->mutex, NULL); pthread_mutex_init(&msExt->mutex, NULL);
pthread_cond_init(&msExt->condition, NULL); pthread_cond_init(&msExt->condition, NULL);
/* concurrent USB read */
concurrent = calloc(usbDevice[reader_index].ccid.bMaxSlotIndex +1,
sizeof(struct multiSlot_ConcurrentAccess));
if (NULL == concurrent)
{
DEBUG_CRITICAL("malloc failed");
free(msExt);
return NULL;
}
for (int slot=0; slot<=usbDevice[reader_index].ccid.bMaxSlotIndex; slot++)
{
/* Create mutex and condition object for the concurrent read */
pthread_mutex_init(&concurrent[slot].mutex, NULL);
pthread_cond_init(&concurrent[slot].condition, NULL);
}
msExt->concurrent = concurrent;
/* create the thread in charge of the interrupt polling */ /* create the thread in charge of the interrupt polling */
pthread_create(&msExt->thread_proc, NULL, Multi_PollingProc, msExt); pthread_create(&msExt->thread_proc, NULL, Multi_PollingProc, msExt);
pthread_create(&msExt->thread_concurrent, NULL, Multi_ReadProc, msExt);
return msExt; return msExt;
} /* Multi_CreateFirstSlot */ } /* Multi_CreateFirstSlot */

View File

@ -27,9 +27,10 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
unsigned char *Buffer); unsigned char *Buffer);
status_t ReadUSB(unsigned int reader_index, unsigned int *length, status_t ReadUSB(unsigned int reader_index, unsigned int *length,
/*@out@*/ unsigned char *Buffer); /*@out@*/ unsigned char *Buffer, int bSeq);
status_t CloseUSB(unsigned int reader_index); status_t CloseUSB(unsigned int reader_index);
status_t DisconnectUSB(unsigned int reader_index);
#include <libusb.h> #include <libusb.h>
/*@null@*/ const struct libusb_interface *get_ccid_usb_interface( /*@null@*/ const struct libusb_interface *get_ccid_usb_interface(

View File

@ -95,6 +95,7 @@ RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
unsigned char buffer[], int voltage) unsigned char buffer[], int voltage)
{ {
unsigned char cmd[10]; unsigned char cmd[10];
int bSeq;
status_t res; status_t res;
int length, count = 1; int length, count = 1;
unsigned int atr_len; unsigned int atr_len;
@ -218,10 +219,11 @@ check_again:
init_voltage = voltage; init_voltage = voltage;
again: again:
bSeq = (*ccid_descriptor->pbSeq)++;
cmd[0] = 0x62; /* IccPowerOn */ cmd[0] = 0x62; /* IccPowerOn */
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd[6] = (*ccid_descriptor->pbSeq)++; cmd[6] = bSeq;
cmd[7] = voltage; cmd[7] = voltage;
cmd[8] = cmd[9] = 0; /* RFU */ cmd[8] = cmd[9] = 0; /* RFU */
@ -232,7 +234,7 @@ again:
/* needed if we go back after a switch to ISO mode */ /* needed if we go back after a switch to ISO mode */
*nlength = length; *nlength = length;
res = ReadPort(reader_index, nlength, buffer); res = ReadPort(reader_index, nlength, buffer, bSeq);
CHECK_STATUS(res) CHECK_STATUS(res)
if (*nlength < CCID_RESPONSE_HEADER_SIZE) if (*nlength < CCID_RESPONSE_HEADER_SIZE)
@ -947,6 +949,7 @@ RESPONSECODE CmdEscapeCheck(unsigned int reader_index,
int mayfail) int mayfail)
{ {
unsigned char *cmd_in, *cmd_out; unsigned char *cmd_in, *cmd_out;
int bSeq;
status_t res; status_t res;
unsigned int length_in, length_out; unsigned int length_in, length_out;
RESPONSECODE return_value = IFD_SUCCESS; RESPONSECODE return_value = IFD_SUCCESS;
@ -977,10 +980,11 @@ again:
goto end; goto end;
} }
bSeq = (*ccid_descriptor->pbSeq)++;
cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */ cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
i2dw(length_in - 10, cmd_in+1); /* dwLength */ i2dw(length_in - 10, cmd_in+1); /* dwLength */
cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ cmd_in[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd_in[6] = (*ccid_descriptor->pbSeq)++; cmd_in[6] = bSeq;
cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */ cmd_in[7] = cmd_in[8] = cmd_in[9] = 0; /* RFU */
/* copy the command */ /* copy the command */
@ -1000,7 +1004,7 @@ again:
time_request: time_request:
length_out = 10 + *RxLength; length_out = 10 + *RxLength;
res = ReadPort(reader_index, &length_out, cmd_out); res = ReadPort(reader_index, &length_out, cmd_out, bSeq);
/* replay the command if NAK /* replay the command if NAK
* This (generally) happens only for the first command sent to the reader * This (generally) happens only for the first command sent to the reader
@ -1072,6 +1076,7 @@ end:
RESPONSECODE CmdPowerOff(unsigned int reader_index) RESPONSECODE CmdPowerOff(unsigned int reader_index)
{ {
unsigned char cmd[10]; unsigned char cmd[10];
int bSeq;
status_t res; status_t res;
unsigned int length; unsigned int length;
RESPONSECODE return_value = IFD_SUCCESS; RESPONSECODE return_value = IFD_SUCCESS;
@ -1124,17 +1129,18 @@ RESPONSECODE CmdPowerOff(unsigned int reader_index)
} }
#endif #endif
bSeq = (*ccid_descriptor->pbSeq)++;
cmd[0] = 0x63; /* IccPowerOff */ cmd[0] = 0x63; /* IccPowerOff */
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd[6] = (*ccid_descriptor->pbSeq)++; cmd[6] = bSeq;
cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */ cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
res = WritePort(reader_index, sizeof(cmd), cmd); res = WritePort(reader_index, sizeof(cmd), cmd);
CHECK_STATUS(res) CHECK_STATUS(res)
length = sizeof(cmd); length = sizeof(cmd);
res = ReadPort(reader_index, &length, cmd); res = ReadPort(reader_index, &length, cmd, bSeq);
CHECK_STATUS(res) CHECK_STATUS(res)
if (length < CCID_RESPONSE_HEADER_SIZE) if (length < CCID_RESPONSE_HEADER_SIZE)
@ -1161,6 +1167,7 @@ RESPONSECODE CmdPowerOff(unsigned int reader_index)
RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[]) RESPONSECODE CmdGetSlotStatus(unsigned int reader_index, unsigned char buffer[])
{ {
unsigned char cmd[10]; unsigned char cmd[10];
int bSeq;
status_t res; status_t res;
unsigned int length; unsigned int length;
RESPONSECODE return_value = IFD_SUCCESS; RESPONSECODE return_value = IFD_SUCCESS;
@ -1247,17 +1254,18 @@ again_status:
InterruptRead(reader_index, 10); InterruptRead(reader_index, 10);
#endif #endif
bSeq = (*ccid_descriptor->pbSeq)++;
cmd[0] = 0x65; /* GetSlotStatus */ cmd[0] = 0x65; /* GetSlotStatus */
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */ cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd[6] = (*ccid_descriptor->pbSeq)++; cmd[6] = bSeq;
cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */ cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
res = WritePort(reader_index, sizeof(cmd), cmd); res = WritePort(reader_index, sizeof(cmd), cmd);
CHECK_STATUS(res) CHECK_STATUS(res)
length = SIZE_GET_SLOT_STATUS; length = SIZE_GET_SLOT_STATUS;
res = ReadPort(reader_index, &length, buffer); res = ReadPort(reader_index, &length, buffer, bSeq);
CHECK_STATUS(res) CHECK_STATUS(res)
if (length < CCID_RESPONSE_HEADER_SIZE) if (length < CCID_RESPONSE_HEADER_SIZE)
@ -1546,7 +1554,7 @@ time_request_ICCD_B:
time_request: time_request:
length = sizeof(cmd); length = sizeof(cmd);
ret = ReadPort(reader_index, &length, cmd); ret = ReadPort(reader_index, &length, cmd, -1);
/* restore the original value of read timeout */ /* restore the original value of read timeout */
ccid_descriptor -> readTimeout = old_timeout; ccid_descriptor -> readTimeout = old_timeout;
@ -2304,15 +2312,17 @@ RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
unsigned int length, unsigned char buffer[]) unsigned int length, unsigned char buffer[])
{ {
unsigned char cmd[10+length]; /* CCID + APDU buffer */ unsigned char cmd[10+length]; /* CCID + APDU buffer */
int bSeq;
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index); _ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
status_t res; status_t res;
DEBUG_COMM2("length: %d bytes", length); DEBUG_COMM2("length: %d bytes", length);
bSeq = (*ccid_descriptor->pbSeq)++;
cmd[0] = 0x61; /* SetParameters */ cmd[0] = 0x61; /* SetParameters */
i2dw(length, cmd+1); /* APDU length */ i2dw(length, cmd+1); /* APDU length */
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */ cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
cmd[6] = (*ccid_descriptor->pbSeq)++; cmd[6] = bSeq;
cmd[7] = protocol; /* bProtocolNum */ cmd[7] = protocol; /* bProtocolNum */
cmd[8] = cmd[9] = 0; /* RFU */ cmd[8] = cmd[9] = 0; /* RFU */
@ -2322,7 +2332,7 @@ RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
CHECK_STATUS(res) CHECK_STATUS(res)
length = sizeof(cmd); length = sizeof(cmd);
res = ReadPort(reader_index, &length, cmd); res = ReadPort(reader_index, &length, cmd, bSeq);
CHECK_STATUS(res) CHECK_STATUS(res)
if (length < CCID_RESPONSE_HEADER_SIZE) if (length < CCID_RESPONSE_HEADER_SIZE)

View File

@ -73,53 +73,46 @@ extern int LogLevel;
#define DEBUG_COMM3(fmt, data1, data2) os_log_info(OS_LOG_DEFAULT, fmt, data1, data2) #define DEBUG_COMM3(fmt, data1, data2) os_log_info(OS_LOG_DEFAULT, fmt, data1, data2)
#define DEBUG_COMM4(fmt, data1, data2, data3) os_log_info(OS_LOG_DEFAULT, fmt, data1, data2, data3) #define DEBUG_COMM4(fmt, data1, data2, data3) os_log_info(OS_LOG_DEFAULT, fmt, data1, data2, data3)
#define DEBUG_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size) #define DEBUG_INFO_XXD(msg, buffer, size) do { if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size); } while (0)
#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, msg, buffer, size) #define DEBUG_XXD(msg, buffer, size) do { if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, msg, buffer, size); } while (0)
#else #else
#define TO_PCSCD_LOG(fmt, CCID_LEVEL, PCSCD_LEVEL) do { if (LogLevel & DEBUG_LEVEL_ ## CCID_LEVEL) Log1(PCSC_LOG_ ## PCSCD_LEVEL, fmt); } while (0)
#define TO_PCSCD_LOG2(fmt, data, CCID_LEVEL, PCSCD_LEVEL) do { if (LogLevel & DEBUG_LEVEL_ ## CCID_LEVEL) Log2(PCSC_LOG_ ## PCSCD_LEVEL, fmt, data); } while (0)
#define TO_PCSCD_LOG3(fmt, data1, data2, CCID_LEVEL, PCSCD_LEVEL) do { if (LogLevel & DEBUG_LEVEL_ ## CCID_LEVEL) Log3(PCSC_LOG_ ## PCSCD_LEVEL, fmt, data1, data2); } while (0)
#define TO_PCSCD_LOG4(fmt, data1, data2, data3, CCID_LEVEL, PCSCD_LEVEL) do { if (LogLevel & DEBUG_LEVEL_ ## CCID_LEVEL) Log4(PCSC_LOG_ ## PCSCD_LEVEL, fmt, data1, data2, data3); } while (0)
#define TO_PCSCD_LOG5(fmt, data1, data2, data3, data4, CCID_LEVEL, PCSCD_LEVEL) do { if (LogLevel & DEBUG_LEVEL_ ## CCID_LEVEL) Log5(PCSC_LOG_ ## PCSCD_LEVEL, fmt, data1, data2, data3, data4); } while (0)
/* DEBUG_CRITICAL */ /* DEBUG_CRITICAL */
#define DEBUG_CRITICAL(fmt) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log1(PCSC_LOG_CRITICAL, fmt) #define DEBUG_CRITICAL(fmt) TO_PCSCD_LOG(fmt, CRITICAL, CRITICAL)
#define DEBUG_CRITICAL2(fmt, data) TO_PCSCD_LOG2(fmt, data, CRITICAL, CRITICAL)
#define DEBUG_CRITICAL2(fmt, data) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log2(PCSC_LOG_CRITICAL, fmt, data) #define DEBUG_CRITICAL3(fmt, data1, data2) TO_PCSCD_LOG3(fmt, data1, data2, CRITICAL, CRITICAL)
#define DEBUG_CRITICAL4(fmt, data1, data2, data3) TO_PCSCD_LOG4(fmt, data1, data2, data3, CRITICAL, CRITICAL)
#define DEBUG_CRITICAL3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log3(PCSC_LOG_CRITICAL, fmt, data1, data2) #define DEBUG_CRITICAL5(fmt, data1, data2, data3, data4) TO_PCSCD_LOG5(fmt, data1, data2, data3, data4, CRITICAL, CRITICAL)
#define DEBUG_CRITICAL4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log4(PCSC_LOG_CRITICAL, fmt, data1, data2, data3)
#define DEBUG_CRITICAL5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log5(PCSC_LOG_CRITICAL, fmt, data1, data2, data3, data4)
/* DEBUG_INFO */ /* DEBUG_INFO */
#define DEBUG_INFO1(fmt) if (LogLevel & DEBUG_LEVEL_INFO) Log1(PCSC_LOG_INFO, fmt) #define DEBUG_INFO1(fmt) TO_PCSCD_LOG(fmt, INFO, INFO)
#define DEBUG_INFO2(fmt, data) TO_PCSCD_LOG2(fmt, data, INFO, INFO)
#define DEBUG_INFO3(fmt, data1, data2) TO_PCSCD_LOG3(fmt, data1, data2, INFO, INFO)
#define DEBUG_INFO4(fmt, data1, data2, data3) TO_PCSCD_LOG4(fmt, data1, data2, data3, INFO, INFO)
#define DEBUG_INFO5(fmt, data1, data2, data3, data4) TO_PCSCD_LOG5(fmt, data1, data2, data3, data4, INFO, INFO)
#define DEBUG_INFO2(fmt, data) if (LogLevel & DEBUG_LEVEL_INFO) Log2(PCSC_LOG_INFO, fmt, data) #define DEBUG_INFO_XXD(msg, buffer, size) do { if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size); } while (0)
#define DEBUG_INFO3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_INFO) Log3(PCSC_LOG_INFO, fmt, data1, data2)
#define DEBUG_INFO4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_INFO) Log4(PCSC_LOG_INFO, fmt, data1, data2, data3)
#define DEBUG_INFO5(fmt, data1, data2, data3, data4) if (LogLevel & DEBUG_LEVEL_INFO) Log5(PCSC_LOG_INFO, fmt, data1, data2, data3, data4)
#define DEBUG_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) LogXxd(PCSC_LOG_INFO, msg, buffer, size)
/* DEBUG_PERIODIC */ /* DEBUG_PERIODIC */
#define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt) #define DEBUG_PERIODIC(fmt) TO_PCSCD_LOG(fmt, PERIODIC, DEBUG)
#define DEBUG_PERIODIC2(fmt, data) TO_PCSCD_LOG2(fmt, data, PERIODIC, DEBUG)
#define DEBUG_PERIODIC2(fmt, data) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log2(PCSC_LOG_DEBUG, fmt, data) #define DEBUG_PERIODIC3(fmt, data1, data2) TO_PCSCD_LOG3(fmt, data1, data2, PERIODIC, DEBUG)
#define DEBUG_PERIODIC3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
/* DEBUG_COMM */ /* DEBUG_COMM */
#define DEBUG_COMM(fmt) if (LogLevel & DEBUG_LEVEL_COMM) Log1(PCSC_LOG_DEBUG, fmt) #define DEBUG_COMM(fmt) TO_PCSCD_LOG(fmt, COMM, DEBUG)
#define DEBUG_COMM2(fmt, data) TO_PCSCD_LOG2(fmt, data, COMM, DEBUG)
#define DEBUG_COMM2(fmt, data) if (LogLevel & DEBUG_LEVEL_COMM) Log2(PCSC_LOG_DEBUG, fmt, data) #define DEBUG_COMM3(fmt, data1, data2) TO_PCSCD_LOG3(fmt, data1, data2, COMM, DEBUG)
#define DEBUG_COMM4(fmt, data1, data2, data3) TO_PCSCD_LOG4(fmt, data1, data2, data3, COMM, DEBUG)
#define DEBUG_COMM3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_COMM) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
#define DEBUG_COMM4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_COMM) Log4(PCSC_LOG_DEBUG, fmt, data1, data2, data3)
/* DEBUG_XXD */ /* DEBUG_XXD */
#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) LogXxd(PCSC_LOG_DEBUG, msg, buffer, size) #define DEBUG_XXD(msg, buffer, size) do { if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, msg, buffer, size); } while (0)
#endif #endif

View File

@ -96,6 +96,7 @@ typedef enum {
#define ClosePort CloseSerial #define ClosePort CloseSerial
#define ReadPort ReadSerial #define ReadPort ReadSerial
#define WritePort WriteSerial #define WritePort WriteSerial
#define DisconnectPort DisconnectSerial
#include "ccid_serial.h" #include "ccid_serial.h"
#else #else
@ -105,6 +106,7 @@ typedef enum {
#define ClosePort CloseUSB #define ClosePort CloseUSB
#define ReadPort ReadUSB #define ReadPort ReadUSB
#define WritePort WriteUSB #define WritePort WriteUSB
#define DisconnectPort DisconnectUSB
#include "ccid_usb.h" #include "ccid_usb.h"
#endif #endif

View File

@ -490,8 +490,12 @@ EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
case TAG_IFD_SLOT_THREAD_SAFE: case TAG_IFD_SLOT_THREAD_SAFE:
if (*Length >= 1) if (*Length >= 1)
{ {
_ccid_descriptor *ccid_desc = get_ccid_descriptor(reader_index);
*Length = 1; *Length = 1;
*Value = 0; /* Can NOT talk to multiple slots at the same time */ if (ccid_desc->bMaxSlotIndex +1 == ccid_desc->bMaxCCIDBusySlots)
*Value = 1; /* all slots can be used simultanesously */
else
*Value = 0; /* Can NOT talk to multiple slots at the same time */
} }
else else
return_value = IFD_ERROR_INSUFFICIENT_BUFFER; return_value = IFD_ERROR_INSUFFICIENT_BUFFER;
@ -602,6 +606,13 @@ EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
break; break;
#endif #endif
#ifdef TAG_IFD_DEVICE_REMOVED
case TAG_IFD_DEVICE_REMOVED:
if (Value && (1 == *Length))
Value[0] = 1;
break;
#endif
case SCARD_ATTR_VENDOR_IFD_SERIAL_NO: case SCARD_ATTR_VENDOR_IFD_SERIAL_NO:
{ {
_ccid_descriptor *ccid_desc; _ccid_descriptor *ccid_desc;
@ -661,6 +672,7 @@ EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
* IFD_ERROR_VALUE_READ_ONLY * IFD_ERROR_VALUE_READ_ONLY
*/ */
RESPONSECODE return_value = IFD_SUCCESS;
(void)Length; (void)Length;
(void)Value; (void)Value;
@ -672,7 +684,20 @@ EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
DEBUG_INFO4("tag: 0x" DWORD_X ", %s (lun: " DWORD_X ")", Tag, DEBUG_INFO4("tag: 0x" DWORD_X ", %s (lun: " DWORD_X ")", Tag,
CcidSlots[reader_index].readerName, Lun); CcidSlots[reader_index].readerName, Lun);
return IFD_NOT_SUPPORTED; switch (Tag)
{
#ifdef TAG_IFD_DEVICE_REMOVED
case TAG_IFD_DEVICE_REMOVED:
if ((1 == Length) && (Value != NULL) && (Value[0] != 0))
DisconnectPort(reader_index);
break;
#endif
default:
return_value = IFD_ERROR_TAG;
}
return return_value;
} /* IFDHSetCapabilities */ } /* IFDHSetCapabilities */
@ -791,10 +816,7 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
/* Do not send CCID command SetParameters or PPS to the CCID /* Do not send CCID command SetParameters or PPS to the CCID
* The CCID will do this himself */ * The CCID will do this himself */
if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP) if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
{
DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
goto end; goto end;
}
/* PTS1? */ /* PTS1? */
if (Flags & IFD_NEGOTIATE_PTS1) if (Flags & IFD_NEGOTIATE_PTS1)
@ -967,6 +989,7 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
&& (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10)) && (atr.ib[1][ATR_INTERFACE_BYTE_TA].value & 0x10))
return IFD_COMMUNICATION_ERROR; return IFD_COMMUNICATION_ERROR;
end:
/* T=1 */ /* T=1 */
if (SCARD_PROTOCOL_T1 == Protocol) if (SCARD_PROTOCOL_T1 == Protocol)
{ {
@ -1046,9 +1069,14 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout); DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
ret = SetParameters(reader_index, 1, sizeof(param), param); if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
if (IFD_SUCCESS != ret) DEBUG_COMM("Skip SetParameters");
return ret; else
{
ret = SetParameters(reader_index, 1, sizeof(param), param);
if (IFD_SUCCESS != ret)
return ret;
}
} }
else else
/* T=0 */ /* T=0 */
@ -1085,14 +1113,18 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */, ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
param[3] /* TC2 */, ccid_desc->dwDefaultClock); param[3] /* TC2 */, ccid_desc->dwDefaultClock);
DEBUG_COMM2("Communication timeout: %d ms", ccid_desc->readTimeout); DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
ret = SetParameters(reader_index, 0, sizeof(param), param); if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
if (IFD_SUCCESS != ret) DEBUG_COMM("Skip SetParameters");
return ret; else
{
ret = SetParameters(reader_index, 0, sizeof(param), param);
if (IFD_SUCCESS != ret)
return ret;
}
} }
end:
/* set IFSC & IFSD in T=1 */ /* set IFSC & IFSD in T=1 */
if ((SCARD_PROTOCOL_T1 == Protocol) if ((SCARD_PROTOCOL_T1 == Protocol)
&& (CCID_CLASS_TPDU == (ccid_desc->dwFeatures & CCID_CLASS_EXCHANGE_MASK))) && (CCID_CLASS_TPDU == (ccid_desc->dwFeatures & CCID_CLASS_EXCHANGE_MASK)))
@ -1195,6 +1227,9 @@ EXTERNAL RESPONSECODE IFDHPowerICC(DWORD Lun, DWORD Action,
CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN; CcidSlots[reader_index].bPowerFlags |= MASK_POWERFLAGS_PDWN;
/* send the command */ /* send the command */
return_value = CmdPowerOff(reader_index);
if (IFD_NO_SUCH_DEVICE == return_value)
goto end;
if (IFD_SUCCESS != CmdPowerOff(reader_index)) if (IFD_SUCCESS != CmdPowerOff(reader_index))
{ {
DEBUG_CRITICAL("PowerDown failed"); DEBUG_CRITICAL("PowerDown failed");
@ -1469,6 +1504,10 @@ EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
allowed = TRUE; allowed = TRUE;
} }
/* allow APDU exchange with this reader without a card in the field */
if (HID_OMNIKEY_5427CK == readerID)
allowed = TRUE;
if (!allowed) if (!allowed)
{ {
DEBUG_INFO1("ifd exchange (Escape command) not allowed"); DEBUG_INFO1("ifd exchange (Escape command) not allowed");
@ -1915,6 +1954,12 @@ EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
/* set back the old LogLevel */ /* set back the old LogLevel */
LogLevel = oldLogLevel; LogLevel = oldLogLevel;
if (IFD_NO_SUCH_DEVICE == return_value)
{
return_value = IFD_ICC_NOT_PRESENT;
goto end;
}
if (return_value != IFD_SUCCESS) if (return_value != IFD_SUCCESS)
return return_value; return return_value;

View File

@ -159,7 +159,8 @@ int t1_transceive(t1_state_t * t1, unsigned int dad,
{ {
ct_buf_t sbuf, rbuf, tbuf; ct_buf_t sbuf, rbuf, tbuf;
unsigned char sdata[T1_BUFFER_SIZE], sblk[5]; unsigned char sdata[T1_BUFFER_SIZE], sblk[5];
unsigned int slen, retries, resyncs; unsigned int slen, resyncs;
int retries;
size_t last_send = 0; size_t last_send = 0;
if (snd_len == 0) if (snd_len == 0)
@ -745,7 +746,7 @@ int t1_negotiate_ifsd(t1_state_t * t1, unsigned int dad, int ifsd)
ct_buf_t sbuf; ct_buf_t sbuf;
unsigned char sdata[T1_BUFFER_SIZE]; unsigned char sdata[T1_BUFFER_SIZE];
unsigned int slen; unsigned int slen;
unsigned int retries; int retries;
size_t snd_len; size_t snd_len;
int n; int n;
unsigned char snd_buf[1]; unsigned char snd_buf[1];
@ -764,14 +765,14 @@ int t1_negotiate_ifsd(t1_state_t * t1, unsigned int dad, int ifsd)
/* Build the block */ /* Build the block */
slen = t1_build(t1, sdata, 0, T1_S_BLOCK | T1_S_IFS, &sbuf, NULL); slen = t1_build(t1, sdata, 0, T1_S_BLOCK | T1_S_IFS, &sbuf, NULL);
/* Send the block */
n = t1_xcv(t1, sdata, slen, sizeof(sdata));
retries--; retries--;
/* ISO 7816-3 Rule 7.4.2 */ /* ISO 7816-3 Rule 7.4.2 */
if (retries <= 0) if (retries < 0)
goto error; goto error;
/* Send the block */
n = t1_xcv(t1, sdata, slen, sizeof(sdata));
if (-1 == n) if (-1 == n)
{ {
DEBUG_CRITICAL("fatal: transmit/receive failed"); DEBUG_CRITICAL("fatal: transmit/receive failed");

View File

@ -28,13 +28,14 @@
#include "debug.h" #include "debug.h"
int ReaderIndex[CCID_DRIVER_MAX_READERS]; int ReaderIndex[CCID_DRIVER_MAX_READERS];
#define FREE_ENTRY -42
void InitReaderIndex(void) void InitReaderIndex(void)
{ {
int i; int i;
for (i=0; i<CCID_DRIVER_MAX_READERS; i++) for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
ReaderIndex[i] = -1; ReaderIndex[i] = FREE_ENTRY;
} /* InitReaderIndex */ } /* InitReaderIndex */
int GetNewReaderIndex(const int Lun) int GetNewReaderIndex(const int Lun)
@ -53,7 +54,7 @@ int GetNewReaderIndex(const int Lun)
} }
for (i=0; i<CCID_DRIVER_MAX_READERS; i++) for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
if (-1 == ReaderIndex[i]) if (FREE_ENTRY == ReaderIndex[i])
{ {
ReaderIndex[i] = Lun; ReaderIndex[i] = Lun;
return i; return i;
@ -77,7 +78,7 @@ int LunToReaderIndex(const int Lun)
void ReleaseReaderIndex(const int index) void ReleaseReaderIndex(const int index)
{ {
ReaderIndex[index] = -1; ReaderIndex[index] = FREE_ENTRY;
} /* ReleaseReaderIndex */ } /* ReleaseReaderIndex */
/* Read a non aligned 16-bit integer */ /* Read a non aligned 16-bit integer */

2
ylwrap
View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2021 Free Software Foundation, Inc.
# #
# Written by Tom Tromey <tromey@cygnus.com>. # Written by Tom Tromey <tromey@cygnus.com>.
# #