pcsc-lite 1.6.4
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 2001-2004 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Copyright (C) 2003-2010 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * Copyright (C) 2003 00009 * Toni Andjelkovic <toni@soth.at> 00010 * Copyright (C) 2003-2004 00011 * Damien Sauveron <damien.sauveron@labri.fr> 00012 * 00013 * $Id: hotplug_libusb.c 5114 2010-08-05 08:02:09Z rousseau $ 00014 */ 00015 00021 #include "config.h" 00022 #ifdef HAVE_LIBUSB 00023 00024 #include <string.h> 00025 #include <sys/types.h> 00026 #include <stdio.h> 00027 #include <dirent.h> 00028 #include <fcntl.h> 00029 #include <time.h> 00030 #include <stdlib.h> 00031 #include <unistd.h> 00032 #include <errno.h> 00033 #include <libusb-1.0/libusb.h> 00034 #include <pthread.h> 00035 00036 #include "misc.h" 00037 #include "wintypes.h" 00038 #include "pcscd.h" 00039 #include "debuglog.h" 00040 #include "parser.h" 00041 #include "readerfactory.h" 00042 #include "winscard_msg.h" 00043 #include "sys_generic.h" 00044 #include "hotplug.h" 00045 #include "utils.h" 00046 00047 #undef DEBUG_HOTPLUG 00048 #define ADD_SERIAL_NUMBER 00049 00050 /* format is "%d:%d", bus_number, device_address */ 00051 #define BUS_DEVICE_STRSIZE 10+1+10+1 00052 00053 #define READER_ABSENT 0 00054 #define READER_PRESENT 1 00055 #define READER_FAILED 2 00056 00057 #define FALSE 0 00058 #define TRUE 1 00059 00060 /* we use the default libusb context */ 00061 #define ctx NULL 00062 00063 pthread_mutex_t usbNotifierMutex; 00064 00065 static pthread_t usbNotifyThread; 00066 static int driverSize = -1; 00067 static char AraKiriHotPlug = FALSE; 00068 static int rescan_pipe[] = { -1, -1 }; 00069 extern int HPForceReaderPolling; 00070 00071 /* values of ifdCapabilities bits */ 00072 #define IFD_GENERATE_HOTPLUG 1 00073 00077 static struct _driverTracker 00078 { 00079 long manuID; 00080 long productID; 00081 00082 char *bundleName; 00083 char *libraryPath; 00084 char *readerName; 00085 int ifdCapabilities; 00086 } *driverTracker = NULL; 00087 #define DRIVER_TRACKER_SIZE_STEP 8 00088 00092 static struct _readerTracker 00093 { 00094 char status; 00095 char bus_device[BUS_DEVICE_STRSIZE]; 00096 char *fullName; 00097 } readerTracker[PCSCLITE_MAX_READERS_CONTEXTS]; 00098 00099 static LONG HPAddHotPluggable(struct libusb_device *dev, 00100 struct libusb_device_descriptor desc, 00101 const char bus_device[], struct _driverTracker *driver); 00102 static LONG HPRemoveHotPluggable(int reader_index); 00103 00104 static LONG HPReadBundleValues(void) 00105 { 00106 LONG rv; 00107 DIR *hpDir; 00108 struct dirent *currFP = NULL; 00109 char fullPath[FILENAME_MAX]; 00110 char fullLibPath[FILENAME_MAX]; 00111 char keyValue[TOKEN_MAX_VALUE_SIZE]; 00112 int listCount = 0; 00113 00114 hpDir = opendir(PCSCLITE_HP_DROPDIR); 00115 00116 if (hpDir == NULL) 00117 { 00118 Log1(PCSC_LOG_ERROR, "Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR); 00119 Log1(PCSC_LOG_ERROR, "Disabling USB support for pcscd."); 00120 return -1; 00121 } 00122 00123 /* allocate a first array */ 00124 driverTracker = calloc(DRIVER_TRACKER_SIZE_STEP, sizeof(*driverTracker)); 00125 if (NULL == driverTracker) 00126 { 00127 Log1(PCSC_LOG_CRITICAL, "Not enough memory"); 00128 return -1; 00129 } 00130 driverSize = DRIVER_TRACKER_SIZE_STEP; 00131 00132 while ((currFP = readdir(hpDir)) != 0) 00133 { 00134 if (strstr(currFP->d_name, ".bundle") != 0) 00135 { 00136 int alias = 0; 00137 00138 /* 00139 * The bundle exists - let's form a full path name and get the 00140 * vendor and product ID's for this particular bundle 00141 */ 00142 snprintf(fullPath, sizeof(fullPath), "%s/%s/Contents/Info.plist", 00143 PCSCLITE_HP_DROPDIR, currFP->d_name); 00144 fullPath[sizeof(fullPath) - 1] = '\0'; 00145 00146 /* while we find a nth ifdVendorID in Info.plist */ 00147 while (LTPBundleFindValueWithKey(fullPath, PCSCLITE_HP_MANUKEY_NAME, 00148 keyValue, alias) == 0) 00149 { 00150 driverTracker[listCount].bundleName = strdup(currFP->d_name); 00151 00152 /* Get ifdVendorID */ 00153 rv = LTPBundleFindValueWithKey(fullPath, 00154 PCSCLITE_HP_MANUKEY_NAME, keyValue, alias); 00155 if (rv == 0) 00156 driverTracker[listCount].manuID = strtol(keyValue, NULL, 16); 00157 00158 /* get ifdProductID */ 00159 rv = LTPBundleFindValueWithKey(fullPath, 00160 PCSCLITE_HP_PRODKEY_NAME, keyValue, alias); 00161 if (rv == 0) 00162 driverTracker[listCount].productID = 00163 strtol(keyValue, NULL, 16); 00164 00165 /* get ifdFriendlyName */ 00166 rv = LTPBundleFindValueWithKey(fullPath, 00167 PCSCLITE_HP_NAMEKEY_NAME, keyValue, alias); 00168 if (rv == 0) 00169 driverTracker[listCount].readerName = strdup(keyValue); 00170 00171 /* get CFBundleExecutable */ 00172 rv = LTPBundleFindValueWithKey(fullPath, 00173 PCSCLITE_HP_LIBRKEY_NAME, keyValue, 0); 00174 if (rv == 0) 00175 { 00176 snprintf(fullLibPath, sizeof(fullLibPath), 00177 "%s/%s/Contents/%s/%s", 00178 PCSCLITE_HP_DROPDIR, currFP->d_name, PCSC_ARCH, 00179 keyValue); 00180 fullLibPath[sizeof(fullLibPath) - 1] = '\0'; 00181 driverTracker[listCount].libraryPath = strdup(fullLibPath); 00182 } 00183 00184 /* Get ifdCapabilities */ 00185 rv = LTPBundleFindValueWithKey(fullPath, 00186 PCSCLITE_HP_CPCTKEY_NAME, keyValue, 0); 00187 if (rv == 0) 00188 driverTracker[listCount].ifdCapabilities = strtol(keyValue, 00189 NULL, 16); 00190 00191 #ifdef DEBUG_HOTPLUG 00192 Log2(PCSC_LOG_INFO, "Found driver for: %s", 00193 driverTracker[listCount].readerName); 00194 #endif 00195 alias++; 00196 00197 if (NULL == driverTracker[listCount].readerName) 00198 continue; 00199 00200 listCount++; 00201 if (listCount >= driverSize) 00202 { 00203 int i; 00204 00205 /* increase the array size */ 00206 driverSize += DRIVER_TRACKER_SIZE_STEP; 00207 #ifdef DEBUG_HOTPLUG 00208 Log2(PCSC_LOG_INFO, 00209 "Increase driverTracker to %d entries", driverSize); 00210 #endif 00211 driverTracker = realloc(driverTracker, 00212 driverSize * sizeof(*driverTracker)); 00213 if (NULL == driverTracker) 00214 { 00215 Log1(PCSC_LOG_CRITICAL, "Not enough memory"); 00216 driverSize = -1; 00217 return -1; 00218 } 00219 00220 /* clean the newly allocated entries */ 00221 for (i=driverSize-DRIVER_TRACKER_SIZE_STEP; i<driverSize; i++) 00222 { 00223 driverTracker[i].manuID = 0; 00224 driverTracker[i].productID = 0; 00225 driverTracker[i].bundleName = NULL; 00226 driverTracker[i].libraryPath = NULL; 00227 driverTracker[i].readerName = NULL; 00228 driverTracker[i].ifdCapabilities = 0; 00229 } 00230 } 00231 } 00232 } 00233 } 00234 00235 driverSize = listCount; 00236 closedir(hpDir); 00237 00238 rv = TRUE; 00239 if (driverSize == 0) 00240 { 00241 Log1(PCSC_LOG_INFO, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR); 00242 Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd"); 00243 rv = FALSE; 00244 } 00245 #ifdef DEBUG_HOTPLUG 00246 else 00247 Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount); 00248 #endif 00249 00250 return rv; 00251 } 00252 00253 static void HPRescanUsbBus(void) 00254 { 00255 int i, j; 00256 char bus_device[BUS_DEVICE_STRSIZE]; 00257 libusb_device **devs, *dev; 00258 ssize_t cnt; 00259 00260 for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 00261 /* clear rollcall */ 00262 readerTracker[i].status = READER_ABSENT; 00263 00264 cnt = libusb_get_device_list(ctx, &devs); 00265 if (cnt < 0) 00266 { 00267 Log1(PCSC_LOG_CRITICAL, "libusb_get_device_list() failed\n"); 00268 return; 00269 } 00270 00271 /* For each USB device */ 00272 cnt = 0; 00273 while ((dev = devs[cnt++]) != NULL) 00274 { 00275 struct libusb_device_descriptor desc; 00276 uint8_t bus_number = libusb_get_bus_number(dev); 00277 uint8_t device_address = libusb_get_device_address(dev); 00278 00279 int r = libusb_get_device_descriptor(dev, &desc); 00280 if (r < 0) 00281 { 00282 Log3(PCSC_LOG_ERROR, "failed to get device descriptor for %d/%d", 00283 bus_number, device_address); 00284 continue; 00285 } 00286 00287 /* check if the device is supported by one driver */ 00288 for (i=0; i<driverSize; i++) 00289 { 00290 if (driverTracker[i].libraryPath != NULL && 00291 desc.idVendor == driverTracker[i].manuID && 00292 desc.idProduct == driverTracker[i].productID) 00293 { 00294 int newreader; 00295 00296 /* A known device has been found */ 00297 snprintf(bus_device, BUS_DEVICE_STRSIZE, "%d:%d", 00298 bus_number, device_address); 00299 bus_device[BUS_DEVICE_STRSIZE - 1] = '\0'; 00300 #ifdef DEBUG_HOTPLUG 00301 Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", 00302 bus_device); 00303 #endif 00304 newreader = TRUE; 00305 00306 /* Check if the reader is a new one */ 00307 for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++) 00308 { 00309 if (strncmp(readerTracker[j].bus_device, 00310 bus_device, BUS_DEVICE_STRSIZE) == 0) 00311 { 00312 /* The reader is already known */ 00313 readerTracker[j].status = READER_PRESENT; 00314 newreader = FALSE; 00315 #ifdef DEBUG_HOTPLUG 00316 Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s", 00317 bus_device); 00318 #endif 00319 break; 00320 } 00321 } 00322 00323 /* New reader found */ 00324 if (newreader) 00325 HPAddHotPluggable(dev, desc, bus_device, &driverTracker[i]); 00326 } 00327 } 00328 } 00329 00330 /* 00331 * check if all the previously found readers are still present 00332 */ 00333 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++) 00334 { 00335 if ((readerTracker[i].status == READER_ABSENT) && 00336 (readerTracker[i].fullName != NULL)) 00337 HPRemoveHotPluggable(i); 00338 } 00339 00340 if (AraKiriHotPlug) 00341 { 00342 int retval; 00343 00344 for (i=0; i<driverSize; i++) 00345 { 00346 /* free strings allocated by strdup() */ 00347 free(driverTracker[i].bundleName); 00348 free(driverTracker[i].libraryPath); 00349 free(driverTracker[i].readerName); 00350 } 00351 free(driverTracker); 00352 00353 Log1(PCSC_LOG_INFO, "Hotplug stopped"); 00354 pthread_exit(&retval); 00355 } 00356 00357 /* free the libusb allocated list & devices */ 00358 libusb_free_device_list(devs, 1); 00359 } 00360 00361 static void HPEstablishUSBNotifications(int pipefd[2]) 00362 { 00363 int i, do_polling; 00364 char c = 42; /* magic value */ 00365 00366 libusb_init(ctx); 00367 00368 /* scan the USB bus for devices at startup */ 00369 HPRescanUsbBus(); 00370 00371 /* signal that the initially connected readers are now visible */ 00372 write(pipefd[1], &c, 1); 00373 close(pipefd[1]); 00374 00375 /* if at least one driver do not have IFD_GENERATE_HOTPLUG */ 00376 do_polling = FALSE; 00377 for (i=0; i<driverSize; i++) 00378 if (driverTracker[i].libraryPath) 00379 if ((driverTracker[i].ifdCapabilities & IFD_GENERATE_HOTPLUG) == 0) 00380 { 00381 Log2(PCSC_LOG_INFO, 00382 "Driver %s does not support IFD_GENERATE_HOTPLUG. Using active polling instead.", 00383 driverTracker[i].bundleName); 00384 if (HPForceReaderPolling < 1) 00385 HPForceReaderPolling = 1; 00386 break; 00387 } 00388 00389 if (HPForceReaderPolling) 00390 { 00391 Log2(PCSC_LOG_INFO, 00392 "Polling forced every %d second(s)", HPForceReaderPolling); 00393 do_polling = TRUE; 00394 } 00395 00396 if (do_polling) 00397 { 00398 while (!AraKiriHotPlug) 00399 { 00400 SYS_Sleep(HPForceReaderPolling); 00401 HPRescanUsbBus(); 00402 } 00403 } 00404 else 00405 { 00406 char dummy; 00407 00408 pipe(rescan_pipe); 00409 while (read(rescan_pipe[0], &dummy, sizeof(dummy)) > 0) 00410 { 00411 Log1(PCSC_LOG_INFO, "Reload serial configuration"); 00412 HPRescanUsbBus(); 00413 #ifdef USE_SERIAL 00414 RFReCheckReaderConf(); 00415 #endif 00416 Log1(PCSC_LOG_INFO, "End reload serial configuration"); 00417 } 00418 close(rescan_pipe[0]); 00419 rescan_pipe[0] = -1; 00420 } 00421 } 00422 00423 LONG HPSearchHotPluggables(void) 00424 { 00425 int i; 00426 int pipefd[2]; 00427 char c; 00428 00429 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++) 00430 { 00431 readerTracker[i].status = READER_ABSENT; 00432 readerTracker[i].bus_device[0] = '\0'; 00433 readerTracker[i].fullName = NULL; 00434 } 00435 00436 if (pipe(pipefd) == -1) 00437 { 00438 Log2(PCSC_LOG_ERROR, "pipe: %s", strerror(errno)); 00439 return -1; 00440 } 00441 00442 if (HPReadBundleValues()) 00443 ThreadCreate(&usbNotifyThread, THREAD_ATTR_DETACHED, 00444 (PCSCLITE_THREAD_FUNCTION( )) HPEstablishUSBNotifications, pipefd); 00445 00446 /* Wait for initial readers to setup */ 00447 read(pipefd[0], &c, 1); 00448 close(pipefd[0]); 00449 00450 return 0; 00451 } 00452 00453 LONG HPStopHotPluggables(void) 00454 { 00455 AraKiriHotPlug = TRUE; 00456 if (rescan_pipe[1] >= 0) 00457 { 00458 close(rescan_pipe[1]); 00459 rescan_pipe[1] = -1; 00460 } 00461 00462 return 0; 00463 } 00464 00465 static LONG HPAddHotPluggable(struct libusb_device *dev, 00466 struct libusb_device_descriptor desc, 00467 const char bus_device[], struct _driverTracker *driver) 00468 { 00469 int i; 00470 char deviceName[MAX_DEVICENAME]; 00471 00472 Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device); 00473 00474 snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb-1.0:%s", 00475 desc.idVendor, desc.idProduct, bus_device); 00476 deviceName[sizeof(deviceName) -1] = '\0'; 00477 00478 pthread_mutex_lock(&usbNotifierMutex); 00479 00480 /* find a free entry */ 00481 for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++) 00482 { 00483 if (readerTracker[i].fullName == NULL) 00484 break; 00485 } 00486 00487 if (i==PCSCLITE_MAX_READERS_CONTEXTS) 00488 { 00489 Log2(PCSC_LOG_ERROR, 00490 "Not enough reader entries. Already found %d readers", i); 00491 pthread_mutex_unlock(&usbNotifierMutex); 00492 return 0; 00493 } 00494 00495 strncpy(readerTracker[i].bus_device, bus_device, 00496 sizeof(readerTracker[i].bus_device)); 00497 readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0'; 00498 00499 #ifdef ADD_SERIAL_NUMBER 00500 if (desc.iSerialNumber) 00501 { 00502 libusb_device_handle *device; 00503 unsigned char serialNumber[MAX_READERNAME]; 00504 char fullname[MAX_READERNAME]; 00505 int ret; 00506 00507 ret = libusb_open(dev, &device); 00508 if (ret < 0) 00509 { 00510 Log2(PCSC_LOG_ERROR, "libusb_open failed: %d", ret); 00511 } 00512 else 00513 { 00514 ret = libusb_get_string_descriptor_ascii(device, desc.iSerialNumber, 00515 serialNumber, MAX_READERNAME); 00516 libusb_close(device); 00517 00518 if (ret < 0) 00519 { 00520 Log2(PCSC_LOG_ERROR, 00521 "libusb_get_string_descriptor_ascii failed: %d", ret); 00522 readerTracker[i].fullName = strdup(driver->readerName); 00523 } 00524 else 00525 { 00526 snprintf(fullname, sizeof(fullname), "%s (%s)", 00527 driver->readerName, serialNumber); 00528 readerTracker[i].fullName = strdup(fullname); 00529 } 00530 } 00531 } 00532 else 00533 #endif 00534 readerTracker[i].fullName = strdup(driver->readerName); 00535 00536 if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i, 00537 driver->libraryPath, deviceName) == SCARD_S_SUCCESS) 00538 readerTracker[i].status = READER_PRESENT; 00539 else 00540 { 00541 readerTracker[i].status = READER_FAILED; 00542 00543 (void)CheckForOpenCT(); 00544 } 00545 00546 pthread_mutex_unlock(&usbNotifierMutex); 00547 00548 return 1; 00549 } /* End of function */ 00550 00551 static LONG HPRemoveHotPluggable(int reader_index) 00552 { 00553 pthread_mutex_lock(&usbNotifierMutex); 00554 00555 Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", reader_index, 00556 readerTracker[reader_index].bus_device); 00557 00558 RFRemoveReader(readerTracker[reader_index].fullName, 00559 PCSCLITE_HP_BASE_PORT + reader_index); 00560 free(readerTracker[reader_index].fullName); 00561 readerTracker[reader_index].status = READER_ABSENT; 00562 readerTracker[reader_index].bus_device[0] = '\0'; 00563 readerTracker[reader_index].fullName = NULL; 00564 00565 pthread_mutex_unlock(&usbNotifierMutex); 00566 00567 return 1; 00568 } /* End of function */ 00569 00573 ULONG HPRegisterForHotplugEvents(void) 00574 { 00575 (void)pthread_mutex_init(&usbNotifierMutex, NULL); 00576 return 0; 00577 } 00578 00579 void HPReCheckSerialReaders(void) 00580 { 00581 if (rescan_pipe[1] >= 0) 00582 { 00583 char dummy = 0; 00584 write(rescan_pipe[1], &dummy, sizeof(dummy)); 00585 } 00586 } 00587 00588 #endif 00589