46#if defined(__APPLE__) && !defined(HAVE_LIBUSB)
47#include <CoreFoundation/CoreFoundation.h>
48#include <IOKit/IOCFPlugIn.h>
49#include <IOKit/IOKitLib.h>
50#include <IOKit/usb/IOUSBLib.h>
67typedef struct HPDriver
73} HPDriver, *HPDriverVector;
78typedef struct HPDevice
82 struct HPDevice *m_next;
83} HPDevice, *HPDeviceList;
89static HPDeviceList sDeviceList = NULL;
91static int HPScan(
void);
92static HPDriver *Drivers = NULL;
98static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
105 while ((obj = IOIteratorNext(iterator)))
106 kret = IOObjectRelease(obj);
115static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
122 while ((obj = IOIteratorNext(iterator)))
123 kret = IOObjectRelease(obj);
137static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
140 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
144 int readersNumber = 0;
145 HPDriverVector bundleVector = NULL;
146 CFArrayRef bundleArray;
147 CFStringRef driverBundlePathString =
148 CFStringCreateWithCString(kCFAllocatorDefault,
150 kCFStringEncodingMacRoman);
151 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
152 driverBundlePathString,
153 kCFURLPOSIXPathStyle, TRUE);
155 CFRelease(driverBundlePathString);
158 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
161 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
165 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
168 CFRelease(pluginUrl);
170 size_t bundleArraySize = CFArrayGetCount(bundleArray);
174 for (i = 0; i < bundleArraySize; i++)
176 CFBundleRef currBundle =
177 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
178 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
180 const void * blobValue = CFDictionaryGetValue(dict,
181 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
185 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
189 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
192 CFArrayRef propertyArray = blobValue;
193 readersNumber += CFArrayGetCount(propertyArray);
200 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
208 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
211 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
215 HPDriver *driverBundle = bundleVector;
216 for (i = 0; i < bundleArraySize; i++)
218 CFBundleRef currBundle =
219 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
220 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
222 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
223 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
225 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
226 CFStringGetSystemEncoding()));
228 const void * blobValue = CFDictionaryGetValue(dict,
229 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
233 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
237 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
239 CFArrayRef vendorArray = blobValue;
240 CFArrayRef productArray;
241 CFArrayRef friendlyNameArray;
242 char *libPath = driverBundle->m_libPath;
245 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
248 productArray = CFDictionaryGetValue(dict,
249 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
252 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
257 friendlyNameArray = CFDictionaryGetValue(dict,
258 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
259 if (!friendlyNameArray)
261 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
265 int reader_nb = CFArrayGetCount(vendorArray);
267 if (reader_nb != CFArrayGetCount(productArray))
270 "Malformed Info.plist: %d vendors and %ld products",
271 reader_nb, CFArrayGetCount(productArray));
275 if (reader_nb != CFArrayGetCount(friendlyNameArray))
278 "Malformed Info.plist: %d vendors and %ld friendlynames",
279 reader_nb, CFArrayGetCount(friendlyNameArray));
284 for (j=0; j<reader_nb; j++)
286 char stringBuffer[1000];
287 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
289 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
290 kCFStringEncodingUTF8);
291 driverBundle->m_vendorId = strtoul(stringBuffer, NULL, 16);
293 strValue = CFArrayGetValueAtIndex(productArray, j);
294 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
295 kCFStringEncodingUTF8);
296 driverBundle->m_productId = strtoul(stringBuffer, NULL, 16);
298 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
299 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
300 kCFStringEncodingUTF8);
301 driverBundle->m_friendlyName = strdup(stringBuffer);
303 if (!driverBundle->m_libPath)
304 driverBundle->m_libPath = strdup(libPath);
307 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
308 driverBundle->m_vendorId);
309 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
310 driverBundle->m_productId);
311 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
312 driverBundle->m_friendlyName);
313 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
322 Log1(PCSC_LOG_ERROR,
"Non array not supported");
325 CFRelease(bundleArray);
332static HPDriver *HPDriverCopy(HPDriver * rhs)
337 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
339 if (!newDriverBundle)
342 newDriverBundle->m_vendorId = rhs->m_vendorId;
343 newDriverBundle->m_productId = rhs->m_productId;
344 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
345 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
347 return newDriverBundle;
353static void HPDriverRelease(HPDriver * driverBundle)
357 free(driverBundle->m_friendlyName);
358 free(driverBundle->m_libPath);
366HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
368 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
372 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
376 newReader->m_driver = HPDriverCopy(bundle);
377 newReader->m_address = address;
378 newReader->m_next = list;
386static void HPDeviceListRelease(HPDeviceList list)
390 for (p = list; p; p = p->m_next)
391 HPDriverRelease(p->m_driver);
397static int HPDeviceEquals(HPDevice * a, HPDevice * b)
399 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
400 && (a->m_driver->m_productId == b->m_driver->m_productId)
401 && (a->m_address == b->m_address);
409HPDriversMatchUSBDevices(HPDriverVector driverBundle,
410 HPDeviceList * readerList)
412 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
417 "error getting USB match from IOServiceMatching()");
421 io_iterator_t usbIter;
422 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
428 "error getting iterator from IOServiceGetMatchingServices()");
432 IOIteratorReset(usbIter);
433 io_object_t usbDevice = 0;
435 while ((usbDevice = IOIteratorNext(usbIter)))
439 kret = IORegistryEntryGetName(usbDevice, namebuf);
443 "error getting device name from IORegistryEntryGetName()");
447 IOCFPlugInInterface **iodev;
450 kret = IOCreatePlugInInterfaceForService(usbDevice,
451 kIOUSBDeviceUserClientTypeID,
452 kIOCFPlugInInterfaceID, &iodev, &score);
455 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
458 IOObjectRelease(usbDevice);
460 IOUSBDeviceInterface **usbdev;
461 HRESULT hres = (*iodev)->QueryInterface(iodev,
462 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
463 (LPVOID *) & usbdev);
465 (*iodev)->Release(iodev);
469 "error querying interface in QueryInterface()");
474 UInt16 productId = 0;
475 UInt32 usbAddress = 0;
477 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
478 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
479 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
480 (*usbdev)->Release(usbdev);
483 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
484 vendorId, productId, usbAddress);
487 for (driver = driverBundle; driver->m_vendorId; ++driver)
489 if ((driver->m_vendorId == vendorId)
490 && (driver->m_productId == productId))
493 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
494 vendorId, productId, usbAddress);
497 HPDeviceListInsert(*readerList, driver, usbAddress);
502 IOObjectRelease(usbIter);
511HPDriversMatchPCCardDevices(HPDriver * driverBundle,
512 HPDeviceList * readerList)
514 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
516 if (pccMatch == NULL)
519 "error getting PCCard match from IOServiceMatching()");
523 io_iterator_t pccIter;
525 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
530 "error getting iterator from IOServiceGetMatchingServices()");
534 IOIteratorReset(pccIter);
535 io_object_t pccDevice = 0;
537 while ((pccDevice = IOIteratorNext(pccIter)))
541 kret = IORegistryEntryGetName(pccDevice, namebuf);
544 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
548 UInt32 productId = 0;
549 UInt32 pccAddress = 0;
551 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
552 kCFAllocatorDefault, 0);
556 Log1(PCSC_LOG_ERROR,
"error getting vendor");
560 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
564 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
565 kCFAllocatorDefault, 0);
568 Log1(PCSC_LOG_ERROR,
"error getting device");
572 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
576 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
577 kCFAllocatorDefault, 0);
580 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
584 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
587 HPDriver *driver = driverBundle;
589 for (; driver->m_vendorId; ++driver)
591 if ((driver->m_vendorId == vendorId)
592 && (driver->m_productId == productId))
595 HPDeviceListInsert(*readerList, driver, pccAddress);
599 IOObjectRelease(pccIter);
604static void HPEstablishUSBNotification(
void)
606 io_iterator_t deviceAddedIterator;
607 io_iterator_t deviceRemovedIterator;
608 CFMutableDictionaryRef matchingDictionary;
609 IONotificationPortRef notificationPort;
612 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
613 CFRunLoopAddSource(CFRunLoopGetCurrent(),
614 IONotificationPortGetRunLoopSource(notificationPort),
615 kCFRunLoopDefaultMode);
617 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
618 if (!matchingDictionary)
620 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
623 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
625 kret = IOServiceAddMatchingNotification(notificationPort,
626 kIOMatchedNotification,
627 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
631 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
633 HPDeviceAppeared(NULL, deviceAddedIterator);
635 kret = IOServiceAddMatchingNotification(notificationPort,
636 kIOTerminatedNotification,
638 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
642 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
644 HPDeviceDisappeared(NULL, deviceRemovedIterator);
647static void HPEstablishPCCardNotification(
void)
649 io_iterator_t deviceAddedIterator;
650 io_iterator_t deviceRemovedIterator;
651 CFMutableDictionaryRef matchingDictionary;
652 IONotificationPortRef notificationPort;
655 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
656 CFRunLoopAddSource(CFRunLoopGetCurrent(),
657 IONotificationPortGetRunLoopSource(notificationPort),
658 kCFRunLoopDefaultMode);
660 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
661 if (!matchingDictionary)
663 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
666 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
668 kret = IOServiceAddMatchingNotification(notificationPort,
669 kIOMatchedNotification,
670 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
674 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
676 HPDeviceAppeared(NULL, deviceAddedIterator);
678 kret = IOServiceAddMatchingNotification(notificationPort,
679 kIOTerminatedNotification,
681 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
685 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
687 HPDeviceDisappeared(NULL, deviceRemovedIterator);
693static void HPDeviceNotificationThread(
void)
695 HPEstablishUSBNotification();
696 HPEstablishPCCardNotification();
705LONG HPSearchHotPluggables(
const char * hpDirPath)
707 Drivers = HPDriversGetFromDirectory(hpDirPath);
715static int HPScan(
void)
717 HPDeviceList devices = NULL;
719 if (HPDriversMatchUSBDevices(Drivers, &devices))
722 if (HPDriversMatchPCCardDevices(Drivers, &devices))
727 for (a = devices; a; a = a->m_next)
732 for (b = sDeviceList; b; b = b->m_next)
734 if (HPDeviceEquals(a, b))
746 asprintf(&deviceName,
"%s", a->m_driver->m_friendlyName);
748 RFAddReader(a->m_driver->m_friendlyName,
749 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
755 for (a = sDeviceList; a; a = a->m_next)
760 for (b = devices; b; b = b->m_next)
762 if (HPDeviceEquals(a, b))
770 RFRemoveReader(a->m_driver->m_friendlyName,
771 PCSCLITE_HP_BASE_PORT + a->m_address,
772 REMOVE_READER_FLAG_REMOVED);
776 HPDeviceListRelease(sDeviceList);
777 sDeviceList = devices;
783pthread_t sHotplugWatcherThread;
788ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
790 ThreadCreate(&sHotplugWatcherThread,
792 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
797LONG HPStopHotPluggables(
void)
802void HPReCheckSerialReaders(
void)
This provides a search API for hot pluggble devices.
Reads lexical config files and updates database.
This keeps a list of defines for pcsc-lite.
This keeps track of a list of currently available reader structures.
This defines some structures and #defines to be used over the transport layer.