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)
104 while ((obj = IOIteratorNext(iterator)))
105 IOObjectRelease(obj);
114static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
120 while ((obj = IOIteratorNext(iterator)))
121 IOObjectRelease(obj);
135static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
138 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
142 int readersNumber = 0;
143 HPDriverVector bundleVector = NULL;
144 CFArrayRef bundleArray;
145 CFStringRef driverBundlePathString =
146 CFStringCreateWithCString(kCFAllocatorDefault,
148 kCFStringEncodingMacRoman);
149 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
150 driverBundlePathString,
151 kCFURLPOSIXPathStyle, TRUE);
153 CFRelease(driverBundlePathString);
156 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
159 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
161 CFRelease(pluginUrl);
164 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
168 size_t bundleArraySize = CFArrayGetCount(bundleArray);
172 for (i = 0; i < bundleArraySize; i++)
174 CFBundleRef currBundle =
175 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
176 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
178 const void * blobValue = CFDictionaryGetValue(dict,
179 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
183 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
184 CFRelease(bundleArray);
188 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
191 CFArrayRef propertyArray = blobValue;
192 readersNumber += CFArrayGetCount(propertyArray);
199 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
207 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
210 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
211 CFRelease(bundleArray);
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);
224 CFRelease(bundleUrl);
226 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
227 CFStringGetSystemEncoding()));
228 CFRelease(bundlePath);
230 const void * blobValue = CFDictionaryGetValue(dict,
231 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
235 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
236 CFRelease(bundleArray);
240 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
242 CFArrayRef vendorArray = blobValue;
243 CFArrayRef productArray;
244 CFArrayRef friendlyNameArray;
245 char *libPath = driverBundle->m_libPath;
248 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
251 productArray = CFDictionaryGetValue(dict,
252 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
255 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
256 CFRelease(bundleArray);
261 friendlyNameArray = CFDictionaryGetValue(dict,
262 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
263 if (!friendlyNameArray)
265 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
266 CFRelease(bundleArray);
270 long reader_nb = CFArrayGetCount(vendorArray);
272 if (reader_nb != CFArrayGetCount(productArray))
275 "Malformed Info.plist: %ld vendors and %ld products",
276 reader_nb, CFArrayGetCount(productArray));
277 CFRelease(bundleArray);
281 if (reader_nb != CFArrayGetCount(friendlyNameArray))
284 "Malformed Info.plist: %ld vendors and %ld friendlynames",
285 reader_nb, CFArrayGetCount(friendlyNameArray));
286 CFRelease(bundleArray);
291 for (j=0; j<reader_nb; j++)
293 char stringBuffer[1000];
294 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
296 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
297 kCFStringEncodingUTF8);
298 driverBundle->m_vendorId = (
unsigned int)strtoul(stringBuffer, NULL, 16);
300 strValue = CFArrayGetValueAtIndex(productArray, j);
301 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
302 kCFStringEncodingUTF8);
303 driverBundle->m_productId = (
unsigned int)strtoul(stringBuffer, NULL, 16);
305 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
306 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
307 kCFStringEncodingUTF8);
308 driverBundle->m_friendlyName = strdup(stringBuffer);
310 if (!driverBundle->m_libPath)
311 driverBundle->m_libPath = strdup(libPath);
314 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
315 driverBundle->m_vendorId);
316 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
317 driverBundle->m_productId);
318 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
319 driverBundle->m_friendlyName);
320 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
329 Log1(PCSC_LOG_ERROR,
"Non array not supported");
332 CFRelease(bundleArray);
339static HPDriver *HPDriverCopy(HPDriver * rhs)
344 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
346 if (!newDriverBundle)
349 newDriverBundle->m_vendorId = rhs->m_vendorId;
350 newDriverBundle->m_productId = rhs->m_productId;
351 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
352 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
354 return newDriverBundle;
360static void HPDriverRelease(HPDriver * driverBundle)
364 free(driverBundle->m_friendlyName);
365 free(driverBundle->m_libPath);
373HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
375 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
379 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
383 newReader->m_driver = HPDriverCopy(bundle);
384 newReader->m_address = address;
385 newReader->m_next = list;
393static void HPDeviceListRelease(HPDeviceList list)
397 for (p = list; p; p = p->m_next)
398 HPDriverRelease(p->m_driver);
404static int HPDeviceEquals(HPDevice * a, HPDevice * b)
406 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
407 && (a->m_driver->m_productId == b->m_driver->m_productId)
408 && (a->m_address == b->m_address);
416HPDriversMatchUSBDevices(HPDriverVector driverBundle,
417 HPDeviceList * readerList)
419 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
424 "error getting USB match from IOServiceMatching()");
428 io_iterator_t usbIter;
429 kern_return_t kret = IOServiceGetMatchingServices(kIOMainPortDefault,
435 "error getting iterator from IOServiceGetMatchingServices()");
439 IOIteratorReset(usbIter);
440 io_object_t usbDevice = 0;
442 while ((usbDevice = IOIteratorNext(usbIter)))
446 kret = IORegistryEntryGetName(usbDevice, namebuf);
450 "error getting device name from IORegistryEntryGetName()");
454 IOCFPlugInInterface **iodev;
457 kret = IOCreatePlugInInterfaceForService(usbDevice,
458 kIOUSBDeviceUserClientTypeID,
459 kIOCFPlugInInterfaceID, &iodev, &score);
462 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
465 IOObjectRelease(usbDevice);
467 IOUSBDeviceInterface **usbdev;
468 HRESULT hres = (*iodev)->QueryInterface(iodev,
469 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
470 (LPVOID *) & usbdev);
472 (*iodev)->Release(iodev);
476 "error querying interface in QueryInterface()");
481 UInt16 productId = 0;
482 UInt32 usbAddress = 0;
484 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
485 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
486 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
487 (*usbdev)->Release(usbdev);
490 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
491 vendorId, productId, usbAddress);
494 for (driver = driverBundle; driver->m_vendorId; ++driver)
496 if ((driver->m_vendorId == vendorId)
497 && (driver->m_productId == productId))
500 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
501 vendorId, productId, usbAddress);
504 HPDeviceListInsert(*readerList, driver, usbAddress);
509 IOObjectRelease(usbIter);
518HPDriversMatchPCCardDevices(HPDriver * driverBundle,
519 HPDeviceList * readerList)
521 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
523 if (pccMatch == NULL)
526 "error getting PCCard match from IOServiceMatching()");
530 io_iterator_t pccIter;
532 IOServiceGetMatchingServices(kIOMainPortDefault, pccMatch,
537 "error getting iterator from IOServiceGetMatchingServices()");
541 IOIteratorReset(pccIter);
542 io_object_t pccDevice = 0;
544 while ((pccDevice = IOIteratorNext(pccIter)))
548 kret = IORegistryEntryGetName(pccDevice, namebuf);
551 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
555 UInt32 productId = 0;
556 UInt32 pccAddress = 0;
558 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
559 kCFAllocatorDefault, 0);
563 Log1(PCSC_LOG_ERROR,
"error getting vendor");
567 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
572 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
573 kCFAllocatorDefault, 0);
576 Log1(PCSC_LOG_ERROR,
"error getting device");
580 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
585 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
586 kCFAllocatorDefault, 0);
589 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
593 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
597 HPDriver *driver = driverBundle;
599 for (; driver->m_vendorId; ++driver)
601 if ((driver->m_vendorId == vendorId)
602 && (driver->m_productId == productId))
605 HPDeviceListInsert(*readerList, driver, pccAddress);
609 IOObjectRelease(pccIter);
614static void HPEstablishUSBNotification(
void)
616 io_iterator_t deviceAddedIterator;
617 io_iterator_t deviceRemovedIterator;
618 CFMutableDictionaryRef matchingDictionary;
619 IONotificationPortRef notificationPort;
622 notificationPort = IONotificationPortCreate(kIOMainPortDefault);
623 CFRunLoopAddSource(CFRunLoopGetCurrent(),
624 IONotificationPortGetRunLoopSource(notificationPort),
625 kCFRunLoopDefaultMode);
627 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
628 if (!matchingDictionary)
630 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
634 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
636 kret = IOServiceAddMatchingNotification(notificationPort,
637 kIOMatchedNotification,
638 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
642 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
644 HPDeviceAppeared(NULL, deviceAddedIterator);
646 kret = IOServiceAddMatchingNotification(notificationPort,
647 kIOTerminatedNotification,
649 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
653 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
655 HPDeviceDisappeared(NULL, deviceRemovedIterator);
658static void HPEstablishPCCardNotification(
void)
660 io_iterator_t deviceAddedIterator;
661 io_iterator_t deviceRemovedIterator;
662 CFMutableDictionaryRef matchingDictionary;
663 IONotificationPortRef notificationPort;
666 notificationPort = IONotificationPortCreate(kIOMainPortDefault);
667 CFRunLoopAddSource(CFRunLoopGetCurrent(),
668 IONotificationPortGetRunLoopSource(notificationPort),
669 kCFRunLoopDefaultMode);
671 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
672 if (!matchingDictionary)
674 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
678 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
680 kret = IOServiceAddMatchingNotification(notificationPort,
681 kIOMatchedNotification,
682 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
686 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
688 HPDeviceAppeared(NULL, deviceAddedIterator);
690 kret = IOServiceAddMatchingNotification(notificationPort,
691 kIOTerminatedNotification,
693 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
697 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
699 HPDeviceDisappeared(NULL, deviceRemovedIterator);
705static void HPDeviceNotificationThread(
void)
707 HPEstablishUSBNotification();
708 HPEstablishPCCardNotification();
717LONG HPSearchHotPluggables(
const char * hpDirPath)
719 Drivers = HPDriversGetFromDirectory(hpDirPath);
727static int HPScan(
void)
729 HPDeviceList devices = NULL;
731 if (HPDriversMatchUSBDevices(Drivers, &devices))
739 if (HPDriversMatchPCCardDevices(Drivers, &devices))
749 for (a = devices; a; a = a->m_next)
754 for (b = sDeviceList; b; b = b->m_next)
756 if (HPDeviceEquals(a, b))
768 asprintf(&deviceName,
"%s", a->m_driver->m_friendlyName);
770 RFAddReader(a->m_driver->m_friendlyName,
771 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
777 for (a = sDeviceList; a; a = a->m_next)
782 for (b = devices; b; b = b->m_next)
784 if (HPDeviceEquals(a, b))
792 RFRemoveReader(a->m_driver->m_friendlyName,
793 PCSCLITE_HP_BASE_PORT + a->m_address,
794 REMOVE_READER_FLAG_REMOVED);
798 HPDeviceListRelease(sDeviceList);
799 sDeviceList = devices;
805pthread_t sHotplugWatcherThread;
810ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
814 ThreadCreate(&sHotplugWatcherThread,
816 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
821LONG HPStopHotPluggables(
void)
826void HPReCheckSerialReaders(
void)
This provides a search API for hot pluggble devices.
Reads lexical config files and updates database.
This keeps track of a list of currently available reader structures.
This defines some structures and #defines to be used over the transport layer.