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