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
14 June 2020
- 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@
# 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 \
$(top_srcdir)/src/PCSC/pcsclite.h.in AUTHORS COPYING ChangeLog \
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)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@ -203,6 +203,8 @@ am__relativize = \
GZIP_ENV = --best
DIST_ARCHIVES = $(distdir).tar.bz2
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
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -689,7 +691,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(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.
@ -311,7 +311,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.2], [],
m4_if([$1], [1.16.3], [],
[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.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
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_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_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_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then

27
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# 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.
@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='pcsc-lite'
PACKAGE_TARNAME='pcsc-lite'
PACKAGE_VERSION='1.9.0'
PACKAGE_STRING='pcsc-lite 1.9.0'
PACKAGE_VERSION='1.9.1'
PACKAGE_STRING='pcsc-lite 1.9.1'
PACKAGE_BUGREPORT=''
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.
# This message is too long to be a string in the A/UX 3.1 sh.
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]...
@ -1466,7 +1466,7 @@ fi
if test -n "$ac_init_help"; then
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
cat <<\_ACEOF
@ -1618,7 +1618,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
pcsc-lite configure 1.9.0
pcsc-lite configure 1.9.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2094,7 +2094,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
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
$ $0 $@
@ -2648,12 +2648,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then
@ -2958,7 +2953,7 @@ fi
# Define the identity of the package.
PACKAGE='pcsc-lite'
VERSION='1.9.0'
VERSION='1.9.1'
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
# values after options handling.
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
CONFIG_FILES = $CONFIG_FILES
@ -16263,7 +16258,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
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,
with options \\"\$ac_cs_config\\"

View File

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

View File

@ -3,7 +3,7 @@
SUBDIRS = . example
doc_DATA = \
README.DAEMON README.polkit
README.polkit
man_MANS = pcscd.8 reader.conf.5
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@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -375,7 +375,7 @@ usbdropdir = @usbdropdir@
usbdropdir_exp = @usbdropdir_exp@
SUBDIRS = . example
doc_DATA = \
README.DAEMON README.polkit
README.polkit
man_MANS = pcscd.8 reader.conf.5
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@
# 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@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.

4
ltmain.sh Normal file → Executable file
View File

@ -31,7 +31,7 @@
PROGRAM=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
@ -2141,7 +2141,7 @@ include the following information:
compiler: $LTCC
compiler flags: $LTCFLAGS
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`
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@
# 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 */
#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) */
#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);
#endif
if (dwLength < 2)
return 0; /** @retval 0 Atr must have TS and T0 */
/*
* Zero out the bitmasks
*/
*availableProtocols = SCARD_PROTOCOL_UNDEFINED;
*currentProtocol = SCARD_PROTOCOL_UNDEFINED;
if (dwLength < 2)
return 0; /** @retval 0 Atr must have TS and T0 */
/*
* Decode the TS byte
*/
@ -218,8 +218,8 @@ short ATRDecodeAtr(int *availableProtocols, int *currentProtocol,
}
#ifdef ATR_DEBUG
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d",
*currentProtocol, *availableProtocols);
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: T=%d, AvailableProtocols: %d",
*currentProtocol - SCARD_PROTOCOL_T0, *availableProtocols);
#endif
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__
#define __atrhandler_h__
#include "wintypes.h"
/*
* Decodes the ATR
*/

View File

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

View File

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

View File

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

View File

@ -41,6 +41,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include "pcsclite.h"
#include "readerfactory.h"
#include "wintypes.h"
/**
* Define an exported public reader state structure so each
* 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__
#define __hotplug_h__
#include "wintypes.h"
#ifndef PCSCLITE_HP_DROPDIR
#define PCSCLITE_HP_DROPDIR "/usr/local/pcsc/drivers/"
#endif

View File

@ -78,6 +78,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define FALSE 0
#define TRUE 1
extern char Add_Interface_In_Name;
extern char Add_Serial_In_Name;
/* we use the default libusb context */
@ -106,6 +107,7 @@ static struct _driverTracker
char *libraryPath;
char *readerName;
int ifdCapabilities;
char *CFBundleName;
} *driverTracker = NULL;
#define DRIVER_TRACKER_SIZE_STEP 8
@ -121,8 +123,10 @@ static struct _readerTracker
static LONG HPAddHotPluggable(struct libusb_device *dev,
struct libusb_device_descriptor desc,
const char bus_device[], int interface,
struct _driverTracker *driver);
const char bus_device[],
const struct libusb_interface *idesc,
struct _driverTracker *driver,
struct _driverTracker *classdriver);
static LONG HPRemoveHotPluggable(int reader_index);
static LONG HPReadBundleValues(void)
@ -170,6 +174,7 @@ static LONG HPReadBundleValues(void)
list_t *manuIDs, *productIDs, *readerNames;
char *libraryPath;
int ifdCapabilities;
char *CFBundleName;
/*
* 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_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 */
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].libraryPath = strdup(fullLibPath);
driverTracker[listCount].ifdCapabilities = ifdCapabilities;
driverTracker[listCount].CFBundleName = CFBundleName;
#ifdef DEBUG_HOTPLUG
Log2(PCSC_LOG_INFO, "Found driver for: %s",
@ -255,6 +269,7 @@ static LONG HPReadBundleValues(void)
driverTracker[i].libraryPath = NULL;
driverTracker[i].readerName = NULL;
driverTracker[i].ifdCapabilities = 0;
driverTracker[i].CFBundleName = NULL;
}
}
}
@ -278,6 +293,44 @@ static LONG HPReadBundleValues(void)
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)
{
int i, j;
@ -292,7 +345,8 @@ static void HPRescanUsbBus(void)
cnt = libusb_get_device_list(ctx, &devs);
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;
}
@ -304,78 +358,76 @@ static void HPRescanUsbBus(void)
struct libusb_config_descriptor *config_desc;
uint8_t bus_number = libusb_get_bus_number(dev);
uint8_t device_address = libusb_get_device_address(dev);
struct _driverTracker *driver, *classdriver;
int interface;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
Log3(PCSC_LOG_ERROR, "failed to get device descriptor for %d/%d",
bus_number, device_address);
Log4(PCSC_LOG_ERROR,
"failed to get device descriptor for %d/%d: %s",
bus_number, device_address, libusb_error_name(r));
continue;
}
r = libusb_get_active_config_descriptor(dev, &config_desc);
if (r < 0)
{
Log3(PCSC_LOG_ERROR, "failed to get device config for %d/%d",
bus_number, device_address);
Log4(PCSC_LOG_ERROR, "failed to get device config for %d/%d: %s",
bus_number, device_address, libusb_error_name(r));
continue;
}
/* check if the device is supported by one driver */
for (i=0; i<driverSize; i++)
driver = get_driver(desc.idVendor, desc.idProduct, &classdriver);
if (NULL == driver)
{
if (driverTracker[i].libraryPath != NULL &&
desc.idVendor == driverTracker[i].manuID &&
desc.idProduct == driverTracker[i].productID)
/* not a smart card reader */
#ifdef DEBUG_HOTPLUG
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;
#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,
if (strncmp(readerTracker[j].bus_device,
bus_device, BUS_DEVICE_STRSIZE) == 0)
{
/* The reader is already known */
readerTracker[j].status = READER_PRESENT;
newreader = FALSE;
{
/* The reader is already known */
readerTracker[j].status = READER_PRESENT;
newreader = FALSE;
#ifdef DEBUG_HOTPLUG
Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
bus_device);
Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
bus_device);
#endif
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]);
}
break;
}
}
/* New reader found */
if (newreader)
HPAddHotPluggable(dev, desc, bus_device,
&config_desc->interface[interface], driver, classdriver);
}
libusb_free_config_descriptor(config_desc);
}
@ -399,6 +451,7 @@ static void HPRescanUsbBus(void)
free(driverTracker[i].bundleName);
free(driverTracker[i].libraryPath);
free(driverTracker[i].readerName);
free(driverTracker[i].CFBundleName);
}
free(driverTracker);
@ -410,7 +463,7 @@ static void HPRescanUsbBus(void)
libusb_free_device_list(devs, 1);
}
static void HPEstablishUSBNotifications(int pipefd[2])
static void * HPEstablishUSBNotifications(int pipefd[2])
{
int i, do_polling;
int r;
@ -419,17 +472,21 @@ static void HPEstablishUSBNotifications(int pipefd[2])
r = libusb_init(ctx);
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 */
kill(getpid(), SIGTERM);
return;
return NULL;
}
/* scan the USB bus for devices at startup */
HPRescanUsbBus();
/* 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 */
do_polling = FALSE;
@ -464,7 +521,11 @@ static void HPEstablishUSBNotifications(int pipefd[2])
{
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)
{
Log1(PCSC_LOG_INFO, "Reload serial configuration");
@ -477,6 +538,8 @@ static void HPEstablishUSBNotifications(int pipefd[2])
close(rescan_pipe[0]);
rescan_pipe[0] = -1;
}
return NULL;
}
LONG HPSearchHotPluggables(void)
@ -505,7 +568,11 @@ LONG HPSearchHotPluggables(void)
(PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
/* 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 */
close(pipefd[0]);
@ -529,21 +596,20 @@ LONG HPStopHotPluggables(void)
static LONG HPAddHotPluggable(struct libusb_device *dev,
struct libusb_device_descriptor desc,
const char bus_device[], int interface,
struct _driverTracker *driver)
const char bus_device[],
const struct libusb_interface *idesc,
struct _driverTracker *driver,
struct _driverTracker *classdriver)
{
int i;
uint8_t iInterface = 0;
uint8_t iSerialNumber = 0;
char deviceName[MAX_DEVICENAME];
Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
if (interface >= 0)
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libhal:/org/freedesktop/Hal/devices/usb_device_%04x_%04x_serialnotneeded_if%d",
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);
snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s",
desc.idVendor, desc.idProduct, bus_device);
deviceName[sizeof(deviceName) -1] = '\0';
@ -567,8 +633,15 @@ static LONG HPAddHotPluggable(struct libusb_device *dev,
strncpy(readerTracker[i].bus_device, bus_device,
sizeof(readerTracker[i].bus_device));
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;
int ret;
@ -576,45 +649,104 @@ static LONG HPAddHotPluggable(struct libusb_device *dev,
ret = libusb_open(dev, &device);
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
{
unsigned char interfaceName[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);
if (ret < 0)
if (ret_interface > 0 && ret_serial > 0)
{
Log2(PCSC_LOG_ERROR,
"libusb_get_string_descriptor_ascii failed: %d", ret);
readerTracker[i].fullName = strdup(driver->readerName);
snprintf(fullname, sizeof(fullname), "%s [%s] (%s)",
driver->readerName, interfaceName, serialNumber);
}
else
{
char fullname[MAX_READERNAME];
snprintf(fullname, sizeof(fullname), "%s (%s)",
driver->readerName, serialNumber);
readerTracker[i].fullName = strdup(fullname);
if (ret_interface > 0)
{
snprintf(fullname, sizeof(fullname), "%s [%s]",
driver->readerName, interfaceName);
}
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);
if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
driver->libraryPath, deviceName) == SCARD_S_SUCCESS)
readerTracker[i].status = READER_PRESENT;
else
LONG ret;
ret = RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
driver->libraryPath, deviceName);
/* 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);
return 1;
@ -654,7 +786,8 @@ void HPReCheckSerialReaders(void)
if (rescan_pipe[1] >= 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 suspectDeviceNumber;
char dirpath[FILENAME_MAX];
char filename[FILENAME_MAX];
char filename[FILENAME_MAX * 2];
int fd, ret;
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).
* This function sets the appropriate protocol to be used on the card.
*/
LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
RESPONSECODE IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol,
UCHAR ucFlags, UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
{
RESPONSECODE rv;
@ -102,9 +102,9 @@ LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
/**
* 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
RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
@ -160,7 +160,7 @@ LONG IFDOpenIFD(READER_CONTEXT * rContext)
/**
* Close a communication channel to the IFD.
*/
LONG IFDCloseIFD(READER_CONTEXT * rContext)
RESPONSECODE IFDCloseIFD(READER_CONTEXT * rContext)
{
RESPONSECODE rv;
int repeat;
@ -201,7 +201,7 @@ again:
/**
* Set capabilities in the reader.
*/
LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
RESPONSECODE IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
DWORD dwLength, PUCHAR pucValue)
{
RESPONSECODE rv;
@ -232,7 +232,7 @@ LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
* Other functions int this file will call
* 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)
{
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.
*/
LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
RESPONSECODE IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
PUCHAR pucAtr, PDWORD pdwAtrLen)
{
RESPONSECODE rv;
@ -548,6 +548,9 @@ LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
return SCARD_E_READER_UNAVAILABLE;
}
if (rv == IFD_ICC_NOT_PRESENT)
return SCARD_E_NO_SMARTCARD;
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__
#define __ifdwrapper_h__
LONG IFDOpenIFD(READER_CONTEXT *);
LONG IFDCloseIFD(READER_CONTEXT *);
LONG IFDPowerICC(READER_CONTEXT *, DWORD, PUCHAR, /*@out@*/ PDWORD);
#include "ifdhandler.h"
#include "readerfactory.h"
#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 IFDControl_v2(READER_CONTEXT *, PUCHAR, DWORD, /*@out@*/ PUCHAR,
PDWORD);
@ -49,8 +53,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
DWORD, LPDWORD);
LONG IFDTransmit(READER_CONTEXT *, SCARD_IO_HEADER,
PUCHAR, DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER);
LONG IFDSetPTS(READER_CONTEXT *, DWORD, UCHAR, UCHAR, UCHAR, UCHAR);
LONG IFDSetCapabilities(READER_CONTEXT *, DWORD, DWORD, PUCHAR);
LONG IFDGetCapabilities(READER_CONTEXT *, DWORD, PDWORD, /*@out@*/ PUCHAR);
RESPONSECODE IFDSetPTS(READER_CONTEXT *, DWORD, UCHAR, UCHAR, UCHAR, UCHAR);
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *, DWORD, DWORD, PUCHAR);
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *, DWORD, PDWORD, /*@out@*/ PUCHAR);
#endif /* __ifdwrapper_h__ */

View File

@ -42,14 +42,14 @@
#define SCARD_INSERTED 0x0002 /**< Card was inserted */
#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_RUN_PID PCSCLITE_IPC_DIR "/pcscd.pid"
#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_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) 2001-2018 by Ludovic Rousseau <ludovic.rousseau@free.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);
}

View File

@ -65,7 +65,7 @@ DWORD PHSetProtocol(struct ReaderContext * rContext,
UCHAR ucChosen;
/* App has specified no protocol */
if (dwPreferred == 0)
if (dwPreferred == SCARD_PROTOCOL_UNDEFINED)
return SET_PROTOCOL_WRONG_ARGUMENT;
/* requested protocol is not available */
@ -108,27 +108,38 @@ DWORD PHSetProtocol(struct ReaderContext * rContext,
(SCARD_PROTOCOL_T0 == ucChosen ? 0 : 1));
rv = IFDSetPTS(rContext, ucChosen, 0x00, 0x00, 0x00, 0x00);
if (IFD_SUCCESS == rv)
protocol = ucChosen;
else
if (IFD_NOT_SUPPORTED == rv)
Log2(PCSC_LOG_INFO, "PTS not supported by driver, using T=%d",
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
else
if (IFD_PROTOCOL_NOT_SUPPORTED == rv)
Log2(PCSC_LOG_INFO, "PTS protocol not supported, using T=%d",
switch(rv)
{
case IFD_SUCCESS:
protocol = ucChosen;
break;
case IFD_NOT_SUPPORTED:
case IFD_PROTOCOL_NOT_SUPPORTED:
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);
}
else
{
Log3(PCSC_LOG_INFO, "PTS failed (%ld), using T=%d", rv,
(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
/* 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;
/* no other protocol to use */
Log2(PCSC_LOG_INFO, "PTS protocol failed (%ld)", rv);
protocol = 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;
}

View File

@ -38,6 +38,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef __prothandler_h__
#define __prothandler_h__
#include "readerfactory.h"
#include "wintypes.h"
DWORD PHSetProtocol(struct ReaderContext *, DWORD, UCHAR, UCHAR);
#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]);
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 */
Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
Log2(log_level, "%s init failed.", readerName);
(void)RFRemoveReader(readerName, port);
return rv;
}
@ -595,7 +599,7 @@ LONG RFRemoveReader(const char *readerName, int port)
for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
{
if (sReadersContexts[i]->vHandle != 0)
if (sReadersContexts[i] && (sReadersContexts[i]->vHandle != 0))
{
strncpy(lpcStripReader,
sReadersContexts[i]->readerState->readerName,
@ -1068,7 +1072,8 @@ LONG RFUnlockAllSharing(SCARDHANDLE hCard, READER_CONTEXT * rContext)
LONG RFInitializeReader(READER_CONTEXT * rContext)
{
LONG rv;
LONG rv = SCARD_S_SUCCESS;
RESPONSECODE rvd;
/* Spawn the event handler thread */
Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
@ -1098,26 +1103,29 @@ LONG RFInitializeReader(READER_CONTEXT * rContext)
#endif
/* 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);
/* IFDOpenIFD() failed */
/* the reader was not started correctly */
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)
@ -1373,6 +1381,8 @@ void RFCleanupReaders(void)
Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08lX", rv);
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@
# 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";
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
/* contains pointers to real functions */
static struct
{
@ -135,6 +137,7 @@ static struct
.SCardSetAttrib = (p_SCardSetAttrib(*))internal_error,
.pcsc_stringify_error = (p_pcsc_stringify_error(*))internal_stringify_error
};
#pragma GCC diagnostic pop
#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
*/
if (rv == SCARD_S_SUCCESS)
if (rv == IFD_SUCCESS)
{
rContext->readerState->cardAtrLength = dwAtrLen;
rContext->readerState->readerState =
@ -907,7 +907,7 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
/* the protocol is unset after a power on */
rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
if (rv == SCARD_S_SUCCESS)
if (rv == IFD_SUCCESS)
{
if (SCARD_UNPOWER_CARD == dwDisposition)
rContext->readerState->readerState = SCARD_PRESENT;
@ -1156,7 +1156,7 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
/*
* Set up the status bit masks on readerState
*/
if (rv == SCARD_S_SUCCESS)
if (rv == IFD_SUCCESS)
{
rContext->readerState->cardAtrLength = dwAtrLen;
rContext->readerState->readerState =
@ -1580,7 +1580,7 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
unsigned long i;
unsigned long prot = rContext->readerState->cardProtocol;
for (i = 0 ; prot != 1 ; i++)
for (i = 0 ; prot != 1 && i < 16; i++)
prot >>= 1;
sSendPci.Protocol = i;
@ -1618,6 +1618,14 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
{
*pcbRecvLength = 0;
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;
}

View File

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

View File

@ -507,9 +507,15 @@ static void * ContextThread(LPVOID newContext)
coStr.dwActiveProtocol = dwActiveProtocol;
if (coStr.rv == SCARD_S_SUCCESS)
{
coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
threadContext);
/* if storing the hCard fails we disconnect */
if (coStr.rv != SCARD_S_SUCCESS)
SCardDisconnect(coStr.hCard, SCARD_LEAVE_CARD);
}
WRITE_BODY(coStr);
}
break;
@ -963,7 +969,7 @@ static LONG MSGAddHandle(SCARDCONTEXT hContext, SCARDHANDLE hCard,
if (listLength >= contextMaxCardHandles)
{
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",
threadContext, listLength, contextMaxCardHandles);
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__
#define __winscard_svc_h__
#include <stdint.h>
#include "wintypes.h"
LONG ContextsInitialize(int, int);
void ContextsDeinitialize(void);
LONG CreateContextThread(uint32_t *);