00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00021 #include "config.h"
00022 #ifdef HAVE_LIBUSB
00023
00024 #include <string.h>
00025 #include <sys/types.h>
00026 #include <stdio.h>
00027 #include <dirent.h>
00028 #include <fcntl.h>
00029 #include <time.h>
00030 #include <stdlib.h>
00031 #include <unistd.h>
00032 #include <errno.h>
00033 #include <usb.h>
00034 #include <pthread.h>
00035
00036 #include "misc.h"
00037 #include "wintypes.h"
00038 #include "pcscd.h"
00039 #include "debuglog.h"
00040 #include "parser.h"
00041 #include "readerfactory.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044 #include "hotplug.h"
00045 #include "utils.h"
00046
00047 #undef DEBUG_HOTPLUG
00048 #define ADD_SERIAL_NUMBER
00049
00050 #define BUS_DEVICE_STRSIZE 256
00051
00052 #define READER_ABSENT 0
00053 #define READER_PRESENT 1
00054 #define READER_FAILED 2
00055
00056 #define FALSE 0
00057 #define TRUE 1
00058
00059 pthread_mutex_t usbNotifierMutex;
00060
00061 static pthread_t usbNotifyThread;
00062 static int driverSize = -1;
00063 static char AraKiriHotPlug = FALSE;
00064 static int rescan_pipe[] = { -1, -1 };
00065 extern int HPForceReaderPolling;
00066
00067
00068 #define IFD_GENERATE_HOTPLUG 1
00069
00073 static struct _driverTracker
00074 {
00075 long manuID;
00076 long productID;
00077
00078 char *bundleName;
00079 char *libraryPath;
00080 char *readerName;
00081 int ifdCapabilities;
00082 } *driverTracker = NULL;
00083 #define DRIVER_TRACKER_SIZE_STEP 8
00084
00088 static struct _readerTracker
00089 {
00090 char status;
00091 char bus_device[BUS_DEVICE_STRSIZE];
00092 char *fullName;
00093 } readerTracker[PCSCLITE_MAX_READERS_CONTEXTS];
00094
00095 static LONG HPReadBundleValues(void);
00096 static LONG HPAddHotPluggable(struct usb_device *dev, const char bus_device[],
00097 struct _driverTracker *driver);
00098 static LONG HPRemoveHotPluggable(int reader_index);
00099 static void HPRescanUsbBus(void);
00100 static void HPEstablishUSBNotifications(int pipefd[2]);
00101
00102 static LONG HPReadBundleValues(void)
00103 {
00104 LONG rv;
00105 DIR *hpDir;
00106 struct dirent *currFP = NULL;
00107 char fullPath[FILENAME_MAX];
00108 char fullLibPath[FILENAME_MAX];
00109 char keyValue[TOKEN_MAX_VALUE_SIZE];
00110 int listCount = 0;
00111
00112 hpDir = opendir(PCSCLITE_HP_DROPDIR);
00113
00114 if (hpDir == NULL)
00115 {
00116 Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
00117 Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd.");
00118 return -1;
00119 }
00120
00121
00122 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP, sizeof(*driverTracker));
00123 if (NULL == driverTracker)
00124 {
00125 Log1(PCSC_LOG_CRITICAL, "Not enough memory");
00126 return -1;
00127 }
00128 driverSize = DRIVER_TRACKER_SIZE_STEP;
00129
00130 while ((currFP = readdir(hpDir)) != 0)
00131 {
00132 if (strstr(currFP->d_name, ".bundle") != 0)
00133 {
00134 int alias = 0;
00135
00136
00137
00138
00139
00140 snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist",
00141 PCSCLITE_HP_DROPDIR, currFP->d_name);
00142 fullPath[sizeof(fullPath) - 1] = '\0';
00143
00144
00145 while (LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_MANUKEY_NAME,
00146 keyValue, alias) == 0)
00147 {
00148 driverTracker[listCount].bundleName = strdup(currFP->d_name);
00149
00150
00151 rv = LTPBundleFindValueWithKey(fullPath,
00152 PCSCLITE_HP_MANUKEY_NAME, keyValue, alias);
00153 if (rv == 0)
00154 driverTracker[listCount].manuID = strtol(keyValue, NULL, 16);
00155
00156
00157 rv = LTPBundleFindValueWithKey(fullPath,
00158 PCSCLITE_HP_PRODKEY_NAME, keyValue, alias);
00159 if (rv == 0)
00160 driverTracker[listCount].productID =
00161 strtol(keyValue, NULL, 16);
00162
00163
00164 rv = LTPBundleFindValueWithKey(fullPath,
00165 PCSCLITE_HP_NAMEKEY_NAME, keyValue, alias);
00166 if (rv == 0)
00167 driverTracker[listCount].readerName = strdup(keyValue);
00168
00169
00170 rv = LTPBundleFindValueWithKey(fullPath,
00171 PCSCLITE_HP_LIBRKEY_NAME, keyValue, 0);
00172 if (rv == 0)
00173 {
00174 snprintf(fullLibPath, sizeof(fullLibPath),
00175 "%s/%s/Contents/%s/%s",
00176 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH,
00177 keyValue);
00178 fullLibPath[sizeof(fullLibPath) - 1] = '\0';
00179 driverTracker[listCount].libraryPath = strdup(fullLibPath);
00180 }
00181
00182
00183 rv = LTPBundleFindValueWithKey(fullPath,
00184 PCSCLITE_HP_CPCTKEY_NAME, keyValue, 0);
00185 if (rv == 0)
00186 driverTracker[listCount].ifdCapabilities = strtol(keyValue,
00187 NULL, 16);
00188
00189 #ifdef DEBUG_HOTPLUG
00190 Log2(PCSC_LOG_INFO, "Found driver for: %s",
00191 driverTracker[listCount].readerName);
00192 #endif
00193 alias++;
00194
00195 if (NULL == driverTracker[listCount].readerName)
00196 continue;
00197
00198 listCount++;
00199 if (listCount >= driverSize)
00200 {
00201 int i;
00202
00203
00204 driverSize += DRIVER_TRACKER_SIZE_STEP;
00205 #ifdef DEBUG_HOTPLUG
00206 Log2(PCSC_LOG_INFO,
00207 "Increase driverTracker to %d entries", driverSize);
00208 #endif
00209 driverTracker = realloc(driverTracker,
00210 driverSize * sizeof(*driverTracker));
00211 if (NULL == driverTracker)
00212 {
00213 Log1(PCSC_LOG_CRITICAL, "Not enough memory");
00214 driverSize = -1;
00215 return -1;
00216 }
00217
00218
00219 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++)
00220 {
00221 driverTracker[i].manuID = 0;
00222 driverTracker[i].productID = 0;
00223 driverTracker[i].bundleName = NULL;
00224 driverTracker[i].libraryPath = NULL;
00225 driverTracker[i].readerName = NULL;
00226 driverTracker[i].ifdCapabilities = 0;
00227 }
00228 }
00229 }
00230 }
00231 }
00232
00233 driverSize = listCount;
00234 closedir(hpDir);
00235
00236 rv = TRUE;
00237 if (driverSize == 0)
00238 {
00239 Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
00240 Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
00241 rv = FALSE;
00242 }
00243 #ifdef DEBUG_HOTPLUG
00244 else
00245 Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
00246 #endif
00247
00248 return rv;
00249 }
00250
00251 static void HPRescanUsbBus(void)
00252 {
00253 int i, j;
00254 struct usb_bus *bus;
00255 struct usb_device *dev;
00256 char bus_device[BUS_DEVICE_STRSIZE];
00257
00258 usb_find_busses();
00259 usb_find_devices();
00260
00261 for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00262
00263 readerTracker[i].status = READER_ABSENT;
00264
00265
00266 for (bus = usb_get_busses(); bus; bus = bus->next)
00267 {
00268
00269 for (dev = bus->devices; dev; dev = dev->next)
00270 {
00271
00272 for (i=0; i<driverSize; i++)
00273 {
00274 if (driverTracker[i].libraryPath != NULL &&
00275 dev->descriptor.idVendor == driverTracker[i].manuID &&
00276 dev->descriptor.idProduct == driverTracker[i].productID)
00277 {
00278 int newreader;
00279
00280
00281 snprintf(bus_device, BUS_DEVICE_STRSIZE, "%s:%s",
00282 bus->dirname, dev->filename);
00283 bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
00284 #ifdef DEBUG_HOTPLUG
00285 Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s",
00286 bus_device);
00287 #endif
00288 newreader = TRUE;
00289
00290
00291 for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++)
00292 {
00293 if (strncmp(readerTracker[j].bus_device,
00294 bus_device, BUS_DEVICE_STRSIZE) == 0)
00295 {
00296
00297 readerTracker[j].status = READER_PRESENT;
00298 newreader = FALSE;
00299 #ifdef DEBUG_HOTPLUG
00300 Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s",
00301 bus_device);
00302 #endif
00303 break;
00304 }
00305 }
00306
00307
00308 if (newreader)
00309 HPAddHotPluggable(dev, bus_device, &driverTracker[i]);
00310 }
00311 }
00312 }
00313
00314 }
00315
00316
00317
00318
00319 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
00320 {
00321 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00322 int fd;
00323 char filename[BUS_DEVICE_STRSIZE];
00324
00325
00326
00327
00328
00329
00330
00331
00332 if (readerTracker[i].status == READER_PRESENT ||
00333 readerTracker[i].fullName == NULL)
00334 continue;
00335
00336 sscanf(readerTracker[i].bus_device, "%*[^:]%*[:]%s", filename);
00337 fd = open(filename, O_RDONLY);
00338 if (fd == -1)
00339 {
00340 if (errno == EBUSY)
00341 {
00342
00343 #ifdef DEBUG_HOTPLUG
00344 Log2(PCSC_LOG_DEBUG, "BSD: EBUSY on %s", filename);
00345 #endif
00346 readerTracker[i].status = READER_PRESENT;
00347 }
00348 #ifdef DEBUG_HOTPLUG
00349 else
00350 Log3(PCSC_LOG_DEBUG, "BSD: %s error: %s", filename,
00351 strerror(errno));
00352 #endif
00353 }
00354 else
00355 {
00356 #ifdef DEBUG_HOTPLUG
00357 Log2(PCSC_LOG_DEBUG, "BSD: %s still present", filename);
00358 #endif
00359 readerTracker[i].status = READER_PRESENT;
00360 close(fd);
00361 }
00362 #endif
00363 if ((readerTracker[i].status == READER_ABSENT) &&
00364 (readerTracker[i].fullName != NULL))
00365 HPRemoveHotPluggable(i);
00366 }
00367
00368 if (AraKiriHotPlug)
00369 {
00370 int retval;
00371
00372 for (i=0; i<driverSize; i++)
00373 {
00374
00375 free(driverTracker[i].bundleName);
00376 free(driverTracker[i].libraryPath);
00377 free(driverTracker[i].readerName);
00378 }
00379 free(driverTracker);
00380
00381 Log1(PCSC_LOG_INFO, "Hotplug stopped");
00382 pthread_exit(&retval);
00383 }
00384 }
00385
00386 static void HPEstablishUSBNotifications(int pipefd[2])
00387 {
00388 int i, do_polling;
00389 char c = 42;
00390
00391
00392
00393 setenv("USB_DEVFS_PATH", "/proc/bus/usb", 0);
00394
00395 usb_init();
00396
00397
00398 HPRescanUsbBus();
00399
00400
00401 write(pipefd[1], &c, 1);
00402 close(pipefd[1]);
00403
00404
00405 do_polling = FALSE;
00406 for (i=0; i<driverSize; i++)
00407 if (driverTracker[i].libraryPath)
00408 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0)
00409 {
00410 Log2(PCSC_LOG_INFO,
00411 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.",
00412 driverTracker[i].bundleName);
00413 if (HPForceReaderPolling < 1)
00414 HPForceReaderPolling = 1;
00415 break;
00416 }
00417
00418 if (HPForceReaderPolling)
00419 {
00420 Log2(PCSC_LOG_INFO,
00421 "Polling forced every %d second(s)", HPForceReaderPolling);
00422 do_polling = TRUE;
00423 }
00424
00425 if (do_polling)
00426 {
00427 while (!AraKiriHotPlug)
00428 {
00429 SYS_Sleep(HPForceReaderPolling);
00430 HPRescanUsbBus();
00431 }
00432 }
00433 else
00434 {
00435 char dummy;
00436
00437 pipe(rescan_pipe);
00438 while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0)
00439 {
00440 Log1(PCSC_LOG_INFO, "Reload serial configuration");
00441 HPRescanUsbBus();
00442 #ifdef USE_SERIAL
00443 RFReCheckReaderConf();
00444 #endif
00445 Log1(PCSC_LOG_INFO, "End reload serial configuration");
00446 }
00447 close(rescan_pipe[0]);
00448 rescan_pipe[0] = -1;
00449 }
00450 }
00451
00452 LONG HPSearchHotPluggables(void)
00453 {
00454 int i;
00455 int pipefd[2];
00456 char c;
00457
00458 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
00459 {
00460 readerTracker[i].status = READER_ABSENT;
00461 readerTracker[i].bus_device[0] = '\0';
00462 readerTracker[i].fullName = NULL;
00463 }
00464
00465 if (pipe(pipefd) == -1)
00466 {
00467 Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno));
00468 return -1;
00469 }
00470
00471 if (HPReadBundleValues())
00472 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
00473 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd);
00474
00475
00476 read(pipefd[0], &c, 1);
00477 close(pipefd[0]);
00478
00479 return 0;
00480 }
00481
00482 LONG HPStopHotPluggables(void)
00483 {
00484 AraKiriHotPlug = TRUE;
00485 if (rescan_pipe[1] >= 0)
00486 {
00487 close(rescan_pipe[1]);
00488 rescan_pipe[1] = -1;
00489 }
00490
00491 return 0;
00492 }
00493
00494 static LONG HPAddHotPluggable(struct usb_device *dev, const char bus_device[],
00495 struct _driverTracker *driver)
00496 {
00497 int i;
00498 char deviceName[MAX_DEVICENAME];
00499
00500 Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
00501
00502 snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb:%s",
00503 dev->descriptor.idVendor, dev->descriptor.idProduct, bus_device);
00504 deviceName[sizeof(deviceName) -1] = '\0';
00505
00506 pthread_mutex_lock(&usbNotifierMutex);
00507
00508
00509 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++)
00510 {
00511 if (readerTracker[i].fullName == NULL)
00512 break;
00513 }
00514
00515 if (i==PCSCLITE_MAX_READERS_CONTEXTS)
00516 {
00517 Log2(PCSC_LOG_ERROR,
00518 "Not enough reader entries. Already found %d readers", i);
00519 pthread_mutex_unlock(&usbNotifierMutex);
00520 return 0;
00521 }
00522
00523 strncpy(readerTracker[i].bus_device, bus_device,
00524 sizeof(readerTracker[i].bus_device));
00525 readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
00526
00527 #ifdef ADD_SERIAL_NUMBER
00528 if (dev->descriptor.iSerialNumber)
00529 {
00530 usb_dev_handle *device;
00531 char serialNumber[MAX_READERNAME];
00532 char fullname[MAX_READERNAME];
00533 int ret;
00534
00535 device = usb_open(dev);
00536 ret = usb_get_string_simple(device, dev->descriptor.iSerialNumber,
00537 serialNumber, MAX_READERNAME);
00538 usb_close(device);
00539
00540 if (ret < 0)
00541 {
00542 Log2(PCSC_LOG_ERROR, "usb_get_string_simple failed: %s",
00543 usb_strerror());
00544 readerTracker[i].fullName = strdup(driver->readerName);
00545 }
00546 else
00547 {
00548 snprintf(fullname, sizeof(fullname), "%s (%s)",
00549 driver->readerName, serialNumber);
00550 readerTracker[i].fullName = strdup(fullname);
00551 }
00552 }
00553 else
00554 #endif
00555 readerTracker[i].fullName = strdup(driver->readerName);
00556
00557 if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
00558 driver->libraryPath, deviceName) == SCARD_S_SUCCESS)
00559 readerTracker[i].status = READER_PRESENT;
00560 else
00561 {
00562 readerTracker[i].status = READER_FAILED;
00563
00564 (void)CheckForOpenCT();
00565 }
00566
00567 pthread_mutex_unlock(&usbNotifierMutex);
00568
00569 return 1;
00570 }
00571
00572 static LONG HPRemoveHotPluggable(int reader_index)
00573 {
00574 pthread_mutex_lock(&usbNotifierMutex);
00575
00576 Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index,
00577 readerTracker[reader_index].bus_device);
00578
00579 RFRemoveReader(readerTracker[reader_index].fullName,
00580 PCSCLITE_HP_BASE_PORT + reader_index);
00581 free(readerTracker[reader_index].fullName);
00582 readerTracker[reader_index].status = READER_ABSENT;
00583 readerTracker[reader_index].bus_device[0] = '\0';
00584 readerTracker[reader_index].fullName = NULL;
00585
00586 pthread_mutex_unlock(&usbNotifierMutex);
00587
00588 return 1;
00589 }
00590
00594 ULONG HPRegisterForHotplugEvents(void)
00595 {
00596 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
00597 return 0;
00598 }
00599
00600 void HPReCheckSerialReaders(void)
00601 {
00602 if (rescan_pipe[1] >= 0)
00603 {
00604 char dummy = 0;
00605 write(rescan_pipe[1], &dummy, sizeof(dummy));
00606 }
00607 }
00608
00609 #endif
00610