New upstream version 1.5.0
This commit is contained in:
parent
3d895c8b7c
commit
d964627ccc
948
ChangeLog
948
ChangeLog
|
@ -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>
|
||||
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 +-
|
||||
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>
|
||||
Date: Sun Jul 25 16:00:35 2021 +0200
|
||||
|
||||
|
|
16
Makefile.in
16
Makefile.in
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -156,13 +156,10 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
CSCOPE = cscope
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \
|
||||
COPYING ChangeLog INSTALL NEWS ar-lib compile config.guess \
|
||||
config.sub depcomp install-sh ltmain.sh missing ylwrap
|
||||
COPYING ChangeLog INSTALL NEWS README.md ar-lib compile \
|
||||
config.guess config.sub install-sh ltmain.sh missing ylwrap
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
|
@ -221,6 +218,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -232,6 +231,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -283,6 +283,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -533,7 +534,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
26
README.md
26
README.md
|
@ -117,6 +117,32 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|||
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
|
||||
- Add support of
|
||||
- Lenovo Lenovo Smartcard Wired Keyboard II
|
||||
|
|
|
@ -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
|
||||
# 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_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
|
||||
[m4_warning([this file was generated for autoconf 2.69.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
|
||||
[m4_warning([this file was generated for autoconf 2.71.
|
||||
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.
|
||||
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/libs to be tested by setting these environment variables.)
|
||||
#
|
||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
|
||||
# needed for multi-threaded programs (defaults to the value of CC
|
||||
# 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,
|
||||
# but also to link with them as well. For example, you might link with
|
||||
# $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
|
||||
# variables in your default LIBS, CFLAGS, and CC:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
|
||||
# CC="$PTHREAD_CC"
|
||||
# CXX="$PTHREAD_CXX"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||
# 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) 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
|
||||
# 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
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 24
|
||||
#serial 31
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [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_LIBS="$LIBS"
|
||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $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
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are 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.
|
||||
# Create a list of thread flags to try. Items with a "," contain both
|
||||
# C compiler flags (before ",") and linker flags (after ","). Other items
|
||||
# starting with a "-" are C compiler flags, and remaining items are
|
||||
# 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"
|
||||
|
||||
|
@ -216,14 +224,47 @@ case $host_os in
|
|||
# that too in a future libc.) So we'll check first for the
|
||||
# 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
|
||||
|
||||
# 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)
|
||||
|
||||
# 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"],
|
||||
[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
|
||||
# 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="!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
|
||||
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])
|
||||
;;
|
||||
|
||||
-mt,pthread)
|
||||
AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
|
||||
PTHREAD_CFLAGS="-mt"
|
||||
PTHREAD_LIBS="-lpthread"
|
||||
*,*)
|
||||
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
|
||||
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
|
||||
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
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# 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; }],
|
||||
[pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
|
@ -415,6 +367,80 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
|
|||
done
|
||||
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:
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
|
@ -460,7 +486,8 @@ if test "x$ax_pthread_ok" = "xyes"; then
|
|||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||
[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=no])
|
||||
])
|
||||
|
@ -482,18 +509,28 @@ if test "x$ax_pthread_ok" = "xyes"; then
|
|||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[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
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
|
||||
|
||||
AC_SUBST([PTHREAD_LIBS])
|
||||
AC_SUBST([PTHREAD_CFLAGS])
|
||||
AC_SUBST([PTHREAD_CC])
|
||||
AC_SUBST([PTHREAD_CXX])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
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
|
||||
])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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -797,7 +834,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
|
|||
[am__api_version='1.16'
|
||||
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.
|
||||
m4_if([$1], [1.16.3], [],
|
||||
m4_if([$1], [1.16.5], [],
|
||||
[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.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
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_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -880,7 +917,7 @@ AC_SUBST([AR])dnl
|
|||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -932,7 +969,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
|
|||
|
||||
# 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
|
||||
# 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.]])
|
||||
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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# 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.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[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 the ones we care about.
|
||||
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
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
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],,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
|
@ -1338,6 +1379,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
|
|||
[m4_define([AC_PROG_OBJCXX],
|
||||
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
|
||||
dnl The testsuite driver may need to know about EXEEXT, so add the
|
||||
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
|
||||
|
@ -1419,7 +1474,7 @@ for _am_header in $config_headers :; do
|
|||
done
|
||||
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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1440,7 +1495,7 @@ if test x"${install_sh+set}" != xset; then
|
|||
fi
|
||||
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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1459,7 +1514,7 @@ fi
|
|||
rmdir .tst 2>/dev/null
|
||||
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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1480,7 +1535,7 @@ fi])
|
|||
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
|
||||
# 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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1592,7 +1647,7 @@ fi
|
|||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1621,7 +1676,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
|
|||
AC_DEFUN([_AM_IF_OPTION],
|
||||
[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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1668,7 +1723,7 @@ AC_LANG_POP([C])])
|
|||
# For backward compatibility.
|
||||
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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1768,7 +1823,7 @@ AC_CONFIG_COMMANDS_PRE(
|
|||
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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1828,7 +1883,7 @@ AC_SUBST([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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -1856,7 +1911,7 @@ fi
|
|||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
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
|
||||
# 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 -*-
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
|
2
ar-lib
2
ar-lib
|
@ -4,7 +4,7 @@
|
|||
me=ar-lib
|
||||
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>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
|
2
compile
2
compile
|
@ -3,7 +3,7 @@
|
|||
|
||||
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>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#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. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
|
@ -118,7 +115,9 @@
|
|||
your system. */
|
||||
#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
|
||||
|
||||
/* composite device are seen as multi-slots */
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Require autoconf 2.61
|
||||
AC_PREREQ([2.69])
|
||||
|
||||
AC_INIT([ccid],[1.4.36])
|
||||
AC_INIT([ccid],[1.5.0])
|
||||
AC_CONFIG_SRCDIR(src/ifdhandler.c)
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip subdir-objects foreign)
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -178,8 +178,6 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
|
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -485,7 +487,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -152,8 +152,6 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = RSA_SecurID Kobil_mIDentity_switch
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -462,7 +464,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -176,8 +176,6 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
|
@ -194,6 +192,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -205,6 +205,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -254,6 +255,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -482,7 +484,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
2
depcomp
2
depcomp
|
@ -3,7 +3,7 @@
|
|||
|
||||
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
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -178,8 +178,6 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
|
@ -196,6 +194,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -207,6 +207,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -256,6 +257,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -498,7 +500,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
2
missing
2
missing
|
@ -3,7 +3,7 @@
|
|||
|
||||
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.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -136,6 +136,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -147,6 +149,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -196,6 +199,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -308,7 +312,6 @@ ctags CTAGS:
|
|||
|
||||
cscope cscopelist:
|
||||
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# List of readers supported by the CCID driver
|
||||
# Generated: 2021-08-30
|
||||
# Generated: 2022-01-27
|
||||
#
|
||||
# DO NOT EDIT BY HAND
|
||||
|
||||
|
@ -131,6 +131,7 @@
|
|||
# ACS
|
||||
0x072F:0x1204:ACS ACR101 ICC Reader
|
||||
0x072F:0x221A:ACS ACR1251 Dual Reader
|
||||
0x072F:0x2224:ACS ACR1281U
|
||||
0x072F:0x223B:ACS ACR1252 Dual Reader
|
||||
0x072F:0x223E:ACS ACR1252 Reader
|
||||
0x072F:0x223F:ACS ACR1255U-J1
|
||||
|
@ -314,16 +315,27 @@
|
|||
|
||||
# Circle
|
||||
0x31AA:0x0224:Circle Idaxis SecurePIV
|
||||
0x31AA:0x0324:Circle CIR315
|
||||
0x31AA:0x1000:Circle CIR115 ICC
|
||||
0x31AA:0x1100:Circle CIR125 ICC
|
||||
0x31AA:0x2000:Circle CIR215 PICC
|
||||
0x31AA:0x2001:Circle CIR215 CL
|
||||
0x31AA:0x2100:Circle CIR215 CL
|
||||
0x31AA:0x3000:Circle CIR315 Dual & 1S
|
||||
0x31AA:0x3001:Circle CIR315
|
||||
0x31AA:0x3002:Circle CIR315 CL
|
||||
0x31AA:0x3003:Circle CIR315 DI
|
||||
0x31AA:0x3100:Circle CIR315
|
||||
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:0x7003:Circle CCR7315
|
||||
0x31AA:0x7004:Circle CIR315
|
||||
0x31AA:0x7005:Circle CCR7125 ICC
|
||||
0x31AA:0x7006:Circle CIR125-DOT ICC
|
||||
|
||||
# COVADIS
|
||||
0x0982:0x0008:COVADIS VEGA-ALPHA
|
||||
|
@ -354,6 +366,9 @@
|
|||
0x09D8:0x0427:Elatec TWN4 SmartCard NFC
|
||||
0x09D8:0x0428:Elatec TWN4/B1.06/CPF3.05/S1SC1.32/P (Beta 3)
|
||||
|
||||
# ELYCTIS
|
||||
0x1FFA:0x0002:ELYCTIS CL reader
|
||||
|
||||
# ESMART
|
||||
0x2CE4:0x7479:ESMART Token GOST
|
||||
|
||||
|
@ -638,6 +653,7 @@
|
|||
0x20A0:0x4109:Nitrokey Nitrokey Storage
|
||||
0x20A0:0x4211:Nitrokey Nitrokey Start
|
||||
0x20A0:0x4230:Nitrokey Nitrokey HSM
|
||||
0x20A0:0x42B2:Nitrokey Nitrokey 3
|
||||
|
||||
# NTT Communications Corp.
|
||||
0x04E6:0x511A:NTT Communications Corp. SCR3310-NTTCom USB SmartCard Reader
|
||||
|
@ -750,9 +766,9 @@
|
|||
0x1209:0xBEEE:SoloKeys Solo 2
|
||||
|
||||
# SONY
|
||||
0x054C:0x0D8F:SONY Felica RC-S660/U
|
||||
0x054C:0x0DC8:SONY Felica RC-S300/S
|
||||
0x054C:0x0DC9:SONY Felica RC-S300/P
|
||||
0x054C:0x0D8F:SONY FeliCa RC-S660/U
|
||||
0x054C:0x0DC8:SONY FeliCa RC-S300/S
|
||||
0x054C:0x0DC9:SONY FeliCa RC-S300/P
|
||||
|
||||
# SPECINFOSYSTEMS
|
||||
0x316E:0x0001:SPECINFOSYSTEMS DIAMOND token
|
||||
|
@ -806,6 +822,9 @@
|
|||
# Teridian Semiconductors
|
||||
0x1862:0x0000:Teridian Semiconductors TSC12xxFV.09
|
||||
|
||||
# Thales
|
||||
0x08E6:0x34C7:Thales Shield M4 Reader
|
||||
|
||||
# THURSBY SOFTWARE
|
||||
0x1976:0x0001:THURSBY SOFTWARE TSS-PK1
|
||||
|
||||
|
@ -878,6 +897,8 @@
|
|||
0x1050:0x0406:Yubico YubiKey FIDO+CCID
|
||||
0x1050:0x0407:Yubico YubiKey OTP+FIDO+CCID
|
||||
|
||||
# ~ELYCTIS
|
||||
|
||||
##########################
|
||||
# section: unsupported
|
||||
##########################
|
||||
|
|
|
@ -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@
|
||||
|
||||
# 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
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -306,8 +306,6 @@ am__define_uniq_tagged_files = \
|
|||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
|
||||
$(top_srcdir)/ylwrap tokenparser.c
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
@ -325,6 +323,8 @@ CCDEPMODE = @CCDEPMODE@
|
|||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
|
@ -336,6 +336,7 @@ ECHO_C = @ECHO_C@
|
|||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
|
@ -385,6 +386,7 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
|||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_CXX = @PTHREAD_CXX@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
|
@ -1052,7 +1054,6 @@ cscopelist-am: $(am__tagged_files)
|
|||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
|
|
|
@ -576,6 +576,14 @@ int ccid_open_hack_post(unsigned int reader_index)
|
|||
* have one */
|
||||
ccid_descriptor->bPINSupport = 0;
|
||||
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 */
|
||||
|
|
|
@ -70,6 +70,11 @@ typedef struct
|
|||
*/
|
||||
char bMaxSlotIndex;
|
||||
|
||||
/*
|
||||
* Maximum number of slots which can be simultaneously busy
|
||||
*/
|
||||
char bMaxCCIDBusySlots;
|
||||
|
||||
/*
|
||||
* Slot in use
|
||||
*/
|
||||
|
@ -232,6 +237,7 @@ typedef struct
|
|||
#define HID_OMNIKEY_5422 0x076B5422
|
||||
#define HID_OMNIKEY_3X21 0x076B3031 /* OMNIKEY 3121 or 3021 or 1021 */
|
||||
#define HID_OMNIKEY_3821 0x076B3821 /* OMNIKEY 3821 */
|
||||
#define HID_OMNIKEY_5427CK 0x076B5427 /* OMNIKEY 5427 CK */
|
||||
#define HID_OMNIKEY_6121 0x076B6632 /* OMNIKEY 6121 */
|
||||
#define CHERRY_XX44 0x046A00A7 /* Cherry Smart Terminal xx44 */
|
||||
#define FUJITSU_D323 0x0BF81024 /* Fujitsu Smartcard Reader D323 */
|
||||
|
@ -239,6 +245,7 @@ typedef struct
|
|||
#define IDENTIV_uTrust3701F 0x04E65791
|
||||
#define IDENTIV_uTrust4701F 0x04E65724
|
||||
#define BIT4ID_MINILECTOR 0x25DD3111
|
||||
#define SAFENET_ETOKEN_5100 0x05290620
|
||||
|
||||
#define VENDOR_GEMALTO 0x08E6
|
||||
#define GET_VENDOR(readerID) ((readerID >> 16) & 0xFFFF)
|
||||
|
|
|
@ -220,7 +220,7 @@ status_t WriteSerial(unsigned int reader_index, unsigned int length,
|
|||
*
|
||||
*****************************************************************************/
|
||||
status_t ReadSerial(unsigned int reader_index,
|
||||
unsigned int *length, unsigned char *buffer)
|
||||
unsigned int *length, unsigned char *buffer, int bSeq)
|
||||
{
|
||||
unsigned char c;
|
||||
int rv;
|
||||
|
@ -228,6 +228,9 @@ status_t ReadSerial(unsigned int reader_index,
|
|||
int to_read;
|
||||
int i;
|
||||
|
||||
/* ignore bSeq */
|
||||
(void)bSeq;
|
||||
|
||||
/* we get the echo first */
|
||||
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.dwMaxDataRate = 344086;
|
||||
serialDevice[reader_index].ccid.bMaxSlotIndex = 0;
|
||||
serialDevice[reader_index].ccid.bMaxCCIDBusySlots = 1;
|
||||
serialDevice[reader_index].ccid.arrayOfSupportedDataRates = SerialTwinDataRates;
|
||||
serialDevice[reader_index].ccid.readTimeout = DEFAULT_COM_READ_TIMEOUT;
|
||||
serialDevice[reader_index].ccid.dwSlotStatus = IFD_ICC_PRESENT;
|
||||
|
@ -934,6 +938,21 @@ status_t CloseSerial(unsigned int reader_index)
|
|||
} /* CloseSerial */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* DisconnectSerial
|
||||
*
|
||||
****************************************************************************/
|
||||
status_t DisconnectSerial(unsigned int reader_index)
|
||||
{
|
||||
(void)reader_index;
|
||||
|
||||
DEBUG_COMM("Disconnect reader");
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
} /* DisconnectSerial */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* get_ccid_descriptor
|
||||
|
|
|
@ -28,8 +28,10 @@ status_t WriteSerial(unsigned int reader_index, unsigned int length,
|
|||
unsigned char *Buffer);
|
||||
|
||||
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 DisconnectSerial(unsigned int reader_index);
|
||||
|
||||
#endif
|
||||
|
|
344
src/ccid_usb.c
344
src/ccid_usb.c
|
@ -28,6 +28,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdatomic.h>
|
||||
#include <unistd.h>
|
||||
#include <ifdhandler.h>
|
||||
|
||||
#include <config.h>
|
||||
|
@ -61,18 +63,30 @@ libusb_context *ctx = NULL;
|
|||
|
||||
#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
|
||||
{
|
||||
int reader_index;
|
||||
|
||||
/* The multi-threaded polling part */
|
||||
int terminated;
|
||||
_Atomic int terminated;
|
||||
int status;
|
||||
unsigned char buffer[CCID_INTERRUPT_SIZE];
|
||||
pthread_t thread_proc;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
struct libusb_transfer *transfer;
|
||||
|
||||
pthread_t thread_concurrent;
|
||||
struct multiSlot_ConcurrentAccess *concurrent;
|
||||
libusb_device_handle *dev_handle;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -99,11 +113,12 @@ typedef struct
|
|||
_ccid_descriptor ccid;
|
||||
|
||||
/* 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) */
|
||||
struct usbDevice_MultiSlot_Extension *multislot_extension;
|
||||
|
||||
char disconnected;
|
||||
} _usbDevice;
|
||||
|
||||
/* The _usbDevice structure must be defined before including ccid_usb.h */
|
||||
|
@ -399,7 +414,7 @@ again_libusb:
|
|||
if ((device_bus || device_addr)
|
||||
&& ((bus_number != device_bus)
|
||||
|| (device_address != device_addr))) {
|
||||
/* not USB the device we are looking for */
|
||||
/* not the USB device we are looking for */
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -543,7 +558,7 @@ again_libusb:
|
|||
}
|
||||
else
|
||||
{
|
||||
/* if an interface number is given by HAL we
|
||||
/* if an interface number is given by udev we
|
||||
* continue with this device. */
|
||||
if (-1 == interface_number)
|
||||
{
|
||||
|
@ -701,7 +716,8 @@ again:
|
|||
usbDevice[reader_index].interface = interface;
|
||||
usbDevice[reader_index].real_nb_opened_slots = 1;
|
||||
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 */
|
||||
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.dwMaxDataRate = dw2i(device_descriptor, 23);
|
||||
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.readTimeout = DEFAULT_COM_READ_TIMEOUT;
|
||||
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 ",
|
||||
(int)reader_index);
|
||||
|
||||
if (usbDevice[reader_index].disconnected)
|
||||
{
|
||||
DEBUG_COMM("Reader disconnected");
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ZLP
|
||||
if (usbDevice[reader_index].ccid.zlp)
|
||||
{ /* Zero Length Packet */
|
||||
|
@ -860,9 +883,9 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
|
|||
|
||||
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].device_address, rv, libusb_error_name(rv));
|
||||
usbDevice[reader_index].device_address, libusb_error_name(rv));
|
||||
|
||||
if (LIBUSB_ERROR_NO_DEVICE == rv)
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
|
@ -880,18 +903,86 @@ status_t WriteUSB(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 actual_length;
|
||||
char debug_header[] = "<- 121234 ";
|
||||
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
||||
int duplicate_frame = 0;
|
||||
|
||||
if (usbDevice[reader_index].disconnected)
|
||||
{
|
||||
DEBUG_COMM("Reader disconnected");
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
|
||||
read_again:
|
||||
(void)snprintf(debug_header, sizeof(debug_header), "<- %06X ",
|
||||
(int)reader_index);
|
||||
|
||||
if (usbDevice[reader_index].multislot_extension)
|
||||
{
|
||||
/* multi slot read */
|
||||
int slot = usbDevice[reader_index].ccid.bCurrentSlotIndex;
|
||||
struct multiSlot_ConcurrentAccess *concurrent = usbDevice[reader_index].multislot_extension->concurrent;
|
||||
|
||||
rv = 0;
|
||||
pthread_mutex_lock(&concurrent[slot].mutex);
|
||||
|
||||
/* 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);
|
||||
|
@ -899,9 +990,10 @@ read_again:
|
|||
if (rv < 0)
|
||||
{
|
||||
*length = 0;
|
||||
DEBUG_CRITICAL5("read failed (%d/%d): %d %s",
|
||||
DEBUG_CRITICAL4("read failed (%d/%d): %s",
|
||||
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)
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
|
@ -910,12 +1002,14 @@ read_again:
|
|||
}
|
||||
|
||||
*length = actual_length;
|
||||
}
|
||||
|
||||
DEBUG_XXD(debug_header, buffer, *length);
|
||||
|
||||
#define BSEQ_OFFSET 6
|
||||
if ((*length >= BSEQ_OFFSET +1)
|
||||
&& (buffer[BSEQ_OFFSET] < *ccid_descriptor->pbSeq -1))
|
||||
&& (bSeq != -1)
|
||||
&& (buffer[BSEQ_OFFSET] != bSeq))
|
||||
{
|
||||
duplicate_frame++;
|
||||
if (duplicate_frame > 10)
|
||||
|
@ -923,7 +1017,7 @@ read_again:
|
|||
DEBUG_CRITICAL("Too many duplicate frame detected");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
DEBUG_INFO1("Duplicate frame detected");
|
||||
DEBUG_INFO1("Invalid frame detected");
|
||||
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 (msExt)
|
||||
{
|
||||
struct multiSlot_ConcurrentAccess *concurrent;
|
||||
|
||||
/* terminate the interrupt waiter thread */
|
||||
Multi_PollingTerminate(msExt);
|
||||
|
||||
|
@ -970,6 +1066,19 @@ status_t CloseUSB(unsigned int reader_index)
|
|||
pthread_cond_destroy(&msExt->condition);
|
||||
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 */
|
||||
free(msExt);
|
||||
|
||||
|
@ -1004,6 +1113,29 @@ status_t CloseUSB(unsigned int reader_index)
|
|||
} /* 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
|
||||
|
@ -1295,9 +1427,10 @@ int ControlUSB(int reader_index, int requesttype, int request, int value,
|
|||
|
||||
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].device_address, ret, libusb_error_name(ret));
|
||||
usbDevice[reader_index].device_address,
|
||||
libusb_error_name(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1357,7 +1490,7 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
|
|||
return IFD_COMMUNICATION_ERROR;
|
||||
}
|
||||
|
||||
usbDevice[reader_index].polling_transfer = transfer;
|
||||
atomic_store(&usbDevice[reader_index].polling_transfer, transfer);
|
||||
|
||||
while (!completed)
|
||||
{
|
||||
|
@ -1380,7 +1513,7 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
|
|||
actual_length = transfer->actual_length;
|
||||
ret = transfer->status;
|
||||
|
||||
usbDevice[reader_index].polling_transfer = NULL;
|
||||
atomic_store(&usbDevice[reader_index].polling_transfer, NULL);
|
||||
libusb_free_transfer(transfer);
|
||||
|
||||
DEBUG_PERIODIC3("after (%d) (%d)", reader_index, ret);
|
||||
|
@ -1396,9 +1529,10 @@ int InterruptRead(int reader_index, int timeout /* in ms */)
|
|||
|
||||
default:
|
||||
/* 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].device_address, ret);
|
||||
usbDevice[reader_index].device_address,
|
||||
libusb_error_name(ret));
|
||||
return_value = IFD_COMMUNICATION_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1422,8 +1556,7 @@ void InterruptStop(int reader_index)
|
|||
return;
|
||||
}
|
||||
|
||||
transfer = usbDevice[reader_index].polling_transfer;
|
||||
usbDevice[reader_index].polling_transfer = NULL;
|
||||
transfer = atomic_load(&usbDevice[reader_index].polling_transfer);
|
||||
if (transfer)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1453,6 +1586,13 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
usbDevice[msExt->reader_index].bus_number,
|
||||
usbDevice[msExt->reader_index].device_address);
|
||||
|
||||
transfer = libusb_alloc_transfer(0);
|
||||
if (NULL == transfer)
|
||||
{
|
||||
DEBUG_COMM("libusb_alloc_transfer error");
|
||||
goto end;
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
while (!msExt->terminated)
|
||||
{
|
||||
|
@ -1460,15 +1600,6 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
usbDevice[msExt->reader_index].bus_number,
|
||||
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,
|
||||
usbDevice[msExt->reader_index].dev_handle,
|
||||
usbDevice[msExt->reader_index].interrupt,
|
||||
|
@ -1480,13 +1611,13 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
rv = libusb_submit_transfer(transfer);
|
||||
if (rv)
|
||||
{
|
||||
libusb_free_transfer(transfer);
|
||||
DEBUG_COMM3("libusb_submit_transfer err %d %s", rv,
|
||||
DEBUG_COMM2("libusb_submit_transfer err %s",
|
||||
libusb_error_name(rv));
|
||||
break;
|
||||
}
|
||||
|
||||
usbDevice[msExt->reader_index].polling_transfer = transfer;
|
||||
atomic_store(&usbDevice[msExt->reader_index].polling_transfer,
|
||||
transfer);
|
||||
|
||||
completed = 0;
|
||||
while (!completed && !msExt->terminated)
|
||||
|
@ -1494,7 +1625,7 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
rv = libusb_handle_events_completed(ctx, &completed);
|
||||
if (rv < 0)
|
||||
{
|
||||
DEBUG_COMM3("libusb_handle_events err %d %s", rv,
|
||||
DEBUG_COMM2("libusb_handle_events err %s",
|
||||
libusb_error_name(rv));
|
||||
|
||||
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)
|
||||
libusb_free_transfer(transfer);
|
||||
else
|
||||
if (0 == rv)
|
||||
{
|
||||
int b, slot;
|
||||
|
||||
actual_length = transfer->actual_length;
|
||||
status = transfer->status;
|
||||
|
||||
libusb_free_transfer(transfer);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case LIBUSB_TRANSFER_COMPLETED:
|
||||
|
@ -1566,10 +1694,10 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
default:
|
||||
/* if libusb_interrupt_transfer() times out
|
||||
* 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].device_address,
|
||||
status);
|
||||
libusb_error_name(status));
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
DEBUG_CRITICAL5("Multi_PollingProc (%d/%d): error %d %s",
|
||||
if (rv != LIBUSB_ERROR_NO_DEVICE)
|
||||
DEBUG_CRITICAL4("Multi_PollingProc (%d/%d): error %s",
|
||||
usbDevice[msExt->reader_index].bus_number,
|
||||
usbDevice[msExt->reader_index].device_address,
|
||||
rv, libusb_error_name(rv));
|
||||
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 */
|
||||
|
@ -1616,6 +1750,7 @@ static void *Multi_PollingProc(void *p_ext)
|
|||
/* Unlock */
|
||||
pthread_mutex_unlock(&msExt->mutex);
|
||||
|
||||
end:
|
||||
/* Now exit */
|
||||
DEBUG_COMM3("Multi_PollingProc (%d/%d): Thread terminated",
|
||||
usbDevice[msExt->reader_index].bus_number,
|
||||
|
@ -1639,7 +1774,7 @@ static void Multi_PollingTerminate(struct usbDevice_MultiSlot_Extension *msExt)
|
|||
{
|
||||
msExt->terminated = TRUE;
|
||||
|
||||
transfer = usbDevice[msExt->reader_index].polling_transfer;
|
||||
transfer = atomic_load(&usbDevice[msExt->reader_index].polling_transfer);
|
||||
|
||||
if (transfer)
|
||||
{
|
||||
|
@ -1668,9 +1803,9 @@ static int Multi_InterruptRead(int reader_index, int timeout /* in ms */)
|
|||
|
||||
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)
|
||||
return 0;
|
||||
return IFD_NO_SUCH_DEVICE;
|
||||
|
||||
DEBUG_PERIODIC3("Multi_InterruptRead (%d), timeout: %d ms",
|
||||
reader_index, timeout);
|
||||
|
@ -1708,9 +1843,9 @@ again:
|
|||
/* Don't forget to unlock the 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)
|
||||
return 0;
|
||||
return IFD_NO_SUCH_DEVICE;
|
||||
|
||||
/* Not stopped */
|
||||
if (status == LIBUSB_TRANSFER_COMPLETED)
|
||||
|
@ -1762,6 +1897,87 @@ static void Multi_InterruptStop(int reader_index)
|
|||
} /* 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
|
||||
|
@ -1770,6 +1986,7 @@ static void Multi_InterruptStop(int reader_index)
|
|||
static struct usbDevice_MultiSlot_Extension *Multi_CreateFirstSlot(int reader_index)
|
||||
{
|
||||
struct usbDevice_MultiSlot_Extension *msExt;
|
||||
struct multiSlot_ConcurrentAccess *concurrent;
|
||||
|
||||
/* Allocate a new extension buffer */
|
||||
msExt = malloc(sizeof(struct usbDevice_MultiSlot_Extension));
|
||||
|
@ -1779,17 +1996,38 @@ static struct usbDevice_MultiSlot_Extension *Multi_CreateFirstSlot(int reader_in
|
|||
/* Remember the 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->transfer = NULL;
|
||||
|
||||
/* Create mutex and condition object for the interrupt polling */
|
||||
pthread_mutex_init(&msExt->mutex, 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 */
|
||||
pthread_create(&msExt->thread_proc, NULL, Multi_PollingProc, msExt);
|
||||
|
||||
pthread_create(&msExt->thread_concurrent, NULL, Multi_ReadProc, msExt);
|
||||
|
||||
return msExt;
|
||||
} /* Multi_CreateFirstSlot */
|
||||
|
||||
|
|
|
@ -27,9 +27,10 @@ status_t WriteUSB(unsigned int reader_index, unsigned int length,
|
|||
unsigned char *Buffer);
|
||||
|
||||
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 DisconnectUSB(unsigned int reader_index);
|
||||
|
||||
#include <libusb.h>
|
||||
/*@null@*/ const struct libusb_interface *get_ccid_usb_interface(
|
||||
|
|
|
@ -95,6 +95,7 @@ RESPONSECODE CmdPowerOn(unsigned int reader_index, unsigned int * nlength,
|
|||
unsigned char buffer[], int voltage)
|
||||
{
|
||||
unsigned char cmd[10];
|
||||
int bSeq;
|
||||
status_t res;
|
||||
int length, count = 1;
|
||||
unsigned int atr_len;
|
||||
|
@ -218,10 +219,11 @@ check_again:
|
|||
init_voltage = voltage;
|
||||
|
||||
again:
|
||||
bSeq = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[0] = 0x62; /* IccPowerOn */
|
||||
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
|
||||
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
|
||||
cmd[6] = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[6] = bSeq;
|
||||
cmd[7] = voltage;
|
||||
cmd[8] = cmd[9] = 0; /* RFU */
|
||||
|
||||
|
@ -232,7 +234,7 @@ again:
|
|||
/* needed if we go back after a switch to ISO mode */
|
||||
*nlength = length;
|
||||
|
||||
res = ReadPort(reader_index, nlength, buffer);
|
||||
res = ReadPort(reader_index, nlength, buffer, bSeq);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
if (*nlength < CCID_RESPONSE_HEADER_SIZE)
|
||||
|
@ -947,6 +949,7 @@ RESPONSECODE CmdEscapeCheck(unsigned int reader_index,
|
|||
int mayfail)
|
||||
{
|
||||
unsigned char *cmd_in, *cmd_out;
|
||||
int bSeq;
|
||||
status_t res;
|
||||
unsigned int length_in, length_out;
|
||||
RESPONSECODE return_value = IFD_SUCCESS;
|
||||
|
@ -977,10 +980,11 @@ again:
|
|||
goto end;
|
||||
}
|
||||
|
||||
bSeq = (*ccid_descriptor->pbSeq)++;
|
||||
cmd_in[0] = 0x6B; /* PC_to_RDR_Escape */
|
||||
i2dw(length_in - 10, cmd_in+1); /* dwLength */
|
||||
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 */
|
||||
|
||||
/* copy the command */
|
||||
|
@ -1000,7 +1004,7 @@ again:
|
|||
|
||||
time_request:
|
||||
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
|
||||
* This (generally) happens only for the first command sent to the reader
|
||||
|
@ -1072,6 +1076,7 @@ end:
|
|||
RESPONSECODE CmdPowerOff(unsigned int reader_index)
|
||||
{
|
||||
unsigned char cmd[10];
|
||||
int bSeq;
|
||||
status_t res;
|
||||
unsigned int length;
|
||||
RESPONSECODE return_value = IFD_SUCCESS;
|
||||
|
@ -1124,17 +1129,18 @@ RESPONSECODE CmdPowerOff(unsigned int reader_index)
|
|||
}
|
||||
#endif
|
||||
|
||||
bSeq = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[0] = 0x63; /* IccPowerOff */
|
||||
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
|
||||
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
|
||||
cmd[6] = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[6] = bSeq;
|
||||
cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
|
||||
|
||||
res = WritePort(reader_index, sizeof(cmd), cmd);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
length = sizeof(cmd);
|
||||
res = ReadPort(reader_index, &length, cmd);
|
||||
res = ReadPort(reader_index, &length, cmd, bSeq);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
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[])
|
||||
{
|
||||
unsigned char cmd[10];
|
||||
int bSeq;
|
||||
status_t res;
|
||||
unsigned int length;
|
||||
RESPONSECODE return_value = IFD_SUCCESS;
|
||||
|
@ -1247,17 +1254,18 @@ again_status:
|
|||
InterruptRead(reader_index, 10);
|
||||
#endif
|
||||
|
||||
bSeq = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[0] = 0x65; /* GetSlotStatus */
|
||||
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0; /* dwLength */
|
||||
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
|
||||
cmd[6] = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[6] = bSeq;
|
||||
cmd[7] = cmd[8] = cmd[9] = 0; /* RFU */
|
||||
|
||||
res = WritePort(reader_index, sizeof(cmd), cmd);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
length = SIZE_GET_SLOT_STATUS;
|
||||
res = ReadPort(reader_index, &length, buffer);
|
||||
res = ReadPort(reader_index, &length, buffer, bSeq);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
if (length < CCID_RESPONSE_HEADER_SIZE)
|
||||
|
@ -1546,7 +1554,7 @@ time_request_ICCD_B:
|
|||
|
||||
time_request:
|
||||
length = sizeof(cmd);
|
||||
ret = ReadPort(reader_index, &length, cmd);
|
||||
ret = ReadPort(reader_index, &length, cmd, -1);
|
||||
|
||||
/* restore the original value of read 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 char cmd[10+length]; /* CCID + APDU buffer */
|
||||
int bSeq;
|
||||
_ccid_descriptor *ccid_descriptor = get_ccid_descriptor(reader_index);
|
||||
status_t res;
|
||||
|
||||
DEBUG_COMM2("length: %d bytes", length);
|
||||
|
||||
bSeq = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[0] = 0x61; /* SetParameters */
|
||||
i2dw(length, cmd+1); /* APDU length */
|
||||
cmd[5] = ccid_descriptor->bCurrentSlotIndex; /* slot number */
|
||||
cmd[6] = (*ccid_descriptor->pbSeq)++;
|
||||
cmd[6] = bSeq;
|
||||
cmd[7] = protocol; /* bProtocolNum */
|
||||
cmd[8] = cmd[9] = 0; /* RFU */
|
||||
|
||||
|
@ -2322,7 +2332,7 @@ RESPONSECODE SetParameters(unsigned int reader_index, char protocol,
|
|||
CHECK_STATUS(res)
|
||||
|
||||
length = sizeof(cmd);
|
||||
res = ReadPort(reader_index, &length, cmd);
|
||||
res = ReadPort(reader_index, &length, cmd, bSeq);
|
||||
CHECK_STATUS(res)
|
||||
|
||||
if (length < CCID_RESPONSE_HEADER_SIZE)
|
||||
|
|
61
src/debug.h
61
src/debug.h
|
@ -73,53 +73,46 @@ extern int LogLevel;
|
|||
#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_INFO_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size)
|
||||
#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, 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) do { if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, msg, buffer, size); } while (0)
|
||||
|
||||
#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 */
|
||||
#define DEBUG_CRITICAL(fmt) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log1(PCSC_LOG_CRITICAL, fmt)
|
||||
|
||||
#define DEBUG_CRITICAL2(fmt, data) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log2(PCSC_LOG_CRITICAL, fmt, data)
|
||||
|
||||
#define DEBUG_CRITICAL3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log3(PCSC_LOG_CRITICAL, fmt, data1, data2)
|
||||
|
||||
#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)
|
||||
#define DEBUG_CRITICAL(fmt) TO_PCSCD_LOG(fmt, CRITICAL, CRITICAL)
|
||||
#define DEBUG_CRITICAL2(fmt, data) TO_PCSCD_LOG2(fmt, data, CRITICAL, CRITICAL)
|
||||
#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_CRITICAL5(fmt, data1, data2, data3, data4) TO_PCSCD_LOG5(fmt, data1, data2, data3, data4, CRITICAL, CRITICAL)
|
||||
|
||||
/* 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_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)
|
||||
#define DEBUG_INFO_XXD(msg, buffer, size) do { if (LogLevel & DEBUG_LEVEL_INFO) log_xxd(PCSC_LOG_INFO, msg, buffer, size); } while (0)
|
||||
|
||||
/* DEBUG_PERIODIC */
|
||||
#define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt)
|
||||
|
||||
#define DEBUG_PERIODIC2(fmt, data) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log2(PCSC_LOG_DEBUG, fmt, data)
|
||||
|
||||
#define DEBUG_PERIODIC3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
|
||||
#define DEBUG_PERIODIC(fmt) TO_PCSCD_LOG(fmt, PERIODIC, DEBUG)
|
||||
#define DEBUG_PERIODIC2(fmt, data) TO_PCSCD_LOG2(fmt, data, PERIODIC, DEBUG)
|
||||
#define DEBUG_PERIODIC3(fmt, data1, data2) TO_PCSCD_LOG3(fmt, data1, data2, PERIODIC, DEBUG)
|
||||
|
||||
/* DEBUG_COMM */
|
||||
#define DEBUG_COMM(fmt) if (LogLevel & DEBUG_LEVEL_COMM) Log1(PCSC_LOG_DEBUG, fmt)
|
||||
|
||||
#define DEBUG_COMM2(fmt, data) if (LogLevel & DEBUG_LEVEL_COMM) Log2(PCSC_LOG_DEBUG, fmt, data)
|
||||
|
||||
#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)
|
||||
#define DEBUG_COMM(fmt) TO_PCSCD_LOG(fmt, COMM, DEBUG)
|
||||
#define DEBUG_COMM2(fmt, data) TO_PCSCD_LOG2(fmt, data, COMM, DEBUG)
|
||||
#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)
|
||||
|
||||
/* 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
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ typedef enum {
|
|||
#define ClosePort CloseSerial
|
||||
#define ReadPort ReadSerial
|
||||
#define WritePort WriteSerial
|
||||
#define DisconnectPort DisconnectSerial
|
||||
#include "ccid_serial.h"
|
||||
|
||||
#else
|
||||
|
@ -105,6 +106,7 @@ typedef enum {
|
|||
#define ClosePort CloseUSB
|
||||
#define ReadPort ReadUSB
|
||||
#define WritePort WriteUSB
|
||||
#define DisconnectPort DisconnectUSB
|
||||
#include "ccid_usb.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -490,7 +490,11 @@ EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
|
|||
case TAG_IFD_SLOT_THREAD_SAFE:
|
||||
if (*Length >= 1)
|
||||
{
|
||||
_ccid_descriptor *ccid_desc = get_ccid_descriptor(reader_index);
|
||||
*Length = 1;
|
||||
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
|
||||
|
@ -602,6 +606,13 @@ EXTERNAL RESPONSECODE IFDHGetCapabilities(DWORD Lun, DWORD Tag,
|
|||
break;
|
||||
#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:
|
||||
{
|
||||
_ccid_descriptor *ccid_desc;
|
||||
|
@ -661,6 +672,7 @@ EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
|
|||
* IFD_ERROR_VALUE_READ_ONLY
|
||||
*/
|
||||
|
||||
RESPONSECODE return_value = IFD_SUCCESS;
|
||||
(void)Length;
|
||||
(void)Value;
|
||||
|
||||
|
@ -672,7 +684,20 @@ EXTERNAL RESPONSECODE IFDHSetCapabilities(DWORD Lun, DWORD Tag,
|
|||
DEBUG_INFO4("tag: 0x" DWORD_X ", %s (lun: " DWORD_X ")", Tag,
|
||||
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 */
|
||||
|
||||
|
||||
|
@ -791,10 +816,7 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
|
|||
/* Do not send CCID command SetParameters or PPS to the CCID
|
||||
* The CCID will do this himself */
|
||||
if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
|
||||
{
|
||||
DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
return IFD_COMMUNICATION_ERROR;
|
||||
|
||||
end:
|
||||
/* T=1 */
|
||||
if (SCARD_PROTOCOL_T1 == Protocol)
|
||||
{
|
||||
|
@ -1046,10 +1069,15 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
|
|||
|
||||
DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
|
||||
|
||||
if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
|
||||
DEBUG_COMM("Skip SetParameters");
|
||||
else
|
||||
{
|
||||
ret = SetParameters(reader_index, 1, sizeof(param), param);
|
||||
if (IFD_SUCCESS != ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* T=0 */
|
||||
{
|
||||
|
@ -1085,14 +1113,18 @@ EXTERNAL RESPONSECODE IFDHSetProtocolParameters(DWORD Lun, DWORD Protocol,
|
|||
ccid_desc->readTimeout = T0_card_timeout(f, d, param[2] /* TC1 */,
|
||||
param[3] /* TC2 */, ccid_desc->dwDefaultClock);
|
||||
|
||||
DEBUG_COMM2("Communication timeout: %d ms", ccid_desc->readTimeout);
|
||||
DEBUG_COMM2("Timeout: %d ms", ccid_desc->readTimeout);
|
||||
|
||||
if (ccid_desc->dwFeatures & CCID_CLASS_AUTO_PPS_PROP)
|
||||
DEBUG_COMM("Skip SetParameters");
|
||||
else
|
||||
{
|
||||
ret = SetParameters(reader_index, 0, sizeof(param), param);
|
||||
if (IFD_SUCCESS != ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
/* set IFSC & IFSD in T=1 */
|
||||
if ((SCARD_PROTOCOL_T1 == Protocol)
|
||||
&& (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;
|
||||
|
||||
/* send the command */
|
||||
return_value = CmdPowerOff(reader_index);
|
||||
if (IFD_NO_SUCH_DEVICE == return_value)
|
||||
goto end;
|
||||
if (IFD_SUCCESS != CmdPowerOff(reader_index))
|
||||
{
|
||||
DEBUG_CRITICAL("PowerDown failed");
|
||||
|
@ -1469,6 +1504,10 @@ EXTERNAL RESPONSECODE IFDHControl(DWORD Lun, DWORD dwControlCode,
|
|||
allowed = TRUE;
|
||||
}
|
||||
|
||||
/* allow APDU exchange with this reader without a card in the field */
|
||||
if (HID_OMNIKEY_5427CK == readerID)
|
||||
allowed = TRUE;
|
||||
|
||||
if (!allowed)
|
||||
{
|
||||
DEBUG_INFO1("ifd exchange (Escape command) not allowed");
|
||||
|
@ -1915,6 +1954,12 @@ EXTERNAL RESPONSECODE IFDHICCPresence(DWORD Lun)
|
|||
/* set back the old LogLevel */
|
||||
LogLevel = oldLogLevel;
|
||||
|
||||
if (IFD_NO_SUCH_DEVICE == return_value)
|
||||
{
|
||||
return_value = IFD_ICC_NOT_PRESENT;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (return_value != IFD_SUCCESS)
|
||||
return return_value;
|
||||
|
||||
|
|
|
@ -159,7 +159,8 @@ int t1_transceive(t1_state_t * t1, unsigned int dad,
|
|||
{
|
||||
ct_buf_t sbuf, rbuf, tbuf;
|
||||
unsigned char sdata[T1_BUFFER_SIZE], sblk[5];
|
||||
unsigned int slen, retries, resyncs;
|
||||
unsigned int slen, resyncs;
|
||||
int retries;
|
||||
size_t last_send = 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;
|
||||
unsigned char sdata[T1_BUFFER_SIZE];
|
||||
unsigned int slen;
|
||||
unsigned int retries;
|
||||
int retries;
|
||||
size_t snd_len;
|
||||
int n;
|
||||
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 */
|
||||
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--;
|
||||
/* ISO 7816-3 Rule 7.4.2 */
|
||||
if (retries <= 0)
|
||||
if (retries < 0)
|
||||
goto error;
|
||||
|
||||
/* Send the block */
|
||||
n = t1_xcv(t1, sdata, slen, sizeof(sdata));
|
||||
|
||||
if (-1 == n)
|
||||
{
|
||||
DEBUG_CRITICAL("fatal: transmit/receive failed");
|
||||
|
|
|
@ -28,13 +28,14 @@
|
|||
#include "debug.h"
|
||||
|
||||
int ReaderIndex[CCID_DRIVER_MAX_READERS];
|
||||
#define FREE_ENTRY -42
|
||||
|
||||
void InitReaderIndex(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
|
||||
ReaderIndex[i] = -1;
|
||||
ReaderIndex[i] = FREE_ENTRY;
|
||||
} /* InitReaderIndex */
|
||||
|
||||
int GetNewReaderIndex(const int Lun)
|
||||
|
@ -53,7 +54,7 @@ int GetNewReaderIndex(const int Lun)
|
|||
}
|
||||
|
||||
for (i=0; i<CCID_DRIVER_MAX_READERS; i++)
|
||||
if (-1 == ReaderIndex[i])
|
||||
if (FREE_ENTRY == ReaderIndex[i])
|
||||
{
|
||||
ReaderIndex[i] = Lun;
|
||||
return i;
|
||||
|
@ -77,7 +78,7 @@ int LunToReaderIndex(const int Lun)
|
|||
|
||||
void ReleaseReaderIndex(const int index)
|
||||
{
|
||||
ReaderIndex[index] = -1;
|
||||
ReaderIndex[index] = FREE_ENTRY;
|
||||
} /* ReleaseReaderIndex */
|
||||
|
||||
/* Read a non aligned 16-bit integer */
|
||||
|
|
Loading…
Reference in New Issue