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>
67 typedef struct HPDriver
73 } HPDriver, *HPDriverVector;
78 typedef struct HPDevice
82 struct HPDevice *m_next;
83 } HPDevice, *HPDeviceList;
89 static HPDeviceList sDeviceList = NULL;
91 static int HPScan(
void);
92 static HPDriver *Drivers = NULL;
98 static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
105 while ((obj = IOIteratorNext(iterator)))
106 kret = IOObjectRelease(obj);
115 static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
122 while ((obj = IOIteratorNext(iterator)))
123 kret = IOObjectRelease(obj);
137 static 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 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
288 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
289 CFStringGetSystemEncoding()), NULL, 16);
291 strValue = CFArrayGetValueAtIndex(productArray, j);
292 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
293 CFStringGetSystemEncoding()), NULL, 16);
295 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
296 const char *cstr = CFStringGetCStringPtr(strValue,
297 CFStringGetSystemEncoding());
301 if (CFStringGetCString(strValue, utf8_str,
sizeof utf8_str,
302 kCFStringEncodingUTF8))
303 driverBundle->m_friendlyName = strdup(utf8_str);
308 driverBundle->m_friendlyName = strdup(cstr);
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 CFStringRef strValue = blobValue;
332 Log3(PCSC_LOG_DEBUG,
"Driver without alias: %s %s",
333 driverBundle->m_friendlyName, driverBundle->m_libPath);
336 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
337 CFStringGetSystemEncoding()), NULL, 16);
339 strValue = (CFStringRef) CFDictionaryGetValue(dict,
340 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
343 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
346 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
347 CFStringGetSystemEncoding()), NULL, 16);
349 strValue = (CFStringRef) CFDictionaryGetValue(dict,
350 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
353 Log1(PCSC_LOG_ERROR,
"error getting product friendly name from bundle");
354 driverBundle->m_friendlyName = strdup(
"unnamed device");
358 const char *cstr = CFStringGetCStringPtr(strValue,
359 CFStringGetSystemEncoding());
361 driverBundle->m_friendlyName = strdup(cstr);
364 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X", driverBundle->m_vendorId);
365 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X", driverBundle->m_productId);
366 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s", driverBundle->m_friendlyName);
367 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
374 CFRelease(bundleArray);
381 static HPDriver *HPDriverCopy(HPDriver * rhs)
386 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
388 if (!newDriverBundle)
391 newDriverBundle->m_vendorId = rhs->m_vendorId;
392 newDriverBundle->m_productId = rhs->m_productId;
393 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
394 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
396 return newDriverBundle;
402 static void HPDriverRelease(HPDriver * driverBundle)
406 free(driverBundle->m_friendlyName);
407 free(driverBundle->m_libPath);
415 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
417 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
421 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
425 newReader->m_driver = HPDriverCopy(bundle);
426 newReader->m_address = address;
427 newReader->m_next = list;
435 static void HPDeviceListRelease(HPDeviceList list)
439 for (p = list; p; p = p->m_next)
440 HPDriverRelease(p->m_driver);
446 static int HPDeviceEquals(HPDevice * a, HPDevice * b)
448 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
449 && (a->m_driver->m_productId == b->m_driver->m_productId)
450 && (a->m_address == b->m_address);
458 HPDriversMatchUSBDevices(HPDriverVector driverBundle,
459 HPDeviceList * readerList)
461 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
466 "error getting USB match from IOServiceMatching()");
470 io_iterator_t usbIter;
471 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
477 "error getting iterator from IOServiceGetMatchingServices()");
481 IOIteratorReset(usbIter);
482 io_object_t usbDevice = 0;
484 while ((usbDevice = IOIteratorNext(usbIter)))
488 kret = IORegistryEntryGetName(usbDevice, namebuf);
492 "error getting device name from IORegistryEntryGetName()");
496 IOCFPlugInInterface **iodev;
499 kret = IOCreatePlugInInterfaceForService(usbDevice,
500 kIOUSBDeviceUserClientTypeID,
501 kIOCFPlugInInterfaceID, &iodev, &score);
504 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
507 IOObjectRelease(usbDevice);
509 IOUSBDeviceInterface **usbdev;
510 HRESULT hres = (*iodev)->QueryInterface(iodev,
511 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
512 (LPVOID *) & usbdev);
514 (*iodev)->Release(iodev);
518 "error querying interface in QueryInterface()");
523 UInt16 productId = 0;
524 UInt32 usbAddress = 0;
526 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
527 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
528 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
529 (*usbdev)->Release(usbdev);
532 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
533 vendorId, productId, usbAddress);
536 for (driver = driverBundle; driver->m_vendorId; ++driver)
538 if ((driver->m_vendorId == vendorId)
539 && (driver->m_productId == productId))
542 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
543 vendorId, productId, usbAddress);
546 HPDeviceListInsert(*readerList, driver, usbAddress);
551 IOObjectRelease(usbIter);
560 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
561 HPDeviceList * readerList)
563 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
565 if (pccMatch == NULL)
568 "error getting PCCard match from IOServiceMatching()");
572 io_iterator_t pccIter;
574 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
579 "error getting iterator from IOServiceGetMatchingServices()");
583 IOIteratorReset(pccIter);
584 io_object_t pccDevice = 0;
586 while ((pccDevice = IOIteratorNext(pccIter)))
590 kret = IORegistryEntryGetName(pccDevice, namebuf);
593 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
597 UInt32 productId = 0;
598 UInt32 pccAddress = 0;
600 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
601 kCFAllocatorDefault, 0);
605 Log1(PCSC_LOG_ERROR,
"error getting vendor");
609 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
613 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
614 kCFAllocatorDefault, 0);
617 Log1(PCSC_LOG_ERROR,
"error getting device");
621 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
625 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
626 kCFAllocatorDefault, 0);
629 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
633 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
636 HPDriver *driver = driverBundle;
638 for (; driver->m_vendorId; ++driver)
640 if ((driver->m_vendorId == vendorId)
641 && (driver->m_productId == productId))
644 HPDeviceListInsert(*readerList, driver, pccAddress);
648 IOObjectRelease(pccIter);
653 static void HPEstablishUSBNotification(
void)
655 io_iterator_t deviceAddedIterator;
656 io_iterator_t deviceRemovedIterator;
657 CFMutableDictionaryRef matchingDictionary;
658 IONotificationPortRef notificationPort;
661 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
662 CFRunLoopAddSource(CFRunLoopGetCurrent(),
663 IONotificationPortGetRunLoopSource(notificationPort),
664 kCFRunLoopDefaultMode);
666 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
667 if (!matchingDictionary)
669 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
672 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
674 kret = IOServiceAddMatchingNotification(notificationPort,
675 kIOMatchedNotification,
676 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
680 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
682 HPDeviceAppeared(NULL, deviceAddedIterator);
684 kret = IOServiceAddMatchingNotification(notificationPort,
685 kIOTerminatedNotification,
687 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
691 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
693 HPDeviceDisappeared(NULL, deviceRemovedIterator);
696 static void HPEstablishPCCardNotification(
void)
698 io_iterator_t deviceAddedIterator;
699 io_iterator_t deviceRemovedIterator;
700 CFMutableDictionaryRef matchingDictionary;
701 IONotificationPortRef notificationPort;
704 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
705 CFRunLoopAddSource(CFRunLoopGetCurrent(),
706 IONotificationPortGetRunLoopSource(notificationPort),
707 kCFRunLoopDefaultMode);
709 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
710 if (!matchingDictionary)
712 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
715 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
717 kret = IOServiceAddMatchingNotification(notificationPort,
718 kIOMatchedNotification,
719 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
723 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
725 HPDeviceAppeared(NULL, deviceAddedIterator);
727 kret = IOServiceAddMatchingNotification(notificationPort,
728 kIOTerminatedNotification,
730 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
734 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
736 HPDeviceDisappeared(NULL, deviceRemovedIterator);
742 static void HPDeviceNotificationThread(
void)
744 HPEstablishUSBNotification();
745 HPEstablishPCCardNotification();
754 LONG HPSearchHotPluggables(
void)
756 Drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
764 static int HPScan(
void)
766 HPDeviceList devices = NULL;
768 if (HPDriversMatchUSBDevices(Drivers, &devices))
771 if (HPDriversMatchPCCardDevices(Drivers, &devices))
776 for (a = devices; a; a = a->m_next)
781 for (b = sDeviceList; b; b = b->m_next)
783 if (HPDeviceEquals(a, b))
791 char deviceName[MAX_DEVICENAME];
795 snprintf(deviceName,
sizeof(deviceName),
796 "%s", a->m_driver->m_friendlyName);
797 deviceName[
sizeof(deviceName)-1] =
'\0';
799 RFAddReader(a->m_driver->m_friendlyName,
800 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
805 for (a = sDeviceList; a; a = a->m_next)
810 for (b = devices; b; b = b->m_next)
812 if (HPDeviceEquals(a, b))
820 RFRemoveReader(a->m_driver->m_friendlyName,
821 PCSCLITE_HP_BASE_PORT + a->m_address,
822 REMOVE_READER_FLAG_REMOVED);
826 HPDeviceListRelease(sDeviceList);
827 sDeviceList = devices;
833 pthread_t sHotplugWatcherThread;
838 ULONG HPRegisterForHotplugEvents(
void)
840 ThreadCreate(&sHotplugWatcherThread,
842 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
847 LONG HPStopHotPluggables(
void)
852 void 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.