00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00020 #include "config.h"
00021 #include <string.h>
00022
00023 #if defined(__linux__) && !defined(HAVE_LIBUSB) && !defined(HAVE_LIBHAL)
00024 #include <sys/types.h>
00025 #include <stdio.h>
00026 #include <dirent.h>
00027 #include <fcntl.h>
00028 #include <time.h>
00029 #include <stdlib.h>
00030 #include <unistd.h>
00031 #include <pthread.h>
00032
00033 #include "misc.h"
00034 #include "pcsclite.h"
00035 #include "pcscd.h"
00036 #include "debuglog.h"
00037 #include "parser.h"
00038 #include "readerfactory.h"
00039 #include "winscard_msg.h"
00040 #include "sys_generic.h"
00041 #include "hotplug.h"
00042 #include "utils.h"
00043
00044 #define PCSCLITE_USB_PATH "/proc/bus/usb"
00045
00046 #define FALSE 0
00047 #define TRUE 1
00048
00049 pthread_mutex_t usbNotifierMutex;
00050
00051 struct usb_device_descriptor
00052 {
00053 u_int8_t bLength;
00054 u_int8_t bDescriptorType;
00055 u_int16_t bcdUSB;
00056 u_int8_t bDeviceClass;
00057 u_int8_t bDeviceSubClass;
00058 u_int8_t bDeviceProtocol;
00059 u_int8_t bMaxPacketSize0;
00060 u_int16_t idVendor;
00061 u_int16_t idProduct;
00062 u_int16_t bcdDevice;
00063 u_int8_t iManufacturer;
00064 u_int8_t iProduct;
00065 u_int8_t iSerialNumber;
00066 u_int8_t bNumConfigurations;
00067 }
00068 __attribute__ ((packed));
00069
00070 static LONG HPAddHotPluggable(int, unsigned long);
00071 static LONG HPRemoveHotPluggable(int, unsigned long);
00072 static LONG HPReadBundleValues(void);
00073 static void HPEstablishUSBNotifications(void);
00074
00075 static pthread_t usbNotifyThread;
00076 static int AraKiriHotPlug = FALSE;
00077 static int bundleSize = 0;
00078
00082 static struct _bundleTracker
00083 {
00084 long manuID;
00085 long productID;
00086
00087 struct _deviceNumber {
00088 int id;
00089 char status;
00090 } deviceNumber[PCSCLITE_MAX_READERS_CONTEXTS];
00091
00092 char *bundleName;
00093 char *libraryPath;
00094 char *readerName;
00095 }
00096 bundleTracker[PCSCLITE_MAX_READERS_CONTEXTS];
00097
00098 static LONG HPReadBundleValues(void)
00099 {
00100
00101 LONG rv;
00102 DIR *hpDir;
00103 struct dirent *currFP = 0;
00104 char fullPath[FILENAME_MAX];
00105 char fullLibPath[FILENAME_MAX];
00106 char keyValue[TOKEN_MAX_VALUE_SIZE];
00107 int listCount = 0;
00108
00109 hpDir = opendir(PCSCLITE_HP_DROPDIR);
00110
00111 if (hpDir == NULL)
00112 {
00113 Log1(PCSC_LOG_INFO,
00114 "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
00115 Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd.");
00116 return -1;
00117 }
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, FILENAME_MAX, "%s/%s/Contents/Info.plist",
00130 PCSCLITE_HP_DROPDIR, currFP->d_name);
00131 fullPath[FILENAME_MAX - 1] = '\0';
00132
00133
00134 while (LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_MANUKEY_NAME,
00135 keyValue, alias) == 0)
00136 {
00137 bundleTracker[listCount].bundleName = strdup(currFP->d_name);
00138
00139
00140 rv = LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_MANUKEY_NAME,
00141 keyValue, alias);
00142 if (rv == 0)
00143 bundleTracker[listCount].manuID = strtol(keyValue, 0, 16);
00144
00145
00146 rv = LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_PRODKEY_NAME,
00147 keyValue, alias);
00148 if (rv == 0)
00149 bundleTracker[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 bundleTracker[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 bundleTracker[listCount].libraryPath = strdup(fullLibPath);
00168 }
00169
00170 listCount++;
00171 alias++;
00172
00173 if (listCount >= sizeof(bundleTracker)/sizeof(bundleTracker[0]))
00174 {
00175 Log2(PCSC_LOG_CRITICAL, "Too many readers declared. Maximum is %d", sizeof(bundleTracker)/sizeof(bundleTracker[0]));
00176 goto end;
00177 }
00178 }
00179 }
00180 }
00181
00182 end:
00183 bundleSize = listCount;
00184
00185 if (bundleSize == 0)
00186 {
00187 Log1(PCSC_LOG_INFO,
00188 "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
00189 Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
00190 }
00191
00192 closedir(hpDir);
00193 return 0;
00194 }
00195
00196 static void HPEstablishUSBNotifications(void)
00197 {
00198
00199 int i, j, usbDeviceStatus;
00200 DIR *dir, *dirB;
00201 struct dirent *entry, *entryB;
00202 int deviceNumber;
00203 int suspectDeviceNumber;
00204 char dirpath[FILENAME_MAX];
00205 char filename[FILENAME_MAX];
00206 int fd, ret;
00207 struct usb_device_descriptor usbDescriptor;
00208
00209 usbDeviceStatus = 0;
00210 suspectDeviceNumber = 0;
00211
00212 while (1)
00213 {
00214 for (i = 0; i < bundleSize; i++)
00215 {
00216 usbDeviceStatus = 0;
00217 suspectDeviceNumber = 0;
00218
00219 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
00220
00221 bundleTracker[i].deviceNumber[j].status = 0;
00222
00223 dir = NULL;
00224 dir = opendir(PCSCLITE_USB_PATH);
00225 if (dir == NULL)
00226 {
00227 Log1(PCSC_LOG_ERROR,
00228 "Cannot open USB path directory: " PCSCLITE_USB_PATH);
00229 return;
00230 }
00231
00232 entry = NULL;
00233 while ((entry = readdir(dir)) != 0)
00234 {
00235
00236
00237
00238
00239 if (entry->d_name[0] == '.')
00240 continue;
00241 if (!strchr("0123456789",
00242 entry->d_name[strlen(entry->d_name) - 1]))
00243 {
00244 continue;
00245 }
00246
00247 sprintf(dirpath, "%s/%s", PCSCLITE_USB_PATH, entry->d_name);
00248
00249 dirB = opendir(dirpath);
00250
00251 if (dirB == NULL)
00252 {
00253 Log2(PCSC_LOG_ERROR,
00254 "USB path seems to have disappeared %s", dirpath);
00255 closedir(dir);
00256 return;
00257 }
00258
00259 while ((entryB = readdir(dirB)) != NULL)
00260 {
00261
00262
00263
00264 if (entryB->d_name[0] == '.')
00265 continue;
00266
00267
00268
00269 sprintf(filename, "%s/%s", dirpath, entryB->d_name);
00270 sscanf(entryB->d_name, "%d", &deviceNumber);
00271
00272 fd = open(filename, O_RDONLY);
00273 if (fd < 0)
00274 continue;
00275
00276 ret = read(fd, (void *) &usbDescriptor,
00277 sizeof(usbDescriptor));
00278
00279 close(fd);
00280
00281 if (ret < 0)
00282 continue;
00283
00284
00285
00286
00287
00288 if (usbDescriptor.idVendor == bundleTracker[i].manuID &&
00289 usbDescriptor.idProduct == bundleTracker[i].productID &&
00290 usbDescriptor.idVendor !=0 &&
00291 usbDescriptor.idProduct != 0)
00292 {
00293 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
00294 {
00295 if (bundleTracker[i].deviceNumber[j].id == deviceNumber &&
00296 bundleTracker[i].deviceNumber[j].id != 0)
00297 {
00298 bundleTracker[i].deviceNumber[j].status = 1;
00299 break;
00300 }
00301 }
00302
00303 if (j == PCSCLITE_MAX_READERS_CONTEXTS)
00304 {
00305 usbDeviceStatus = 1;
00306 suspectDeviceNumber = deviceNumber;
00307 }
00308 }
00309
00310 }
00311
00312 closedir(dirB);
00313
00314 }
00315
00316
00317 if (usbDeviceStatus == 1)
00318 {
00319 pthread_mutex_lock(&usbNotifierMutex);
00320
00321 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
00322 {
00323 if (bundleTracker[i].deviceNumber[j].id == 0)
00324 break;
00325 }
00326
00327 if (j == PCSCLITE_MAX_READERS_CONTEXTS)
00328 Log1(PCSC_LOG_ERROR,
00329 "Too many identical readers plugged in");
00330 else
00331 {
00332 HPAddHotPluggable(i, j+1);
00333 bundleTracker[i].deviceNumber[j].id = suspectDeviceNumber;
00334 }
00335
00336 pthread_mutex_unlock(&usbNotifierMutex);
00337 }
00338 else
00339 if (usbDeviceStatus == 0)
00340 {
00341
00342 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
00343 {
00344 if (bundleTracker[i].deviceNumber[j].id != 0 &&
00345 bundleTracker[i].deviceNumber[j].status == 0)
00346 {
00347 pthread_mutex_lock(&usbNotifierMutex);
00348 HPRemoveHotPluggable(i, j+1);
00349 bundleTracker[i].deviceNumber[j].id = 0;
00350 pthread_mutex_unlock(&usbNotifierMutex);
00351 }
00352 }
00353 }
00354 else
00355 {
00356
00357
00358
00359 }
00360
00361 if (dir)
00362 closedir(dir);
00363
00364 }
00365
00366 SYS_Sleep(1);
00367 if (AraKiriHotPlug)
00368 {
00369 int retval;
00370
00371 Log1(PCSC_LOG_INFO, "Hotplug stopped");
00372 pthread_exit(&retval);
00373 }
00374
00375 }
00376 }
00377
00378 LONG HPSearchHotPluggables(void)
00379 {
00380 int i, j;
00381
00382 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00383 {
00384 bundleTracker[i].productID = 0;
00385 bundleTracker[i].manuID = 0;
00386
00387 for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
00388 bundleTracker[i].deviceNumber[j].id = 0;
00389 }
00390
00391 HPReadBundleValues();
00392
00393 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED,
00394 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, 0);
00395
00396 return 0;
00397 }
00398
00399 LONG HPStopHotPluggables(void)
00400 {
00401 AraKiriHotPlug = TRUE;
00402
00403 return 0;
00404 }
00405
00406 static LONG HPAddHotPluggable(int i, unsigned long usbAddr)
00407 {
00408
00409
00410 RFAddReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr,
00411 bundleTracker[i].libraryPath, "");
00412
00413 return 1;
00414 }
00415
00416 static LONG HPRemoveHotPluggable(int i, unsigned long usbAddr)
00417 {
00418 RFRemoveReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr);
00419
00420 return 1;
00421 }
00422
00426 ULONG HPRegisterForHotplugEvents(void)
00427 {
00428 (void)pthread_mutex_init(&usbNotifierMutex, NULL);
00429 return 0;
00430 }
00431
00432 void HPReCheckSerialReaders(void)
00433 {
00434 }
00435
00436 #endif