static LONG HPRemoveHotPluggable(int reader_index)
{
	SYS_MutexLock(&usbNotifierMutex);

	Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
		readerTracker[reader_index].bus_device);

	RFRemoveReader(readerTracker[reader_index].fullName,
		PCSCLITE_HP_BASE_PORT + reader_index);
	free(readerTracker[reader_index].fullName);
	readerTracker[reader_index].status = READER_ABSENT;
	readerTracker[reader_index].bus_device[0] = '\0';
	readerTracker[reader_index].fullName = NULL;

	SYS_MutexUnLock(&usbNotifierMutex);

	return 1;
}	/* End of function */
static LONG HPRemoveHotPluggable(int i, unsigned long usbAddr)
{
	RFRemoveReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr);

	return 1;
}	/* End of function */
Beispiel #3
0
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, *classdriver;
		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);
		if (!devpath)
		{
			/* the device disapeared? */
			Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed");
			continue;
		}

		driver = get_driver(parent, devpath, &classdriver);
		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);
		}
	}
}
LONG RFAddReader(const char *readerNameLong, int port, const char *library,
	const char *device)
{
	DWORD dwContext = 0, dwGetSize;
	UCHAR ucGetData[1], ucThread[1];
	LONG rv, parentNode;
	int i, j;
	int lrv = 0;
	char *readerName = NULL;

	if ((readerNameLong == NULL) || (library == NULL) || (device == NULL))
		return SCARD_E_INVALID_VALUE;

#ifdef FILTER_NAMES
	const char *ro_filter = getenv("PCSCLITE_FILTER_IGNORE_READER_NAMES");
	if (ro_filter)
	{
		char *filter, *next;

		/* get a RW copy of the env string */
		filter = alloca(strlen(ro_filter)+1);
		strcpy(filter, ro_filter);

		while (filter)
		{
			/* ':' is the separator */
			next = strchr(filter, ':');
			if (next)
			{
				/* NUL terminate the current pattern */
				*next = '\0';
			}

			/* if filter is non empty and found in the reader name */
			if (*filter && strstr(readerNameLong, filter))
			{
				Log3(PCSC_LOG_ERROR,
					"Reader name \"%s\" contains \"%s\": ignored",
					readerNameLong, filter);
				return SCARD_E_READER_UNAVAILABLE;
			}

			if (next)
				/* next pattern */
				filter = next+1;
			else
				/* end */
				filter = NULL;
		}
	}
#endif

	/* allocate memory that is automatically freed */
	readerName = alloca(strlen(readerNameLong)+1);
	strcpy(readerName, readerNameLong);

	/* Reader name too long? also count " 00 00"*/
	if (strlen(readerName) > MAX_READERNAME - sizeof(" 00 00"))
	{
		Log3(PCSC_LOG_ERROR,
			"Reader name too long: %zd chars instead of max %zd. Truncating!",
			strlen(readerName), MAX_READERNAME - sizeof(" 00 00"));
		readerName[MAX_READERNAME - sizeof(" 00 00")] = '\0';
	}

	/* Same name, same port, same device - duplicate reader cannot be used */
	if (dwNumReadersContexts != 0)
	{
		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
		{
			if (sReadersContexts[i]->vHandle != 0)
			{
				char lpcStripReader[MAX_READERNAME];
				int tmplen;

				/* get the reader name without the reader and slot numbers */
				strncpy(lpcStripReader,
					sReadersContexts[i]->readerState->readerName,
					sizeof(lpcStripReader));
				tmplen = strlen(lpcStripReader);
				lpcStripReader[tmplen - 6] = 0;

				if ((strcmp(readerName, lpcStripReader) == 0)
					&& (port == sReadersContexts[i]->port)
					&& (strcmp(device, sReadersContexts[i]->device) == 0))
				{
					Log1(PCSC_LOG_ERROR, "Duplicate reader found.");
					return SCARD_E_DUPLICATE_READER;
				}
			}
		}
	}

	/* We must find an empty slot to put the reader structure */
	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
	{
		if (sReadersContexts[i]->vHandle == 0)
		{
			dwContext = i;
			break;
		}
	}

	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
	{
		/* No more spots left return */
		return SCARD_E_NO_MEMORY;
	}

	/* Check and set the readername to see if it must be enumerated */
	parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName,
		library, port);
	if (parentNode < -1)
		return SCARD_E_NO_MEMORY;

	sReadersContexts[dwContext]->library = strdup(library);
	sReadersContexts[dwContext]->device = strdup(device);
	sReadersContexts[dwContext]->version = 0;
	sReadersContexts[dwContext]->port = port;
	sReadersContexts[dwContext]->mMutex = NULL;
	sReadersContexts[dwContext]->contexts = 0;
	sReadersContexts[dwContext]->pthThread = 0;
	sReadersContexts[dwContext]->hLockId = 0;
	sReadersContexts[dwContext]->LockCount = 0;
	sReadersContexts[dwContext]->vHandle = NULL;
	sReadersContexts[dwContext]->pFeeds = NULL;
	sReadersContexts[dwContext]->pMutex = NULL;
	sReadersContexts[dwContext]->pthCardEvent = NULL;

	lrv = list_init(&sReadersContexts[dwContext]->handlesList);
	if (lrv < 0)
	{
		Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
		return SCARD_E_NO_MEMORY;
	}

	lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList,
		RDR_CLIHANDLES_seeker);
	if (lrv < 0)
	{
		Log2(PCSC_LOG_CRITICAL,
			"list_attributes_seeker failed with return value: %d", lrv);
		return SCARD_E_NO_MEMORY;
	}

	(void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock,
		NULL);

	(void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock,
		NULL);
	sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;

	/* reference count */
	(void)pthread_mutex_init(&sReadersContexts[dwContext]->reference_lock,
		NULL);
	sReadersContexts[dwContext]->reference = 1;

	/* If a clone to this reader exists take some values from that clone */
	if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
	{
		sReadersContexts[dwContext]->pFeeds =
		  sReadersContexts[parentNode]->pFeeds;
		*(sReadersContexts[dwContext])->pFeeds += 1;
		sReadersContexts[dwContext]->vHandle =
		  sReadersContexts[parentNode]->vHandle;
		sReadersContexts[dwContext]->mMutex =
		  sReadersContexts[parentNode]->mMutex;
		sReadersContexts[dwContext]->pMutex =
		  sReadersContexts[parentNode]->pMutex;

		/* Call on the parent driver to see if it is thread safe */
		dwGetSize = sizeof(ucThread);
		rv = IFDGetCapabilities(sReadersContexts[parentNode],
			TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);

		if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
		{
			Log1(PCSC_LOG_INFO, "Driver is thread safe");
			sReadersContexts[dwContext]->mMutex = NULL;
			sReadersContexts[dwContext]->pMutex = NULL;
		}
		else
			*(sReadersContexts[dwContext])->pMutex += 1;
	}

	if (sReadersContexts[dwContext]->pFeeds == NULL)
	{
		sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int));

		/* Initialize pFeeds to 1, otherwise multiple
		   cloned readers will cause pcscd to crash when
		   RFUnloadReader unloads the driver library
		   and there are still devices attached using it --mikeg*/
		*(sReadersContexts[dwContext])->pFeeds = 1;
	}

	if (sReadersContexts[dwContext]->mMutex == 0)
	{
		sReadersContexts[dwContext]->mMutex =
			malloc(sizeof(pthread_mutex_t));
		(void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL);
	}

	if (sReadersContexts[dwContext]->pMutex == NULL)
	{
		sReadersContexts[dwContext]->pMutex = malloc(sizeof(int));
		*(sReadersContexts[dwContext])->pMutex = 1;
	}

	dwNumReadersContexts += 1;

	rv = RFInitializeReader(sReadersContexts[dwContext]);
	if (rv != SCARD_S_SUCCESS)
	{
		/* Cannot connect to reader. Exit gracefully */
		Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
		(void)RFRemoveReader(readerName, port);
		return rv;
	}

	/* asynchronous card movement?  */
	{
		RESPONSECODE (*fct)(DWORD, int) = NULL;

		dwGetSize = sizeof(fct);

		rv = IFDGetCapabilities(sReadersContexts[dwContext],
			TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
		if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
		{
			Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
		}
		else
		{
			sReadersContexts[dwContext]->pthCardEvent = fct;
			Log1(PCSC_LOG_INFO, "Using the reader polling thread");
		}

		rv = EHSpawnEventHandler(sReadersContexts[dwContext]);
		if (rv != SCARD_S_SUCCESS)
		{
			Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
			(void)RFRemoveReader(readerName, port);
			return rv;
		}
	}

	/* Call on the driver to see if there are multiple slots */
	dwGetSize = sizeof(ucGetData);
	rv = IFDGetCapabilities((sReadersContexts[dwContext]),
		TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData);

	int nbSlots = ucGetData[0];
	if (rv != IFD_SUCCESS || dwGetSize != 1 || nbSlots == 0)
		/* Reader does not have this defined.  Must be a single slot
		 * reader so we can just return SCARD_S_SUCCESS. */
		return SCARD_S_SUCCESS;

	if (1 == nbSlots)
		/* Reader has only one slot */
		return SCARD_S_SUCCESS;

	/*
	 * Check the number of slots and create a different
	 * structure for each one accordingly
	 */

	/* Initialize the rest of the slots */
	for (j = 1; j < nbSlots; j++)
	{
		char *tmpReader = NULL;
		DWORD dwContextB = 0;
		RESPONSECODE (*fct)(DWORD, int) = NULL;

		/* We must find an empty spot to put the reader structure */
		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
		{
			if (sReadersContexts[i]->vHandle == 0)
			{
				dwContextB = i;
				break;
			}
		}

		if (i == PCSCLITE_MAX_READERS_CONTEXTS)
		{
			/* No more slot left return */
			RFRemoveReader(readerName, port);
			return SCARD_E_NO_MEMORY;
		}

		/* Copy the previous reader name and increment the slot number */
		tmpReader = sReadersContexts[dwContextB]->readerState->readerName;
		memcpy(tmpReader,
			sReadersContexts[dwContext]->readerState->readerName,
			sizeof(sReadersContexts[dwContextB]->readerState->readerName));
		snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j);

		sReadersContexts[dwContextB]->library =
			sReadersContexts[dwContext]->library;
		sReadersContexts[dwContextB]->device =
			sReadersContexts[dwContext]->device;
		sReadersContexts[dwContextB]->version =
		  sReadersContexts[dwContext]->version;
		sReadersContexts[dwContextB]->port =
		  sReadersContexts[dwContext]->port;
		sReadersContexts[dwContextB]->vHandle =
		  sReadersContexts[dwContext]->vHandle;
		sReadersContexts[dwContextB]->mMutex =
		  sReadersContexts[dwContext]->mMutex;
		sReadersContexts[dwContextB]->pMutex =
		  sReadersContexts[dwContext]->pMutex;
		sReadersContexts[dwContextB]->slot =
			sReadersContexts[dwContext]->slot + j;
		sReadersContexts[dwContextB]->pthCardEvent = NULL;

		/*
		 * Added by Dave - slots did not have a pFeeds
		 * parameter so it was by luck they were working
		 */
		sReadersContexts[dwContextB]->pFeeds =
		  sReadersContexts[dwContext]->pFeeds;

		/* Added by Dave for multiple slots */
		*(sReadersContexts[dwContextB])->pFeeds += 1;

		sReadersContexts[dwContextB]->contexts = 0;
		sReadersContexts[dwContextB]->hLockId = 0;
		sReadersContexts[dwContextB]->LockCount = 0;

		lrv = list_init(&sReadersContexts[dwContextB]->handlesList);
		if (lrv < 0)
		{
			Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv);
			return SCARD_E_NO_MEMORY;
		}

		lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList,
			RDR_CLIHANDLES_seeker);
		if (lrv < 0)
		{
			Log2(PCSC_LOG_CRITICAL,
					"list_attributes_seeker failed with return value: %d", lrv);
			return SCARD_E_NO_MEMORY;
		}

		(void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL);
		(void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock,
			NULL);
		sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED;

		/* reference count */
		(void)pthread_mutex_init(&sReadersContexts[dwContextB]->reference_lock,
			NULL);
		sReadersContexts[dwContextB]->reference = 1;

		/* Call on the parent driver to see if the slots are thread safe */
		dwGetSize = sizeof(ucThread);
		rv = IFDGetCapabilities((sReadersContexts[dwContext]),
			TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread);

		if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
		{
			Log1(PCSC_LOG_INFO, "Driver is slot thread safe");

			sReadersContexts[dwContextB]->library =
				strdup(sReadersContexts[dwContext]->library);
			sReadersContexts[dwContextB]->device =
				strdup(sReadersContexts[dwContext]->device);
			sReadersContexts[dwContextB]->mMutex =
				malloc(sizeof(pthread_mutex_t));
			(void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex,
				NULL);

			sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int));
			*(sReadersContexts[dwContextB])->pMutex = 1;
		}
		else
			*(sReadersContexts[dwContextB])->pMutex += 1;

		dwNumReadersContexts += 1;

		rv = RFInitializeReader(sReadersContexts[dwContextB]);
		if (rv != SCARD_S_SUCCESS)
		{
			/* Cannot connect to slot. Exit gracefully */
			(void)RFRemoveReader(readerName, port);
			return rv;
		}

		/* asynchronous card movement? */
		dwGetSize = sizeof(fct);

		rv = IFDGetCapabilities((sReadersContexts[dwContextB]),
			TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct);
		if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct)))
		{
			Log1(PCSC_LOG_INFO, "Using the pcscd polling thread");
		}
		else
		{
			sReadersContexts[dwContextB]->pthCardEvent = fct;
			Log1(PCSC_LOG_INFO, "Using the reader polling thread");
		}

		rv = EHSpawnEventHandler(sReadersContexts[dwContextB]);
		if (rv != SCARD_S_SUCCESS)
		{
			Log2(PCSC_LOG_ERROR, "%s init failed.", readerName);
			(void)RFRemoveReader(readerName, port);
			return rv;
		}
	}

	return SCARD_S_SUCCESS;
}
Beispiel #5
0
/*
 * Scans the hotplug driver directory and looks in the system for
 * matching devices.
 * Adds or removes matching readers as necessary.
 */
LONG HPSearchHotPluggables(void)
{
	HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);

	if (!drivers)
		return 1;

	HPDeviceList devices = NULL;

	if (HPDriversMatchUSBDevices(drivers, &devices))
		return -1;

	if (HPDriversMatchPCCardDevices(drivers, &devices))
		return -1;

	HPDevice *a;

	for (a = devices; a; a = a->m_next)
	{
		int found = FALSE;
		HPDevice *b;

		for (b = sDeviceList; b; b = b->m_next)
		{
			if (HPDeviceEquals(a, b))
			{
				found = TRUE;
				break;
			}
		}
		if (!found)
		{
			char deviceName[MAX_DEVICENAME];

			/* the format should be "usb:%04x/%04x" but Apple uses the
			 * friendly name instead */
			snprintf(deviceName, sizeof(deviceName),
				"%s", a->m_driver->m_friendlyName);
			deviceName[sizeof(deviceName)-1] = '\0';

			RFAddReader(a->m_driver->m_friendlyName,
				PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
				deviceName);
		}
	}

	for (a = sDeviceList; a; a = a->m_next)
	{
		int found = FALSE;
		HPDevice *b;

		for (b = devices; b; b = b->m_next)
		{
			if (HPDeviceEquals(a, b))
			{
				found = TRUE;
				break;
			}
		}
		if (!found)
		{
			RFRemoveReader(a->m_driver->m_friendlyName,
				PCSCLITE_HP_BASE_PORT + a->m_address);
		}
	}

	HPDeviceListRelease(sDeviceList);
	sDeviceList = devices;
	HPDriverVectorRelease(drivers);

	return 0;
}
/*
 * Scans the hotplug driver directory and looks in the system for
 * matching devices.
 * Adds or removes matching readers as necessary.
 */
