New upstream version 1.9.1

This commit is contained in:
Ludovic Rousseau 2021-02-16 17:37:49 +01:00
parent f9c7c07a4d
commit a8f556e1c1
36 changed files with 1210 additions and 287 deletions

View File

@ -1,3 +1,18 @@
1.9.1: Ludovic Rousseau
16 February 2021
- Do not (possibly) lock a reader if allocating hCard fails
- Fix a hang in SCardTransmit()
- Do not report an error if the wrong interface is used by the driver
- Update reader state when a card is removed during an exchange
- readerfactory: Make sure a freed Reader Context is not accessed
- PHSetProtocol(): supports T=0&1 cards on T=0 reader
- hotplug-libusb:
. support CCIDCLASSDRIVER
. add interface name to reader name
. remove obsolete libhal scheme
- Some other minor improvements
1.9.0: Ludovic Rousseau 1.9.0: Ludovic Rousseau
14 June 2020 14 June 2020
- SCardEndTransaction(): greatly improve performances (x300) - SCardEndTransaction(): greatly improve performances (x300)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -164,7 +164,7 @@ DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/src/PCSC/pcsclite.h.in AUTHORS COPYING ChangeLog \ $(top_srcdir)/src/PCSC/pcsclite.h.in AUTHORS COPYING ChangeLog \
INSTALL NEWS README TODO ar-lib compile config.guess \ INSTALL NEWS README TODO ar-lib compile config.guess \
config.sub install-sh ltmain.sh missing ylwrap config.sub depcomp install-sh ltmain.sh missing ylwrap
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION) distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir) top_distdir = $(distdir)
@ -203,6 +203,8 @@ am__relativize = \
GZIP_ENV = --best GZIP_ENV = --best
DIST_ARCHIVES = $(distdir).tar.bz2 DIST_ARCHIVES = $(distdir).tar.bz2
DIST_TARGETS = dist-bzip2 DIST_TARGETS = dist-bzip2
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -689,7 +691,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \ --srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \

13
aclocal.m4 vendored
View File

