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