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