pcsc-lite 1.5.5
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 2002-2004 00005 * Stephen M. Webb <stephenw@cryptocard.com> 00006 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00007 * David Corcoran <corcoran@linuxnet.com> 00008 * 00009 * $Id: hotplug_macosx.c 2494 2007-03-27 12:17:53Z rousseau $ 00010 */ 00011 00017 #include "config.h" 00018 #include "misc.h" 00019 #include "pcscd.h" 00020 00021 #if defined(__APPLE__) && !defined(HAVE_LIBUSB) 00022 #include <CoreFoundation/CoreFoundation.h> 00023 #include <IOKit/IOCFPlugIn.h> 00024 #include <IOKit/IOKitLib.h> 00025 #include <IOKit/usb/IOUSBLib.h> 00026 #include <stdlib.h> 00027 #include <string.h> 00028 00029 #include "debuglog.h" 00030 #include "parser.h" 00031 #include "readerfactory.h" 00032 #include "winscard_msg.h" 00033 #include "sys_generic.h" 00034 #include "hotplug.h" 00035 00036 #undef DEBUG_HOTPLUG 00037 00038 char ReCheckSerialReaders = FALSE; 00039 00040 /* 00041 * An aggregation of useful information on a driver bundle in the 00042 * drop directory. 00043 */ 00044 typedef struct HPDriver 00045 { 00046 UInt32 m_vendorId; /* unique vendor's manufacturer code */ 00047 UInt32 m_productId; /* manufacturer's unique product code */ 00048 char *m_friendlyName; /* bundle friendly name */ 00049 char *m_libPath; /* bundle's plugin library location */ 00050 } HPDriver, *HPDriverVector; 00051 00052 /* 00053 * An aggregation on information on currently active reader drivers. 00054 */ 00055 typedef struct HPDevice 00056 { 00057 HPDriver *m_driver; /* driver bundle information */ 00058 UInt32 m_address; /* unique system address of device */ 00059 struct HPDevice *m_next; /* next device in list */ 00060 } HPDevice, *HPDeviceList; 00061 00062 /* 00063 * Pointer to a list of (currently) known hotplug reader devices (and their 00064 * drivers). 00065 */ 00066 static HPDeviceList sDeviceList = NULL; 00067 00068 /* 00069 * A callback to handle the asynchronous appearance of new devices that are 00070 * candidates for PCSC readers. 00071 */ 00072 static void HPDeviceAppeared(void *refCon, io_iterator_t iterator) 00073 { 00074 kern_return_t kret; 00075 io_service_t obj; 00076 00077 while ((obj = IOIteratorNext(iterator))) 00078 kret = IOObjectRelease(obj); 00079 00080 HPSearchHotPluggables(); 00081 } 00082 00083 /* 00084 * A callback to handle the asynchronous disappearance of devices that are 00085 * possibly PCSC readers. 00086 */ 00087 static void HPDeviceDisappeared(void *refCon, io_iterator_t iterator) 00088 { 00089 kern_return_t kret; 00090 io_service_t obj; 00091 00092 while ((obj = IOIteratorNext(iterator))) 00093 kret = IOObjectRelease(obj); 00094 00095 HPSearchHotPluggables(); 00096 } 00097 00098 00099 /* 00100 * Creates a vector of driver bundle info structures from the hot-plug driver 00101 * directory. 00102 * 00103 * Returns NULL on error and a pointer to an allocated HPDriver vector on 00104 * success. The caller must free the HPDriver with a call to 00105 * HPDriversRelease(). 00106 */ 00107 static HPDriverVector HPDriversGetFromDirectory(const char *driverBundlePath) 00108 { 00109 int i; 00110 #ifdef DEBUG_HOTPLUG 00111 Log2(PCSC_LOG_DEBUG, "Entering HPDriversGetFromDirectory: %s", 00112 driverBundlePath); 00113 #endif 00114 00115 int readersNumber = 0; 00116 HPDriverVector bundleVector = NULL; 00117 CFArrayRef bundleArray; 00118 CFStringRef driverBundlePathString = 00119 CFStringCreateWithCString(kCFAllocatorDefault, 00120 driverBundlePath, 00121 kCFStringEncodingMacRoman); 00122 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, 00123 driverBundlePathString, 00124 kCFURLPOSIXPathStyle, TRUE); 00125 00126 CFRelease(driverBundlePathString); 00127 if (!pluginUrl) 00128 { 00129 Log1(PCSC_LOG_ERROR, "error getting plugin directory URL"); 00130 return NULL; 00131 } 00132 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault, 00133 pluginUrl, NULL); 00134 if (!bundleArray) 00135 { 00136 Log1(PCSC_LOG_ERROR, "error getting plugin directory bundles"); 00137 return NULL; 00138 } 00139 CFRelease(pluginUrl); 00140 00141 size_t bundleArraySize = CFArrayGetCount(bundleArray); 00142 00143 /* get the number of readers (including aliases) */ 00144 for (i = 0; i < bundleArraySize; i++) 00145 { 00146 CFBundleRef currBundle = 00147 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i); 00148 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle); 00149 00150 const void * blobValue = CFDictionaryGetValue(dict, 00151 CFSTR(PCSCLITE_HP_MANUKEY_NAME)); 00152 00153 if (!blobValue) 00154 { 00155 Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle"); 00156 return NULL; 00157 } 00158 00159 if (CFGetTypeID(blobValue) == CFArrayGetTypeID()) 00160 { 00161 /* alias found, each reader count as 1 */ 00162 CFArrayRef propertyArray = blobValue; 00163 readersNumber += CFArrayGetCount(propertyArray); 00164 } 00165 else 00166 /* No alias, only one reader supported */ 00167 readersNumber++; 00168 } 00169 #ifdef DEBUG_HOTPLUG 00170 Log2(PCSC_LOG_DEBUG, "Total of %d readers supported", readersNumber); 00171 #endif 00172 00173 /* The last entry is an end marker (m_vendorId = 0) 00174 * see checks in HPDriversMatchUSBDevices:503 00175 * and HPDriverVectorRelease:376 */ 00176 readersNumber++; 00177 00178 bundleVector = (HPDriver *) calloc(readersNumber, sizeof(HPDriver)); 00179 if (!bundleVector) 00180 { 00181 Log1(PCSC_LOG_ERROR, "memory allocation failure"); 00182 return NULL; 00183 } 00184 00185 HPDriver *driverBundle = bundleVector; 00186 for (i = 0; i < bundleArraySize; i++) 00187 { 00188 CFBundleRef currBundle = 00189 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i); 00190 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle); 00191 00192 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle); 00193 CFStringRef bundlePath = CFURLCopyPath(bundleUrl); 00194 00195 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath, 00196 CFStringGetSystemEncoding())); 00197 00198 const void * blobValue = CFDictionaryGetValue(dict, 00199 CFSTR(PCSCLITE_HP_MANUKEY_NAME)); 00200 00201 if (!blobValue) 00202 { 00203 Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle"); 00204 return bundleVector; 00205 } 00206 00207 if (CFGetTypeID(blobValue) == CFArrayGetTypeID()) 00208 { 00209 CFArrayRef vendorArray = blobValue; 00210 CFArrayRef productArray; 00211 CFArrayRef friendlyNameArray; 00212 char *libPath = driverBundle->m_libPath; 00213 00214 #ifdef DEBUG_HOTPLUG 00215 Log2(PCSC_LOG_DEBUG, "Driver with aliases: %s", libPath); 00216 #endif 00217 /* get list of ProductID */ 00218 productArray = CFDictionaryGetValue(dict, 00219 CFSTR(PCSCLITE_HP_PRODKEY_NAME)); 00220 if (!productArray) 00221 { 00222 Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); 00223 return bundleVector; 00224 } 00225 00226 /* get list of FriendlyName */ 00227 friendlyNameArray = CFDictionaryGetValue(dict, 00228 CFSTR(PCSCLITE_HP_NAMEKEY_NAME)); 00229 if (!friendlyNameArray) 00230 { 00231 Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); 00232 return bundleVector; 00233 } 00234 00235 int reader_nb = CFArrayGetCount(vendorArray); 00236 00237 if (reader_nb != CFArrayGetCount(productArray)) 00238 { 00239 Log3(PCSC_LOG_ERROR, 00240 "Malformed Info.plist: %d vendors and %d products", 00241 reader_nb, CFArrayGetCount(productArray)); 00242 return bundleVector; 00243 } 00244 00245 if (reader_nb != CFArrayGetCount(friendlyNameArray)) 00246 { 00247 Log3(PCSC_LOG_ERROR, 00248 "Malformed Info.plist: %d vendors and %d friendlynames", 00249 reader_nb, CFArrayGetCount(friendlyNameArray)); 00250 return bundleVector; 00251 } 00252 00253 int j; 00254 for (j=0; j<reader_nb; j++) 00255 { 00256 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j); 00257 00258 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue, 00259 CFStringGetSystemEncoding()), NULL, 16); 00260 00261 strValue = CFArrayGetValueAtIndex(productArray, j); 00262 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue, 00263 CFStringGetSystemEncoding()), NULL, 16); 00264 00265 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j); 00266 const char *cstr = CFStringGetCStringPtr(strValue, 00267 CFStringGetSystemEncoding()); 00268 00269 driverBundle->m_friendlyName = strdup(cstr); 00270 if (!driverBundle->m_libPath) 00271 driverBundle->m_libPath = strdup(libPath); 00272 00273 #ifdef DEBUG_HOTPLUG 00274 Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X", 00275 driverBundle->m_vendorId); 00276 Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X", 00277 driverBundle->m_productId); 00278 Log2(PCSC_LOG_DEBUG, "Friendly name: %s", 00279 driverBundle->m_friendlyName); 00280 Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath); 00281 #endif 00282 00283 /* go to next bundle in the vector */ 00284 driverBundle++; 00285 } 00286 } 00287 else 00288 { 00289 CFStringRef strValue = blobValue; 00290 00291 #ifdef DEBUG_HOTPLUG 00292 Log3(PCSC_LOG_DEBUG, "Driver without alias: %s", 00293 driverBundle, driverBundle->m_libPath); 00294 #endif 00295 00296 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue, 00297 CFStringGetSystemEncoding()), NULL, 16); 00298 00299 strValue = (CFStringRef) CFDictionaryGetValue(dict, 00300 CFSTR(PCSCLITE_HP_PRODKEY_NAME)); 00301 if (!strValue) 00302 { 00303 Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); 00304 return bundleVector; 00305 } 00306 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue, 00307 CFStringGetSystemEncoding()), NULL, 16); 00308 00309 strValue = (CFStringRef) CFDictionaryGetValue(dict, 00310 CFSTR(PCSCLITE_HP_NAMEKEY_NAME)); 00311 if (!strValue) 00312 { 00313 Log1(PCSC_LOG_ERROR, "error getting product friendly name from bundle"); 00314 driverBundle->m_friendlyName = strdup("unnamed device"); 00315 } 00316 else 00317 { 00318 const char *cstr = CFStringGetCStringPtr(strValue, 00319 CFStringGetSystemEncoding()); 00320 00321 driverBundle->m_friendlyName = strdup(cstr); 00322 } 00323 #ifdef DEBUG_HOTPLUG 00324 Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X", driverBundle->m_vendorId); 00325 Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X", driverBundle->m_productId); 00326 Log2(PCSC_LOG_DEBUG, "Friendly name: %s", driverBundle->m_friendlyName); 00327 Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath); 00328 #endif 00329 00330 /* go to next bundle in the vector */ 00331 driverBundle++; 00332 } 00333 } 00334 CFRelease(bundleArray); 00335 return bundleVector; 00336 } 00337 00338 /* 00339 * Copies a driver bundle instance. 00340 */ 00341 static HPDriver *HPDriverCopy(HPDriver * rhs) 00342 { 00343 if (!rhs) 00344 return NULL; 00345 00346 HPDriver *newDriverBundle = (HPDriver *) calloc(1, sizeof(HPDriver)); 00347 00348 if (!newDriverBundle) 00349 return NULL; 00350 00351 newDriverBundle->m_vendorId = rhs->m_vendorId; 00352 newDriverBundle->m_productId = rhs->m_productId; 00353 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName); 00354 newDriverBundle->m_libPath = strdup(rhs->m_libPath); 00355 00356 return newDriverBundle; 00357 } 00358 00359 /* 00360 * Releases resources allocated to a driver bundle vector. 00361 */ 00362 static void HPDriverRelease(HPDriver * driverBundle) 00363 { 00364 if (driverBundle) 00365 { 00366 free(driverBundle->m_friendlyName); 00367 free(driverBundle->m_libPath); 00368 } 00369 } 00370 00371 /* 00372 * Releases resources allocated to a driver bundle vector. 00373 */ 00374 static void HPDriverVectorRelease(HPDriverVector driverBundleVector) 00375 { 00376 if (driverBundleVector) 00377 { 00378 HPDriver *b; 00379 00380 for (b = driverBundleVector; b->m_vendorId; ++b) 00381 HPDriverRelease(b); 00382 00383 free(driverBundleVector); 00384 } 00385 } 00386 00387 /* 00388 * Inserts a new reader device in the list. 00389 */ 00390 static HPDeviceList 00391 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address) 00392 { 00393 HPDevice *newReader = (HPDevice *) calloc(1, sizeof(HPDevice)); 00394 00395 if (!newReader) 00396 { 00397 Log1(PCSC_LOG_ERROR, "memory allocation failure"); 00398 return list; 00399 } 00400 00401 newReader->m_driver = HPDriverCopy(bundle); 00402 newReader->m_address = address; 00403 newReader->m_next = list; 00404 00405 return newReader; 00406 } 00407 00408 /* 00409 * Frees resources allocated to a HPDeviceList. 00410 */ 00411 static void HPDeviceListRelease(HPDeviceList list) 00412 { 00413 HPDevice *p; 00414 00415 for (p = list; p; p = p->m_next) 00416 HPDriverRelease(p->m_driver); 00417 } 00418 00419 /* 00420 * Compares two driver bundle instances for equality. 00421 */ 00422 static int HPDeviceEquals(HPDevice * a, HPDevice * b) 00423 { 00424 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId) 00425 && (a->m_driver->m_productId == b->m_driver->m_productId) 00426 && (a->m_address == b->m_address); 00427 } 00428 00429 /* 00430 * Finds USB devices currently registered in the system that match any of 00431 * the drivers detected in the driver bundle vector. 00432 */ 00433 static int 00434 HPDriversMatchUSBDevices(HPDriverVector driverBundle, 00435 HPDeviceList * readerList) 00436 { 00437 CFDictionaryRef usbMatch = IOServiceMatching("IOUSBDevice"); 00438 00439 if (0 == usbMatch) 00440 { 00441 Log1(PCSC_LOG_ERROR, 00442 "error getting USB match from IOServiceMatching()"); 00443 return 1; 00444 } 00445 00446 io_iterator_t usbIter; 00447 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault, 00448 usbMatch, &usbIter); 00449 00450 if (kret != 0) 00451 { 00452 Log1(PCSC_LOG_ERROR, 00453 "error getting iterator from IOServiceGetMatchingServices()"); 00454 return 1; 00455 } 00456 00457 IOIteratorReset(usbIter); 00458 io_object_t usbDevice = 0; 00459 00460 while ((usbDevice = IOIteratorNext(usbIter))) 00461 { 00462 char namebuf[1024]; 00463 00464 kret = IORegistryEntryGetName(usbDevice, namebuf); 00465 if (kret != 0) 00466 { 00467 Log1(PCSC_LOG_ERROR, 00468 "error getting device name from IORegistryEntryGetName()"); 00469 return 1; 00470 } 00471 00472 IOCFPlugInInterface **iodev; 00473 SInt32 score; 00474 00475 kret = IOCreatePlugInInterfaceForService(usbDevice, 00476 kIOUSBDeviceUserClientTypeID, 00477 kIOCFPlugInInterfaceID, &iodev, &score); 00478 if (kret != 0) 00479 { 00480 Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); 00481 return 1; 00482 } 00483 IOObjectRelease(usbDevice); 00484 00485 IOUSBDeviceInterface **usbdev; 00486 HRESULT hres = (*iodev)->QueryInterface(iodev, 00487 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), 00488 (LPVOID *) & usbdev); 00489 00490 (*iodev)->Release(iodev); 00491 if (hres) 00492 { 00493 Log1(PCSC_LOG_ERROR, 00494 "error querying interface in QueryInterface()"); 00495 return 1; 00496 } 00497 00498 UInt16 vendorId = 0; 00499 UInt16 productId = 0; 00500 UInt32 usbAddress = 0; 00501 00502 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId); 00503 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId); 00504 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress); 00505 (*usbdev)->Release(usbdev); 00506 00507 HPDriver *driver; 00508 for (driver = driverBundle; driver->m_vendorId; ++driver) 00509 { 00510 if ((driver->m_vendorId == vendorId) 00511 && (driver->m_productId == productId)) 00512 { 00513 *readerList = 00514 HPDeviceListInsert(*readerList, driver, usbAddress); 00515 } 00516 } 00517 } 00518 00519 IOObjectRelease(usbIter); 00520 return 0; 00521 } 00522 00523 /* 00524 * Finds PC Card devices currently registered in the system that match any of 00525 * the drivers detected in the driver bundle vector. 00526 */ 00527 static int 00528 HPDriversMatchPCCardDevices(HPDriver * driverBundle, 00529 HPDeviceList * readerList) 00530 { 00531 CFDictionaryRef pccMatch = IOServiceMatching("IOPCCard16Device"); 00532 00533 if (pccMatch == NULL) 00534 { 00535 Log1(PCSC_LOG_ERROR, 00536 "error getting PCCard match from IOServiceMatching()"); 00537 return 1; 00538 } 00539 00540 io_iterator_t pccIter; 00541 kern_return_t kret = 00542 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch, 00543 &pccIter); 00544 if (kret != 0) 00545 { 00546 Log1(PCSC_LOG_ERROR, 00547 "error getting iterator from IOServiceGetMatchingServices()"); 00548 return 1; 00549 } 00550 00551 IOIteratorReset(pccIter); 00552 io_object_t pccDevice = 0; 00553 00554 while ((pccDevice = IOIteratorNext(pccIter))) 00555 { 00556 char namebuf[1024]; 00557 00558 kret = IORegistryEntryGetName(pccDevice, namebuf); 00559 if (kret != 0) 00560 { 00561 Log1(PCSC_LOG_ERROR, "error getting plugin interface from IOCreatePlugInInterfaceForService()"); 00562 return 1; 00563 } 00564 UInt32 vendorId = 0; 00565 UInt32 productId = 0; 00566 UInt32 pccAddress = 0; 00567 CFTypeRef valueRef = 00568 IORegistryEntryCreateCFProperty(pccDevice, CFSTR("VendorID"), 00569 kCFAllocatorDefault, 0); 00570 00571 if (!valueRef) 00572 { 00573 Log1(PCSC_LOG_ERROR, "error getting vendor"); 00574 } 00575 else 00576 { 00577 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, 00578 &vendorId); 00579 } 00580 valueRef = 00581 IORegistryEntryCreateCFProperty(pccDevice, CFSTR("DeviceID"), 00582 kCFAllocatorDefault, 0); 00583 if (!valueRef) 00584 { 00585 Log1(PCSC_LOG_ERROR, "error getting device"); 00586 } 00587 else 00588 { 00589 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, 00590 &productId); 00591 } 00592 valueRef = 00593 IORegistryEntryCreateCFProperty(pccDevice, CFSTR("SocketNumber"), 00594 kCFAllocatorDefault, 0); 00595 if (!valueRef) 00596 { 00597 Log1(PCSC_LOG_ERROR, "error getting PC Card socket"); 00598 } 00599 else 00600 { 00601 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type, 00602 &pccAddress); 00603 } 00604 HPDriver *driver = driverBundle; 00605 00606 for (; driver->m_vendorId; ++driver) 00607 { 00608 if ((driver->m_vendorId == vendorId) 00609 && (driver->m_productId == productId)) 00610 { 00611 *readerList = 00612 HPDeviceListInsert(*readerList, driver, pccAddress); 00613 } 00614 } 00615 } 00616 IOObjectRelease(pccIter); 00617 return 0; 00618 } 00619 00620 00621 static void HPEstablishUSBNotification(void) 00622 { 00623 io_iterator_t deviceAddedIterator; 00624 io_iterator_t deviceRemovedIterator; 00625 CFMutableDictionaryRef matchingDictionary; 00626 IONotificationPortRef notificationPort; 00627 IOReturn kret; 00628 00629 notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 00630 CFRunLoopAddSource(CFRunLoopGetCurrent(), 00631 IONotificationPortGetRunLoopSource(notificationPort), 00632 kCFRunLoopDefaultMode); 00633 00634 matchingDictionary = IOServiceMatching("IOUSBDevice"); 00635 if (!matchingDictionary) 00636 { 00637 Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed"); 00638 } 00639 matchingDictionary = 00640 (CFMutableDictionaryRef) CFRetain(matchingDictionary); 00641 00642 kret = IOServiceAddMatchingNotification(notificationPort, 00643 kIOMatchedNotification, 00644 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator); 00645 if (kret) 00646 { 00647 Log2(PCSC_LOG_ERROR, 00648 "IOServiceAddMatchingNotification()-1 failed with code %d", kret); 00649 } 00650 HPDeviceAppeared(NULL, deviceAddedIterator); 00651 00652 kret = IOServiceAddMatchingNotification(notificationPort, 00653 kIOTerminatedNotification, 00654 matchingDictionary, 00655 HPDeviceDisappeared, NULL, &deviceRemovedIterator); 00656 if (kret) 00657 { 00658 Log2(PCSC_LOG_ERROR, 00659 "IOServiceAddMatchingNotification()-2 failed with code %d", kret); 00660 } 00661 HPDeviceDisappeared(NULL, deviceRemovedIterator); 00662 } 00663 00664 static void HPEstablishPCCardNotification(void) 00665 { 00666 io_iterator_t deviceAddedIterator; 00667 io_iterator_t deviceRemovedIterator; 00668 CFMutableDictionaryRef matchingDictionary; 00669 IONotificationPortRef notificationPort; 00670 IOReturn kret; 00671 00672 notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 00673 CFRunLoopAddSource(CFRunLoopGetCurrent(), 00674 IONotificationPortGetRunLoopSource(notificationPort), 00675 kCFRunLoopDefaultMode); 00676 00677 matchingDictionary = IOServiceMatching("IOPCCard16Device"); 00678 if (!matchingDictionary) 00679 { 00680 Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed"); 00681 } 00682 matchingDictionary = 00683 (CFMutableDictionaryRef) CFRetain(matchingDictionary); 00684 00685 kret = IOServiceAddMatchingNotification(notificationPort, 00686 kIOMatchedNotification, 00687 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator); 00688 if (kret) 00689 { 00690 Log2(PCSC_LOG_ERROR, 00691 "IOServiceAddMatchingNotification()-1 failed with code %d", kret); 00692 } 00693 HPDeviceAppeared(NULL, deviceAddedIterator); 00694 00695 kret = IOServiceAddMatchingNotification(notificationPort, 00696 kIOTerminatedNotification, 00697 matchingDictionary, 00698 HPDeviceDisappeared, NULL, &deviceRemovedIterator); 00699 if (kret) 00700 { 00701 Log2(PCSC_LOG_ERROR, 00702 "IOServiceAddMatchingNotification()-2 failed with code %d", kret); 00703 } 00704 HPDeviceDisappeared(NULL, deviceRemovedIterator); 00705 } 00706 00707 /* 00708 * Thread runner (does not return). 00709 */ 00710 static void HPDeviceNotificationThread(void) 00711 { 00712 HPEstablishUSBNotification(); 00713 HPEstablishPCCardNotification(); 00714 CFRunLoopRun(); 00715 } 00716 00717 /* 00718 * Scans the hotplug driver directory and looks in the system for 00719 * matching devices. 00720 * Adds or removes matching readers as necessary. 00721 */ 00722 LONG HPSearchHotPluggables(void) 00723 { 00724 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR); 00725 00726 if (!drivers) 00727 return 1; 00728 00729 HPDeviceList devices = NULL; 00730 00731 if (HPDriversMatchUSBDevices(drivers, &devices)) 00732 return -1; 00733 00734 if (HPDriversMatchPCCardDevices(drivers, &devices)) 00735 return -1; 00736 00737 HPDevice *a; 00738 00739 for (a = devices; a; a = a->m_next) 00740 { 00741 int found = FALSE; 00742 HPDevice *b; 00743 00744 for (b = sDeviceList; b; b = b->m_next) 00745 { 00746 if (HPDeviceEquals(a, b)) 00747 { 00748 found = TRUE; 00749 break; 00750 } 00751 } 00752 if (!found) 00753 { 00754 char deviceName[MAX_DEVICENAME]; 00755 00756 /* the format should be "usb:%04x/%04x:libusb:%s" but we do not 00757 * know the libusb string. So it is not possible to differentiate 00758 * two identical readers :-( */ 00759 snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x", 00760 (unsigned int)a->m_driver->m_vendorId, 00761 (unsigned int)a->m_driver->m_productId); 00762 deviceName[sizeof(deviceName)-1] = '\0'; 00763 00764 RFAddReader(a->m_driver->m_friendlyName, 00765 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath, 00766 deviceName); 00767 } 00768 } 00769 00770 for (a = sDeviceList; a; a = a->m_next) 00771 { 00772 int found = FALSE; 00773 HPDevice *b; 00774 00775 for (b = devices; b; b = b->m_next) 00776 { 00777 if (HPDeviceEquals(a, b)) 00778 { 00779 found = TRUE; 00780 break; 00781 } 00782 } 00783 if (!found) 00784 { 00785 RFRemoveReader(a->m_driver->m_friendlyName, 00786 PCSCLITE_HP_BASE_PORT + a->m_address); 00787 } 00788 } 00789 00790 HPDeviceListRelease(sDeviceList); 00791 sDeviceList = devices; 00792 HPDriverVectorRelease(drivers); 00793 00794 return 0; 00795 } 00796 00797 00798 PCSCLITE_THREAD_T sHotplugWatcherThread; 00799 00800 /* 00801 * Sets up callbacks for device hotplug events. 00802 */ 00803 ULONG HPRegisterForHotplugEvents(void) 00804 { 00805 SYS_ThreadCreate(&sHotplugWatcherThread, 00806 THREAD_ATTR_DEFAULT, 00807 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL); 00808 00809 return 0; 00810 } 00811 00812 LONG HPStopHotPluggables(void) 00813 { 00814 return 0; 00815 } 00816 00817 void HPReCheckSerialReaders(void) 00818 { 00819 } 00820 00821 #endif /* __APPLE__ */ 00822