pcsc-lite 1.6.4
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 2001-2003 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Copyright (C) 2002-2010 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * The USB code was based partly on Johannes Erdfelt 00010 * libusb code found at libusb.sourceforge.net 00011 * 00012 * $Id: hotplug_linux.c 5047 2010-06-29 14:39:24Z rousseau $ 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 * The bundle exists - let's form a full path name and get the 00127 * vendor and product ID's for this particular bundle 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 /* while we find a nth ifdVendorID in Info.plist */ 00134 while (LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_MANUKEY_NAME, 00135 keyValue, alias) == 0) 00136 { 00137 bundleTracker[listCount].bundleName = strdup(currFP->d_name); 00138 00139 /* Get ifdVendorID */ 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 /* get ifdProductID */ 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 /* get ifdFriendlyName */ 00153 rv = LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_NAMEKEY_NAME, 00154 keyValue, alias); 00155 if (rv == 0) 00156 bundleTracker[listCount].readerName = strdup(keyValue); 00157 00158 /* get CFBundleExecutable */ 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 /* clear rollcall */ 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 * Skip anything starting with a 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 * Skip anything starting with a 00263 */ 00264 if (entryB->d_name[0] == '.') 00265 continue; 00266 00267 /* Get the device number so we can distinguish 00268 multiple readers */ 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 * Device is found and we don't know about it 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; /* i'm here */ 00299 break; 00300 } 00301 } 00302 00303 if (j == PCSCLITE_MAX_READERS_CONTEXTS) 00304 { 00305 usbDeviceStatus = 1; 00306 suspectDeviceNumber = deviceNumber; 00307 } 00308 } 00309 00310 } /* End of while */ 00311 00312 closedir(dirB); 00313 00314 } /* End of while */ 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 * Do nothing - no USB devices found 00358 */ 00359 } 00360 00361 if (dir) 00362 closedir(dir); 00363 00364 } /* End of for..loop */ 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 } /* End of while loop */ 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 /* NOTE: The deviceName is an empty string "" until someone implements 00409 * the code to get it */ 00410 RFAddReader(bundleTracker[i].readerName, PCSCLITE_HP_BASE_PORT + usbAddr, 00411 bundleTracker[i].libraryPath, ""); 00412 00413 return 1; 00414 } /* End of function */ 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 } /* End of function */ 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 /* __linux__ && !HAVE_LIBUSB */