46 #include <sys/types.h> 72 #define BUS_DEVICE_STRSIZE 10+1+10+1+10+1 74 #define READER_ABSENT 0 75 #define READER_PRESENT 1 76 #define READER_FAILED 2 81 extern char Add_Serial_In_Name;
86 pthread_mutex_t usbNotifierMutex;
88 static pthread_t usbNotifyThread;
89 static int driverSize = -1;
90 static char AraKiriHotPlug = FALSE;
91 static int rescan_pipe[] = { -1, -1 };
92 extern int HPForceReaderPolling;
95 #define IFD_GENERATE_HOTPLUG 1 100 static struct _driverTracker
103 unsigned int productID;
109 } *driverTracker = NULL;
110 #define DRIVER_TRACKER_SIZE_STEP 8 115 static struct _readerTracker
118 char bus_device[BUS_DEVICE_STRSIZE];
122 static LONG HPAddHotPluggable(
struct libusb_device *dev,
123 struct libusb_device_descriptor desc,
124 const char bus_device[],
int interface,
125 struct _driverTracker *driver);
126 static LONG HPRemoveHotPluggable(
int reader_index);
128 static LONG HPReadBundleValues(
void)
132 struct dirent *currFP = NULL;
133 char fullPath[FILENAME_MAX];
134 char fullLibPath[FILENAME_MAX];
137 hpDir = opendir(PCSCLITE_HP_DROPDIR);
141 Log1(PCSC_LOG_ERROR,
"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
142 Log1(PCSC_LOG_ERROR,
"Disabling USB support for pcscd.");
147 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP,
sizeof(*driverTracker));
148 if (NULL == driverTracker)
150 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
153 driverSize = DRIVER_TRACKER_SIZE_STEP;
155 #define GET_KEY(key, values) \ 156 rv = LTPBundleFindValueWithKey(&plist, key, values); \ 159 Log2(PCSC_LOG_ERROR, "Value/Key not defined for " key " in %s", \ 164 while ((currFP = readdir(hpDir)) != 0)
166 if (strstr(currFP->d_name,
".bundle") != 0)
170 list_t *manuIDs, *productIDs, *readerNames;
178 snprintf(fullPath,
sizeof(fullPath),
"%s/%s/Contents/Info.plist",
179 PCSCLITE_HP_DROPDIR, currFP->d_name);
180 fullPath[
sizeof(fullPath) - 1] =
'\0';
182 rv = bundleParse(fullPath, &plist);
187 GET_KEY(PCSCLITE_HP_LIBRKEY_NAME, &values)
188 libraryPath = list_get_at(values, 0);
189 (void)snprintf(fullLibPath,
sizeof(fullLibPath),
190 "%s/%s/Contents/%s/%s",
191 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
193 fullLibPath[
sizeof(fullLibPath) - 1] =
'\0';
196 GET_KEY(PCSCLITE_HP_CPCTKEY_NAME, &values)
197 ifdCapabilities = strtol(list_get_at(values, 0), NULL, 16);
199 GET_KEY(PCSCLITE_HP_MANUKEY_NAME, &manuIDs)
200 GET_KEY(PCSCLITE_HP_PRODKEY_NAME, &productIDs)
201 GET_KEY(PCSCLITE_HP_NAMEKEY_NAME, &readerNames)
204 for (alias=0; alias<list_size(manuIDs); alias++)
209 value = list_get_at(manuIDs, alias);
210 driverTracker[listCount].manuID = strtol(value, NULL, 16);
212 value = list_get_at(productIDs, alias);
213 driverTracker[listCount].productID = strtol(value, NULL, 16);
215 driverTracker[listCount].readerName = strdup(list_get_at(readerNames, alias));
218 driverTracker[listCount].bundleName = strdup(currFP->d_name);
219 driverTracker[listCount].libraryPath = strdup(fullLibPath);
220 driverTracker[listCount].ifdCapabilities = ifdCapabilities;
223 Log2(PCSC_LOG_INFO,
"Found driver for: %s",
224 driverTracker[listCount].readerName);
227 if (listCount >= driverSize)
232 driverSize += DRIVER_TRACKER_SIZE_STEP;
235 "Increase driverTracker to %d entries", driverSize);
237 driverTracker = realloc(driverTracker,
238 driverSize *
sizeof(*driverTracker));
239 if (NULL == driverTracker)
241 Log1(PCSC_LOG_CRITICAL,
"Not enough memory");
248 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
250 driverTracker[i].manuID = 0;
251 driverTracker[i].productID = 0;
252 driverTracker[i].bundleName = NULL;
253 driverTracker[i].libraryPath = NULL;
254 driverTracker[i].readerName = NULL;
255 driverTracker[i].ifdCapabilities = 0;
259 bundleRelease(&plist);
263 driverSize = listCount;
268 Log1(PCSC_LOG_INFO,
"No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
269 Log1(PCSC_LOG_INFO,
"Disabling USB support for pcscd");
273 Log2(PCSC_LOG_INFO,
"Found drivers for %d readers", listCount);
279 static void HPRescanUsbBus(
void)
282 char bus_device[BUS_DEVICE_STRSIZE];
283 libusb_device **devs, *dev;
288 readerTracker[i].status = READER_ABSENT;
290 cnt = libusb_get_device_list(ctx, &devs);
293 Log1(PCSC_LOG_CRITICAL,
"libusb_get_device_list() failed\n");
299 while ((dev = devs[cnt++]) != NULL)
301 struct libusb_device_descriptor desc;
302 struct libusb_config_descriptor *config_desc;
303 uint8_t bus_number = libusb_get_bus_number(dev);
304 uint8_t device_address = libusb_get_device_address(dev);
306 int r = libusb_get_device_descriptor(dev, &desc);
309 Log3(PCSC_LOG_ERROR,
"failed to get device descriptor for %d/%d",
310 bus_number, device_address);
314 r = libusb_get_active_config_descriptor(dev, &config_desc);
317 Log3(PCSC_LOG_ERROR,
"failed to get device config for %d/%d",
318 bus_number, device_address);
323 for (i=0; i<driverSize; i++)
325 if (driverTracker[i].libraryPath != NULL &&
326 desc.idVendor == driverTracker[i].manuID &&
327 desc.idProduct == driverTracker[i].productID)
332 Log3(PCSC_LOG_DEBUG,
"Found matching USB device: %d:%d",
333 bus_number, device_address);
336 for (interface = 0;
interface < config_desc->bNumInterfaces;
342 snprintf(bus_device, BUS_DEVICE_STRSIZE,
"%d:%d:%d",
343 bus_number, device_address, interface);
344 bus_device[BUS_DEVICE_STRSIZE - 1] =
'\0';
350 if (strncmp(readerTracker[j].bus_device,
351 bus_device, BUS_DEVICE_STRSIZE) == 0)
354 readerTracker[j].status = READER_PRESENT;
357 Log2(PCSC_LOG_DEBUG,
"Refresh USB device: %s",
367 if (config_desc->bNumInterfaces > 1)
368 HPAddHotPluggable(dev, desc, bus_device,
369 interface, &driverTracker[i]);
371 HPAddHotPluggable(dev, desc, bus_device,
372 -1, &driverTracker[i]);
377 libusb_free_config_descriptor(config_desc);
385 if ((readerTracker[i].status == READER_ABSENT) &&
386 (readerTracker[i].fullName != NULL))
387 HPRemoveHotPluggable(i);
394 for (i=0; i<driverSize; i++)
397 free(driverTracker[i].bundleName);
398 free(driverTracker[i].libraryPath);
399 free(driverTracker[i].readerName);
403 Log1(PCSC_LOG_INFO,
"Hotplug stopped");
404 pthread_exit(&retval);
408 libusb_free_device_list(devs, 1);
411 static void HPEstablishUSBNotifications(
int pipefd[2])
417 r = libusb_init(ctx);
420 Log2(PCSC_LOG_CRITICAL,
"libusb_init failed: %d", r);
422 kill(getpid(), SIGTERM);
430 write(pipefd[1], &c, 1);
434 for (i=0; i<driverSize; i++)
435 if (driverTracker[i].libraryPath)
436 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
439 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
440 driverTracker[i].bundleName);
441 if (HPForceReaderPolling < 1)
442 HPForceReaderPolling = 1;
446 if (HPForceReaderPolling)
449 "Polling forced every %d second(s)", HPForceReaderPolling);
455 while (!AraKiriHotPlug)
466 while (read(rescan_pipe[0], &dummy,
sizeof(dummy)) > 0)
468 Log1(PCSC_LOG_INFO,
"Reload serial configuration");
471 RFReCheckReaderConf();
473 Log1(PCSC_LOG_INFO,
"End reload serial configuration");
475 close(rescan_pipe[0]);
480 LONG HPSearchHotPluggables(
void)
486 readerTracker[i].status = READER_ABSENT;
487 readerTracker[i].bus_device[0] =
'\0';
488 readerTracker[i].fullName = NULL;
491 if (HPReadBundleValues() > 0)
496 if (pipe(pipefd) == -1)
498 Log2(PCSC_LOG_ERROR,
"pipe: %s", strerror(errno));
502 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
503 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
506 read(pipefd[0], &c, 1);
516 LONG HPStopHotPluggables(
void)
518 AraKiriHotPlug = TRUE;
519 if (rescan_pipe[1] >= 0)
521 close(rescan_pipe[1]);
528 static LONG HPAddHotPluggable(
struct libusb_device *dev,
529 struct libusb_device_descriptor desc,
530 const char bus_device[],
int interface,
531 struct _driverTracker *driver)
534 char deviceName[MAX_DEVICENAME];
536 Log2(PCSC_LOG_INFO,
"Adding USB device: %s", bus_device);
539 snprintf(deviceName,
sizeof(deviceName),
"usb:%04x/%04x:libhal:/org/freedesktop/Hal/devices/usb_device_%04x_%04x_serialnotneeded_if%d",
540 desc.idVendor, desc.idProduct, desc.idVendor, desc.idProduct,
543 snprintf(deviceName,
sizeof(deviceName),
"usb:%04x/%04x:libusb-1.0:%s",
544 desc.idVendor, desc.idProduct, bus_device);
546 deviceName[
sizeof(deviceName) -1] =
'\0';
548 pthread_mutex_lock(&usbNotifierMutex);
553 if (readerTracker[i].fullName == NULL)
560 "Not enough reader entries. Already found %d readers", i);
561 pthread_mutex_unlock(&usbNotifierMutex);
565 strncpy(readerTracker[i].bus_device, bus_device,
566 sizeof(readerTracker[i].bus_device));
567 readerTracker[i].bus_device[
sizeof(readerTracker[i].bus_device) - 1] =
'\0';
569 if (Add_Serial_In_Name && desc.iSerialNumber)
571 libusb_device_handle *device;
574 ret = libusb_open(dev, &device);
577 Log2(PCSC_LOG_ERROR,
"libusb_open failed: %d", ret);
581 unsigned char serialNumber[MAX_READERNAME];
583 ret = libusb_get_string_descriptor_ascii(device, desc.iSerialNumber,
584 serialNumber, MAX_READERNAME);
585 libusb_close(device);
590 "libusb_get_string_descriptor_ascii failed: %d", ret);
591 readerTracker[i].fullName = strdup(driver->readerName);
595 char fullname[MAX_READERNAME];
597 snprintf(fullname,
sizeof(fullname),
"%s (%s)",
598 driver->readerName, serialNumber);
599 readerTracker[i].fullName = strdup(fullname);
604 readerTracker[i].fullName = strdup(driver->readerName);
606 if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
608 readerTracker[i].status = READER_PRESENT;
611 readerTracker[i].status = READER_FAILED;
613 (void)CheckForOpenCT();
616 pthread_mutex_unlock(&usbNotifierMutex);
621 static LONG HPRemoveHotPluggable(
int reader_index)
623 pthread_mutex_lock(&usbNotifierMutex);
625 Log3(PCSC_LOG_INFO,
"Removing USB device[%d]: %s", reader_index,
626 readerTracker[reader_index].bus_device);
628 RFRemoveReader(readerTracker[reader_index].fullName,
629 PCSCLITE_HP_BASE_PORT + reader_index);
630 free(readerTracker[reader_index].fullName);
631 readerTracker[reader_index].status = READER_ABSENT;
632 readerTracker[reader_index].bus_device[0] =
'\0';
633 readerTracker[reader_index].fullName = NULL;
635 pthread_mutex_unlock(&usbNotifierMutex);
643 ULONG HPRegisterForHotplugEvents(
void)
645 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
649 void HPReCheckSerialReaders(
void)
652 if (rescan_pipe[1] >= 0)
655 write(rescan_pipe[1], &dummy,
sizeof(dummy));
#define SCARD_S_SUCCESS
No error was encountered.
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.