LONG HPSearchHotPluggables(void)
{
	HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);

	if (!drivers)
		return 1;

	HPDeviceList devices = NULL;

	if (HPDriversMatchUSBDevices(drivers, &devices))
		return -1;

	if (HPDriversMatchPCCardDevices(drivers, &devices))
		return -1;

	HPDevice *a;

	for (a = devices; a; a = a->m_next)
	{
		int found = FALSE;
		HPDevice *b;

		for (b = sDeviceList; b; b = b->m_next)
		{
			if (HPDeviceEquals(a, b))
			{
				found = TRUE;
				break;
			}
		}
		if (!found)
		{
			char deviceName[MAX_DEVICENAME];

			/* the format should be "usb:%04x/%04x:libusb:%s" but we do not
			 * know the libusb string. So it is not possible to differentiate
			 * two identical readers :-( */
			snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x",
				(unsigned int)a->m_driver->m_vendorId,
				(unsigned int)a->m_driver->m_productId);
			deviceName[sizeof(deviceName)-1] = '\0';

			RFAddReader(a->m_driver->m_friendlyName,
				PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
				deviceName);
		}
	}

	for (a = sDeviceList; a; a = a->m_next)
	{
		int found = FALSE;
		HPDevice *b;

		for (b = devices; b; b = b->m_next)
		{
			if (HPDeviceEquals(a, b))
			{
				found = TRUE;
				break;
			}
		}
		if (!found)
		{
			RFRemoveReader(a->m_driver->m_friendlyName,
				PCSCLITE_HP_BASE_PORT + a->m_address);
		}
	}

	HPDeviceListRelease(sDeviceList);
	sDeviceList = devices;
	HPDriverVectorRelease(drivers);

	return 0;
}