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