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;
95 static void HPDeviceAppeared(
void *refCon, io_iterator_t iterator)
102 while ((obj = IOIteratorNext(iterator)))
103 kret = IOObjectRelease(obj);
105 HPSearchHotPluggables();
112 static void HPDeviceDisappeared(
void *refCon, io_iterator_t iterator)
119 while ((obj = IOIteratorNext(iterator)))
120 kret = IOObjectRelease(obj);
122 HPSearchHotPluggables();
134 static HPDriverVector HPDriversGetFromDirectory(
const char *driverBundlePath)
137 Log2(PCSC_LOG_DEBUG,
"Entering HPDriversGetFromDirectory: %s",
141 int readersNumber = 0;
142 HPDriverVector bundleVector = NULL;
143 CFArrayRef bundleArray;
144 CFStringRef driverBundlePathString =
145 CFStringCreateWithCString(kCFAllocatorDefault,
147 kCFStringEncodingMacRoman);
148 CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
149 driverBundlePathString,
150 kCFURLPOSIXPathStyle, TRUE);
152 CFRelease(driverBundlePathString);
155 Log1(PCSC_LOG_ERROR,
"error getting plugin directory URL");
158 bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault,
162 Log1(PCSC_LOG_ERROR,
"error getting plugin directory bundles");
165 CFRelease(pluginUrl);
167 size_t bundleArraySize = CFArrayGetCount(bundleArray);
171 for (i = 0; i < bundleArraySize; i++)
173 CFBundleRef currBundle =
174 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
175 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
177 const void * blobValue = CFDictionaryGetValue(dict,
178 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
182 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
186 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
189 CFArrayRef propertyArray = blobValue;
190 readersNumber += CFArrayGetCount(propertyArray);
197 Log2(PCSC_LOG_DEBUG,
"Total of %d readers supported", readersNumber);
205 bundleVector = calloc(readersNumber,
sizeof(HPDriver));
208 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
212 HPDriver *driverBundle = bundleVector;
213 for (i = 0; i < bundleArraySize; i++)
215 CFBundleRef currBundle =
216 (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i);
217 CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle);
219 CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle);
220 CFStringRef bundlePath = CFURLCopyPath(bundleUrl);
222 driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath,
223 CFStringGetSystemEncoding()));
225 const void * blobValue = CFDictionaryGetValue(dict,
226 CFSTR(PCSCLITE_HP_MANUKEY_NAME));
230 Log1(PCSC_LOG_ERROR,
"error getting vendor ID from bundle");
234 if (CFGetTypeID(blobValue) == CFArrayGetTypeID())
236 CFArrayRef vendorArray = blobValue;
237 CFArrayRef productArray;
238 CFArrayRef friendlyNameArray;
239 char *libPath = driverBundle->m_libPath;
242 Log2(PCSC_LOG_DEBUG,
"Driver with aliases: %s", libPath);
245 productArray = CFDictionaryGetValue(dict,
246 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
249 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
254 friendlyNameArray = CFDictionaryGetValue(dict,
255 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
256 if (!friendlyNameArray)
258 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
262 int reader_nb = CFArrayGetCount(vendorArray);
264 if (reader_nb != CFArrayGetCount(productArray))
267 "Malformed Info.plist: %d vendors and %ld products",
268 reader_nb, CFArrayGetCount(productArray));
272 if (reader_nb != CFArrayGetCount(friendlyNameArray))
275 "Malformed Info.plist: %d vendors and %ld friendlynames",
276 reader_nb, CFArrayGetCount(friendlyNameArray));
281 for (j=0; j<reader_nb; j++)
283 CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j);
285 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
286 CFStringGetSystemEncoding()), NULL, 16);
288 strValue = CFArrayGetValueAtIndex(productArray, j);
289 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
290 CFStringGetSystemEncoding()), NULL, 16);
292 strValue = CFArrayGetValueAtIndex(friendlyNameArray, j);
293 const char *cstr = CFStringGetCStringPtr(strValue,
294 CFStringGetSystemEncoding());
296 driverBundle->m_friendlyName = strdup(cstr);
297 if (!driverBundle->m_libPath)
298 driverBundle->m_libPath = strdup(libPath);
301 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X",
302 driverBundle->m_vendorId);
303 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X",
304 driverBundle->m_productId);
305 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s",
306 driverBundle->m_friendlyName);
307 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
316 CFStringRef strValue = blobValue;
319 Log3(PCSC_LOG_DEBUG,
"Driver without alias: %s %s",
320 driverBundle->m_friendlyName, driverBundle->m_libPath);
323 driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue,
324 CFStringGetSystemEncoding()), NULL, 16);
326 strValue = (CFStringRef) CFDictionaryGetValue(dict,
327 CFSTR(PCSCLITE_HP_PRODKEY_NAME));
330 Log1(PCSC_LOG_ERROR,
"error getting product ID from bundle");
333 driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue,
334 CFStringGetSystemEncoding()), NULL, 16);
336 strValue = (CFStringRef) CFDictionaryGetValue(dict,
337 CFSTR(PCSCLITE_HP_NAMEKEY_NAME));
340 Log1(PCSC_LOG_ERROR,
"error getting product friendly name from bundle");
341 driverBundle->m_friendlyName = strdup(
"unnamed device");
345 const char *cstr = CFStringGetCStringPtr(strValue,
346 CFStringGetSystemEncoding());
348 driverBundle->m_friendlyName = strdup(cstr);
351 Log2(PCSC_LOG_DEBUG,
"VendorID: 0x%04X", driverBundle->m_vendorId);
352 Log2(PCSC_LOG_DEBUG,
"ProductID: 0x%04X", driverBundle->m_productId);
353 Log2(PCSC_LOG_DEBUG,
"Friendly name: %s", driverBundle->m_friendlyName);
354 Log2(PCSC_LOG_DEBUG,
"Driver: %s", driverBundle->m_libPath);
361 CFRelease(bundleArray);
368 static HPDriver *HPDriverCopy(HPDriver * rhs)
373 HPDriver *newDriverBundle = calloc(1,
sizeof(HPDriver));
375 if (!newDriverBundle)
378 newDriverBundle->m_vendorId = rhs->m_vendorId;
379 newDriverBundle->m_productId = rhs->m_productId;
380 newDriverBundle->m_friendlyName = strdup(rhs->m_friendlyName);
381 newDriverBundle->m_libPath = strdup(rhs->m_libPath);
383 return newDriverBundle;
389 static void HPDriverRelease(HPDriver * driverBundle)
393 free(driverBundle->m_friendlyName);
394 free(driverBundle->m_libPath);
401 static void HPDriverVectorRelease(HPDriverVector driverBundleVector)
403 if (driverBundleVector)
407 for (b = driverBundleVector; b->m_vendorId; ++b)
410 free(driverBundleVector);
418 HPDeviceListInsert(HPDeviceList list, HPDriver * bundle, UInt32 address)
420 HPDevice *newReader = calloc(1,
sizeof(HPDevice));
424 Log1(PCSC_LOG_ERROR,
"memory allocation failure");
428 newReader->m_driver = HPDriverCopy(bundle);
429 newReader->m_address = address;
430 newReader->m_next = list;
438 static void HPDeviceListRelease(HPDeviceList list)
442 for (p = list; p; p = p->m_next)
443 HPDriverRelease(p->m_driver);
449 static int HPDeviceEquals(HPDevice * a, HPDevice * b)
451 return (a->m_driver->m_vendorId == b->m_driver->m_vendorId)
452 && (a->m_driver->m_productId == b->m_driver->m_productId)
453 && (a->m_address == b->m_address);
461 HPDriversMatchUSBDevices(HPDriverVector driverBundle,
462 HPDeviceList * readerList)
464 CFDictionaryRef usbMatch = IOServiceMatching(
"IOUSBDevice");
469 "error getting USB match from IOServiceMatching()");
473 io_iterator_t usbIter;
474 kern_return_t kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
480 "error getting iterator from IOServiceGetMatchingServices()");
484 IOIteratorReset(usbIter);
485 io_object_t usbDevice = 0;
487 while ((usbDevice = IOIteratorNext(usbIter)))
491 kret = IORegistryEntryGetName(usbDevice, namebuf);
495 "error getting device name from IORegistryEntryGetName()");
499 IOCFPlugInInterface **iodev;
502 kret = IOCreatePlugInInterfaceForService(usbDevice,
503 kIOUSBDeviceUserClientTypeID,
504 kIOCFPlugInInterfaceID, &iodev, &score);
507 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
510 IOObjectRelease(usbDevice);
512 IOUSBDeviceInterface **usbdev;
513 HRESULT hres = (*iodev)->QueryInterface(iodev,
514 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
515 (LPVOID *) & usbdev);
517 (*iodev)->Release(iodev);
521 "error querying interface in QueryInterface()");
526 UInt16 productId = 0;
527 UInt32 usbAddress = 0;
529 kret = (*usbdev)->GetDeviceVendor(usbdev, &vendorId);
530 kret = (*usbdev)->GetDeviceProduct(usbdev, &productId);
531 kret = (*usbdev)->GetLocationID(usbdev, &usbAddress);
532 (*usbdev)->Release(usbdev);
535 Log4(PCSC_LOG_DEBUG,
"Found USB device 0x%04X:0x%04X at 0x%X",
536 vendorId, productId, usbAddress);
539 for (driver = driverBundle; driver->m_vendorId; ++driver)
541 if ((driver->m_vendorId == vendorId)
542 && (driver->m_productId == productId))
545 Log4(PCSC_LOG_DEBUG,
"Adding USB device %04X:%04X at 0x%X",
546 vendorId, productId, usbAddress);
549 HPDeviceListInsert(*readerList, driver, usbAddress);
554 IOObjectRelease(usbIter);
563 HPDriversMatchPCCardDevices(HPDriver * driverBundle,
564 HPDeviceList * readerList)
566 CFDictionaryRef pccMatch = IOServiceMatching(
"IOPCCard16Device");
568 if (pccMatch == NULL)
571 "error getting PCCard match from IOServiceMatching()");
575 io_iterator_t pccIter;
577 IOServiceGetMatchingServices(kIOMasterPortDefault, pccMatch,
582 "error getting iterator from IOServiceGetMatchingServices()");
586 IOIteratorReset(pccIter);
587 io_object_t pccDevice = 0;
589 while ((pccDevice = IOIteratorNext(pccIter)))
593 kret = IORegistryEntryGetName(pccDevice, namebuf);
596 Log1(PCSC_LOG_ERROR,
"error getting plugin interface from IOCreatePlugInInterfaceForService()");
600 UInt32 productId = 0;
601 UInt32 pccAddress = 0;
603 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"VendorID"),
604 kCFAllocatorDefault, 0);
608 Log1(PCSC_LOG_ERROR,
"error getting vendor");
612 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
616 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"DeviceID"),
617 kCFAllocatorDefault, 0);
620 Log1(PCSC_LOG_ERROR,
"error getting device");
624 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
628 IORegistryEntryCreateCFProperty(pccDevice, CFSTR(
"SocketNumber"),
629 kCFAllocatorDefault, 0);
632 Log1(PCSC_LOG_ERROR,
"error getting PC Card socket");
636 CFNumberGetValue((CFNumberRef) valueRef, kCFNumberSInt32Type,
639 HPDriver *driver = driverBundle;
641 for (; driver->m_vendorId; ++driver)
643 if ((driver->m_vendorId == vendorId)
644 && (driver->m_productId == productId))
647 HPDeviceListInsert(*readerList, driver, pccAddress);
651 IOObjectRelease(pccIter);
656 static void HPEstablishUSBNotification(
void)
658 io_iterator_t deviceAddedIterator;
659 io_iterator_t deviceRemovedIterator;
660 CFMutableDictionaryRef matchingDictionary;
661 IONotificationPortRef notificationPort;
664 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
665 CFRunLoopAddSource(CFRunLoopGetCurrent(),
666 IONotificationPortGetRunLoopSource(notificationPort),
667 kCFRunLoopDefaultMode);
669 matchingDictionary = IOServiceMatching(
"IOUSBDevice");
670 if (!matchingDictionary)
672 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
675 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
677 kret = IOServiceAddMatchingNotification(notificationPort,
678 kIOMatchedNotification,
679 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
683 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
685 HPDeviceAppeared(NULL, deviceAddedIterator);
687 kret = IOServiceAddMatchingNotification(notificationPort,
688 kIOTerminatedNotification,
690 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
694 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
696 HPDeviceDisappeared(NULL, deviceRemovedIterator);
699 static void HPEstablishPCCardNotification(
void)
701 io_iterator_t deviceAddedIterator;
702 io_iterator_t deviceRemovedIterator;
703 CFMutableDictionaryRef matchingDictionary;
704 IONotificationPortRef notificationPort;
707 notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
708 CFRunLoopAddSource(CFRunLoopGetCurrent(),
709 IONotificationPortGetRunLoopSource(notificationPort),
710 kCFRunLoopDefaultMode);
712 matchingDictionary = IOServiceMatching(
"IOPCCard16Device");
713 if (!matchingDictionary)
715 Log1(PCSC_LOG_ERROR,
"IOServiceMatching() failed");
718 (CFMutableDictionaryRef) CFRetain(matchingDictionary);
720 kret = IOServiceAddMatchingNotification(notificationPort,
721 kIOMatchedNotification,
722 matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
726 "IOServiceAddMatchingNotification()-1 failed with code %d", kret);
728 HPDeviceAppeared(NULL, deviceAddedIterator);
730 kret = IOServiceAddMatchingNotification(notificationPort,
731 kIOTerminatedNotification,
733 HPDeviceDisappeared, NULL, &deviceRemovedIterator);
737 "IOServiceAddMatchingNotification()-2 failed with code %d", kret);
739 HPDeviceDisappeared(NULL, deviceRemovedIterator);
745 static void HPDeviceNotificationThread(
void)
747 HPEstablishUSBNotification();
748 HPEstablishPCCardNotification();
757 LONG HPSearchHotPluggables(
void)
759 HPDriver *drivers = HPDriversGetFromDirectory(PCSCLITE_HP_DROPDIR);
764 HPDeviceList devices = NULL;
766 if (HPDriversMatchUSBDevices(drivers, &devices))
769 if (HPDriversMatchPCCardDevices(drivers, &devices))
774 for (a = devices; a; a = a->m_next)
779 for (b = sDeviceList; b; b = b->m_next)
781 if (HPDeviceEquals(a, b))
789 char deviceName[MAX_DEVICENAME];
793 snprintf(deviceName,
sizeof(deviceName),
794 "%s", a->m_driver->m_friendlyName);
795 deviceName[
sizeof(deviceName)-1] =
'\0';
797 RFAddReader(a->m_driver->m_friendlyName,
798 PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
803 for (a = sDeviceList; a; a = a->m_next)
808 for (b = devices; b; b = b->m_next)
810 if (HPDeviceEquals(a, b))
818 RFRemoveReader(a->m_driver->m_friendlyName,
819 PCSCLITE_HP_BASE_PORT + a->m_address);
823 HPDeviceListRelease(sDeviceList);
824 sDeviceList = devices;
825 HPDriverVectorRelease(drivers);
831 pthread_t sHotplugWatcherThread;
836 ULONG HPRegisterForHotplugEvents(
void)
838 ThreadCreate(&sHotplugWatcherThread,
840 (PCSCLITE_THREAD_FUNCTION( )) HPDeviceNotificationThread, NULL);
845 LONG HPStopHotPluggables(
void)
850 void HPReCheckSerialReaders(
void)
Reads lexical config files and updates database.
This defines some structures and #defines to be used over the transport layer.
This keeps a list of defines for pcsc-lite.
This keeps track of a list of currently available reader structures.
This provides a search API for hot pluggble devices.