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