25 #include <sys/types.h>
49 #define ADD_SERIAL_NUMBER
52 #define BUS_DEVICE_STRSIZE 10+1+10+1+10+1
54 #define READER_ABSENT 0
55 #define READER_PRESENT 1
56 #define READER_FAILED 2
64 pthread_mutex_t usbNotifierMutex;
66 static pthread_t usbNotifyThread;
67 static int driverSize = -1;
68 static char AraKiriHotPlug = FALSE;
69 static int rescan_pipe[] = { -1, -1 };
70 extern int HPForceReaderPolling;
73 #define IFD_GENERATE_HOTPLUG 1
78 static struct _driverTracker
81 unsigned int productID;
87 } *driverTracker = NULL;
88 #define DRIVER_TRACKER_SIZE_STEP 8
93 static struct _readerTracker
96 char bus_device[BUS_DEVICE_STRSIZE];
100 static LONG HPAddHotPluggable(
struct libusb_device *dev,
101 struct libusb_device_descriptor desc,
102 const char bus_device[],
int interface,
103 struct _driverTracker *driver);
104 static LONG HPRemoveHotPluggable(
int reader_index);
106 static LONG HPReadBundleValues(
void)
110 struct dirent *currFP = NULL;
111 char fullPath[FILENAME_MAX];
112 char fullLibPath[FILENAME_MAX];
115 hpDir = opendir(PCSCLITE_HP_DROPDIR);
119 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
120 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
125 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP,
sizeof(*driverTracker));
126 if (NULL == driverTracker)
128 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
131 driverSize = DRIVER_TRACKER_SIZE_STEP;
133 #define GET_KEY(key, values) \
134 rv = LTPBundleFindValueWithKey(&plist, key, values); \
137 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \
142 while ((currFP = readdir(hpDir)) != 0)
144 if (strstr(currFP->d_name,
".bundle") != 0)
148 list_t *manuIDs, *productIDs, *readerNames;
156 snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
157 PCSCLITE_HP_DROPDIR, currFP->d_name);
158 fullPath[
sizeof(fullPath) - 1] =
'\0';
165 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
166 libraryPath = list_get_at(values, 0);
167 (
void)snprintf(fullLibPath, sizeof(fullLibPath),
168 "%s/%s/Contents/%s/%s",
169 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
171 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
174 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
175 ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
177 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
178 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
179 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
182 for (alias=0; alias<list_size(manuIDs); alias++)
187 value = list_get_at(manuIDs, alias);
188 driverTracker[listCount].manuID = strtol(value, NULL, 16);
190 value = list_get_at(productIDs, alias);
191 driverTracker[listCount].productID = strtol(value, NULL, 16);
193 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
196 driverTracker[listCount].bundleName = strdup(currFP->d_name);
197 driverTracker[listCount].libraryPath = strdup(fullLibPath);
198 driverTracker[listCount].ifdCapabilities = ifdCapabilities;
201 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
202 driverTracker[listCount].readerName);
205 if (listCount >= driverSize)
210 driverSize += DRIVER_TRACKER_SIZE_STEP;
213 "Increase driverTracker to %d entries", driverSize);
215 driverTracker = realloc(driverTracker,
216 driverSize *
sizeof(*driverTracker));
217 if (NULL == driverTracker)
219 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
226 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
228 driverTracker[i].manuID = 0;
229 driverTracker[i].productID = 0;
230 driverTracker[i].bundleName = NULL;
231 driverTracker[i].libraryPath = NULL;
232 driverTracker[i].readerName = NULL;
233 driverTracker[i].ifdCapabilities = 0;
241 driverSize = listCount;
247 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
248 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
253 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
259 static void HPRescanUsbBus(
void)
262 char bus_device[BUS_DEVICE_STRSIZE];
263 libusb_device **devs, *dev;
268 readerTracker[i].status = READER_ABSENT;
270 cnt = libusb_get_device_list(ctx, &devs);
273 Log1(PCSC_LOG_CRITICAL,
"libusb_get_device_list() failed\n");
279 while ((dev = devs[cnt++]) != NULL)
281 struct libusb_device_descriptor desc;
282 struct libusb_config_descriptor *config_desc;
283 uint8_t bus_number = libusb_get_bus_number(dev);
284 uint8_t device_address = libusb_get_device_address(dev);
286 int r = libusb_get_device_descriptor(dev, &desc);
289 Log3(PCSC_LOG_ERROR,
"failed to get device descriptor for %d/%d",
290 bus_number, device_address);
294 r = libusb_get_active_config_descriptor(dev, &config_desc);
297 Log3(PCSC_LOG_ERROR,
"failed to get device config for %d/%d",
298 bus_number, device_address);
303 for (i=0; i<driverSize; i++)
305 if (driverTracker[i].libraryPath != NULL &&
306 desc.idVendor == driverTracker[i].manuID &&
307 desc.idProduct == driverTracker[i].productID)
312 Log3(PCSC_LOG_DEBUG,
"Found matching USB device: %d:%d",
313 bus_number, device_address);
316 for (interface = 0;
interface < config_desc->bNumInterfaces;
322 snprintf(bus_device, BUS_DEVICE_STRSIZE,
"%d:%d:%d",
323 bus_number, device_address, interface);
324 bus_device[BUS_DEVICE_STRSIZE - 1] =
'\0';
330 if (strncmp(readerTracker[j].bus_device,
331 bus_device, BUS_DEVICE_STRSIZE) == 0)
334 readerTracker[j].status = READER_PRESENT;
337 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s",
347 if (config_desc->bNumInterfaces > 1)
348 HPAddHotPluggable(dev, desc, bus_device,
349 interface, &driverTracker[i]);
351 HPAddHotPluggable(dev, desc, bus_device,
352 -1, &driverTracker[i]);
357 libusb_free_config_descriptor(config_desc);
365 if ((readerTracker[i].status == READER_ABSENT) &&
366 (readerTracker[i].fullName != NULL))
367 HPRemoveHotPluggable(i);
374 for (i=0; i<driverSize; i++)
377 free(driverTracker[i].bundleName);
378 free(driverTracker[i].libraryPath);
379 free(driverTracker[i].readerName);
383 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
384 pthread_exit(&retval);
388 libusb_free_device_list(devs, 1);
391 static void HPEstablishUSBNotifications(
int pipefd[2])
397 r = libusb_init(ctx);
400 Log2(PCSC_LOG_CRITICAL,
"libusb_init failed: %d", r);
402 kill(getpid(), SIGTERM);
410 write(pipefd[1], &c, 1);
415 for (i=0; i<driverSize; i++)
416 if (driverTracker[i].libraryPath)
417 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
420 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
421 driverTracker[i].bundleName);
422 if (HPForceReaderPolling < 1)
423 HPForceReaderPolling = 1;
427 if (HPForceReaderPolling)
430 "Polling forced every %d second(s)", HPForceReaderPolling);
436 while (!AraKiriHotPlug)
447 while (read(rescan_pipe[0], &dummy,
sizeof(dummy)) > 0)
449 Log1(PCSC_LOG_INFO,
"Reload serial configuration");
452 RFReCheckReaderConf();
454 Log1(PCSC_LOG_INFO,
"End reload serial configuration");
456 close(rescan_pipe[0]);
461 LONG HPSearchHotPluggables(
void)
467 readerTracker[i].status = READER_ABSENT;
468 readerTracker[i].bus_device[0] =
'\0';
469 readerTracker[i].fullName = NULL;
472 if (HPReadBundleValues())
477 if (pipe(pipefd) == -1)
479 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
483 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
484 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
487 read(pipefd[0], &c, 1);
494 LONG HPStopHotPluggables(
void)
496 AraKiriHotPlug = TRUE;
497 if (rescan_pipe[1] >= 0)
499 close(rescan_pipe[1]);
506 static LONG HPAddHotPluggable(
struct libusb_device *dev,
507 struct libusb_device_descriptor desc,
508 const char bus_device[],
int interface,
509 struct _driverTracker *driver)
512 char deviceName[MAX_DEVICENAME];
514 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", bus_device);
517 snprintf(deviceName,
sizeof(deviceName),
"usb:%04x/%04x:libhal:/org/freedesktop/Hal/devices/usb_device_%04x_%04x_serialnotneeded_if%d",
518 desc.idVendor, desc.idProduct, desc.idVendor, desc.idProduct,
521 snprintf(deviceName,
sizeof(deviceName),
"usb:%04x/%04x:libusb-1.0:%s",
522 desc.idVendor, desc.idProduct, bus_device);
524 deviceName[
sizeof(deviceName) -1] =
'\0';
526 pthread_mutex_lock(&usbNotifierMutex);
531 if (readerTracker[i].fullName == NULL)
535 if (i==PCSCLITE_MAX_READERS_CONTEXTS)
538 "Not enough reader entries. Already found %d readers", i);
539 pthread_mutex_unlock(&usbNotifierMutex);
543 strncpy(readerTracker[i].bus_device, bus_device,
544 sizeof(readerTracker[i].bus_device));
545 readerTracker[i].bus_device[
sizeof(readerTracker[i].bus_device) - 1] =
'\0';
547 #ifdef ADD_SERIAL_NUMBER
548 if (desc.iSerialNumber)
550 libusb_device_handle *device;
551 unsigned char serialNumber[MAX_READERNAME];
552 char fullname[MAX_READERNAME];
555 ret = libusb_open(dev, &device);
558 Log2(PCSC_LOG_ERROR,
"libusb_open failed: %d", ret);
562 ret = libusb_get_string_descriptor_ascii(device, desc.iSerialNumber,
563 serialNumber, MAX_READERNAME);
564 libusb_close(device);
569 "libusb_get_string_descriptor_ascii failed: %d", ret);
570 readerTracker[i].fullName = strdup(driver->readerName);
574 snprintf(fullname,
sizeof(fullname),
"%s (%s)",
575 driver->readerName, serialNumber);
576 readerTracker[i].fullName = strdup(fullname);
582 readerTracker[i].fullName = strdup(driver->readerName);
584 if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
586 readerTracker[i].status = READER_PRESENT;
589 readerTracker[i].status = READER_FAILED;
591 (void)CheckForOpenCT();
594 pthread_mutex_unlock(&usbNotifierMutex);
599 static LONG HPRemoveHotPluggable(
int reader_index)
601 pthread_mutex_lock(&usbNotifierMutex);
603 Log3(PCSC_LOG_INFO,
"Removing USB device[%d]: %s", reader_index,
604 readerTracker[reader_index].bus_device);
606 RFRemoveReader(readerTracker[reader_index].fullName,
607 PCSCLITE_HP_BASE_PORT + reader_index);
608 free(readerTracker[reader_index].fullName);
609 readerTracker[reader_index].status = READER_ABSENT;
610 readerTracker[reader_index].bus_device[0] =
'\0';
611 readerTracker[reader_index].fullName = NULL;
613 pthread_mutex_unlock(&usbNotifierMutex);
621 ULONG HPRegisterForHotplugEvents(
void)
623 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
627 void HPReCheckSerialReaders(
void)
630 if (rescan_pipe[1] >= 0)
633 write(rescan_pipe[1], &dummy,
sizeof(dummy));
This handles abstract system level calls.
int SYS_Sleep(int)
Makes the current process sleep for some seconds.
Reads lexical config files and updates database.
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
This defines some structures and #defines to be used over the transport layer.
This keeps a list of Windows(R) types.
This keeps a list of defines for pcsc-lite.
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.
int bundleParse(const char *fileName, list_t *l)
Parse a Info.plist file and file a list.
void bundleRelease(list_t *l)
Free the list created by bundleParse()
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx