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,
163 CFRelease(pluginUrl);
166 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
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");
186 CFRelease(bundleArray);
190 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
193 CFArrayRef propertyArray = blobValue;
194 readersNumber += CFArrayGetCount(propertyArray);
201 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
209 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
212 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
213 CFRelease(bundleArray);
217 HPDriver *driverBundle = bundleVector;
218 for (i = 0; i < bundleArraySize; i++)
220 CFBundleRef currBundle =
221 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
222 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
224 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
225 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
226 CFRelease(bundleUrl);
228 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
229 CFStringGetSystemEncoding()));
230 CFRelease(bundlePath);
232 const void * blobValue = CFDictionaryGetValue(dict,
233 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
237 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
238 CFRelease(bundleArray);
242 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
244 CFArrayRef vendorArray = blobValue;
245 CFArrayRef productArray;
246 CFArrayRef friendlyNameArray;
247 char *libPath = driverBundle->m_libPath;
250 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
253 productArray = CFDictionaryGetValue(dict,
254 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
257 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
258 CFRelease(bundleArray);
263 friendlyNameArray = CFDictionaryGetValue(dict,
264 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
265 if (!friendlyNameArray)
267 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
268 CFRelease(bundleArray);
272 long reader_nb = CFArrayGetCount(vendorArray);
274 if (reader_nb != CFArrayGetCount(productArray))
277 "Malformed Info.plist: %ld vendors and %ld products",
278 reader_nb, CFArrayGetCount(productArray));
279 CFRelease(bundleArray);
283 if (reader_nb != CFArrayGetCount(friendlyNameArray))
286 "Malformed Info.plist: %ld vendors and %ld friendlynames",
287 reader_nb, CFArrayGetCount(friendlyNameArray));
288 CFRelease(bundleArray);
293 for (j=0; j<reader_nb; j++)
295 char stringBuffer[1000];
296 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
298 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
299 kCFStringEncodingUTF8);
300 driverBundle->m_vendorId = (
unsigned int)strtoul(stringBuffer, NULL, 16);
302 strValue = CFArrayGetValueAtIndex(productArray, j);
303 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
304 kCFStringEncodingUTF8);
305 driverBundle->m_productId = (
unsigned int)strtoul(stringBuffer, NULL, 16);
307 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
308 CFStringGetCString(strValue, stringBuffer,
sizeof stringBuffer,
309 kCFStringEncodingUTF8);
310 driverBundle->m_friendlyName = strdup(stringBuffer);
312 if (!driverBundle->m_libPath)
313 driverBundle->m_libPath = strdup(libPath);
316 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
317 driverBundle->m_vendorId);
318 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
319 driverBundle->m_productId);
320 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
321 driverBundle->m_friendlyName);
322 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
331 Log1(PCSC_LOG_ERROR,
"Non array not supported");
334 CFRelease(bundleArray);
341static HPDriver *HPDriverCopy(HPDriver * rhs)
346 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
348 if (!newDriverBundle)
351 newDriverBundle->m_vendorId = rhs->m_vendorId;
352 newDriverBundle->m_productId = rhs->m_productId;
353 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
354 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
356 return newDriverBundle;
362static void HPDriverRelease(HPDriver * driverBundle)
366 free(driverBundle->m_friendlyName);
367 free(driverBundle->m_libPath);
375HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
377 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
381 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
385 newReader->m_driver = HPDriverCopy(bundle);
386 newReader->m_address = address;
387 newReader->m_next = list;
395static void HPDeviceListRelease(HPDeviceList list)
399 for (p = list; p; p = p->m_next)
400 HPDriverRelease(p->m_driver);
406static int HPDeviceEquals(HPDevice * a, HPDevice * b)
408 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
409 && (a->m_driver->m_productId == b->m_driver->m_productId)
410 && (a->m_address == b->m_address);
418HPDriversMatchUSBDevices(HPDriverVector driverBundle,
419 HPDeviceList * readerList)
421 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
426 "error getting USB match from IOServiceMatching()");
430 io_iterator_t usbIter;
431 kern_return_t kret = IOServiceGetMatchingServices(kIOMainPortDefault,
437 "error getting iterator from IOServiceGetMatchingServices()");
441 IOIteratorReset(usbIter);
442 io_object_t usbDevice = 0;
444 while ((usbDevice = IOIteratorNext(usbIter)))
448 kret = IORegistryEntryGetName(usbDevice, namebuf);
452 "error getting device name from IORegistryEntryGetName()");
456 IOCFPlugInInterface **iodev;
459 kret = IOCreatePlugInInterfaceForService(usbDevice,
460 kIOUSBDeviceUserClientTypeID,
461 kIOCFPlugInInterfaceID, &iodev, &score);
464 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
467 IOObjectRelease(usbDevice);
469 IOUSBDeviceInterface **usbdev;
470 HRESULT hres = (*iodev)->QueryInterface(iodev,
471 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
472 (LPVOID *) & usbdev);
474 (*iodev)->Release(iodev);
478 "error querying interface in QueryInterface()");
483 UInt16 productId = 0;
484 UInt32 usbAddress = 0;
486 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
487 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
488 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
489 (*usbdev)->Release(usbdev);
492 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
493 vendorId, productId, usbAddress);
496 for (driver = driverBundle; driver->m_vendorId; ++driver)
498 if ((driver->m_vendorId == vendorId)
499 && (driver->m_productId == productId))
502 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
503 vendorId, productId, usbAddress);
506 HPDeviceListInsert(*readerList, driver, usbAddress);
511 IOObjectRelease(usbIter);
520HPDriversMatchPCCardDevices(HPDriver * driverBundle,
521 HPDeviceList * readerList)
523 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
525 if (pccMatch == NULL)
528 "error getting PCCard match from IOServiceMatching()");
532 io_iterator_t pccIter;
534 IOServiceGetMatchingServices(kIOMainPortDefault, pccMatch,
539 "error getting iterator from IOServiceGetMatchingServices()");
543 IOIteratorReset(pccIter);
544 io_object_t pccDevice = 0;
546 while ((pccDevice = IOIteratorNext(pccIter)))
550 kret = IORegistryEntryGetName(pccDevice, namebuf);
553 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
557 UInt32 productId = 0;
558 UInt32 pccAddress = 0;
560 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
561 kCFAllocatorDefault, 0);
565 Log1(PCSC_LOG_ERROR,
"error getting vendor");
569 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
574 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
575 kCFAllocatorDefault, 0);
578 Log1(PCSC_LOG_ERROR,
"error getting device");
582 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
587 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
588 kCFAllocatorDefault, 0);
591 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
595 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
599 HPDriver *driver = driverBundle;
601 for (; driver->m_vendorId; ++driver)
603 if ((driver->m_vendorId == vendorId)
604 && (driver->m_productId == productId))
607 HPDeviceListInsert(*readerList, driver, pccAddress);
611 IOObjectRelease(pccIter);
616static void HPEstablishUSBNotification(
void)
618 io_iterator_t deviceAddedIterator;
619 io_iterator_t deviceRemovedIterator;
620 CFMutableDictionaryRef matchingDictionary;
621 IONotificationPortRef notificationPort;
624 notificationPort = IONotificationPortCreate(kIOMainPortDefault);
625 CFRunLoopAddSource(CFRunLoopGetCurrent(),
626 IONotificationPortGetRunLoopSource(notificationPort),
627 kCFRunLoopDefaultMode);
629 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
630 if (!matchingDictionary)
632 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
636 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
638 kret = IOServiceAddMatchingNotification(notificationPort,
639 kIOMatchedNotification,
640 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
644 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
646 HPDeviceAppeared(NULL, deviceAddedIterator);
648 kret = IOServiceAddMatchingNotification(notificationPort,
649 kIOTerminatedNotification,
651 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
655 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
657 HPDeviceDisappeared(NULL, deviceRemovedIterator);
660static void HPEstablishPCCardNotification(
void)
662 io_iterator_t deviceAddedIterator;
663 io_iterator_t deviceRemovedIterator;
664 CFMutableDictionaryRef matchingDictionary;
665 IONotificationPortRef notificationPort;
668 notificationPort = IONotificationPortCreate(kIOMainPortDefault);
669 CFRunLoopAddSource(CFRunLoopGetCurrent(),
670 IONotificationPortGetRunLoopSource(notificationPort),
671 kCFRunLoopDefaultMode);
673 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
674 if (!matchingDictionary)
676 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
680 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
682 kret = IOServiceAddMatchingNotification(notificationPort,
683 kIOMatchedNotification,
684 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
688 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
690 HPDeviceAppeared(NULL, deviceAddedIterator);
692 kret = IOServiceAddMatchingNotification(notificationPort,
693 kIOTerminatedNotification,
695 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
699 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
701 HPDeviceDisappeared(NULL, deviceRemovedIterator);
707static void HPDeviceNotificationThread(
void)
709 HPEstablishUSBNotification();
710 HPEstablishPCCardNotification();
719LONG HPSearchHotPluggables(
const char * hpDirPath)
721 Drivers = HPDriversGetFromDirectory(hpDirPath);
729static int HPScan(
void)
731 HPDeviceList devices = NULL;
733 if (HPDriversMatchUSBDevices(Drivers, &devices))
741 if (HPDriversMatchPCCardDevices(Drivers, &devices))
751 for (a = devices; a; a = a->m_next)
756 for (b = sDeviceList; b; b = b->m_next)
758 if (HPDeviceEquals(a, b))
770 asprintf(&deviceName,
"%s", a->m_driver->m_friendlyName);
772 RFAddReader(a->m_driver->m_friendlyName,
773 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
779 for (a = sDeviceList; a; a = a->m_next)
784 for (b = devices; b; b = b->m_next)
786 if (HPDeviceEquals(a, b))
794 RFRemoveReader(a->m_driver->m_friendlyName,
795 PCSCLITE_HP_BASE_PORT + a->m_address,
796 REMOVE_READER_FLAG_REMOVED);
800 HPDeviceListRelease(sDeviceList);
801 sDeviceList = devices;
807pthread_t sHotplugWatcherThread;
812ULONG HPRegisterForHotplugEvents(
const char * hpDirPath)
816 ThreadCreate(&sHotplugWatcherThread,
818 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
823LONG HPStopHotPluggables(
void)
828void 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.