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