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