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