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