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