[Pcsclite-cvs-commit] r5638 - in /trunk/PCSC: configure.in src/Makefile.am src/PCSC/ifdhandler.h src/hotplug_generic.c src/hotplug_libhal.c src/hotplug_libudev.c src/hotplug_linux.c
rousseau at users.alioth.debian.org
rousseau at users.alioth.debian.org
Fri Feb 25 13:37:00 UTC 2011
Author: rousseau
Date: Fri Feb 25 13:36:57 2011
New Revision: 5638
URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=5638
Log:
Use libudev instead of (deprecated) libhal for the USB hotplug mechanism.
Added:
trunk/PCSC/src/hotplug_libudev.c (with props)
Removed:
trunk/PCSC/src/hotplug_libhal.c
Modified:
trunk/PCSC/configure.in
trunk/PCSC/src/Makefile.am
trunk/PCSC/src/PCSC/ifdhandler.h
trunk/PCSC/src/hotplug_generic.c
trunk/PCSC/src/hotplug_linux.c
Modified: trunk/PCSC/configure.in
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/configure.in?rev=5638&op=diff
==============================================================================
--- trunk/PCSC/configure.in (original)
+++ trunk/PCSC/configure.in Fri Feb 25 13:36:57 2011
@@ -165,56 +165,56 @@
PCSCLITE_FEATURES="${PCSCLITE_FEATURES} usb"
fi
-# --enable-libhal
-AC_ARG_ENABLE(libhal,
- AC_HELP_STRING([--disable-libhal],[do not use libhal]),
- [ use_libhal="${enableval}" ], [ use_libhal="${use_libhal-yes}" ] )
-
-# check if libhal is used
-if test "x$use_libhal" != xno ; then
- PKG_CHECK_MODULES(LIBHAL, hal, [],
- [ AC_MSG_ERROR([install libhal-dev or use --disable-libhal]) ])
+# --enable-libudev
+AC_ARG_ENABLE(libudev,
+ AC_HELP_STRING([--disable-libudev],[do not use libudev]),
+ [ use_libudev="${enableval}" ], [ use_libudev="${use_libudev-yes}" ] )
+
+# check if libudev is used
+if test "x$use_libudev" != xno ; then
+ PKG_CHECK_MODULES(LIBUDEV, libudev, [],
+ [ AC_MSG_ERROR([install libudev-dev or use --disable-libudev]) ])
saved_CPPFLAGS="$CPPFLAGS"
saved_LIBS="$LIBS"
- CPPFLAGS="$CPPFLAGS $LIBHAL_CFLAGS"
- LIBS="$LDFLAGS $LIBHAL_LIBS"
-
- AC_CHECK_HEADERS(libhal.h, [],
- [ AC_MSG_ERROR([libhal.h not found, use ./configure LIBHAL_CFLAGS=...]) ])
+ CPPFLAGS="$CPPFLAGS $LIBUDEV_CFLAGS"
+ LIBS="$LDFLAGS $LIBUDEV_LIBS"
+
+ AC_CHECK_HEADERS(libudev.h, [],
+ [ AC_MSG_ERROR([libudev.h not found, use ./configure LIBUDEV_CFLAGS=...]) ])
LIBS="$LIBS $COREFOUNDATION $IOKIT"
- AC_MSG_CHECKING([for libhal_ctx_new])
- AC_TRY_LINK_FUNC(libhal_ctx_new, [ AC_MSG_RESULT([yes]) ],
- [ AC_MSG_ERROR([libhal not found, use ./configure LIBHAL_LIBS=...]) ])
-
- # everything needed for libhal support is present
- use_libhal=yes
+ AC_MSG_CHECKING([for udev_monitor_unref])
+ AC_TRY_LINK_FUNC(udev_monitor_unref, [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_ERROR([udev_monitor_unref not found, use ./configure LIBUDEV_LIBS=...]) ])
+
+ # everything needed for libudev support is present
+ use_libudev=yes
CPPFLAGS="$saved_CPPFLAGS"
LIBS="$saved_LIBS"
fi
-AC_SUBST(LIBHAL_CFLAGS)
-AC_SUBST(LIBHAL_LIBS)
-
-if test x$use_libhal = xyes; then
- AC_DEFINE(HAVE_LIBHAL, 1, [Libhal is available])
- PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libhal"
+AC_SUBST(LIBUDEV_CFLAGS)
+AC_SUBST(LIBUDEV_LIBS)
+
+if test x$use_libudev = xyes; then
+ AC_DEFINE(HAVE_LIBUDEV, 1, [Libudev is available])
+ PCSCLITE_FEATURES="${PCSCLITE_FEATURES} libudev"
fi
# --enable-libusb
AC_ARG_ENABLE(libusb,
AC_HELP_STRING([--enable-libusb],[use libusb]),
[ use_libusb="${enableval}" ],
- [ if test "x$use_libhal" = xyes ; then use_libusb="${use_libusb-no}" ;
+ [ if test "x$use_libudev" = xyes ; then use_libusb="${use_libusb-no}" ;
else use_libusb="${use_libusb-yes}" ; fi ] )
# check if libusb is used
if test "x$use_libusb" != xno ; then
- if test "x$use_libhal" != xno ; then
- AC_MSG_ERROR([You can't use libhal _and_ libusb. Select only one.])
+ if test "x$use_libudev" != xno ; then
+ AC_MSG_ERROR([You can't use libudev _and_ libusb. Select only one.])
fi
PKG_CHECK_MODULES(LIBUSB, libusb-1.0, [],
@@ -370,7 +370,7 @@
PCSC_ARCH: ${PCSC_ARCH}
pcscd binary ${PCSCD_BINARY}
-libhal support: ${use_libhal}
+libudev support: ${use_libudev}
libusb support: ${use_libusb}
USB drop directory: ${usbdropdir}
ATR parsing messages: ${debugatr}
Modified: trunk/PCSC/src/Makefile.am
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/Makefile.am?rev=5638&op=diff
==============================================================================
--- trunk/PCSC/src/Makefile.am (original)
+++ trunk/PCSC/src/Makefile.am Fri Feb 25 13:36:57 2011
@@ -14,7 +14,7 @@
if ENABLE_USB
USB_CONFIG = tokenparser.l \
- hotplug_libhal.c \
+ hotplug_libudev.c \
hotplug_libusb.c \
hotplug_linux.c \
hotplug_macosx.c
@@ -83,12 +83,12 @@
winscard_msg_srv.c \
winscard_svc.c \
winscard_svc.h
-pcscd_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(LIBUSB_CFLAGS) $(LIBHAL_CFLAGS) \
+pcscd_CFLAGS = $(CFLAGS) $(PTHREAD_CFLAGS) $(LIBUSB_CFLAGS) $(LIBUDEV_CFLAGS) \
-DPCSCD -DSIMCLIST_NO_DUMPRESTORE
pcscd_LDFLAGS = $(LDFLAGS) -export-dynamic
pcscd_LDADD = \
$(PTHREAD_LIBS) $(COREFOUNDATION) \
- $(LIBUSB_LIBS) $(LIBDL) $(IOKIT) $(LIBHAL_LIBS) \
+ $(LIBUSB_LIBS) $(LIBDL) $(IOKIT) $(LIBUDEV_LIBS) \
$(PTHREAD_LIBS) $(PTHREAD_CFLAGS)
fix-rights: install-sbinPROGRAMS
Modified: trunk/PCSC/src/PCSC/ifdhandler.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/PCSC/ifdhandler.h?rev=5638&op=diff
==============================================================================
--- trunk/PCSC/src/PCSC/ifdhandler.h (original)
+++ trunk/PCSC/src/PCSC/ifdhandler.h Fri Feb 25 13:36:57 2011
@@ -426,25 +426,29 @@
So it is something like: <tt>usb:08e6/3437:libusb:001:042</tt> under
GNU/Linux.
-- libhal
-
- If pcscd is compiled with libhal support instead of libusb (default
- since pcsc-lite 1.4.100) the string will look like:
+- libudev
+
+ If pcscd is compiled with libudev support instead of libusb (default
+ since pcsc-lite 1.6.8) the string will look like:
@code
- printf("usb:%04x/%04x:libhal:%s", idVendor, idProduct, udi)
+ printf("usb:%04x/%04x:libudev:%d:%s", idVendor, idProduct,
+ bInterfaceNumber, devpath);
@endcode
- udi is the Universal Device Id at the HAL level.
+ bInterfaceNumber is the number of the interface on the device. It is
+ only usefull for devices with more than one CCID interface.
+
+ devpath is the filename of the device on the file system.
So it is something like:
- <tt>usb:08e6/3437:libhal:/org/freedesktop/Hal/devices/usb_device_8e6_3437_noserial_if0</tt>
+ <tt>usb:08e6/3437:libudev:0:/dev/bus/usb/008/047</tt>
under GNU/Linux.
- other
If the driver does not understand the <tt>:libusb:</tt> or
- <tt>:libhal:</tt> scheme or if a new scheme is used, the driver should
+ <tt>:libudev:</tt> scheme or if a new scheme is used, the driver should
ignore the part it does not understand instead of failing.
The driver shall recognize the <tt>usb:VID/PID</tt> part and, only if
Modified: trunk/PCSC/src/hotplug_generic.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/hotplug_generic.c?rev=5638&op=diff
==============================================================================
--- trunk/PCSC/src/hotplug_generic.c (original)
+++ trunk/PCSC/src/hotplug_generic.c Fri Feb 25 13:36:57 2011
@@ -27,7 +27,7 @@
#define FALSE 0
#endif
-#if !defined(__APPLE__) && !defined(HAVE_LIBUSB) && !defined(__linux__) && !defined(HAVE_LIBHAL)
+#if !defined(__APPLE__) && !defined(HAVE_LIBUSB) && !defined(__linux__) && !defined(HAVE_LIBUDEV)
LONG HPSearchHotPluggables(void)
{
Added: trunk/PCSC/src/hotplug_libudev.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/hotplug_libudev.c?rev=5638&op=file
==============================================================================
--- trunk/PCSC/src/hotplug_libudev.c (added)
+++ trunk/PCSC/src/hotplug_libudev.c Fri Feb 25 13:36:57 2011
@@ -1,0 +1,644 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2011
+ * Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *
+ * $Id$
+ */
+
+/**
+ * @file
+ * @brief This provides a search API for hot pluggble devices using libudev
+ */
+
+#include "config.h"
+#if defined(HAVE_LIBUDEV) && defined(USE_USB)
+
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <libudev.h>
+
+#include "debuglog.h"
+#include "parser.h"
+#include "readerfactory.h"
+#include "sys_generic.h"
+#include "hotplug.h"
+#include "utils.h"
+#include "strlcpycat.h"
+
+#undef DEBUG_HOTPLUG
+#define ADD_SERIAL_NUMBER
+#define ADD_INTERFACE_NAME
+
+#define FALSE 0
+#define TRUE 1
+
+pthread_mutex_t usbNotifierMutex;
+
+static pthread_t usbNotifyThread;
+static int driverSize = -1;
+static char AraKiriHotPlug = FALSE;
+
+/**
+ * keep track of drivers in a dynamically allocated array
+ */
+static struct _driverTracker
+{
+ unsigned int manuID;
+ unsigned int productID;
+
+ char *bundleName;
+ char *libraryPath;
+ char *readerName;
+ char *CFBundleName;
+} *driverTracker = NULL;
+#define DRIVER_TRACKER_SIZE_STEP 10
+
+/* The CCID driver already supports 176 readers.
+ * We start with a big array size to avoid reallocation. */
+#define DRIVER_TRACKER_INITIAL_SIZE 200
+
+typedef enum {
+ READER_ABSENT,
+ READER_PRESENT,
+ READER_FAILED
+} readerState_t;
+
+/**
+ * keep track of PCSCLITE_MAX_READERS_CONTEXTS simultaneous readers
+ */
+static struct _readerTracker
+{
+ readerState_t status; /** reader state */
+ char bInterfaceNumber; /** interface number on the device */
+ char *devpath; /**< device name seen by udev */
+ char *fullName; /**< full reader name (including serial number) */
+} readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
+
+
+static LONG HPReadBundleValues(void)
+{
+ LONG rv;
+ DIR *hpDir;
+ struct dirent *currFP = NULL;
+ char fullPath[FILENAME_MAX];
+ char fullLibPath[FILENAME_MAX];
+ int listCount = 0;
+
+ hpDir = opendir(PCSCLITE_HP_DROPDIR);
+
+ if (NULL == hpDir)
+ {
+ Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
+ Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
+ return -1;
+ }
+
+ /* allocate a first array */
+ driverSize = DRIVER_TRACKER_INITIAL_SIZE;
+ driverTracker = calloc(driverSize, sizeof(*driverTracker));
+ if (NULL == driverTracker)
+ {
+ Log1(PCSC_LOG_CRITICAL, "Not enough memory");
+ return -1;
+ }
+
+#define GET_KEY(key, values) \
+ rv = LTPBundleFindValueWithKey(&plist, key, values); \
+ if (rv) \
+ { \
+ Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
+ fullPath); \
+ continue; \
+ }
+
+ while ((currFP = readdir(hpDir)) != 0)
+ {
+ if (strstr(currFP->d_name, ".bundle") != 0)
+ {
+ unsigned int alias;
+ list_t plist, *values;
+ list_t *manuIDs, *productIDs, *readerNames;
+ char *CFBundleName;
+ char *libraryPath;
+
+ /*
+ * The bundle exists - let's form a full path name and get the
+ * vendor and product ID's for this particular bundle
+ */
+ (void)snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
+ PCSCLITE_HP_DROPDIR, currFP->d_name);
+ fullPath[sizeof(fullPath) - 1] = '\0';
+
+ rv = bundleParse(fullPath, &plist);
+ if (rv)
+ continue;
+
+ /* get CFBundleExecutable */
+ GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
+ libraryPath = list_get_at(values, 0);
+ (void)snprintf(fullLibPath, sizeof(fullLibPath),
+ "%s/%s/Contents/%s/%s",
+ PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
+ libraryPath);
+ fullLibPath[sizeof(fullLibPath) - 1] = '\0';
+
+ GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
+ 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++)
+ {
+ char *value;
+
+ /* variables entries */
+ value = list_get_at(manuIDs, alias);
+ driverTracker[listCount].manuID = strtol(value, NULL, 16);
+
+ value = list_get_at(productIDs, alias);
+ driverTracker[listCount].productID = strtol(value, NULL, 16);
+
+ driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
+
+ /* constant entries for a same driver */
+ driverTracker[listCount].bundleName = strdup(currFP->d_name);
+ driverTracker[listCount].libraryPath = strdup(fullLibPath);
+ driverTracker[listCount].CFBundleName = CFBundleName;
+
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_INFO, "Found driver for: %s",
+ driverTracker[listCount].readerName);
+#endif
+ listCount++;
+ if (listCount >= driverSize)
+ {
+ int i;
+
+ /* increase the array size */
+ driverSize += DRIVER_TRACKER_SIZE_STEP;
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_INFO,
+ "Increase driverTracker to %d entries", driverSize);
+#endif
+ driverTracker = realloc(driverTracker,
+ driverSize * sizeof(*driverTracker));
+ if (NULL == driverTracker)
+ {
+ Log1(PCSC_LOG_CRITICAL, "Not enough memory");
+ driverSize = -1;
+ return -1;
+ }
+
+ /* clean the newly allocated entries */
+ for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
+ {
+ driverTracker[i].manuID = 0;
+ driverTracker[i].productID = 0;
+ driverTracker[i].bundleName = NULL;
+ driverTracker[i].libraryPath = NULL;
+ driverTracker[i].readerName = NULL;
+ driverTracker[i].CFBundleName = NULL;
+ }
+ }
+ }
+ bundleRelease(&plist);
+ }
+ }
+
+ driverSize = listCount;
+ (void)closedir(hpDir);
+
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
+#endif
+
+ return 0;
+} /* HPReadBundleValues */
+
+
+/*@null@*/ static struct _driverTracker *get_driver(struct udev_device *dev,
+ const char *devpath)
+{
+ int i;
+ unsigned int idVendor, idProduct;
+ static struct _driverTracker *classdriver, *driver;
+ const char *str;
+
+ str = udev_device_get_sysattr_value(dev, "idVendor");
+ if (!str)
+ {
+ Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
+ return NULL;
+ }
+ sscanf(str, "%X", &idVendor);
+
+ str = udev_device_get_sysattr_value(dev, "idProduct");
+ if (!str)
+ {
+ Log1(PCSC_LOG_ERROR, "udev_device_get_sysattr_value() failed");
+ return NULL;
+ }
+ sscanf(str, "%X", &idProduct);
+
+ Log4(PCSC_LOG_DEBUG,
+ "Looking for a driver for VID: 0x%04X, PID: 0x%04X, path: %s",
+ idVendor, idProduct, devpath);
+
+ 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 HPAddDevice(struct udev_device *dev, struct udev_device *parent,
+ const char *devpath)
+{
+ int i;
+ char deviceName[MAX_DEVICENAME];
+ char fullname[MAX_READERNAME];
+ struct _driverTracker *driver;
+ const char *sSerialNumber = NULL, *sInterfaceName = NULL;
+ LONG ret;
+ int bInterfaceNumber;
+
+ driver = get_driver(parent, devpath);
+ if (NULL == driver)
+ {
+ /* not a smart card reader */
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_DEBUG, "%s is not a supported smart card reader",
+ devpath);
+#endif
+ return;
+ }
+
+ Log2(PCSC_LOG_INFO, "Adding USB device: %s", driver->readerName);
+
+ bInterfaceNumber = atoi(udev_device_get_sysattr_value(dev,
+ "bInterfaceNumber"));
+ (void)snprintf(deviceName, sizeof(deviceName),
+ "usb:%04x/%04x:libudev:%d:%s", driver->manuID, driver->productID,
+ bInterfaceNumber, devpath);
+ deviceName[sizeof(deviceName) -1] = '\0';
+
+ (void)pthread_mutex_lock(&usbNotifierMutex);
+
+ /* find a free entry */
+ for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
+ {
+ if (NULL == readerTracker[i].fullName)
+ break;
+ }
+
+ if (PCSCLITE_MAX_READERS_CONTEXTS == i)
+ {
+ Log2(PCSC_LOG_ERROR,
+ "Not enough reader entries. Already found %d readers", i);
+ (void)pthread_mutex_unlock(&usbNotifierMutex);
+ return;
+ }
+
+#ifdef ADD_INTERFACE_NAME
+ sInterfaceName = udev_device_get_sysattr_value(dev, "interface");
+#endif
+
+#ifdef ADD_SERIAL_NUMBER
+ sSerialNumber = udev_device_get_sysattr_value(parent, "serial");
+#endif
+
+ /* name from the Info.plist file */
+ strlcpy(fullname, driver->readerName, sizeof(fullname));
+
+ /* interface name from the device (if any) */
+ if (sInterfaceName)
+ {
+ strlcat(fullname, " [", sizeof(fullname));
+ strlcat(fullname, sInterfaceName, sizeof(fullname));
+ strlcat(fullname, "]", sizeof(fullname));
+ }
+
+ /* serial number from the device (if any) */
+ if (sSerialNumber)
+ {
+ /* only add the serial number if it is not already present in the
+ * interface name */
+ if (!sInterfaceName || NULL == strstr(sInterfaceName, sSerialNumber))
+ {
+ strlcat(fullname, " (", sizeof(fullname));
+ strlcat(fullname, sSerialNumber, sizeof(fullname));
+ strlcat(fullname, ")", sizeof(fullname));
+ }
+ }
+
+ readerTracker[i].fullName = strdup(fullname);
+ readerTracker[i].devpath = strdup(devpath);
+ readerTracker[i].status = READER_PRESENT;
+ readerTracker[i].bInterfaceNumber = bInterfaceNumber;
+
+ ret = RFAddReader(fullname, PCSCLITE_HP_BASE_PORT + i,
+ driver->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;
+
+ (void)CheckForOpenCT();
+ }
+
+ (void)pthread_mutex_unlock(&usbNotifierMutex);
+} /* HPAddDevice */
+
+
+static void HPRescanUsbBus(struct udev *udev)
+{
+ int i, j;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+
+ /* all reader are marked absent */
+ for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+ readerTracker[i].status = READER_ABSENT;
+
+ /* Create a list of the devices in the 'usb' subsystem. */
+ enumerate = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(enumerate, "usb");
+ udev_enumerate_scan_devices(enumerate);
+ devices = udev_enumerate_get_list_entry(enumerate);
+
+ /* For each item enumerated */
+ udev_list_entry_foreach(dev_list_entry, devices)
+ {
+ const char *devpath;
+ struct udev_device *dev, *parent;
+ struct _driverTracker *driver;
+ int newreader;
+ int bInterfaceNumber;
+ const char *interface;
+
+ /* Get the filename of the /sys entry for the device
+ and create a udev_device object (dev) representing it */
+ devpath = udev_list_entry_get_name(dev_list_entry);
+ dev = udev_device_new_from_syspath(udev, devpath);
+
+ /* The device pointed to by dev contains information about
+ the interface. In order to get information about the USB
+ device, get the parent device with the subsystem/devtype pair
+ of "usb"/"usb_device". This will be several levels up the
+ tree, but the function will find it.*/
+ parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
+ "usb_device");
+ if (!parent)
+ continue;
+
+ devpath = udev_device_get_devnode(parent);
+ driver = get_driver(parent, devpath);
+ if (NULL == driver)
+ /* no driver known for this device */
+ continue;
+
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", devpath);
+#endif
+
+ newreader = TRUE;
+ bInterfaceNumber = 0;
+ interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber");
+ if (interface)
+ bInterfaceNumber = atoi(interface);
+
+ /* Check if the reader is a new one */
+ for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
+ {
+ if (readerTracker[j].devpath
+ && (strcmp(readerTracker[j].devpath, devpath) == 0)
+ && (bInterfaceNumber == readerTracker[j].bInterfaceNumber))
+ {
+ /* The reader is already known */
+ readerTracker[j].status = READER_PRESENT;
+ newreader = FALSE;
+#ifdef DEBUG_HOTPLUG
+ Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s", devpath);
+#endif
+ break;
+ }
+ }
+
+ /* New reader found */
+ if (newreader)
+ HPAddDevice(dev, parent, devpath);
+
+ /* free device */
+ udev_device_unref(dev);
+ }
+
+ /* Free the enumerator object */
+ udev_enumerate_unref(enumerate);
+
+ /* check if all the previously found readers are still present */
+ for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
+ {
+ if ((READER_ABSENT == readerTracker[i].status)
+ && (readerTracker[i].fullName != NULL))
+ {
+ pthread_mutex_lock(&usbNotifierMutex);
+
+ Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", i,
+ readerTracker[i].devpath);
+
+ RFRemoveReader(readerTracker[i].fullName,
+ PCSCLITE_HP_BASE_PORT + i);
+
+ readerTracker[i].status = READER_ABSENT;
+ free(readerTracker[i].devpath);
+ readerTracker[i].devpath = NULL;
+ free(readerTracker[i].fullName);
+ readerTracker[i].fullName = NULL;
+
+ pthread_mutex_unlock(&usbNotifierMutex);
+ }
+ }
+}
+
+static void HPEstablishUSBNotifications(struct udev *udev)
+{
+ struct udev_monitor *udev_monitor;
+ int r, i;
+
+ udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
+
+ /* filter only the interfaces */
+ r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb",
+ "usb_interface");
+ if (r)
+ {
+ Log2(PCSC_LOG_ERROR, "udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r);
+ return;
+ }
+
+ r = udev_monitor_enable_receiving(udev_monitor);
+ if (r)
+ {
+ Log2(PCSC_LOG_ERROR, "udev_monitor_enable_receiving() error: %d\n", r);
+ return;
+ }
+
+ while (!AraKiriHotPlug)
+ {
+ struct udev_device *dev, *parent;
+ const char *action, *devpath;
+
+#ifdef DEBUG_HOTPLUG
+ Log0(PCSC_LOG_INFO);
+#endif
+
+ dev = udev_monitor_receive_device(udev_monitor);
+ if (!dev)
+ {
+ Log1(PCSC_LOG_ERROR, "udev_monitor_receive_device() error\n");
+ return;
+ }
+
+ action = udev_device_get_action(dev);
+ if (0 == strcmp("remove", action))
+ {
+ Log1(PCSC_LOG_INFO, "Device removed");
+ HPRescanUsbBus(udev);
+ continue;
+ }
+
+ if (strcmp("add", action))
+ continue;
+
+ parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb",
+ "usb_device");
+ devpath = udev_device_get_devnode(parent);
+
+ HPAddDevice(dev, parent, devpath);
+
+ /* free device */
+ udev_device_unref(dev);
+
+ }
+
+ for (i=0; i<driverSize; i++)
+ {
+ /* free strings allocated by strdup() */
+ free(driverTracker[i].bundleName);
+ free(driverTracker[i].libraryPath);
+ free(driverTracker[i].readerName);
+ }
+ free(driverTracker);
+
+ Log1(PCSC_LOG_INFO, "Hotplug stopped");
+} /* HPEstablishUSBNotifications */
+
+
+/***
+ * Start a thread waiting for hotplug events
+ */
+LONG HPSearchHotPluggables(void)
+{
+ int i;
+
+ for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
+ {
+ readerTracker[i].status = READER_ABSENT;
+ readerTracker[i].bInterfaceNumber = 0;
+ readerTracker[i].devpath = NULL;
+ readerTracker[i].fullName = NULL;
+ }
+
+ return HPReadBundleValues();
+} /* HPSearchHotPluggables */
+
+
+/**
+ * Stop the hotplug thread
+ */
+LONG HPStopHotPluggables(void)
+{
+ AraKiriHotPlug = TRUE;
+
+ return 0;
+} /* HPStopHotPluggables */
+
+
+/**
+ * Sets up callbacks for device hotplug events.
+ */
+ULONG HPRegisterForHotplugEvents(void)
+{
+ struct udev *udev;
+
+ (void)pthread_mutex_init(&usbNotifierMutex, NULL);
+
+ if (driverSize <= 0)
+ {
+ Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: "
+ PCSCLITE_HP_DROPDIR);
+ Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
+ return 0;
+ }
+
+ /* Create the udev object */
+ udev = udev_new();
+ if (!udev)
+ {
+ Log1(PCSC_LOG_ERROR, "udev_new() failed");
+ return 0;
+ }
+
+ HPRescanUsbBus(udev);
+
+ (void)ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
+ (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, udev);
+
+ return 0;
+} /* HPRegisterForHotplugEvents */
+
+
+void HPReCheckSerialReaders(void)
+{
+ /* nothing to do here */
+#ifdef DEBUG_HOTPLUG
+ Log0(PCSC_LOG_ERROR);
+#endif
+} /* HPReCheckSerialReaders */
+
+#endif
+
Propchange: trunk/PCSC/src/hotplug_libudev.c
------------------------------------------------------------------------------
svn:keywords = Id
Modified: trunk/PCSC/src/hotplug_linux.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/hotplug_linux.c?rev=5638&op=diff
==============================================================================
--- trunk/PCSC/src/hotplug_linux.c (original)
+++ trunk/PCSC/src/hotplug_linux.c Fri Feb 25 13:36:57 2011
@@ -20,7 +20,7 @@
#include "config.h"
#include <string.h>
-#if defined(__linux__) && !defined(HAVE_LIBUSB) && !defined(HAVE_LIBHAL)
+#if defined(__linux__) && !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUDEV)
#include <sys/types.h>
#include <stdio.h>
#include <dirent.h>
More information about the Pcsclite-cvs-commit
mailing list