@ -1,4 +1,4 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*- # generated automatically by aclocal 1.16.3 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2020 Free Software Foundation, Inc.
@ -311,7 +311,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.2], [], m4_if([$1], [1.16.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -327,7 +327,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.2])dnl [AM_AUTOMAKE_VERSION([1.16.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@ -1093,12 +1093,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then if test x"${MISSING+set}" != xset; then
case $am_aux_dir in MISSING="\${SHELL} '$am_aux_dir/missing'"
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi fi
# Use eval to expand $SHELL # Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then if eval "$MISSING --is-lightweight"; then

27
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for pcsc-lite 1.9.0. # Generated by GNU Autoconf 2.69 for pcsc-lite 1.9.1.
# #
# #
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='pcsc-lite' PACKAGE_NAME='pcsc-lite'
PACKAGE_TARNAME='pcsc-lite' PACKAGE_TARNAME='pcsc-lite'
PACKAGE_VERSION='1.9.0' PACKAGE_VERSION='1.9.1'
PACKAGE_STRING='pcsc-lite 1.9.0' PACKAGE_STRING='pcsc-lite 1.9.1'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='' PACKAGE_URL=''
@ -1395,7 +1395,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures pcsc-lite 1.9.0 to adapt to many kinds of systems. \`configure' configures pcsc-lite 1.9.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1466,7 +1466,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of pcsc-lite 1.9.0:";; short | recursive ) echo "Configuration of pcsc-lite 1.9.1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1618,7 +1618,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
pcsc-lite configure 1.9.0 pcsc-lite configure 1.9.1
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -2094,7 +2094,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by pcsc-lite $as_me 1.9.0, which was It was created by pcsc-lite $as_me 1.9.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2648,12 +2648,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
am_aux_dir=`cd "$ac_aux_dir" && pwd` am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then if test x"${MISSING+set}" != xset; then
case $am_aux_dir in MISSING="\${SHELL} '$am_aux_dir/missing'"
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi fi
# Use eval to expand $SHELL # Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then if eval "$MISSING --is-lightweight"; then
@ -2958,7 +2953,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='pcsc-lite' PACKAGE='pcsc-lite'
VERSION='1.9.0' VERSION='1.9.1'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -16197,7 +16192,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by pcsc-lite $as_me 1.9.0, which was This file was extended by pcsc-lite $as_me 1.9.1, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -16263,7 +16258,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
pcsc-lite config.status 1.9.0 pcsc-lite config.status 1.9.1
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -3,7 +3,7 @@
AC_PREREQ([2.69]) AC_PREREQ([2.69])
AC_INIT([pcsc-lite],[1.9.0]) AC_INIT([pcsc-lite],[1.9.1])
AC_CONFIG_SRCDIR(src/pcscdaemon.c) AC_CONFIG_SRCDIR(src/pcscdaemon.c)
AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip) AM_INIT_AUTOMAKE(1.8 dist-bzip2 no-dist-gzip)
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])

View File

@ -3,7 +3,7 @@
SUBDIRS = . example SUBDIRS = . example
doc_DATA = \ doc_DATA = \
README.DAEMON README.polkit README.polkit
man_MANS = pcscd.8 reader.conf.5 man_MANS = pcscd.8 reader.conf.5
man_in = pcscd.8.in reader.conf.5.in man_in = pcscd.8.in reader.conf.5.in

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -375,7 +375,7 @@ usbdropdir = @usbdropdir@
usbdropdir_exp = @usbdropdir_exp@ usbdropdir_exp = @usbdropdir_exp@
SUBDIRS = . example SUBDIRS = . example
doc_DATA = \ doc_DATA = \
README.DAEMON README.polkit README.polkit
man_MANS = pcscd.8 reader.conf.5 man_MANS = pcscd.8 reader.conf.5
man_in = pcscd.8.in reader.conf.5.in man_in = pcscd.8.in reader.conf.5.in

View File

@ -1,15 +0,0 @@
To install pcsc-lite as a daemon that is automatically started up at
boot you must use the following command in one of your rc files or add an
entry to your rc.d/init.d/ directory for Redhat/Mandrake users.
nohup /usr/local/pcsc/bin/pcscd </dev/null >> /var/log/pcscd.log 2>&1 &
If you installed using ./configure --enable-daemon then just use:
pcscd
Mac OS X Users may create a Startup by doing the following:
Copy the files SmartcardServices and StartupParameters.plist from the
/etc directory to /System/Library/StartupItems/SmartcardServices.
( You will have to create the SmartcardServices directory )

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.

4
ltmain.sh Normal file → Executable file
View File

@ -31,7 +31,7 @@
PROGRAM=libtool PROGRAM=libtool
PACKAGE=libtool PACKAGE=libtool
VERSION="2.4.6 Debian-2.4.6-14" VERSION="2.4.6 Debian-2.4.6-15"
package_revision=2.4.6 package_revision=2.4.6
@ -2141,7 +2141,7 @@ include the following information:
compiler: $LTCC compiler: $LTCC
compiler flags: $LTCFLAGS compiler flags: $LTCFLAGS
linker: $LD (gnu? $with_gnu_ld) linker: $LD (gnu? $with_gnu_ld)
version: $progname $scriptversion Debian-2.4.6-14 version: $progname $scriptversion Debian-2.4.6-15
automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.

View File

@ -279,7 +279,7 @@ extern const SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci;
#define INFINITE 0xFFFFFFFF /**< Infinite timeout */ #define INFINITE 0xFFFFFFFF /**< Infinite timeout */
#endif #endif
#define PCSCLITE_VERSION_NUMBER "1.9.0" /**< Current version */ #define PCSCLITE_VERSION_NUMBER "1.9.1" /**< Current version */
/** Maximum readers context (a slot is count as a reader) */ /** Maximum readers context (a slot is count as a reader) */
#define PCSCLITE_MAX_READERS_CONTEXTS 16 #define PCSCLITE_MAX_READERS_CONTEXTS 16

View File

@ -75,15 +75,15 @@ short ATRDecodeAtr(int *availableProtocols, int *currentProtocol,
LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength); LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
#endif #endif
if (dwLength < 2)
return 0; /** @retval 0 Atr must have TS and T0 */
/* /*
* Zero out the bitmasks * Zero out the bitmasks
*/ */
*availableProtocols = SCARD_PROTOCOL_UNDEFINED; *availableProtocols = SCARD_PROTOCOL_UNDEFINED;
*currentProtocol = SCARD_PROTOCOL_UNDEFINED; *currentProtocol = SCARD_PROTOCOL_UNDEFINED;
if (dwLength < 2)
return 0; /** @retval 0 Atr must have TS and T0 */
/* /*
* Decode the TS byte * Decode the TS byte
*/ */
@ -218,8 +218,8 @@ short ATRDecodeAtr(int *availableProtocols, int *currentProtocol,
} }
#ifdef ATR_DEBUG #ifdef ATR_DEBUG
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d", Log3(PCSC_LOG_DEBUG, "CurrentProtocol: T=%d, AvailableProtocols: %d",
*currentProtocol, *availableProtocols); *currentProtocol - SCARD_PROTOCOL_T0, *availableProtocols);
#endif #endif
return 1; /** @retval 1 Success */ return 1; /** @retval 1 Success */

View File

@ -39,6 +39,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __atrhandler_h__ #ifndef __atrhandler_h__
#define __atrhandler_h__ #define __atrhandler_h__
#include "wintypes.h"
/* /*
* Decodes the ATR * Decodes the ATR
*/ */

View File

@ -35,6 +35,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __configfile_h__ #ifndef __configfile_h__
#define __configfile_h__ #define __configfile_h__
#include "readerfactory.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {

View File

@ -38,6 +38,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __dyn_generic_h__ #ifndef __dyn_generic_h__
#define __dyn_generic_h__ #define __dyn_generic_h__
#include "wintypes.h"
LONG DYN_LoadLibrary(void **, char *); LONG DYN_LoadLibrary(void **, char *);
LONG DYN_CloseLibrary(void **); LONG DYN_CloseLibrary(void **);
LONG DYN_GetAddress(void *, /*@out@*/ void **, const char *, int); LONG DYN_GetAddress(void *, /*@out@*/ void **, const char *, int);

View File

@ -104,7 +104,7 @@ LONG EHUnregisterClientForEvent(int32_t filedes)
{ {
LONG rv = EHTryToUnregisterClientForEvent(filedes); LONG rv = EHTryToUnregisterClientForEvent(filedes);
if (rv < 0) if (rv != SCARD_S_SUCCESS)
Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes); Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes);
return rv; return rv;

View File

@ -41,6 +41,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h> #include <stdint.h>
#include "pcsclite.h"
#include "readerfactory.h"
#include "wintypes.h"
/** /**
* Define an exported public reader state structure so each * Define an exported public reader state structure so each
* application gets instant notification of changes in state. * application gets instant notification of changes in state.

View File

@ -38,6 +38,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __hotplug_h__ #ifndef __hotplug_h__
#define __hotplug_h__ #define __hotplug_h__
#include "wintypes.h"
#ifndef PCSCLITE_HP_DROPDIR #ifndef PCSCLITE_HP_DROPDIR
#define PCSCLITE_HP_DROPDIR "/usr/local/pcsc/drivers/" #define PCSCLITE_HP_DROPDIR "/usr/local/pcsc/drivers/"
#endif #endif

View File

@ -78,6 +78,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
extern char Add_Interface_In_Name;
extern char Add_Serial_In_Name; extern char Add_Serial_In_Name;
/* we use the default libusb context */ /* we use the default libusb context */
@ -106,6 +107,7 @@ static struct _driverTracker
char *libraryPath; char *libraryPath;
char *readerName; char *readerName;
int ifdCapabilities; int ifdCapabilities;
char *CFBundleName;
} *driverTracker = NULL; } *driverTracker = NULL;
#define DRIVER_TRACKER_SIZE_STEP 8 #define DRIVER_TRACKER_SIZE_STEP 8
@ -121,8 +123,10 @@ static struct _readerTracker
static LONG HPAddHotPluggable(struct libusb_device *dev, static LONG HPAddHotPluggable(struct libusb_device *dev,
struct libusb_device_descriptor desc, struct libusb_device_descriptor desc,
const char bus_device[], int interface, const char bus_device[],
struct _driverTracker *driver); const struct libusb_interface *idesc,
struct _driverTracker *driver,
struct _driverTracker *classdriver);
static LONG HPRemoveHotPluggable(int reader_index); static LONG HPRemoveHotPluggable(int reader_index);
static LONG HPReadBundleValues(void) static LONG HPReadBundleValues(void)
@ -170,6 +174,7 @@ static LONG HPReadBundleValues(void)
list_t *manuIDs, *productIDs, *readerNames; list_t *manuIDs, *productIDs, *readerNames;
char *libraryPath; char *libraryPath;
int ifdCapabilities; int ifdCapabilities;
char *CFBundleName;
/* /*
* The bundle exists - let's form a full path name and get the * The bundle exists - let's form a full path name and get the
@ -200,6 +205,14 @@ static LONG HPReadBundleValues(void)
GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs) GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames) GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
/* Get CFBundleName */
rv = LTPBundleFindValueWithKey(&plist, PCSCLITE_HP_CFBUNDLE_NAME,
&values);
if (rv)
CFBundleName = NULL;
else
CFBundleName = strdup(list_get_at(values, 0));
/* while we find a nth ifdVendorID in Info.plist */ /* while we find a nth ifdVendorID in Info.plist */
for (alias=0; alias<list_size(manuIDs); alias++) for (alias=0; alias<list_size(manuIDs); alias++)
{ {
@ -218,6 +231,7 @@ static LONG HPReadBundleValues(void)
driverTracker[listCount].bundleName = strdup(currFP->d_name); driverTracker[listCount].bundleName = strdup(currFP->d_name);
driverTracker[listCount].libraryPath = strdup(fullLibPath); driverTracker[listCount].libraryPath = strdup(fullLibPath);
driverTracker[listCount].ifdCapabilities = ifdCapabilities; driverTracker[listCount].ifdCapabilities = ifdCapabilities;
driverTracker[listCount].CFBundleName = CFBundleName;
#ifdef DEBUG_HOTPLUG #ifdef DEBUG_HOTPLUG
Log2(PCSC_LOG_INFO, "Found driver for: %s", Log2(PCSC_LOG_INFO, "Found driver for: %s",
@ -255,6 +269,7 @@ static LONG HPReadBundleValues(void)
driverTracker[i].libraryPath = NULL; driverTracker[i].libraryPath = NULL;
driverTracker[i].readerName = NULL; driverTracker[i].readerName = NULL;
driverTracker[i].ifdCapabilities = 0; driverTracker[i].ifdCapabilities = 0;
driverTracker[i].CFBundleName = NULL;
} }
} }
} }
@ -278,6 +293,44 @@ static LONG HPReadBundleValues(void)
return driverSize; return driverSize;
} }
static struct _driverTracker *get_driver(unsigned int idVendor,
unsigned int idProduct, struct _driverTracker **classdriver)
{
int i;
static struct _driverTracker *driver;
#ifdef DEBUG_HOTPLUG
Log3(PCSC_LOG_DEBUG,
"Looking for a driver for VID: 0x%04X, PID: 0x%04X",
idVendor, idProduct);
#endif
*classdriver = NULL;
driver = NULL;
/* check if the device is supported by one driver */
for (i=0; i<driverSize; i++)
{
if (driverTracker[i].libraryPath != NULL &&
idVendor == driverTracker[i].manuID &&
idProduct == driverTracker[i].productID)
{
if ((driverTracker[i].CFBundleName != NULL)
&& (0 == strcmp(driverTracker[i].CFBundleName, "CCIDCLASSDRIVER")))
*classdriver = &driverTracker[i];
else
/* it is not a CCID Class driver */
driver = &driverTracker[i];
}
}
/* if we found a specific driver */
if (driver)
return driver;
/* else return the Class driver (if any) */
return *classdriver;
}
static void HPRescanUsbBus(void) static void HPRescanUsbBus(void)
{ {
int i, j; int i, j;
@ -292,7 +345,8 @@ static void HPRescanUsbBus(void)
cnt = libusb_get_device_list(ctx, &devs); cnt = libusb_get_device_list(ctx, &devs);
if (cnt < 0) if (cnt < 0)
{ {
Log1(PCSC_LOG_CRITICAL, "libusb_get_device_list() failed\n"); Log2(PCSC_LOG_CRITICAL, "libusb_get_device_list() failed: %s",
libusb_error_name(cnt));
return; return;
} }
@ -304,78 +358,76 @@ static void HPRescanUsbBus(void)
struct libusb_config_descriptor *config_desc; struct libusb_config_descriptor *config_desc;
uint8_t bus_number = libusb_get_bus_number(dev); uint8_t bus_number = libusb_get_bus_number(dev);
uint8_t device_address = libusb_get_device_address(dev); uint8_t device_address = libusb_get_device_address(dev);
struct _driverTracker *driver, *classdriver;
int interface;
int r = libusb_get_device_descriptor(dev, &desc); int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) if (r < 0)
{ {
Log3(PCSC_LOG_ERROR, "failed to get device descriptor for %d/%d", Log4(PCSC_LOG_ERROR,
bus_number, device_address); "failed to get device descriptor for %d/%d: %s",
bus_number, device_address, libusb_error_name(r));
continue; continue;
} }
r = libusb_get_active_config_descriptor(dev, &config_desc); r = libusb_get_active_config_descriptor(dev, &config_desc);
if (r < 0) if (r < 0)
{ {
Log3(PCSC_LOG_ERROR, "failed to get device config for %d/%d", Log4(PCSC_LOG_ERROR, "failed to get device config for %d/%d: %s",
bus_number, device_address); bus_number, device_address, libusb_error_name(r));
continue; continue;
} }
/* check if the device is supported by one driver */ driver = get_driver(desc.idVendor, desc.idProduct, &classdriver);
for (i=0; i<driverSize; i++) if (NULL == driver)
{ {
if (driverTracker[i].libraryPath != NULL && /* not a smart card reader */
desc.idVendor == driverTracker[i].manuID && #ifdef DEBUG_HOTPLUG
desc.idProduct == driverTracker[i].productID) Log3(PCSC_LOG_DEBUG, "%d/%d is not a supported smart card reader",
bus_number, device_address);
#endif
continue;
}
#ifdef DEBUG_HOTPLUG
Log3(PCSC_LOG_DEBUG, "Found matching USB device: %d:%d",
bus_number, device_address);
#endif
for (interface = 0; interface < config_desc->bNumInterfaces;
interface++)
{
int newreader;
/* A known device has been found */
snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d:%d",
bus_number, device_address, interface);
bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
newreader = TRUE;
/* Check if the reader is a new one */
for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
{ {
int interface; if (strncmp(readerTracker[j].bus_device,
#ifdef DEBUG_HOTPLUG
Log3(PCSC_LOG_DEBUG, "Found matching USB device: %d:%d",
bus_number, device_address);
#endif
for (interface = 0; interface < config_desc->bNumInterfaces;
interface++)
{
int newreader;
/* A known device has been found */
snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d:%d",
bus_number, device_address, interface);
bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
newreader = TRUE;
/* Check if the reader is a new one */
for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
{
if (strncmp(readerTracker[j].bus_device,
bus_device, BUS_DEVICE_STRSIZE) == 0) bus_device, BUS_DEVICE_STRSIZE) == 0)
{ {
/* The reader is already known */ /* The reader is already known */
readerTracker[j].status = READER_PRESENT; readerTracker[j].status = READER_PRESENT;
newreader = FALSE; newreader = FALSE;
#ifdef DEBUG_HOTPLUG #ifdef DEBUG_HOTPLUG
Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s", Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
bus_device); bus_device);
#endif #endif
break; break;
}
}
/* New reader found */
if (newreader)
{
if (config_desc->bNumInterfaces > 1)
HPAddHotPluggable(dev, desc, bus_device,
interface, &driverTracker[i]);
else
HPAddHotPluggable(dev, desc, bus_device,
-1, &driverTracker[i]);
}
} }
} }
/* New reader found */
if (newreader)
HPAddHotPluggable(dev, desc, bus_device,
&config_desc->interface[interface], driver, classdriver);
} }
libusb_free_config_descriptor(config_desc); libusb_free_config_descriptor(config_desc);
} }
@ -399,6 +451,7 @@ static void HPRescanUsbBus(void)
free(driverTracker[i].bundleName); free(driverTracker[i].bundleName);
free(driverTracker[i].libraryPath); free(driverTracker[i].libraryPath);
free(driverTracker[i].readerName); free(driverTracker[i].readerName);
free(driverTracker[i].CFBundleName);
} }
free(driverTracker); free(driverTracker);
@ -410,7 +463,7 @@ static void HPRescanUsbBus(void)
libusb_free_device_list(devs, 1); libusb_free_device_list(devs, 1);
} }
static void HPEstablishUSBNotifications(int pipefd[2]) static void * HPEstablishUSBNotifications(int pipefd[2])
{ {
int i, do_polling; int i, do_polling;
int r; int r;
@ -419,17 +472,21 @@ static void HPEstablishUSBNotifications(int pipefd[2])
r = libusb_init(ctx); r = libusb_init(ctx);
if (r < 0) if (r < 0)
{ {
Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %d", r); Log2(PCSC_LOG_CRITICAL, "libusb_init failed: %s", libusb_error_name(r));
/* emergency exit */ /* emergency exit */
kill(getpid(), SIGTERM); kill(getpid(), SIGTERM);
return; return NULL;
} }
/* scan the USB bus for devices at startup */ /* scan the USB bus for devices at startup */
HPRescanUsbBus(); HPRescanUsbBus();
/* signal that the initially connected readers are now visible */ /* signal that the initially connected readers are now visible */
write(pipefd[1], &c, 1); if (write(pipefd[1], &c, 1) == -1)
{
Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
return NULL;
}
/* if at least one driver do not have IFD_GENERATE_HOTPLUG */ /* if at least one driver do not have IFD_GENERATE_HOTPLUG */
do_polling = FALSE; do_polling = FALSE;
@ -464,7 +521,11 @@ static void HPEstablishUSBNotifications(int pipefd[2])
{ {
char dummy; char dummy;
pipe(rescan_pipe); if (pipe(rescan_pipe) == -1)
{
Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
return NULL;
}
while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0) while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
{ {
Log1(PCSC_LOG_INFO, "Reload serial configuration"); Log1(PCSC_LOG_INFO, "Reload serial configuration");
@ -477,6 +538,8 @@ static void HPEstablishUSBNotifications(int pipefd[2])
close(rescan_pipe[0]); close(rescan_pipe[0]);
rescan_pipe[0] = -1; rescan_pipe[0] = -1;
} }
return NULL;
} }
LONG HPSearchHotPluggables(void) LONG HPSearchHotPluggables(void)
@ -505,7 +568,11 @@ LONG HPSearchHotPluggables(void)
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd); (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
/* Wait for initial readers to setup */ /* Wait for initial readers to setup */
read(pipefd[0], &c, 1); if (read(pipefd[0], &c, 1) == -1)
{
Log2(PCSC_LOG_ERROR, "read: %s", strerror(errno));
return -1;
};
/* cleanup pipe fd */ /* cleanup pipe fd */
close(pipefd[0]); close(pipefd[0]);
@ -529,21 +596,20 @@ LONG HPStopHotPluggables(void)
static LONG HPAddHotPluggable(struct libusb_device *dev, static LONG HPAddHotPluggable(struct libusb_device *dev,
struct libusb_device_descriptor desc, struct libusb_device_descriptor desc,
const char bus_device[], int interface, const char bus_device[],
struct _driverTracker *driver) const struct libusb_interface *idesc,
struct _driverTracker *driver,
struct _driverTracker *classdriver)
{ {
int i; int i;
uint8_t iInterface = 0;
uint8_t iSerialNumber = 0;
char deviceName[MAX_DEVICENAME]; char deviceName[MAX_DEVICENAME];
Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device); Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
if (interface >= 0) snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s",
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libhal:/org/freedesktop/Hal/devices/usb_device_%04x_%04x_serialnotneeded_if%d", desc.idVendor, desc.idProduct, bus_device);
desc.idVendor, desc.idProduct, desc.idVendor, desc.idProduct,
interface);
else
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s",
desc.idVendor, desc.idProduct, bus_device);
deviceName[sizeof(deviceName) -1] = '\0'; deviceName[sizeof(deviceName) -1] = '\0';
@ -567,8 +633,15 @@ static LONG HPAddHotPluggable(struct libusb_device *dev,
strncpy(readerTracker[i].bus_device, bus_device, strncpy(readerTracker[i].bus_device, bus_device,
sizeof(readerTracker[i].bus_device)); sizeof(readerTracker[i].bus_device));
readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0'; readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
readerTracker[i].fullName = NULL;
if (Add_Serial_In_Name && desc.iSerialNumber) if (Add_Interface_In_Name && idesc->num_altsetting > 0)
iInterface = idesc->altsetting[0].iInterface;
if (Add_Serial_In_Name)
iSerialNumber = desc.iSerialNumber;
if (iSerialNumber != 0 || iInterface != 0)
{ {
libusb_device_handle *device; libusb_device_handle *device;
int ret; int ret;
@ -576,45 +649,104 @@ static LONG HPAddHotPluggable(struct libusb_device *dev,
ret = libusb_open(dev, &device); ret = libusb_open(dev, &device);
if (ret < 0) if (ret < 0)
{ {
Log2(PCSC_LOG_ERROR, "libusb_open failed: %d", ret); Log2(PCSC_LOG_ERROR, "libusb_open failed: %s",
libusb_error_name(ret));
} }
else else
{ {
unsigned char interfaceName[MAX_READERNAME];
unsigned char serialNumber[MAX_READERNAME]; unsigned char serialNumber[MAX_READERNAME];
char fullname[MAX_READERNAME * 3];
fullname[0] = '\0';
int ret_interface = 0;
int ret_serial = 0;
if (iInterface)
{
ret_interface = libusb_get_string_descriptor_ascii(device,
iInterface, interfaceName, sizeof interfaceName);
if (ret_interface < 0)
{
Log2(PCSC_LOG_ERROR,
"libusb_get_string_descriptor_ascii failed: %s",
libusb_error_name(ret_interface));
}
}
if (iSerialNumber)
{
ret_serial = libusb_get_string_descriptor_ascii(device,
iSerialNumber, serialNumber, sizeof serialNumber);
if (ret_serial < 0)
{
Log2(PCSC_LOG_ERROR,
"libusb_get_string_descriptor_ascii failed: %s",
libusb_error_name(ret_serial));
}
}
ret = libusb_get_string_descriptor_ascii(device, desc.iSerialNumber,
serialNumber, MAX_READERNAME);
libusb_close(device); libusb_close(device);
if (ret < 0) if (ret_interface > 0 && ret_serial > 0)
{ {
Log2(PCSC_LOG_ERROR, snprintf(fullname, sizeof(fullname), "%s [%s] (%s)",
"libusb_get_string_descriptor_ascii failed: %d", ret); driver->readerName, interfaceName, serialNumber);
readerTracker[i].fullName = strdup(driver->readerName);
} }
else else
{ {
char fullname[MAX_READERNAME]; if (ret_interface > 0)
{
snprintf(fullname, sizeof(fullname), "%s (%s)", snprintf(fullname, sizeof(fullname), "%s [%s]",
driver->readerName, serialNumber); driver->readerName, interfaceName);
readerTracker[i].fullName = strdup(fullname); }
else
{
if (ret_serial > 0)
{
snprintf(fullname, sizeof(fullname), "%s (%s)",
driver->readerName, serialNumber);
}
}
} }
if (fullname[0] != '\0')
readerTracker[i].fullName = strdup(fullname);
} }
} }
else
if (readerTracker[i].fullName == NULL)
readerTracker[i].fullName = strdup(driver->readerName); readerTracker[i].fullName = strdup(driver->readerName);
if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i, LONG ret;
driver->libraryPath, deviceName) == SCARD_S_SUCCESS) ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
readerTracker[i].status = READER_PRESENT; driver->libraryPath, deviceName);
else /* success by default */
readerTracker[i].status = READER_PRESENT;
if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
{ {
readerTracker[i].status = READER_FAILED; Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
driver->readerName);
(void)CheckForOpenCT(); if (classdriver && driver != classdriver)
{
/* the reader can also be used by the a class driver */
ret = RFAddReader(readerTracker[i].fullName,
PCSCLITE_HP_BASE_PORT + i,
classdriver->libraryPath, deviceName);
if ((SCARD_S_SUCCESS != ret) && (SCARD_E_UNKNOWN_READER != ret))
{
Log2(PCSC_LOG_ERROR, "Failed adding USB device: %s",
driver->readerName);
readerTracker[i].status = READER_FAILED;
}
}
else
readerTracker[i].status = READER_FAILED;
} }
if (READER_FAILED == readerTracker[i].status)
(void)CheckForOpenCT();
pthread_mutex_unlock(&usbNotifierMutex); pthread_mutex_unlock(&usbNotifierMutex);
return 1; return 1;
@ -654,7 +786,8 @@ void HPReCheckSerialReaders(void)
if (rescan_pipe[1] >= 0) if (rescan_pipe[1] >= 0)
{ {
char dummy = 0; char dummy = 0;
write(rescan_pipe[1], &dummy, sizeof(dummy)); if (write(rescan_pipe[1], &dummy, sizeof(dummy)) == -1)
Log2(PCSC_LOG_ERROR, "write: %s", strerror(errno));
} }
} }

View File

@ -237,7 +237,7 @@ static void HPEstablishUSBNotifications(void)
int deviceNumber; int deviceNumber;
int suspectDeviceNumber; int suspectDeviceNumber;
char dirpath[FILENAME_MAX]; char dirpath[FILENAME_MAX];
char filename[FILENAME_MAX]; char filename[FILENAME_MAX * 2];
int fd, ret; int fd, ret;
struct usb_device_descriptor usbDescriptor; struct usb_device_descriptor usbDescriptor;

View File

@ -64,8 +64,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Set the protocol type selection (PTS). * Set the protocol type selection (PTS).
* This function sets the appropriate protocol to be used on the card. * This function sets the appropriate protocol to be used on the card.
*/ */
LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags, RESPONSECODE IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol,
UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3) UCHAR ucFlags, UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
{ {
RESPONSECODE rv; RESPONSECODE rv;
@ -102,9 +102,9 @@ LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
/** /**
* Open a communication channel to the IFD. * Open a communication channel to the IFD.
*/ */
LONG IFDOpenIFD(READER_CONTEXT * rContext) RESPONSECODE IFDOpenIFD(READER_CONTEXT * rContext)
{ {
RESPONSECODE rv = 0; RESPONSECODE rv = IFD_SUCCESS;
#ifndef PCSCLITE_STATIC_DRIVER #ifndef PCSCLITE_STATIC_DRIVER
RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL; RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
@ -160,7 +160,7 @@ LONG IFDOpenIFD(READER_CONTEXT * rContext)
/** /**
* Close a communication channel to the IFD. * Close a communication channel to the IFD.
*/ */
LONG IFDCloseIFD(READER_CONTEXT * rContext) RESPONSECODE IFDCloseIFD(READER_CONTEXT * rContext)
{ {
RESPONSECODE rv; RESPONSECODE rv;
int repeat; int repeat;
@ -201,7 +201,7 @@ again:
/** /**
* Set capabilities in the reader. * Set capabilities in the reader.
*/ */
LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag, RESPONSECODE IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
DWORD dwLength, PUCHAR pucValue) DWORD dwLength, PUCHAR pucValue)
{ {
RESPONSECODE rv; RESPONSECODE rv;
@ -232,7 +232,7 @@ LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
* Other functions int this file will call * Other functions int this file will call
* the driver directly to not cause a deadlock. * the driver directly to not cause a deadlock.
*/ */
LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag, RESPONSECODE IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
PDWORD pdwLength, PUCHAR pucValue) PDWORD pdwLength, PUCHAR pucValue)
{ {
RESPONSECODE rv; RESPONSECODE rv;
@ -262,7 +262,7 @@ LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
/** /**
* Power up/down or reset's an ICC located in the IFD. * Power up/down or reset's an ICC located in the IFD.
*/ */
LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction, RESPONSECODE IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
PUCHAR pucAtr, PDWORD pdwAtrLen) PUCHAR pucAtr, PDWORD pdwAtrLen)
{ {
RESPONSECODE rv; RESPONSECODE rv;
@ -548,6 +548,9 @@ LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
return SCARD_E_READER_UNAVAILABLE; return SCARD_E_READER_UNAVAILABLE;
} }
if (rv == IFD_ICC_NOT_PRESENT)
return SCARD_E_NO_SMARTCARD;
return SCARD_E_NOT_TRANSACTED; return SCARD_E_NOT_TRANSACTED;
} }
} }

View File

@ -39,9 +39,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __ifdwrapper_h__ #ifndef __ifdwrapper_h__
#define __ifdwrapper_h__ #define __ifdwrapper_h__
LONG IFDOpenIFD(READER_CONTEXT *); #include "ifdhandler.h"
LONG IFDCloseIFD(READER_CONTEXT *); #include "readerfactory.h"
LONG IFDPowerICC(READER_CONTEXT *, DWORD, PUCHAR, /*@out@*/ PDWORD); #include "wintypes.h"
RESPONSECODE IFDOpenIFD(READER_CONTEXT *);
RESPONSECODE IFDCloseIFD(READER_CONTEXT *);
RESPONSECODE IFDPowerICC(READER_CONTEXT *, DWORD, PUCHAR, /*@out@*/ PDWORD);
LONG IFDStatusICC(READER_CONTEXT *, /*@out@*/ PDWORD); LONG IFDStatusICC(READER_CONTEXT *, /*@out@*/ PDWORD);
LONG IFDControl_v2(READER_CONTEXT *, PUCHAR, DWORD, /*@out@*/ PUCHAR, LONG IFDControl_v2(READER_CONTEXT *, PUCHAR, DWORD, /*@out@*/ PUCHAR,
PDWORD); PDWORD);
@ -49,8 +53,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
DWORD, LPDWORD); DWORD, LPDWORD);
LONG IFDTransmit(READER_CONTEXT *, SCARD_IO_HEADER, LONG IFDTransmit(READER_CONTEXT *, SCARD_IO_HEADER,
PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER); PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER);
LONG IFDSetPTS(READER_CONTEXT *, DWORD, UCHAR, UCHAR, UCHAR, UCHAR); RESPONSECODE IFDSetPTS(READER_CONTEXT *, DWORD, UCHAR, UCHAR, UCHAR, UCHAR);
LONG IFDSetCapabilities(READER_CONTEXT *, DWORD, DWORD, PUCHAR); RESPONSECODE IFDSetCapabilities(READER_CONTEXT *, DWORD, DWORD, PUCHAR);
LONG IFDGetCapabilities(READER_CONTEXT *, DWORD, PDWORD, /*@out@*/ PUCHAR); RESPONSECODE IFDGetCapabilities(READER_CONTEXT *, DWORD, PDWORD, /*@out@*/ PUCHAR);
#endif /* __ifdwrapper_h__ */ #endif /* __ifdwrapper_h__ */

View File

@ -42,14 +42,14 @@
#define SCARD_INSERTED 0x0002 /**< Card was inserted */ #define SCARD_INSERTED 0x0002 /**< Card was inserted */
#define SCARD_REMOVED 0x0004 /**< Card was removed */ #define SCARD_REMOVED 0x0004 /**< Card was removed */
#define PCSCLITE_CONFIG_DIR "/usr/local/etc/reader.conf.d" #define PCSCLITE_CONFIG_DIR "/etc/reader.conf.d"
#define PCSCLITE_IPC_DIR USE_IPCDIR #define PCSCLITE_IPC_DIR USE_IPCDIR
#define PCSCLITE_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid" #define PCSCLITE_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid"
#define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm" #define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm"
#define PCSCLITE_VERSION_NUMBER "1.9.0" /**< Current version */ #define PCSCLITE_VERSION_NUMBER "1.9.1" /**< Current version */
#define PCSCLITE_STATUS_POLL_RATE 400000 /**< Status polling rate */ #define PCSCLITE_STATUS_POLL_RATE 400000 /**< Status polling rate */
#define PCSCLITE_LOCK_POLL_RATE 100000 /**< Lock polling rate */ #define PCSCLITE_LOCK_POLL_RATE 100000 /**< Lock polling rate */

View File

@ -839,7 +839,7 @@ static void print_version(void)
printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n"); printf("Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.\n");
printf("Copyright (C) 2001-2018 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n"); printf("Copyright (C) 2001-2018 by Ludovic Rousseau <ludovic.rousseau@free.fr>.\n");
printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n"); printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.\n");
printf("Report bugs to <pcsclite-muscle@lists.alioth.debian.org>.\n"); printf("Report bugs to <pcsclite-muscle@lists.infradead.org>.\n");
printf ("Enabled features:%s\n", PCSCLITE_FEATURES); printf ("Enabled features:%s\n", PCSCLITE_FEATURES);
} }

View File

@ -65,7 +65,7 @@ DWORD PHSetProtocol(struct ReaderContext * rContext,
UCHAR ucChosen; UCHAR ucChosen;
/* App has specified no protocol */ /* App has specified no protocol */
if (dwPreferred == 0) if (dwPreferred == SCARD_PROTOCOL_UNDEFINED)
return SET_PROTOCOL_WRONG_ARGUMENT; return SET_PROTOCOL_WRONG_ARGUMENT;
/* requested protocol is not available */ /* requested protocol is not available */
@ -108,27 +108,38 @@ DWORD PHSetProtocol(struct ReaderContext * rContext,
(SCARD_PROTOCOL_T0 == ucChosen ? 0 : 1)); (SCARD_PROTOCOL_T0 == ucChosen ? 0 : 1));
rv = IFDSetPTS(rContext, ucChosen, 0x00, 0x00, 0x00, 0x00); rv = IFDSetPTS(rContext, ucChosen, 0x00, 0x00, 0x00, 0x00);
if (IFD_SUCCESS == rv) switch(rv)
protocol = ucChosen; {
else case IFD_SUCCESS:
if (IFD_NOT_SUPPORTED == rv) protocol = ucChosen;
Log2(PCSC_LOG_INFO, "PTS not supported by driver, using T=%d", break;
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
else case IFD_NOT_SUPPORTED:
if (IFD_PROTOCOL_NOT_SUPPORTED == rv) case IFD_PROTOCOL_NOT_SUPPORTED:
Log2(PCSC_LOG_INFO, "PTS protocol not supported, using T=%d", case IFD_ERROR_NOT_SUPPORTED:
if (protocol != dwPreferred)
{
Log3(PCSC_LOG_INFO,
"Set PTS failed (%ld). Using T=%d", rv,
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1); (SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
}
else else
{ {
Log3(PCSC_LOG_INFO, "PTS failed (%ld), using T=%d", rv, /* no other protocol to use */
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1); Log2(PCSC_LOG_INFO, "PTS protocol failed (%ld)", rv);
protocol = SET_PROTOCOL_PPS_FAILED;
/* ISO 7816-3:1997 ch. 7.2 PPS protocol page 14
* - If the PPS exchange is unsuccessful, then the interface device
* shall either reset or reject the card.
*/
return SET_PROTOCOL_PPS_FAILED;
} }
break;
default:
Log2(PCSC_LOG_INFO, "Set PTS failed (%ld)", rv);
/* ISO 7816-3:1997 ch. 7.2 PPS protocol page 14
* - If the PPS exchange is unsuccessful, then the interface
* device shall either reset or reject the card.
*/
protocol = SET_PROTOCOL_PPS_FAILED;
}
return protocol; return protocol;
} }

View File

@ -38,6 +38,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __prothandler_h__ #ifndef __prothandler_h__
#define __prothandler_h__ #define __prothandler_h__
#include "readerfactory.h"
#include "wintypes.h"
DWORD PHSetProtocol(struct ReaderContext *, DWORD, UCHAR, UCHAR); DWORD PHSetProtocol(struct ReaderContext *, DWORD, UCHAR, UCHAR);
#define SET_PROTOCOL_WRONG_ARGUMENT -1 #define SET_PROTOCOL_WRONG_ARGUMENT -1

View File

@ -372,8 +372,12 @@ LONG RFAddReader(const char *readerNameLong, int port, const char *library,
rv = RFInitializeReader(sReadersContexts[dwContext]); rv = RFInitializeReader(sReadersContexts[dwContext]);
if (rv != SCARD_S_SUCCESS) if (rv != SCARD_S_SUCCESS)
{ {
int log_level = PCSC_LOG_ERROR;
if (SCARD_E_UNKNOWN_READER == rv)
log_level = PCSC_LOG_INFO;
/* Cannot connect to reader. Exit gracefully */ /* Cannot connect to reader. Exit gracefully */
Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); Log2(log_level, "%s init failed.", readerName);
(void)RFRemoveReader(readerName, port); (void)RFRemoveReader(readerName, port);
return rv; return rv;
} }
@ -595,7 +599,7 @@ LONG RFRemoveReader(const char *readerName, int port)
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
{ {
if (sReadersContexts[i]->vHandle != 0) if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
{ {
strncpy(lpcStripReader, strncpy(lpcStripReader,
sReadersContexts[i]->readerState->readerName, sReadersContexts[i]->readerState->readerName,
@ -1068,7 +1072,8 @@ LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
LONG RFInitializeReader(READER_CONTEXT * rContext) LONG RFInitializeReader(READER_CONTEXT * rContext)
{ {
LONG rv; LONG rv = SCARD_S_SUCCESS;
RESPONSECODE rvd;
/* Spawn the event handler thread */ /* Spawn the event handler thread */
Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s", Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
@ -1098,26 +1103,29 @@ LONG RFInitializeReader(READER_CONTEXT * rContext)
#endif #endif
/* tries to open the port */ /* tries to open the port */
rv = IFDOpenIFD(rContext); rvd = IFDOpenIFD(rContext);
if (rv != IFD_SUCCESS) if (rvd != IFD_SUCCESS)
{ {
Log3(PCSC_LOG_CRITICAL, "Open Port 0x%X Failed (%s)", int log_level = PCSC_LOG_CRITICAL;
rv = SCARD_E_INVALID_TARGET;
if (IFD_NO_SUCH_DEVICE == rvd)
{
/* wrong interface on a composite device? */
log_level = PCSC_LOG_INFO;
rv = SCARD_E_UNKNOWN_READER;
}
Log3(log_level, "Open Port 0x%X Failed (%s)",
rContext->port, rContext->device); rContext->port, rContext->device);
/* IFDOpenIFD() failed */
/* the reader was not started correctly */ /* the reader was not started correctly */
rContext->slot = -1; rContext->slot = -1;
/* IFDOpenIFD() failed */
rContext->slot = -1;
if (IFD_NO_SUCH_DEVICE == rv)
return SCARD_E_UNKNOWN_READER;
else
return SCARD_E_INVALID_TARGET;
} }
return SCARD_S_SUCCESS; return rv;
} }
void RFUnInitializeReader(READER_CONTEXT * rContext) void RFUnInitializeReader(READER_CONTEXT * rContext)
@ -1373,6 +1381,8 @@ void RFCleanupReaders(void)
Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv); Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv);
free(sReadersContexts[i]); free(sReadersContexts[i]);
sReadersContexts[i] = NULL;
} }
} }

View File

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.

View File

@ -91,6 +91,8 @@ static const char * internal_stringify_error(void)
return "No spy pcsc_stringify_error() function"; return "No spy pcsc_stringify_error() function";
} }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
/* contains pointers to real functions */ /* contains pointers to real functions */
static struct static struct
{ {
@ -135,6 +137,7 @@ static struct
.SCardSetAttrib = (p_SCardSetAttrib(*))internal_error, .SCardSetAttrib = (p_SCardSetAttrib(*))internal_error,
.pcsc_stringify_error = (p_pcsc_stringify_error(*))internal_stringify_error .pcsc_stringify_error = (p_pcsc_stringify_error(*))internal_stringify_error
}; };
#pragma GCC diagnostic pop
#define LOG log_line("%s:%d", __FILE__, __LINE__) #define LOG log_line("%s:%d", __FILE__, __LINE__)

View File

@ -600,7 +600,7 @@ LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
/* /*
* Set up the status bit masks on readerState * Set up the status bit masks on readerState
*/ */
if (rv == SCARD_S_SUCCESS) if (rv == IFD_SUCCESS)
{ {
rContext->readerState->cardAtrLength = dwAtrLen; rContext->readerState->cardAtrLength = dwAtrLen;
rContext->readerState->readerState = rContext->readerState->readerState =
@ -907,7 +907,7 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
/* the protocol is unset after a power on */ /* the protocol is unset after a power on */
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED; rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
if (rv == SCARD_S_SUCCESS) if (rv == IFD_SUCCESS)
{ {
if (SCARD_UNPOWER_CARD == dwDisposition) if (SCARD_UNPOWER_CARD == dwDisposition)
rContext->readerState->readerState = SCARD_PRESENT; rContext->readerState->readerState = SCARD_PRESENT;
@ -1156,7 +1156,7 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
/* /*
* Set up the status bit masks on readerState * Set up the status bit masks on readerState
*/ */
if (rv == SCARD_S_SUCCESS) if (rv == IFD_SUCCESS)
{ {
rContext->readerState->cardAtrLength = dwAtrLen; rContext->readerState->cardAtrLength = dwAtrLen;
rContext->readerState->readerState = rContext->readerState->readerState =
@ -1580,7 +1580,7 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
unsigned long i; unsigned long i;
unsigned long prot = rContext->readerState->cardProtocol; unsigned long prot = rContext->readerState->cardProtocol;
for (i = 0 ; prot != 1 ; i++) for (i = 0 ; prot != 1 && i < 16; i++)
prot >>= 1; prot >>= 1;
sSendPci.Protocol = i; sSendPci.Protocol = i;
@ -1618,6 +1618,14 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
{ {
*pcbRecvLength = 0; *pcbRecvLength = 0;
Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv); Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
if (SCARD_E_NO_SMARTCARD == rv)
{
rContext->readerState->cardAtrLength = 0;
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
rContext->readerState->readerState = SCARD_ABSENT;
}
goto exit; goto exit;
} }

View File

@ -43,6 +43,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h> #include <stdint.h>
#include "pcsclite.h"
#include "wintypes.h"
/** Major version of the current message protocol */ /** Major version of the current message protocol */
#define PROTOCOL_VERSION_MAJOR 4 #define PROTOCOL_VERSION_MAJOR 4
/** Minor version of the current message protocol */ /** Minor version of the current message protocol */

View File

@ -507,9 +507,15 @@ static void * ContextThread(LPVOID newContext)
coStr.dwActiveProtocol = dwActiveProtocol; coStr.dwActiveProtocol = dwActiveProtocol;
if (coStr.rv == SCARD_S_SUCCESS) if (coStr.rv == SCARD_S_SUCCESS)
{
coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard, coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
threadContext); threadContext);
/* if storing the hCard fails we disconnect */
if (coStr.rv != SCARD_S_SUCCESS)
SCardDisconnect(coStr.hCard, SCARD_LEAVE_CARD);
}
WRITE_BODY(coStr); WRITE_BODY(coStr);
} }
break; break;
@ -963,7 +969,7 @@ static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
if (listLength >= contextMaxCardHandles) if (listLength >= contextMaxCardHandles)
{ {
Log4(PCSC_LOG_DEBUG, Log4(PCSC_LOG_DEBUG,
"Too many card handles for thread context @%p: %d (max is %d)" "Too many card handles for thread context @%p: %d (max is %d). "
"Restart pcscd with --max-card-handle-per-thread value", "Restart pcscd with --max-card-handle-per-thread value",
threadContext, listLength, contextMaxCardHandles); threadContext, listLength, contextMaxCardHandles);
retval = SCARD_E_NO_MEMORY; retval = SCARD_E_NO_MEMORY;

View File

@ -41,6 +41,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __winscard_svc_h__ #ifndef __winscard_svc_h__
#define __winscard_svc_h__ #define __winscard_svc_h__
#include <stdint.h>
#include "wintypes.h"
LONG ContextsInitialize(int, int); LONG ContextsInitialize(int, int);
void ContextsDeinitialize(void); void ContextsDeinitialize(void);
LONG CreateContextThread(uint32_t *); LONG CreateContextThread(uint32_t *);